diff --git a/EXTENSIONS b/EXTENSIONS index 8b7823de6b8b..d656b6ca5614 100644 --- a/EXTENSIONS +++ b/EXTENSIONS @@ -26,11 +26,6 @@ Status legend == Server APIs == -------------------------------------------------------------------------------- -EXTENSION: activescript -PRIMARY MAINTAINER: Wez Furlong -MAINTENANCE: Odd Fixes -STATUS: Experimental ------------------------------------------------------------------------------- EXTENSION: aolserver MAINTENANCE: Unknown @@ -41,14 +36,19 @@ PRIMARY MAINTAINER: Rasmus Lerdorf MAINTENANCE: Maintained STATUS: Working ------------------------------------------------------------------------------- -EXTENSION: apache2handler / apache2filter +EXTENSION: apache_hooks +MAINTENANCE: Unknown +STATUS: Unknown +------------------------------------------------------------------------------- +EXTENSION: apache2filter PRIMARY MAINTAINER: Aaron Bannert MAINTENANCE: Maintained STATUS: Experimental ------------------------------------------------------------------------------- -EXTENSION: apache_hooks -MAINTENANCE: Unknown -STATUS: Unknown +EXTENSION: apache2handler +PRIMARY MAINTAINER: Aaron Bannert +MAINTENANCE: Maintained +STATUS: Experimental ------------------------------------------------------------------------------- EXTENSION: caudium MAINTENANCE: Unknown @@ -63,6 +63,11 @@ MAINTENANCE: Marcus Boerger , Edin Kadribasic +MAINTENANCE: Unknown +STATUS: Unknown +------------------------------------------------------------------------------- EXTENSION: embed PRIMARY MAINTAINER: Edin Kadribasic MAINTENANCE: Maintained @@ -129,12 +134,8 @@ STATUS: Working SINCE: 4.0.6 COMMENT: DB abstraction for odbc, mysql, pgsql, mssql, fbsql and more, see documentation ------------------------------------------------------------------------------- -EXTENSION: filepro -MAINTENANCE: Unknown -STATUS: Unknown -------------------------------------------------------------------------------- -EXTENSION: hwapi -PRIMARY MAINTAINER: Uwe Steinmann +EXTENSION: fbsql +PRIMARY MAINTAINER: Frank M. Kromann MAINTENANCE: Unknown STATUS: Unknown ------------------------------------------------------------------------------- @@ -175,6 +176,26 @@ MAINTENANCE: Maintained STATUS: Experimental SINCE: 5.0 ------------------------------------------------------------------------------- +EXTENSION: oci8 +PRIMARY MAINTAINER: Antony Dovgal +MAINTENANCE: Maintained +STATUS: Working +------------------------------------------------------------------------------- +EXTENSION: odbc +PRIMARY MAINTAINER: Daniel R. Kalowsky +MAINTENANCE: Maintained +STATUS: Working +COMMENT: Working +------------------------------------------------------------------------------- +EXTENSION: oracle +MAINTENANCE: Orphaned +STATUS: Working +COMMENT: Using the new OCI8 driver is encouraged where possible. +------------------------------------------------------------------------------- +EXTENSION: ovrimos +MAINTENANCE: Unknown +STATUS: Unknown +------------------------------------------------------------------------------- EXTENSION: pgsql PRIMARY MAINTAINER: Marcus Boerger , Yasuo Ohgaki MAINTENANCE: Maintained @@ -196,22 +217,6 @@ EXTENSION: sybase_ct MAINTENANCE: Unknown STATUS: Working ------------------------------------------------------------------------------- -EXTENSION: oci8 -PRIMARY MAINTAINER: Antony Dovgal -MAINTENANCE: Maintained -STATUS: Working -------------------------------------------------------------------------------- -EXTENSION: odbc -PRIMARY MAINTAINER: Daniel R. Kalowsky -MAINTENANCE: Maintained -STATUS: Working -COMMENT: Working -------------------------------------------------------------------------------- -EXTENSION: oracle -MAINTENANCE: Orphaned -STATUS: Working -COMMENT: Using the new OCI8 driver is encouraged where possible. -------------------------------------------------------------------------------- == XML extensions == @@ -220,7 +225,7 @@ COMMENT: Using the new OCI8 driver is encouraged where possible. EXTENSION: dom PRIMARY MAINTAINER: Christian Stocker , Rob Richards , Marcus Boerger MAINTENANCE: Maintained -STATUS: Experimental +STATUS: Working SINCE: 5.0 ------------------------------------------------------------------------------- EXTENSION: simplexml @@ -229,6 +234,11 @@ MAINTENANCE: Maintained STATUS: Experimental SINCE: 5.0 ------------------------------------------------------------------------------- +EXTENSION: soap +PRIMARY MAINTAINER: Dmitry Stogov +MAINTENANCE: Maintained +STATUS: Experimental +------------------------------------------------------------------------------- EXTENSION: wddx PRIMARY MAINTAINER: Andrei Zmievski MAINTENANCE: Maintained @@ -247,7 +257,7 @@ STATUS: Experimental EXTENSION: xsl PRIMARY MAINTAINER: Christian Stocker , Rob Richards MAINTENANCE: Maintained -STATUS: Experimental +STATUS: Working SINCE: 5.0 ------------------------------------------------------------------------------- @@ -265,11 +275,6 @@ MAINTENANCE: Odd Fixes STATUS: Working SINCE: 4.0.3 ------------------------------------------------------------------------------- -EXTENSION: dio -MAINTENANCE: Orphaned -STATUS: Working -SINCE: 4.0.6 -------------------------------------------------------------------------------- EXTENSION: calendar PRIMARY MAINTAINER: Hartmut Holzgraefe MAINTENANCE: Odd Fixes @@ -297,17 +302,31 @@ MAINTENANCE: Maintained STATUS: Working SINCE: 4.0.2 ------------------------------------------------------------------------------- +EXTENSION: dio +MAINTENANCE: Orphaned +STATUS: Working +SINCE: 4.0.6 +------------------------------------------------------------------------------- EXTENSION: exif PRIMARY MAINTAINER: Marcus Boerger MAINTENANCE: Maintained STATUS: Working SINCE: 4.2 ------------------------------------------------------------------------------- +EXTENSION: fam +PRIMARY MAINTAINER: Sascha Schumann +MAINTENANCE: Unknown +STATUS: Unknown +------------------------------------------------------------------------------- EXTENSION: fdf PRIMARY MAINTAINER: Uwe Steinmann MAINTENANCE: Maintained STATUS: Unknown ------------------------------------------------------------------------------- +EXTENSION: filepro +MAINTENANCE: Unknown +STATUS: Unknown +------------------------------------------------------------------------------- EXTENSION: ftp PRIMARY MAINTAINER: Stefan Esser (sesser@php.net) MAINTENANCE: Maintained @@ -327,6 +346,11 @@ MAINTENANCE: Unknown STATUS: Unknown SINCE: 4.0.4 ------------------------------------------------------------------------------- +EXTENSION: hwapi +PRIMARY MAINTAINER: Uwe Steinmann +MAINTENANCE: Unknown +STATUS: Unknown +------------------------------------------------------------------------------- EXTENSION: iconv PRIMARY MAINTAINER: Moriyoshi Koizumi MAINTENANCE: Maintained @@ -337,6 +361,11 @@ PRIMARY MAINTAINER: Chuck Hagenbuch MAINTENANCE: Odd Fixes STATUS: Working ------------------------------------------------------------------------------- +EXTENSION: ircg +PRIMARY MAINTAINER: Sascha Schumann +MAINTENANCE: Unknown +STATUS: Unknown +------------------------------------------------------------------------------- EXTENSION: ldap PRIMARY MAINTAINER: Stig Venaas MAINTENANCE: Maintained @@ -352,33 +381,63 @@ PRIMARY MAINTAINER: Derick Rethans MAINTENANCE: Maintained STATUS: Working ------------------------------------------------------------------------------- +EXTENSION: mcve +PRIMARY MAINTAINER: Unknown +MAINTENANCE: Unknown +STATUS: Unknown +------------------------------------------------------------------------------- EXTENSION: mhash PRIMARY MAINTAINER: Sascha Schumann MAINTENANCE: Maintained STATUS: Working ------------------------------------------------------------------------------- +EXTENSION: mime_magic +PRIMARY MAINTAINER: Unknown +MAINTENANCE: Deprecated +STATUS: Experimental +COMMENT: Use PECL's fileinfo extension instead +------------------------------------------------------------------------------- +EXTENSION: ming +PRIMARY MAINTAINER: Frank M. Kromann +MAINTENANCE: Unknown +STATUS: Experimental +------------------------------------------------------------------------------- +EXTENSION: mnogosearch +PRIMARY MAINTAINER: Sergey Kartashoff +MAINTENANCE: Unknown +STATUS: Unknown +------------------------------------------------------------------------------- +EXTENSION: mono +PRIMARY MAINTAINER: Sterling Hughes +MAINTENANCE: Unknown +STATUS: Unknown +------------------------------------------------------------------------------- EXTENSION: msession -PRIMARY MAINTAINER Mark L. Woodward mlwmohawk@mohawksoft.com +PRIMARY MAINTAINER Mark L. Woodward MAINTENANCE: Maintained STATUS: Working/Experimental COMMENT: Tested on Linux, should work on other UNIX platforms. Backend server code can compile under Windows. ------------------------------------------------------------------------------- +EXTENSION: ncurses +PRIMARY MAINTAINER Ilia Alshanetsky , Wez Furlong , Hartmut Holzgraefe , Georg Richter +MAINTENANCE: Unknown +STATUS: Experimental +------------------------------------------------------------------------------- EXTENSION: openssl PRIMARY MAINTAINER: Wez Furlong MAINTENANCE: Maintained STATUS: Experimental SINCE: 4.0.4 ------------------------------------------------------------------------------- +EXTENSION: pcntl +MAINTENANCE: Unknown +STATUS: Experimental +------------------------------------------------------------------------------- EXTENSION: pcre PRIMARY MAINTAINER: Andrei Zmievski MAINTENANCE: Maintained STATUS: Working ------------------------------------------------------------------------------- -EXTENSION: pdf -PRIMARY MAINTAINER: Uwe Steinmann -MAINTENANCE: Maintained -STATUS: Working -------------------------------------------------------------------------------- EXTENSION: pfpro PRIMARY MAINTAINER: David Croft MAINTENANCE: Maintained @@ -439,6 +498,20 @@ EXTENSION: sysvshm MAINTENANCE: Unknown STATUS: Working ------------------------------------------------------------------------------- +EXTENSION: tidy +PRIMARY MAINTAINER: John Coggeshall , Ilia Alshanetsky +MAINTENANCE: Maintained +STATUS: Unknown +------------------------------------------------------------------------------- +EXTENSION: tokenizer +PRIMARY MAINTAINER: Andrei Zmievski +MAINTENANCE: Unknown +STATUS: Unknown +------------------------------------------------------------------------------- +EXTENSION: w32api +MAINTENANCE: Unknown +STATUS: Experimental +------------------------------------------------------------------------------- EXTENSION: yaz PRIMARY MAINTAINER: Adam Dickmeiss MAINTENANCE: Maintained diff --git a/INSTALL b/INSTALL index 5a9a4f07aa40..f305d0be8fac 100644 --- a/INSTALL +++ b/INSTALL @@ -1,422 +1,1535 @@ -Installation Instructions for PHP 5 ------------------------------------ -STOP! +Installing PHP + _________________________________________________________________ + + Table of Contents + Preface + 1. General Installation Considerations + 2. Installation on Unix systems + + Apache 1.3.x on Unix systems + Apache 2.0 on Unix systems + Caudium + fhttpd related notes + Sun, iPlanet and Netscape servers on Sun Solaris + CGI and commandline setups + HP-UX specific installation notes + OpenBSD installation notes + Solaris specific installation tips + Gentoo installation notes + + 3. Installation on Mac OS X + + Using Packages + Compiling for OS X Server + Compiling for MacOS X Client + + 4. Installation of PECL extensions + + Introduction to PECL Installations + Downloading PECL extensions + PECL for Windows users + Compiling shared PECL extensions with PEAR + Compiling shared PECL extensions with phpize + Compiling PECL extensions statically into PHP + + 5. Problems? + + Read the FAQ + Other problems + Bug reports + + 6. Runtime Configuration + + The configuration file + How to change configuration settings + _________________________________________________________________ + +Preface + + These installation instructions were generated from the HTML version + of the PHP Manual so formatting and linking have been altered. See the + online and updated version at: http://php.net/install.unix + _________________________________________________________________ + +Chapter 1. General Installation Considerations + + Before starting the installation, first you need to know what do you + want to use PHP for. There are three main fields you can use PHP, as + described in the What can PHP do? section: + + * Server-side scripting + * Command line scripting + * Client-side GUI applications + + For the first and most common form, you need three things: PHP itself, + a web server and a web browser. You probably already have a web + browser, and depending on your operating system setup, you may also + have a web server (e.g. Apache on Linux and MacOS X; IIS on Windows). + You may also rent webspace at a company. This way, you don't need to + set up anything on your own, only write your PHP scripts, upload it to + the server you rent, and see the results in your browser. + + While setting up the server and PHP on your own, you have two choices + for the method of connecting PHP to the server. For many servers PHP + has a direct module interface (also called SAPI). These servers + include Apache, Microsoft Internet Information Server, Netscape and + iPlanet servers. Many other servers have support for ISAPI, the + Microsoft module interface (OmniHTTPd for example). If PHP has no + module support for your web server, you can always use it as a CGI or + FastCGI processor. This means you set up your server to use the CGI + executable of PHP to process all PHP file requests on the server. + + If you are also interested to use PHP for command line scripting (e.g. + write scripts autogenerating some images for you offline, or + processing text files depending on some arguments you pass to them), + you always need the command line executable. For more information, + read the section about writing command line PHP applications. In this + case, you need no server and no browser. + + With PHP you can also write desktop GUI applications using the PHP-GTK + extension. This is a completely different approach than writing web + pages, as you do not output any HTML, but manage windows and objects + within them. For more information about PHP-GTK, please visit the site + dedicated to this extension. PHP-GTK is not included in the official + PHP distribution. + + From now on, this section deals with setting up PHP for web servers on + Unix and Windows with server module interfaces and CGI executables. + You will also find information on the command line executable in the + following sections. + + PHP source code and binary distributions for Windows can be found at + http://www.php.net/downloads.php. We recommend you to choose a mirror + nearest to you for downloading the distributions. + _________________________________________________________________ + +Chapter 2. Installation on Unix systems + + This section will guide you through the general configuration and + installation of PHP on Unix systems. Be sure to investigate any + sections specific to your platform or web server before you begin the + process. + + As our manual outlines in the General Installation Considerations + section, we are mainly dealing with web centric setups of PHP in this + section, although we will cover setting up PHP for command line usage + as well. + + There are several ways to install PHP for the Unix platform, either + with a compile and configure process, or through various pre-packaged + methods. This documentation is mainly focused around the process of + compiling and configuring PHP. Many Unix like systems have some sort + of package installation system. This can assist in setting up a + standard configuration, but if you need to have a different set of + features (such as a secure server, or a different database driver), + you may need to build PHP and/or your webserver. If you are unfamiliar + with building and compiling your own software, it is worth checking to + see whether somebody has already built a packaged version of PHP with + the features you need. + + Prerequisite knowledge and software for compiling: + + * Basic Unix skills (being able to operate "make" and a C compiler) + * An ANSI C compiler + * flex: Version 2.5.4 + * bison: Version 1.28 (preferred), 1.35, or 1.75 + * A web server + * Any module specific components (such as gd, pdf libs, etc.) + + The initial PHP setup and configuration process is controlled by the + use of the commandline options of the configure script. You could get + a list of all available options along with short explanations running + ./configure --help. Our manual documents the different options + separately. You will find the core options in the appendix, while the + different extension specific options are descibed on the reference + pages. + + When PHP is configured, you are ready to build the module and/or + executables. The command make should take care of this. If it fails + and you can't figure out why, see the Problems section. + _________________________________________________________________ + +Apache 1.3.x on Unix systems + + This section contains notes and hints specific to Apache installs of + PHP on Unix platforms. We also have instructions and notes for Apache + 2 on a separate page. + + You can select arguments to add to the configure on line 10 below from + the list of core configure options and from extension specific options + described at the respective places in the manual. The version numbers + have been omitted here, to ensure the instructions are not incorrect. + You will need to replace the 'xxx' here with the correct values from + your files. + + Example 2-1. Installation Instructions (Apache Shared Module Version) + for PHP +1. gunzip apache_xxx.tar.gz +2. tar -xvf apache_xxx.tar +3. gunzip php-xxx.tar.gz +4. tar -xvf php-xxx.tar +5. cd apache_xxx +6. ./configure --prefix=/www --enable-module=so +7. make +8. make install +9. cd ../php-xxx + +10. Now, configure your PHP. This is where you customize your PHP + with various options, like which extensions will be enabled. Do a + ./configure --help for a list of available options. In our example + we'll do a simple configure with Apache 1 and MySQL support. Your + path to apxs may differ from our example. + + ./configure --with-mysql --with-apxs=/www/bin/apxs + +11. make +12. make install + + If you decide to change your configure options after installation, + you only need to repeat the last three steps. You only need to + restart apache for the new module to take effect. A recompile of + Apache is not needed. + + Note that unless told otherwise, 'make install' will also install PEAR, + various PHP tools such as phpize, install the PHP CLI, and more. + +13. Setup your php.ini file: + + cp php.ini-dist /usr/local/lib/php.ini + + You may edit your .ini file to set PHP options. If you prefer your + php.ini in another location, use --with-config-file-path=/some/path in + step 10. + + If you instead choose php.ini-recommended, be certain to read the list + of changes within, as they affect how PHP behaves. + +14. Edit your httpd.conf to load the PHP module. The path on the right hand + side of the LoadModule statement must point to the path of the PHP + module on your system. The make install from above may have already + added this for you, but be sure to check. + + For PHP 4: + + LoadModule php4_module libexec/libphp4.so + + For PHP 5: -Before going any further, please remember you are going to find more -up to date instructions in the online manual, located here: - -http://www.php.net/manual/en/install.apache.php - -For Apache 2, instructions and up-to-date information regarding its -support status, is available here: - -http://www.php.net/manual/en/install.apache2.php - -It is strongly recommended that you read the manual page before going -further. However, for the impatient, here is a quick set of steps that -will build PHP as (first) a dynamic Apache module (DSO) for Apache 1.3.x -with MySQL support and then a static module. A more verbose explanation follows. - -For installing PHP on other web servers, refer to one of the following -files: - - sapi/aolserver/README - sapi/pi3web/README - sapi/servlet/README - sapi/thttpd/README - README.Zeus - -Some notes: - -1: Only install either the static module or the dynamic one. Do not - install both. - -2: If you are recompiling PHP to add new extensions or upgrading - something like GD, remove the config.cache file before you re-run - configure. - -3: If you are on Linux and have installed shared libraries, make - sure the location of these shared libraries are listed in your - /etc/ld.so.conf file. For example, if you have: - - /usr/local/lib/mysql/libmysqlclient.so - - Make sure /etc/ld.so.conf contains: - - /usr/local/lib/mysql - - Then run ldconfig. - -If you want both PHP 3 and 4 modules in the same Apache server, check the -bottom of this file for instructions. - -INSTALLATION WITH THE ZEUS WEB SERVER: ---Please see the 'README.Zeus' file included in this distribution - - -QUICK INSTALL (DSO) - -For this to work your Apache httpd must have mod_so enabled. -Check using httpd -l. You should see something like: - -Compiled-in modules: - http_core.c - mod_so.c - -Chances are you will see a lot more modules than these two. That's ok, -as long as mod_so.c shows up you can proceed with the following steps: - -$ gunzip -c php-4.x.y.tar.gz | tar xf - -$ cd php-4.x.y -$ ./configure --with-mysql --with-apxs -$ make -$ make install - -If you get an error telling you that the apxs script could not be found, -look for it on your system and if you find it, provide the full path to it -as: --with-apxs=/path/to/apxs - -Make sure you specify the version of apxs that is actually installed on -your system and NOT the one that is in the apache source tarball. - -Next you must copy php.ini-dist to the appropriate place (normally -/usr/local/lib/php.ini) and edit it as necessary to set PHP options. - -The only thing left to do is to edit your httpd.conf file and make sure the -PHP 4 mime type is there and uncommented. You need a line that looks like -this: - - AddType application/x-httpd-php .php - -Then restart your server (apachectl restart) and you should be able to -serve up PHP files now. Make a test file called test.php and put some -PHP tags in it. Like , for example. - - -QUICK INSTALL (Static) - -$ gunzip -c apache_1.3.x.tar.gz | tar xf - -$ cd apache_1.3.x -$ ./configure -$ cd .. - -$ gunzip -c php-4.x.y.tar.gz | tar xf - -$ cd php-4.x.y -$ ./configure --with-mysql --with-apache=../apache_1.3.x -$ make -$ make install + LoadModule php5_module libexec/libphp5.so -$ cd ../apache_1.3.x -$ ./configure --prefix=/www --activate-module=src/modules/php5/libphp5.a - (The above line is correct! Yes, we know libphp5.a does not exist at this - stage. It isn't supposed to. It will be created.) -$ make - (you should now have an httpd binary which you can copy to your Apache bin dir if - is is your first install then you need to "make install" as well) -$ cd ../php-4.x.y -$ cp php.ini-dist /usr/local/lib/php.ini -You can edit /usr/local/lib/php.ini file to set PHP options. -Edit your httpd.conf or srm.conf file and add: - AddType application/x-httpd-php .php +15. And in the AddModule section of httpd.conf, somewhere under the + ClearModuleList, add this: + For PHP 4: -VERBOSE INSTALL + AddModule mod_php4.c -Chances are you are reading this because the quick install steps above -did not work for you. If this is the case, congratulations, you are -among the elite few that actually reads documentation. It really is -not a difficult install and once you have done it once you will fly -through it. + For PHP 5: -Installing PHP can be done in four simple steps: + AddModule mod_php5.c -1. Unpack your distribution file. +16. Tell Apache to parse certain extensions as PHP. For example, + let's have Apache parse the .php extension as PHP. You could + have any extension(s) parse as PHP by simply adding more, with + each separated by a space. We'll add .phtml to demonstrate. - You will have downloaded a file named something like php-4.x.y.tar.gz. - Unzip this file with a command like: gunzip php-4.x.y.tar.gz + AddType application/x-httpd-php .php .phtml - Next you have to untar it with: tar -xvf php-4.x.y.tar + It's also common to setup the .phps extension to show highlighted PHP + source, this can be done with: - This will create a php-4.x.y directory. cd into this new directory. + AddType application/x-httpd-php-source .phps -2a. Configure PHP (Dynamic Module) - Skip to 2b if you wish to build - a static module +17. Use your normal procedure for starting the Apache server. (You must + stop and restart the server, not just cause the server to reload by + using a HUP or USR1 signal.) - You now have to choose the options you would like. There are quite - a few of them. To see a list, type: ./configure --help + Alternatively, to install PHP as a static object: - The only options that you are likely to want to use are the ones in - the last section entitled, "--enable and --with options recognized:" + Example 2-2. Installation Instructions (Static Module Installation for + Apache) for PHP +1. gunzip -c apache_1.3.x.tar.gz | tar xf - +2. cd apache_1.3.x +3. ./configure +4. cd .. - A popular choice is to build the Apache module version. In order to - build PHP as a dynamic module for Apache-1.3.x you have to first have - Apache installed. Assuming Apache is already installed, make sure - the shared object module is enabled. To check this, type: httpd -l - You should see something like: +5. gunzip -c php-4.x.y.tar.gz | tar xf - +6. cd php-4.x.y +7. ./configure --with-mysql --with-apache=../apache_1.3.x +8. make +9. make install + +10. cd ../apache_1.3.x - Compiled-in modules: - http_core.c - mod_so.c +11. ./configure --prefix=/www --activate-module=src/modules/php4/libphp4.a + (The above line is correct! Yes, we know libphp4.a does not exist at this + stage. It isn't supposed to. It will be created.) - You will most likely have a lot more modules than what is shown here. - As long as mod_so.c shows up in the list, PHP should be happy. +12. make + (you should now have an httpd binary which you can copy to your Apache bin +dir if + is is your first install then you need to "make install" as well) - Now, type: ./configure --with-mysql --with-apxs +13. cd ../php-4.x.y +14. cp php.ini-dist /usr/local/lib/php.ini - If you get an error telling you that the apxs script could not be found, - look for it on your system and if you find it, provide the full path to it - as: --with-apxs=/path/to/apxs +15. You can edit /usr/local/lib/php.ini file to set PHP options. + Edit your httpd.conf or srm.conf file and add: + AddType application/x-httpd-php .php - Make sure you specify the version of apxs that is actually installed on - your system and NOT the one that is in the apache source tarball. - - You might also want other flags on this configure line. --with-mysql - is just an example. + Depending on your Apache install and Unix variant, there are many + possible ways to stop and restart the server. Below are some typical + lines used in restarting the server, for different apache/unix + installations. You should replace /path/to/ with the path to these + applications on your systems. - There are a few things that can go wrong during this configure step. - The most common is that you have asked for an option and that the - configure script can not find the files required to enable this - option in PHP. Chances are you can provide the full path to the - base directory under which the related files were installed. For - example, if you have installed the GD library in /opt/gd which means - that /opt/gd/include has your GD header files and /opt/gd/lib contains - your GD library files, you would use --with-gd=/opt/gd + Example 2-3. Example commands for restarting Apache +1. Several Linux and SysV variants: +/etc/rc.d/init.d/httpd restart - Skip to step 3 for compilation and installation instructions. +2. Using apachectl scripts: +/path/to/apachectl stop +/path/to/apachectl start -2b. Configure PHP (Static Module) - Skip if you performed 2a +3. httpdctl and httpsdctl (Using OpenSSL), similar to apachectl: +/path/to/httpsdctl stop +/path/to/httpsdctl start - You now have to choose the options you would like. There are quite - a few of them. To see a list, type: ./configure --help +4. Using mod_ssl, or another SSL server, you may want to manually +stop and start: +/path/to/apachectl stop +/path/to/apachectl startssl - The only options that you are likely to want to use are the ones in - the last section entitled, "--enable and --with options recognized:" + The locations of the apachectl and http(s)dctl binaries often vary. If + your system has locate or whereis or which commands, these can assist + you in finding your server control programs. - A popular choice is to build the Apache module version. You need - to know where the source code directory for your Apache server is - located. Then use an option like: --with-apache=/usr/local/src/apache - if that is your Apache source code directory. If you only specify - --with-apache, then it will default to look for your Apache source - in /usr/local/etc/httpd. + Different examples of compiling PHP for apache are as follows: - NOTE: The directory you specify should be the top-level of the - unpacked Apache (or Stronghold) distribution. The configure program - will automatically look for httpd.h in different directories under that - location depending on which version of Apache, including Stronghold, - you are running. + ./configure --with-apxs --with-pgsql + + This will create a libphp4.so shared library that is loaded into + Apache using a LoadModule line in Apache's httpd.conf file. The + PostgreSQL support is embedded into this libphp4.so library. + + ./configure --with-apxs --with-pgsql=shared + + This will create a libphp4.so shared library for Apache, but it will + also create a pgsql.so shared library that is loaded into PHP either + by using the extension directive in php.ini file or by loading it + explicitly in a script using the dl() function. + + ./configure --with-apache=/path/to/apache_source --with-pgsql + + This will create a libmodphp4.a library, a mod_php4.c and some + accompanying files and copy this into the src/modules/php4 directory + in the Apache source tree. Then you compile Apache using + --activate-module=src/modules/php4/libphp4.a and the Apache build + system will create libphp4.a and link it statically into the httpd + binary. The PostgreSQL support is included directly into this httpd + binary, so the final result here is a single httpd binary that + includes all of Apache and all of PHP. + + ./configure --with-apache=/path/to/apache_source --with-pgsql=shared + + Same as before, except instead of including PostgreSQL support + directly into the final httpd you will get a pgsql.so shared library + that you can load into PHP from either the php.ini file or directly + using dl(). + + When choosing to build PHP in different ways, you should consider the + advantages and drawbacks of each method. Building as a shared object + will mean that you can compile apache separately, and don't have to + recompile everything as you add to, or change, PHP. Building PHP into + apache (static method) means that PHP will load and run faster. For + more information, see the Apache webpage on DSO support. + + Note: Apache's default httpd.conf currently ships with a section + that looks like this: + +User nobody +Group "#-1" + + Unless you change that to "Group nogroup" or something like that + ("Group daemon" is also very common) PHP will not be able to open + files. + + Note: Make sure you specify the installed version of apxs when + using --with-apxs=/path/to/apxs. You must NOT use the apxs version + that is in the apache sources but the one that is actually + installed on your system. + _________________________________________________________________ - For MySQL support, since newer versions of MySQL installs its various - components under /usr/local, this is the default. If you have - changed the location you can specify it with: --with-mysql=/opt/local - for example. Otherwise just use: --with-mysql +Apache 2.0 on Unix systems - *NOTE* If you are using Apache 1.3b6 or later, you should run the - Apache Configure script at least once before compiling PHP. It - doesn't matter how you have Apache configured at this point. + This section contains notes and hints specific to Apache 2.0 installs + of PHP on Unix systems. - Skip to step 3b at this point. + Warning -3. Compile and install the files. Simply type: make install + We do not recommend using a threaded MPM in production with Apache2. + Use the prefork MPM instead, or use Apache1. For information on why, + read the related FAQ entry on using Apache2 with a threaded MPM -3a. Dynamic Module Installation + You are highly encouraged to take a look at the Apache Documentation + to get a basic understanding of the Apache 2.0 Server. - Nothing else is needed here. Proceed to step 4a. + PHP and Apache 2.0.x compatibility notes: The following versions of + PHP are known to work with the most recent version of Apache 2.0.x: -3b. Static Module Installation + * PHP 4.3.0 or later available at http://www.php.net/downloads.php. + * the latest stable development version. Get the source code + http://snaps.php.net/php4-latest.tar.gz or download binaries for + Windows http://snaps.php.net/win32/php4-win32-latest.zip. + * a prerelease version downloadable from http://qa.php.net/. + * you have always the option to obtain PHP through anonymous CVS. - For the Apache module version this will copy the appropriate files - to the src/modules/php5 directory in your Apache distribution if - you are using Apache 1.3.x. If you are still running Apache 1.2.x - these files will be copied directly to the main src directory. + These versions of PHP are compatible to Apache 2.0.40 and later. - For Apache 1.3b6 and later, you can use the new APACI configuration - mechanism. To automatically build Apache with PHP support, use: + Apache 2.0 SAPI-support started with PHP 4.2.0. PHP 4.2.3 works + with Apache 2.0.39, don't use any other version of Apache with PHP + 4.2.3. However, the recommended setup is to use PHP 4.3.0 or later + with the most recent version of Apache2. - cd apache_1.3.x - ./configure --prefix=//apache \ - --activate-module=src/modules/php5/libphp5.a - make - make install + All mentioned versions of PHP will work still with Apache 1.3.x. - If you do not wish to use this new configuration tool, the old - install procedure (src/Configure) will work fine. + Download the most recent version of Apache 2.0 and a fitting PHP + version from the above mentioned places. This quick guide covers only + the basics to get started with Apache 2.0 and PHP. For more + information read the Apache Documentation. The version numbers have + been omitted here, to ensure the instructions are not incorrect. You + will need to replace the 'NN' here with the correct values from your + files. - If you are using the old Apache ./Configure script, you will have to - edit the Apache src/Configuration file manually. If you do not have - this file, copy Configuration.tmpl to Configuration. + Example 2-4. Installation Instructions (Apache 2 Shared Module + Version) +1. gzip -d httpd-2_0_NN.tar.gz +2. tar xvf httpd-2_0_NN.tar +3. gunzip php-NN.tar.gz +4. tar -xvf php-NN.tar +5. cd httpd-2_0_NN +6. ./configure --enable-so +7. make +8. make install - For Apache 1.3.x add: + Now you have Apache 2.0.NN available under /usr/local/apache2, + configured with loadable module support and the standard MPM prefork. + To test the installation use your normal procedure for starting + the Apache server, e.g.: + /usr/local/apache2/bin/apachectl start + and stop the server to go on with the configuration for PHP: + /usr/local/apache2/bin/apachectl stop. - AddModule modules/php5/libphp5.a +9. cd ../php-NN - For Apache 1.3.x don't do anything else. Just add this line and then - run "./Configure" followed by "make". +10. Now, configure your PHP. This is where you customize your PHP + with various options, like which extensions will be enabled. Do a + ./configure --help for a list of available options. In our example + we'll do a simple configure with Apache 2 and MySQL support. Your + path to apxs may differ, in fact, the binary may even be named apxs2 on + your system. - For Apache 1.2.x add: + ./configure --with-apxs2=/usr/local/apache2/bin/apxs --with-mysql - Module php5_module mod_php5.o +11. make +12. make install - For Apache 1.2.x you will also have to look in the libphp5.module file, - which was copied to the src directory. The EXTRA_LIBS line in the Apache - Configuration file needs to be set to use the same libs as specified on - the LIBS line in libphp5.module. You also need to make sure to add - "-L." to the beginning of the EXTRA_LIBS line. + If you decide to change your configure options after installation, + you only need to repeat the last three steps. You only need to + restart apache for the new module to take effect. A recompile of + Apache is not needed. - So, as an example, your EXTRA_LIBS line might look like: + Note that unless told otherwise, 'make install' will also install PEAR, + various PHP tools such as phpize, install the PHP CLI, and more. - EXTRA_LIBS=-L. -lphp5 -lgdbm -ldb -L/usr/local/mysql/lib -lmysqlclient +13. Setup your php.ini - NOTE: You should not enclose the EXTRA_LIBS line in double-quotes, as it - is in the libphp5.module file. + cp php.ini-dist /usr/local/lib/php.ini - Also, look at the RULE_WANTHSREGEX setting in the libphp5.module file - and set the WANTHSREGEX directive accordingly in your Configuration file. - This last step applies to versions of Apache prior to 1.3b3. + You may edit your .ini file to set PHP options. If you prefer having + php.ini in another location, use --with-config-file-path=/some/path in + step 10. - This is a bit of a hassle, but should serve as incentive to move to - Apache 1.3.x where this step has been eliminated. + If you instead choose php.ini-recommended, be certain to read the list + of changes within, as they affect how PHP behaves. - Once you are satisfied with your Configuration settings, type: ./Configure - If you get errors, chances are that you forgot a library or made a typo - somewhere. Re-edit Configuration and try again. If it goes well, - type: make +14. Edit your httpd.conf to load the PHP module. The path on the right hand + side of the LoadModule statement must point to the path of the PHP + module on your system. The make install from above may have already + added this for you, but be sure to check. - Assuming it compiles without errors, proceed to step 4b. + For PHP 4: -4a. Setting up the server. (Dynamic Module) + LoadModule php4_module libexec/libphp4.so - The make install command in step 3 should have done most of your - work for you. It actually edits your httpd.conf file and tries to - enable the dynamic PHP module. To verify this, look for a line that - looks like this: + For PHP 5: LoadModule php5_module libexec/libphp5.so - The actual path before the libphp5.so part might differ slightly. This - is likely fine. If you are paranoid you can examine the output from the - make install step to see where the libphp5.so file was actually put and - place the full path to this file on this LoadModule line. - - If somewhere in your httpd.conf file you have a ClearModuleList line - then you also need this line: - - AddModule mod_php5.c - - And finally you need to tell Apache which file extension should trigger - PHP. You do this by creating a special mime type and associating it - with an extension. We suggest using: - - AddType application/x-httpd-php .php - - You are however free to use any extension you wish, including .html. - - Note! If a line has a # at the beginning, then it is commented out - and you need to remove the # for that line to take effect. - - Finally you need to copy php.ini-dist to the appropriate place - (normally /usr/local/lib/php.ini) and edit if necessary. +15. Tell Apache to parse certain extensions as PHP. For example, + let's have Apache parse the .php extension as PHP. You could + have any extension(s) parse as PHP by simply adding more, with + each separated by a space. We'll add .phtml to demonstrate. - Once you have made these changes you should be ready to restart your - server and try it out. Type: apachectl restart - -4b. Setting up the server. (Static Module) - - You should now have a new httpd binary. Shut down your existing server, - if you have one, and copy this new binary overtop of it. Perhaps make - a backup of your previous one first. Then edit your conf/httpd.conf file - and add the line: + AddType application/x-httpd-php .php .phtml - AddType application/x-httpd-php .php - - There is also an interesting feature which can be quite instructive and - helpful while debugging. That is the option of having colour syntax - highlighting. To enable this, add the following line: + It's also common to setup the .phps extension to show highlighted PHP + source, this can be done with: AddType application/x-httpd-php-source .phps - Any file ending in .phps will now be displayed with full colour syntax - highlighting instead of being executed. - - Note that on some older server setups, the AddType lines are in the - conf/srm.conf file instead of conf/httpd.conf. - - Note! If a line has a # at the beginning, then it is commented out - and you need to remove the # for that line to take effect. +16. Use your normal procedure for starting the Apache server, e.g.: + + /usr/local/apache2/bin/apachectl start + + Following the steps above you will have a running Apache 2.0 with + support for PHP as SAPI module. Of course there are many more + configuration options available for both, Apache and PHP. For more + information use ./configure --help in the corresponding source tree. + In case you wish to build a multithreaded version of Apache 2.0 you + must overwrite the standard MPM-Module prefork either with worker or + perchild. To do so append to your configure line in step 6 above + either the option --with-mpm=worker or --with-mpm=perchild. Take care + about the consequences and understand what you are doing. For more + information read the Apache documentation about the MPM-Modules. + + Note: If you want to use content negotiation, read the Apache + MultiViews FAQ. + + Note: To build a multithreaded version of Apache your system must + support threads. This also implies to build PHP with experimental + Zend Thread Safety (ZTS). Therefore not all extensions might be + available. The recommended setup is to build Apache with the + standard prefork MPM-Module. + _________________________________________________________________ + +Caudium + + PHP 4 can be built as a Pike module for the Caudium webserver. Note + that this is not supported with PHP 3. Follow the simple instructions + below to install PHP 4 for Caudium. + + Example 2-5. Caudium Installation Instructions +1. Make sure you have Caudium installed prior to attempting to + install PHP 4. For PHP 4 to work correctly, you will need Pike + 7.0.268 or newer. For the sake of this example we assume that + Caudium is installed in /opt/caudium/server/. +2. Change directory to php-x.y.z (where x.y.z is the version number). +3. ./configure --with-caudium=/opt/caudium/server +4. make +5. make install +6. Restart Caudium if it's currently running. +7. Log into the graphical configuration interface and go to the + virtual server where you want to add PHP 4 support. +8. Click Add Module and locate and then add the PHP 4 Script Support module. +9. If the documentation says that the 'PHP 4 interpreter isn't + available', make sure that you restarted the server. If you did + check /opt/caudium/logs/debug/default.1 for any errors related to + PHP4.so. Also make sure that + caudium/server/lib/[pike-version]/PHP4.so + is present. +10. Configure the PHP Script Support module if needed. + + You can of course compile your Caudium module with support for the + various extensions available in PHP 4. See the reference pages for + extension specific configure options. + + Note: When compiling PHP 4 with MySQL support you must make sure + that the normal MySQL client code is used. Otherwise there might be + conflicts if your Pike already has MySQL support. You do this by + specifying a MySQL install directory the --with-mysql option. + _________________________________________________________________ + +fhttpd related notes + + To build PHP as an fhttpd module, answer "yes" to "Build as an fhttpd + module?" (the --with-fhttpd=DIR option to configure) and specify the + fhttpd source base directory. The default directory is + /usr/local/src/fhttpd. If you are running fhttpd, building PHP as a + module will give better performance, more control and remote execution + capability. + + Note: Support for fhttpd is no longer available as of PHP 4.3.0. + _________________________________________________________________ + +Sun, iPlanet and Netscape servers on Sun Solaris + + This section contains notes and hints specific to Sun Java System Web + Server, Sun ONE Web Server, iPlanet and Netscape server installs of + PHP on Sun Solaris. + + From PHP 4.3.3 on you can use PHP scripts with the NSAPI module to + generate custom directory listings and error pages. Additional + functions for Apache compatibility are also available. For support in + current webservers read the note about subrequests. + + You can find more information about setting up PHP for the Netscape + Enterprise Server (NES) here: + http://benoit.noss.free.fr/php/install-php4.html + + To build PHP with Sun JSWS/Sun ONE WS/iPlanet/Netscape webservers, + enter the proper install directory for the --with-nsapi=[DIR] option. + The default directory is usually /opt/netscape/suitespot/. Please also + read /php-xxx-version/sapi/nsapi/nsapi-readme.txt. + + 1. Install the following packages from http://www.sunfreeware.com/ or + another download site: + + autoconf-2.13 + automake-1.4 + bison-1_25-sol26-sparc-local + flex-2_5_4a-sol26-sparc-local + gcc-2_95_2-sol26-sparc-local + gzip-1.2.4-sol26-sparc-local + m4-1_4-sol26-sparc-local + make-3_76_1-sol26-sparc-local + mysql-3.23.24-beta (if you want mysql support) + perl-5_005_03-sol26-sparc-local + tar-1.13 (GNU tar) + 2. Make sure your path includes the proper directories + PATH=.:/usr/local/bin:/usr/sbin:/usr/bin:/usr/ccs/bin and make it + available to your system export PATH. + 3. gunzip php-x.x.x.tar.gz (if you have a .gz dist, otherwise go to + 4). + 4. tar xvf php-x.x.x.tar + 5. Change to your extracted PHP directory: cd ../php-x.x.x + 6. For the following step, make sure /opt/netscape/suitespot/ is + where your netscape server is installed. Otherwise, change to the + correct path and run: + +./configure --with-mysql=/usr/local/mysql \ +--with-nsapi=/opt/netscape/suitespot/ \ +--enable-libgcc + + 7. Run make followed by make install. + + After performing the base install and reading the appropriate readme + file, you may need to perform some additional configuration steps. + + Configuration Instructions for Sun/iPlanet/Netscape. Firstly you may + need to add some paths to the LD_LIBRARY_PATH environment for the + server to find all the shared libs. This can best done in the start + script for your webserver. The start script is often located in: + /path/to/server/https-servername/start. You may also need to edit the + configuration files that are located in: + /path/to/server/https-servername/config/. + + 1. Add the following line to mime.types (you can do that by the + administration server): + +type=magnus-internal/x-httpd-php exts=php + + 2. Edit magnus.conf (for servers >= 6) or obj.conf (for servers < 6) + and add the following, shlib will vary depending on your system, + it will be something like /opt/netscape/suitespot/bin/libphp4.so. + You should place the following lines after mime types init. + +Init fn="load-modules" funcs="php4_init,php4_execute,php4_auth_trans" shlib="/o +pt/netscape/suitespot/bin/libphp4.so" +Init fn="php4_init" LateInit="yes" errorString="Failed to initialize PHP!" [php +_ini="/path/to/php.ini"] + + (PHP >= 4.3.3) The php_ini parameter is optional but with it you + can place your php.ini in your webserver config directory. + 3. Configure the default object in obj.conf (for virtual server + classes [version 6.0+] in their vserver.obj.conf): + + +. +. +. +.#NOTE this next line should happen after all 'ObjectType' and before all 'AddL +og' lines +Service fn="php4_execute" type="magnus-internal/x-httpd-php" [inikey=value inik +ey=value ...] +. +. + + + (PHP >= 4.3.3) As additional parameters you can add some special + php.ini-values, for example you can set a + docroot="/path/to/docroot" specific to the context php4_execute is + called. For boolean ini-keys please use 0/1 as value, not + "On","Off",... (this will not work correctly), e.g. + zlib.output_compression=1 instead of zlib.output_compression="On" + 4. This is only needed if you want to configure a directory that only + consists of PHP scripts (same like a cgi-bin directory): + + +ObjectType fn="force-type" type="magnus-internal/x-httpd-php" +Service fn=php4_execute [inikey=value inikey=value ...] + + + After that you can configure a directory in the Administration + server and assign it the style x-httpd-php. All files in it will + get executed as PHP. This is nice to hide PHP usage by renaming + files to .html. + 5. Setup of authentication: PHP authentication cannot be used with + any other authentication. ALL AUTHENTICATION IS PASSED TO YOUR PHP + SCRIPT. To configure PHP Authentication for the entire server, add + the following line to your default object: + + +AuthTrans fn=php4_auth_trans +. +. +. + + + 6. To use PHP Authentication on a single directory, add the + following: + + +AuthTrans fn=php4_auth_trans + + + Note: The stacksize that PHP uses depends on the configuration of + the webserver. If you get crashes with very large PHP scripts, it + is recommended to raise it with the Admin Server (in the section + "MAGNUS EDITOR"). + _________________________________________________________________ + +CGI environment and recommended modifications in php.ini + + Important when writing PHP scripts is the fact that Sun JSWS/Sun ONE + WS/iPlanet/Netscape is a multithreaded web server. Because of that all + requests are running in the same process space (the space of the + webserver itself) and this space has only one environment. If you want + to get CGI variables like PATH_INFO, HTTP_HOST etc. it is not the + correct way to try this in the old PHP 3.x way with getenv() or a + similar way (register globals to environment, $_ENV). You would only + get the environment of the running webserver without any valid CGI + variables! + + Note: Why are there (invalid) CGI variables in the environment? + + Answer: This is because you started the webserver process from the + admin server which runs the startup script of the webserver, you + wanted to start, as a CGI script (a CGI script inside of the admin + server!). This is why the environment of the started webserver has + some CGI environment variables in it. You can test this by starting + the webserver not from the administration server. Use the command + line as root user and start it manually - you will see there are no + CGI-like environment variables. + + Simply change your scripts to get CGI variables in the correct way for + PHP 4.x by using the superglobal $_SERVER. If you have older scripts + which use $HTTP_HOST, etc., you should turn on register_globals in + php.ini and change the variable order too (important: remove "E" from + it, because you do not need the environment here): +variables_order = "GPCS" +register_globals = On + _________________________________________________________________ + +Special use for error pages or self-made directory listings (PHP >= 4.3.3) + + You can use PHP to generate the error pages for "404 Not Found" or + similar. Add the following line to the object in obj.conf for every + error page you want to overwrite: +Error fn="php4_execute" code=XXX script="/path/to/script.php" [inikey=value ini +key=value...] + + where XXX is the HTTP error code. Please delete any other Error + directives which could interfere with yours. If you want to place a + page for all errors that could exist, leave the code parameter out. + Your script can get the HTTP status code with $_SERVER['ERROR_TYPE']. + + Another possibility is to generate self-made directory listings. Just + create a PHP script which displays a directory listing and replace the + corresponding default Service line for + type="magnus-internal/directory" in obj.conf with the following: +Service fn="php4_execute" type="magnus-internal/directory" script="/path/to/scr +ipt.php" [inikey=value inikey=value...] + + For both error and directory listing pages the original URI and + translated URI are in the variables $_SERVER['PATH_INFO'] and + $_SERVER['PATH_TRANSLATED']. + _________________________________________________________________ + +Note about nsapi_virtual() and subrequests (PHP >= 4.3.3) + + The NSAPI module now supports the nsapi_virtual() function (alias: + virtual()) to make subrequests on the webserver and insert the result + in the webpage. This function uses some undocumented features from the + NSAPI library. On Unix the module automatically looks for the needed + functions and uses them if available. If not, nsapi_virtual() is + disabled. + + Note: But be warned: Support for nsapi_virtual() is EXPERIMENTAL!!! + _________________________________________________________________ + +CGI and commandline setups + + The default is to build PHP as a CGI program. This creates a + commandline interpreter, which can be used for CGI processing, or for + non-web-related PHP scripting. If you are running a web server PHP has + module support for, you should generally go for that solution for + performance reasons. However, the CGI version enables users to run + different PHP-enabled pages under different user-ids. + + Warning + + By using the CGI setup, your server is open to several possible + attacks. Please read our CGI security section to learn how to defend + yourself from those attacks. + + As of PHP 4.3.0, some important additions have happened to PHP. A new + SAPI named CLI also exists and it has the same name as the CGI binary. + What is installed at {PREFIX}/bin/php depends on your configure line + and this is described in detail in the manual section named Using PHP + from the command line. For further details please read that section of + the manual. + _________________________________________________________________ + +Testing + + If you have built PHP as a CGI program, you may test your build by + typing make test. It is always a good idea to test your build. This + way you may catch a problem with PHP on your platform early instead of + having to struggle with it later. + _________________________________________________________________ + +Benchmarking + + If you have built PHP 3 as a CGI program, you may benchmark your build + by typing make bench. Note that if safe mode is on by default, the + benchmark may not be able to finish if it takes longer then the 30 + seconds allowed. This is because the set_time_limit() can not be used + in safe mode. Use the max_execution_time configuration setting to + control this time for your own scripts. make bench ignores the + configuration file. + + Note: make bench is only available for PHP 3. + _________________________________________________________________ + +Using Variables + + Some server supplied environment variables are not defined in the + current CGI/1.1 specification. Only the following variables are + defined there: AUTH_TYPE, CONTENT_LENGTH, CONTENT_TYPE, + GATEWAY_INTERFACE, PATH_INFO, PATH_TRANSLATED, QUERY_STRING, + REMOTE_ADDR, REMOTE_HOST, REMOTE_IDENT, REMOTE_USER, REQUEST_METHOD, + SCRIPT_NAME, SERVER_NAME, SERVER_PORT, SERVER_PROTOCOL, and + SERVER_SOFTWARE. Everything else should be treated as 'vendor + extensions'. + _________________________________________________________________ + +HP-UX specific installation notes + + This section contains notes and hints specific to installing PHP on + HP-UX systems. (Contributed by paul_mckay at clearwater-it dot co dot + uk). + + Note: These tips were written for PHP 4.0.4 and Apache 1.3.9. + + 1. You need gzip, download a binary distribution from + http://hpux.connect.org.uk/ftp/hpux/Gnu/gzip-1.2.4a/gzip-1.2.4a-sd + -10.20.depot.Z uncompress the file and install using swinstall. + 2. You need gcc, download a binary distribution from + http://gatekeep.cs.utah.edu/ftp/hpux/Gnu/gcc-2.95.2/gcc-2.95.2-sd- + 10.20.depot.gz. uncompress this file and install gcc using + swinstall. + 3. You need the GNU binutils, you can download a binary distribution + from + http://hpux.connect.org.uk/ftp/hpux/Gnu/binutils-2.9.1/binutils-2. + 9.1-sd-10.20.depot.gz. uncompress this file and install binutils + using swinstall. + 4. You now need bison, you can download a binary distribution from + http://hpux.connect.org.uk/ftp/hpux/Gnu/bison-1.28/bison-1.28-sd-1 + 0.20.depot.gz, install as above. + 5. You now need flex, you need to download the source from one of the + http://www.gnu.org mirrors. It is in the non-gnu directory of the + ftp site. Download the file, gunzip, then tar -xvf it. Go into the + newly created flex directory and run ./configure, followed by + make, and then make install. + If you have errors here, it's probably because gcc etc. are not in + your PATH so add them to your PATH. + 6. Download the PHP and apache sources. + 7. gunzip and tar -xvf them. We need to hack a couple of files so + that they can compile OK. + 8. Firstly the configure file needs to be hacked because it seems to + lose track of the fact that you are a hpux machine, there will be + a better way of doing this but a cheap and cheerful hack is to put + lt_target=hpux10.20 on line 47286 of the configure script. + 9. Next, the Apache GuessOS file needs to be hacked. Under + apache_1.3.9/src/helpers change line 89 from echo + "hp${HPUXMACH}-hpux${HPUXVER}"; exit 0 to: echo + "hp${HPUXMACH}-hp-hpux${HPUXVER}"; exit 0 + 10. You cannot install PHP as a shared object under HP-UX so you must + compile it as a static, just follow the instructions at the Apache + page. + 11. PHP and Apache should have compiled OK, but Apache won't start. + you need to create a new user for Apache, e.g. www, or apache. You + then change lines 252 and 253 of the conf/httpd.conf in Apache so + that instead of + +User nobody +Group nogroup + + you have something like + +User www +Group sys + + This is because you can't run Apache as nobody under hp-ux. Apache + and PHP should then work. + _________________________________________________________________ + +OpenBSD installation notes + + This section contains notes and hints specific to installing PHP on + OpenBSD 3.6. + _________________________________________________________________ + +Using Binary Packages + + Using binary packages to install PHP on OpenBSD is the recommended and + simplest method. The core package has been separated from the various + modules, and each can be installed and removed independently from the + others. The files you need can be found on your OpenBSD CD or on the + FTP site. + + The main package you need to install is php4-core-4.3.8.tgz, which + contains the basic engine (plus gettext and iconv). Next, take a look + at the module packages, such as php4-mysql-4.3.8.tgz or + php4-imap-4.3.8.tgz. You need to use the phpxs command to activate and + deactivate these modules in your php.ini. + + Example 2-6. OpenBSD Package Install Example +# pkg_add php4-core-4.3.8.tgz +# /usr/local/sbin/phpxs -s +# cp /usr/local/share/doc/php4/php.ini-recommended /var/www/conf/php.ini + (add in mysql) +# pkg_add php4-mysql-4.3.8.tgz +# /usr/local/sbin/phpxs -a mysql + (add in imap) +# pkg_add php4-imap-4.3.8.tgz +# /usr/local/sbin/phpxs -a imap + (remove mysql as a test) +# pkg_delete php4-mysql-4.3.8 +# /usr/local/sbin/phpxs -r mysql + (install the PEAR libraries) +# pkg_add php4-pear-4.3.8.tgz + + Read the packages(7) manual page for more information about binary + packages on OpenBSD. + _________________________________________________________________ + +Using Ports + + You can also compile up PHP from source using the ports tree. However, + this is only recommended for users familiar with OpenBSD. The PHP 4 + port is split into two sub-directories: core and extensions. The + extensions directory generates sub-packages for all of the supported + PHP modules. If you find you do not want to create some of these + modules, use the no_* FLAVOR. For example, to skip building the imap + module, set the FLAVOR to no_imap. + _________________________________________________________________ + +Common Problems + + * The default install of Apache runs inside a chroot(2) jail, which + will restrict PHP scripts to accessing files under /var/www. You + will therefore need to create a /var/www/tmp directory for PHP + session files to be stored, or use an alternative session backend. + In addition, database sockets need to be placed inside the jail or + listen on the localhost interface. If you use network functions, + some files from /etc such as /etc/resolv.conf and /etc/services + will need to be moved into /var/www/etc. The OpenBSD PEAR package + automatically installs into the correct chroot directories, so no + special modification is needed there. More information on the + OpenBSD Apache is available in the OpenBSD FAQ. + * The OpenBSD 3.6 package for the gd extension requires XFree86 to + be installed. If you do not wish to use some of the font features + that require X11, install the php4-gd-4.3.8-no_x11.tgz package + instead. + _________________________________________________________________ + +Older Releases + + Older releases of OpenBSD used the FLAVORS system to compile up a + statically linked PHP. Since it is hard to generate binary packages + using this method, it is now deprecated. You can still use the old + stable ports trees if you wish, but they are unsupported by the + OpenBSD team. If you have any comments about this, the current + maintainer for the port is Anil Madhavapeddy (avsm at openbsd dot + org). + _________________________________________________________________ + +Solaris specific installation tips + + This section contains notes and hints specific to installing PHP on + Solaris systems. + _________________________________________________________________ + +Required software + + Solaris installs often lack C compilers and their related tools. Read + this FAQ for information on why using GNU versions for some of these + tools is necessary. The required software is as follows: + + * gcc (recommended, other C compilers may work) + * make + * flex + * bison + * m4 + * autoconf + * automake + * perl + * gzip + * tar + * GNU sed + + In addition, you will need to install (and possibly compile) any + additional software specific to your configuration, such as Oracle or + MySQL. + _________________________________________________________________ + +Using Packages + + You can simplify the Solaris install process by using pkgadd to + install most of your needed components. + _________________________________________________________________ + +Gentoo installation notes + + This section contains notes and hints specific to installing PHP on + Gentoo Linux. + _________________________________________________________________ + +Using Portage (emerge) + + While you can just download the PHP source and compile it yourself, + using Gentoo's packaging system is the simplest and cleanest method of + installing PHP. If you are not familiar with building software on + Linux, this is the way to go. + + If you have built your Gentoo system so far, you are probably used to + Portage already. Installing Apache and PHP is no different than the + other system tools. + + The first decision you need to make is whether you want to install + Apache 1.3.x or Apache 2.x. While both can be used with PHP, the steps + given below will use Apache 1.3.x. Another thing to consider is + whether your local Portage tree is up to date. If you have not updated + it recently, you need to run emerge sync before anything else. This + way, you will be using the most recent stable version of Apache and + PHP. + + Now that everything is in place, you can use the following example to + install Apache and PHP: + + Example 2-7. Gentoo Install Example with Apache 1.3 +# emerge \/mod_php-.ebuild config +# nano /etc/conf.d/apache + Add "-D PHP4" to APACHE_OPTS + +# rc-update add apache default +# /etc/init.d/apache start + + You can read more about emerge in the excellent Portage Manual + provided on the Gentoo website. + + If you need to use Apache 2, you can simply use emerge apache in the + last example. + _________________________________________________________________ + +Better control on configuration + + In the last section, PHP was emerged without any activated modules. As + of this writing, the only module activated by default with Portage is + XML which is needed by PEAR. This may not be what you want and you + will soon discover that you need more activated modules, like MySQL, + gettext, GD, etc. + + When you compile PHP from source yourself, you need to activate + modules via the configure command. With Gentoo, you can simply provide + USE flags which will be passed to the configure script automatically. + To see which USE flags to use with emerge, you can try: + + Example 2-8. Getting the list of valid USE flags +# USE="-*" emerge -pv php + +[ebuild N ] dev-php/php-4.3.6-r1 -X -berkdb -crypt -curl -debug -doc +-fdftk -firebird -flash -freetds -gd -gd-external -gdbm -gmp -hardenedphp +-imap -informix -ipv6 -java -jpeg -kerberos -ldap -mcal -memlimit -mssql +-mysql -ncurses -nls -oci8 -odbc -pam -pdflib -png -postgres -qt -readline +-snmp -spell -ssl -tiff -truetype -xml2 -yaz 3,876 kB + + As you can see from the last output, PHP considers a lot of USE flags. + Look at them closely and choose what you need. If you choose a flag + and you do not have the proper libraries, Portage will compile them + for you. It is a good idea to use emerge -pv again to see what Portage + will compile in accordance to your USE flags. As an example, if you do + not have X installed and you choose to include X in the USE flags, + Portage will compile X prior to PHP, which can take a couple of hours. + + If you choose to compile PHP with MySQL, cURL and GD support, the + command will look something like this: + + Example 2-9. Install PHP with USE flags + # USE="-* curl mysql gd" emerge php mod_php + + As in the last example, do not forget to emerge php as well as + mod_php. php is responsible for the command line version of PHP as + mod_php is for the Apache module version of PHP. + _________________________________________________________________ + +Common Problems + + * If you see the PHP source instead of the result the script should + produce, you have probably forgot to edit /etc/conf.d/apache. + Apache needs to be started with the -D PHP4 flag. To see if the + flag is present, you should be able to see it when using ps ax | + grep apache while Apache is running. + * Due to slotting problems, you might end up with more than one + version of PHP installed on your system. If this is the case, you + need to unmerge the old versions manually by using emerge unmerge + mod_php-. + * If you cannot emerge PHP because of Java, try putting -* in front + of your USE flags like in the above examples. + * If you are having problems configuring Apache and PHP, you can + always search the Gentoo Forums. Try searching with the keywords + "Apache PHP". + _________________________________________________________________ + +Chapter 3. Installation on Mac OS X + + This section contains notes and hints specific to installing PHP on + Mac OS X. There are two slightly different versions of Mac OS X, + Client and Server, our manual deals with installing PHP on both + systems. Note that PHP is not available for MacOS 9 and earlier + versions. + _________________________________________________________________ + +Using Packages + + There are a few pre-packaged and pre-compiled versions of PHP for Mac + OS X. This can help in setting up a standard configuration, but if you + need to have a different set of features (such as a secure server, or + a different database driver), you may need to build PHP and/or your + web server yourself. If you are unfamiliar with building and compiling + your own software, it's worth checking whether somebody has already + built a packaged version of PHP with the features you need. + _________________________________________________________________ + +Compiling for OS X Server + + Mac OS X Server install. + + 1. Get the latest distributions of Apache and PHP. + 2. Untar them, and run the configure program on Apache like so. + +./configure --exec-prefix=/usr \ +--localstatedir=/var \ +--mandir=/usr/share/man \ +--libexecdir=/System/Library/Apache/Modules \ +--iconsdir=/System/Library/Apache/Icons \ +--includedir=/System/Library/Frameworks/Apache.framework/Versions/1.3/Headers \ +--enable-shared=max \ +--enable-module=most \ +--target=apache + + 3. If you want the compiler to do some optimization, you may also + want to add this line: + +setenv OPTIM=-O2 + + 4. Next, go to the PHP 4 source directory and configure it. + +./configure --prefix=/usr \ + --sysconfdir=/etc \ + --localstatedir=/var \ + --mandir=/usr/share/man \ + --with-xml \ + --with-apache=/src/apache_1.3.12 + + If you have any other additions (MySQL, GD, etc.), be sure to add + them here. For the --with-apache string, put in the path to your + apache source directory, for example /src/apache_1.3.12. + 5. Type make and make install. This will add a directory to your + Apache source directory under src/modules/php4. + 6. Now, reconfigure Apache to build in PHP 4. + +./configure --exec-prefix=/usr \ +--localstatedir=/var \ +--mandir=/usr/share/man \ +--libexecdir=/System/Library/Apache/Modules \ +--iconsdir=/System/Library/Apache/Icons \ +--includedir=/System/Library/Frameworks/Apache.framework/Versions/1.3/Headers \ +--enable-shared=max \ +--enable-module=most \ +--target=apache \ +--activate-module=src/modules/php4/libphp4.a + + You may get a message telling you that libmodphp4.a is out of + date. If so, go to the src/modules/php4 directory inside your + Apache source directory and run this command: ranlib libmodphp4.a. + Then go back to the root of the Apache source directory and run + the above configure command again. That'll bring the link table up + to date. Run make and make install again. + 7. Copy and rename the php.ini-dist file to your bin directory from + your PHP 4 source directory: cp php.ini-dist + /usr/local/bin/php.ini or (if your don't have a local directory) + cp php.ini-dist /usr/bin/php.ini. + _________________________________________________________________ + +Compiling for MacOS X Client + + The following instructions will help you install a PHP module for the + Apache web server included in MacOS X. This version includes support + for the MySQL and PostgreSQL databases. These instructions are + graciously provided by Marc Liyanage. + + Warning + + Be careful when you do this, you could screw up your Apache web + server! + + Do this to install: + + 1. Open a terminal window. + 2. Type wget + http://www.diax.ch/users/liyanage/software/macosx/libphp4.so.gz, + wait for the download to finish. + 3. Type gunzip libphp4.so.gz. + 4. Type sudo apxs -i -a -n php4 libphp4.so + 5. Now type sudo open -a TextEdit /etc/httpd/httpd.conf. TextEdit + will open with the web server configuration file. Locate these two + lines towards the end of the file: (Use the Find command) + +#AddType application/x-httpd-php .php +#AddType application/x-httpd-php-source .phps + + Remove the two hash marks (#), then save the file and quit + TextEdit. + 6. Finally, type sudo apachectl graceful to restart the web server. + + PHP should now be up and running. You can test it by dropping a file + into your Sites folder which is called test.php. Into that file, write + this line: . + + Now open up 127.0.0.1/~your_username/test.php in your web browser. You + should see a status table with information about the PHP module. + _________________________________________________________________ + +Chapter 4. Installation of PECL extensions + +Introduction to PECL Installations + + PHP extensions may be installed in a variety of ways. PECL is a + repository of PHP extensions living within the PEAR structure, and the + following demonstrates how to install these extensions. + + These instructions assume /your/phpsrcdir/ is the path to the PHP + source, and extname is the name of the PECL extension. Adjust + accordingly. These instructions also assume a familiarity with the + pear command. + + Shared extensions may be installed by including them inside of php.ini + using the extension PHP directive. See also the extensions_dir + directive, and dl(). The installation methods described below do not + automatically configure PHP to include these extensions, this step + must be done manually. + + When building PHP modules, it's important to have the appropriate + versions of the required tools (autoconf, automake, libtool, etc.) See + the Anonymous CVS Instructions for details on the required tools, and + required versions. + _________________________________________________________________ + +Downloading PECL extensions + + There are several options for downloading PECL extensions, such as: + + * http://pecl.php.net + Listed here is information like the ChangeLog, release + information, requirements, revisions, etc. Although not every PECL + extension has a webpage, most do. + * pear download extname + The pear command may also be used to download source files. + Specific revisions may also be specified. + * CVS + All PECL files reside in CVS. A web-based view may be seen at + http://cvs.php.net/pecl/. To download straight from CVS, consider + the following where phpfi is the password for user cvsread: + +$ cvs -d:pserver:cvsread@cvs.php.net:/repository login +$ cvs -d:pserver:cvsread@cvs.php.net:/repository co pecl/extname + + * Windows downloads + Windows users may find compiled PECL binaries by downloading the + Collection of PECL modules from the PHP Downloads page, and by + retrieving a PECL Snapshot. To compile PHP under Windows, read the + Win32 Build README. + _________________________________________________________________ + +PECL for Windows users - When you are finished making changes to your httpd.conf file, you need - to copy php.ini-dist to the appropriate place (normally - /usr/local/lib/php.ini) and edit if necessary. You can then - start up your server. + Like with any other PHP extension DLL, to install move the PECL + extension DLLs into the extension_dir folder and include them within + php.ini. For example: -5. Testing it all worked + extension=php_extname.dll - Create a test file named test.php in your web tree somewhere and - put some test PHP tags in it. is a good first test. - This tag tells PHP to do a braindump and tells you all sorts of things - about itself. + After doing this, restart the web server. + _________________________________________________________________ +Compiling shared PECL extensions with PEAR -WHY DISABLING -fPIC WORKS ON LINUX + PEAR makes it easy to create shared PHP extensions. Using the pear + command, do the following: - From: Martin v. Loewis - To: glibc-linux@ricardo.ecn.wfu.edu - Subject: Re: Shared library -shared vs. -fpic + $ pear install extname - [In reply to Kaz Kylheku ] + That will download the source for extname, and compile it on the + system. This results in an extname.so file that may then be included + in php.ini - > PIC stands for Position-Independent Code. + In case the systems preferred_state is set higher than an available + extname version, like it's set to stable and the extension is still in + beta, either alter the preferred_state via pear config-set or specify + a specific version of the PECL extension. For example: - Correct. + $ pear install extname-0.1.1 - > Code isn't position-independent (or ``relocatable'') cannot be - > loaded at an arbitrary address; + Regardless, pear will copy this extname.so into the extensions + directory. Adjust php.ini accordingly. + _________________________________________________________________ - Wrong. +Compiling shared PECL extensions with phpize - > it requires some references to be patched at load time. + If using pear is not an option, like for building shared PECL + extensions from CVS, or for unreleased PECL packages, then creating a + shared extension may also be done by manually using the phpize + command. The pear command essentially does this but it may also be + done manually. Assuming the source file is named extname.tgz, and that + it was downloaded into the current directory, consider the following: - Correct. +$ pear download extname +$ gzip -d < extname.tgz | tar -xvf - +$ cd extname +$ phpize +$ ./configure && make - > Shared libraries need to be relocatable because it's not known - > beforehand what address they will be loaded at + Upon success, this will create extname.so and put it into the modules/ + and/or .libs/ directory within the extname/ source. Move this shared + extension (extname.so) into the PHP extensions directory, and adjust + php.ini accordingly. + _________________________________________________________________ - Correct, depending on the meaning of "relocatable". PIC code typically - does not contain relocations; that's why its position-independent. +Compiling PECL extensions statically into PHP - > Just because you don't specify -fPIC doesn't mean that the compiler - > won't emit position-independent code; the option prevents it from - > emitting position-dependent code in situations where it otherwise - > would. + To statically include the extension within the PHP build, put the + extensions source into the ext/ directory found in the PHP source. For + example: - Correct. However, a non-trivial shared library typically won't be - position-independent unless explicitly compiled with - -fPIC. Linux/glibc indeed does not require a shared library to be - position-independent; instead, it will perform the relocations in the - binary, even if they refer to code pages. As a result, those relocated - pages won't be shared across processes, anymore. - - Regards, - Martin - -USING PHP 3 AND PHP 4 AS CONCURRENT APACHE MODULES - - With some (newer) installations of Apache, it's possible to compile both - PHP 3 and PHP 4, and run them concurrently. - - Note, it's only really wise to do this if you need to use the PHP 3 engine - to maintain backwards compatibility. - - To enable it, configure PHP 3 and PHP 4 to use APXS (--with-apxs) and the - necessary link extensions (--enable-versioning). Otherwise, all standard - installations instructions apply. For example: - - $ ./configure \ - --with-apxs=/apache/bin/apxs \ - --enable-versioning \ - --with-mysql \ +$ cd /your/phpsrcdir/ext +$ pear download extname +$ gzip -d < extname.tgz | tar -xvf - +$ mv extname-x.x.x extname +$ rm package.xml + This will result in the following directory: + /your/phpsrcdir/ext/extname + From here, build PHP as normal: +$ cd /your/phpsrcdir +$ ./buildconf +$ ./configure --help +$ ./configure --with-extname --enable-someotherext --with-foobar +$ make +$ make install + Whether --enable-extname or --with-extname is used depends on the + extension. Typically an extension that does not require external + libraries uses --enable. To be sure, run the following after + buildconf: + + $ ./configure --help | grep extname + _________________________________________________________________ + +Chapter 5. Problems? + +Read the FAQ + + Some problems are more common than others. The most common ones are + listed in the PHP FAQ, part of this manual. + _________________________________________________________________ + +Other problems + + If you are still stuck, someone on the PHP installation mailing list + may be able to help you. You should check out the archive first, in + case someone already answered someone else who had the same problem as + you. The archives are available from the support page on + http://www.php.net/support.php. To subscribe to the PHP installation + mailing list, send an empty mail to + php-install-subscribe@lists.php.net. The mailing list address is + php-install@lists.php.net. + + If you want to get help on the mailing list, please try to be precise + and give the necessary details about your environment (which operating + system, what PHP version, what web server, if you are running PHP as + CGI or a server module, safe mode, etc...), and preferably enough code + to make others able to reproduce and test your problem. + _________________________________________________________________ + +Bug reports + + If you think you have found a bug in PHP, please report it. The PHP + developers probably don't know about it, and unless you report it, + chances are it won't be fixed. You can report bugs using the + bug-tracking system at http://bugs.php.net/. Please do not send bug + reports in mailing list or personal letters. The bug system is also + suitable to submit feature requests. + + Read the How to report a bug document before submitting any bug + reports! + _________________________________________________________________ + +Chapter 6. Runtime Configuration + +The configuration file + + The configuration file (called php3.ini in PHP 3, and simply php.ini + as of PHP 4) is read when PHP starts up. For the server module + versions of PHP, this happens only once when the web server is + started. For the CGI and CLI version, it happens on every invocation. + + The default location of php.ini is a compile time option (see the FAQ + entry), but can be changed for the CGI and CLI version with the -c + command line switch, see the chapter about using PHP from the command + line. You can also use the environment variable PHPRC for an + additional path to search for a php.ini file. + + If php-SAPI.ini exists (where SAPI is used SAPI, so the filename is + e.g. php-cli.ini or php-apache.ini), it's used instead of php.ini. + + Note: The Apache web server changes the directory to root at + startup causing PHP to attempt to read php.ini from the root + filesystem if it exists. + + The php.ini directives handled by extensions are documented + respectively on the pages of the extensions themselves. The list of + the core directives is available in the appendix. Probably not all the + PHP directives are documented in the manual though. For a completel + list of directives available in your PHP version, please read your + well commented php.ini file. Alternatively, you may find the the + latest php.ini from CVS helpful too. + + Example 6-1. php.ini example +; any text on a line after an unquoted semicolon (;) is ignored +[php] ; section markers (text within square brackets) are also ignored +; Boolean values can be set to either: +; true, on, yes +; or false, off, no, none +register_globals = off +track_errors = yes + +; you can enclose strings in double-quotes +include_path = ".:/usr/local/lib/php" + +; backslashes are treated the same as any other character +include_path = ".;c:\php\lib" + _________________________________________________________________ + +How to change configuration settings + +Running PHP as an Apache module + + When using PHP as an Apache module, you can also change the + configuration settings using directives in Apache configuration files + (e.g. httpd.conf) and .htaccess files. You will need "AllowOverride + Options" or "AllowOverride All" privileges to do so. + + With PHP 4 and PHP 5, there are several Apache directives that allow + you to change the PHP configuration from within the Apache + configuration files. For a listing of which directives are + PHP_INI_ALL, PHP_INI_PERDIR, or PHP_INI_SYSTEM, have a look at the + List of php.ini directives appendix. + + Note: With PHP 3, there are Apache directives that correspond to + each configuration setting in the php3.ini name, except the name is + prefixed by "php3_". + + php_value name value + Sets the value of the specified directive. Can be used only + with PHP_INI_ALL and PHP_INI_PERDIR type directives. To clear a + previously set value use none as the value. + + Note: Don't use php_value to set boolean values. php_flag (see + below) should be used instead. + + php_flag name on|off + Used to set a boolean configuration directive. Can be used only + with PHP_INI_ALL and PHP_INI_PERDIR type directives. + + php_admin_value name value + Sets the value of the specified directive. This can not be used + in .htaccess files. Any directive type set with php_admin_value + can not be overridden by .htaccess or virtualhost directives. + To clear a previously set value use none as the value. + + php_admin_flag name on|off + Used to set a boolean configuration directive. This can not be + used in .htaccess files. Any directive type set with + php_admin_flag can not be overridden by .htaccess or + virtualhost directives. + + Example 6-2. Apache configuration example + + php_value include_path ".:/usr/local/lib/php" + php_admin_flag safe_mode on + + + php_value include_path ".:/usr/local/lib/php" + php_admin_flag safe_mode on + + + php3_include_path ".:/usr/local/lib/php" + php3_safe_mode on + + + Caution + + PHP constants do not exist outside of PHP. For example, in httpd.conf + you can not use PHP constants such as E_ALL or E_NOTICE to set the + error_reporting directive as they will have no meaning and will + evaluate to 0. Use the associated bitmask values instead. These + constants can be used in php.ini + _________________________________________________________________ + +Changing PHP configuration via the Windows registry + + When running PHP on Windows, the configuration values can be modified + on a per-directory basis using the Windows registry. The configuration + values are stored in the registry key HKLM\SOFTWARE\PHP\Per Directory + Values, in the sub-keys corresponding to the path names. For example, + configuration values for the directory c:\inetpub\wwwroot would be + stored in the key HKLM\SOFTWARE\PHP\Per Directory + Values\c\inetpub\wwwroot. The settings for the directory would be + active for any script running from this directory or any subdirectory + of it. The values under the key should have the name of the PHP + configuration directive and the string value. PHP constants in the + values are not parsed. However, only configuration values changeable + in PHP_INI_USER can be set this way, PHP_INI_PERDIR values can not. + _________________________________________________________________ + +Other interfaces to PHP + + Regardless of how you run PHP, you can change certain values at + runtime of your scripts through ini_set(). See the documentation on + the ini_set() page for more information. + + If you are interested in a complete list of configuration settings on + your system with their current values, you can execute the phpinfo() + function, and review the resulting page. You can also access the + values of individual configuration directives at runtime using + ini_get() or get_cfg_var(). diff --git a/Makefile.global b/Makefile.global index e30bc42f7882..c59751bc5af7 100644 --- a/Makefile.global +++ b/Makefile.global @@ -69,7 +69,7 @@ clean: distclean: clean rm -f config.cache config.log config.status Makefile.objects Makefile.fragments libtool main/php_config.h stamp-h php5.spec sapi/apache/libphp5.module buildmk.stamp - egrep define'.*include/php' configure|sed 's/.*>//'|xargs rm -f + egrep define'.*include/php' $(top_srcdir)/configure|sed 's/.*>//'|xargs rm -f find . -name Makefile | xargs rm -f .PHONY: all clean install distclean test diff --git a/NEWS b/NEWS index 2a57e828b3e2..a89e0c28bc67 100644 --- a/NEWS +++ b/NEWS @@ -1,7 +1,639 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? 2004, PHP 5.0.1 +23 Oct 2026, PHP 5.0.5-p1 +- Fixed GHSA-w8hw-w9fx-j79w (Avoid state corruption via bailout). + (CVE-2026-109618) (Arnaud, ilutov) +- Fixed GHSA-6wmf-4rv5-p3rp (Avoid state corruption via bailout). + (CVE-2026-109619) (Arnaud, ilutov) + +05 Sep 2005, PHP 5.0.5 +- Upgraded PCRE library to version 5.0. (Andrei) +- Removed php_check_syntax() function which never worked properly. (Ilia) +- Added new function mysqli_set_charset(). (Georg) +- Added man pages for "phpize" and "php-config" scripts. (Jakub Vrana) +- Added support for .cc files in extensions. (Brian) +- Added PHP_INT_MAX and PHP_INT_SIZE as predefined constants. (Andrey) +- Changed sha1_file() and md5_file() functions to use streams instead of + low level IO. (Uwe) +- Changed ming to support official 0.2a and 0.3 library versions. (Marcus) +- Fixed failing queries problem (FALSE returned) with mysqli_query() on 64 bit. + (Andrey) +- Fixed memory corruption in pg_copy_from() in case the as_null parameter was + passed. (Derick) +- Fixed ext/mysqli to allocate less memory when fetching bound params + of type (MEDIUM|LONG)BLOB/(MEDIUM|LONG)TEXT. (Andrey) +- Fixed memory corruption in ImageTTFText() with 64bit systems. (Andrey) +- Fixed memory corruption in stristr(). (Derick) +- Fixed segfaults when CURL callback functions throw exception. (Tony) +- Fixed various reentrancy bugs in user-sort functions, solves bugs #33286 and + #33295. (Mike Bretz) +- Fixed bug #34307 (on_modify handler not called to set the default value if + setting from php.ini was invalid). (Andrei) +- Fixed bug #34302 (date('W') do not return leading zeros for week 1 to 9). + (Derick) +- Fixed bug #34299 (ReflectionClass::isInstantiable() returns true for abstract + classes). (Marcus) +- Fixed bug #34277 (array_filter() crashes with references and objects). + (Dmitry) +- Fixed bug #34260 (Segfault with callbacks (array_map) + overloading). + (Dmitry) +- Fixed bug #34137 (assigning array element by reference causes binary mess). + (Dmitry) +- Fixed bug #34078 (Reflection API problems in methods with boolean or + null default values). (Tony) +- Fixed bug #34064 (arr[] as param to function is allowed only if function + receives argument by reference). (Dmitry) +- Fixed bug #34062 (Crash in catch block when many arguments are used). + (Dmitry) +- Fixed bug #33989 (extract($GLOBALS,EXTR_REFS) crashes PHP). (Dmitry) +- Fixed bug #33940 (array_map() fails to pass by reference when called + recursively). (Dmitry) +- Fixed bug #33853 (php:function call __autoload with lowercase param). (Marcus) +- Fixed bug #33802 (throw Exception in error handler causes crash). (Dmitry) +- Fixed bug #33723 (php_value overrides php_admin_value). (Dmitry) +- Fixed bug #33710 (ArrayAccess objects doen't initialize $this). (Dmitry) +- Fixed bug #33588 (LDAP: RootDSE query not possible). (Jani) +- Fixed bug #33558 (warning with nested calls to functions returning by + reference). (Dmitry) +- Fixed bug #33520 (crash if safe_mode is on and session.save_path is changed). + (Dmitry) +- Fixed bug #33491 (crash after extending MySQLi internal class). (Tony) +- Fixed bug #33340 (CLI Crash when calling php:function from XSLT). (Rob) +- Fixed bug #33277 (private method accessed by child class). (Dmitry) +- Fixed bug #33268 (iconv_strlen() works only with a parameter of < 3 in + length). (Ilia) +- Fixed bug #33263 (mysqli_real_escape doesn't work in __construct) (Georg) +- Fixed bug #33257 (array_splice() inconsistent when passed function instead + of variable). (Dmitry) +- Fixed bug #33243 (ze1_compatibility_mode does not work as expected). (Dmitry) +- Fixed bug #33242 (Mangled error message when stream fails). (Derick) +- Fixed bug #33222 (segfault when CURL handle is closed in a callback). (Tony) +- Fixed bug #33214 (odbc_next_result does not signal SQL errors with + 2-statement SQL batches). (rich at kastle dot com, Tony) +- Fixed bug #33210 (relax jpeg recursive loop protection). (Ilia) +- Fixed bug #33200 (preg_replace(): magic_quotes_sybase=On makes 'e' modifier + misbehave). (Jani) +- Fixed bug #33185 (--enable-session=shared does not build). (Jani) +- Fixed bug #33171 (foreach enumerates private fields declared in base + classes). (Dmitry) +- Fixed bug #33164 (Soap extension incorrectly detects HTTP/1.1). (Ilia) +- Fixed bug #33156 (cygwin version of setitimer doesn't accept ITIMER_PROF). + (Nuno) +- Fixed bug #33116 (crash when assigning class name to global variable in + __autoload). (Dmitry) +- Fixed bug #33090 (mysqli_prepare() doesn't return an error). (Georg) +- Fixed bug #33076 (str_ireplace() incorrectly counts result string length + and may cause segfault). (Tony) +- Fixed bug #33072 (Add a safemode/open_basedir check for runtime + "session.save_path" change using session_save_path() function). (Rasmus) +- Fixed bug #33070 (Improved performance of bzdecompress() by several orders + of magnitude). (Ilia) +- Fixed bug #33059 (crash when moving xml attribute set in dtd). (Ilia) +- Fixed bug #33057 (Don't send extraneous entity-headers on a 304 as per + RFC 2616 section 10.3.5) (Rasmus, Choitel) +- Fixed bug #33019 (socket errors cause memory leaks in php_strerror()). + (jwozniak23 at poczta dot onet dot pl, Tony). +- Fixed bug #33017 ("make distclean" gives an error with VPATH build). (Jani) +- Fixed bug #33013 ("next month" was handled wrong while parsing dates). + (Derick) +- Fixed bug #32981 (ReflectionMethod::getStaticVariables() causes apache2.0.54 + seg fault). (Dmitry) +- Fixed bug #32956 (mysql_bind_result() doesn't support MYSQL_TYPE_NULL). (Georg) +- Fixed bug #32947 (Incorrect option for mysqli default password). (Georg) +- Fixed bug #32944 (Disabling session.use_cookies doesn't prevent reading + session cookies). (Jani, Tony) +- Fixed bug #32941 (Sending structured SOAP fault kills a php). (Dmitry) +- Fixed bug #32936 (http redirects URLs are not checked for control chars). (Ilia) +- Fixed bug #32933 (Cannot extend class "SQLiteDatabase"). (Marcus) +- Fixed bug #32932 (Oracle LDAP: ldap_get_entries(), invalid pointer). (Jani) +- Fixed bug #32930 (class extending DOMDocument doesn't clone properly). (Rob) +- Fixed bug #32904 (pg_get_notify() ignores result_type parameter). (Tony) +- Fixed bug #32852 (Crash with singleton and __destruct when + zend.ze1_compatibility_mode = On). (Dmitry) +- Fixed bug #32813 (parse_url() does not handle scheme-only urls properly). (Ilia) +- Fixed bug #32810 (temporary files not using plain file wrapper). (Ilia) +- Fixed bug #32809 (Missing T1LIB support on Windows). (Edin) +- Fixed bug #32802 (General cookie overrides more specific cookie). (Ilia) +- Fixed bugs #32800, #32830 (ext/odbc: Problems with 64bit systems). (Jani) +- Fixed bug #32799 (crash: calling the corresponding global var during the + destruct). (Dmitry) +- Fixed bug #32776 (SOAP doesn't support one-way operations). (Dmitry) +- Fixed bug #32773 (GMP functions break when second parameter is 0). (Stas) +- Fixed bug #32759 (incorrect determination of default value (COM)). (Wez) +- Fixed bug #32758 (Cannot access safearray properties in VB6 objects). (Wez) +- Fixed bug #32755 (Segfault in replaceChild() when DocumentFragment has + no children). (Rob) +- Fixed bug #32753 (Undefined constant SQLITE_NOTADB). (Ilia) +- Fixed bug #32742 (segmentation fault when the stream with a wrapper + is not closed). (Tony, Dmitry) +- Fixed bug #32699 (pg_affected_rows() was defined when it was not available). + (Derick) +- Fixed bug #32686 (Require/include file in destructor causes segfault). + (Marcus) +- Fixed bug #32682 (ext/mssql: Error on module shutdown when called from + activescript). (Frank) +- Fixed bug #32674 (exception in iterator causes crash). (Dmitry) +- Fixed bug #32660 (Assignment by reference causes crash when field access is + overloaded (__get)). (Dmitry) +- Fixed bug #32647 (Using register_shutdown_function() with invalid callback + can crash PHP). (Jani) +- Fixed bug #32615 (Segfault in replaceChild() using fragment when + previousSibling is NULL). (Rob) +- Fixed bug #32613 (ext/snmp: use of snmp_shutdown() causes snmpapp.conf + access errors). (Jani, ric at arizona dot edu) +- Fixed bug #32608 (html_entity_decode() converts single quotes even if + ENT_NOQUOTES is given). (Ilia) +- Fixed bug #32596 (Segfault/Memory Leak by getClass (etc) in __destruct). + (Dmitry) +- Fixed bug #32591 (ext/mysql: Unsatisfied symbol: ntohs with HP-UX). (Jani) +- Fixed bug #32589 (Possible crash inside imap_mail_compose, with charsets). + (Ilia) +- Fixed bug #32587 (Apache2: errors sent to error_log do not include + timestamps). (Jani) +- Fixed bug #32560 (configure looks for incorrect db2 library). (Tony) +- Fixed bug #32553 (mmap loads only the 1st 2000000 bytes on Win32). (Ilia) +- Fixed bug #32533 (proc_get_status() returns the incorrect process status). (Ilia) +- Fixed bug #32530 (chunk_split() does not append endstr if chunklen is + longer then the original string). (Ilia) +- Fixed bug #32491 (File upload error - unable to create a temporary file). + (Uwe Schindler) +- Fixed bug #32405 (mysqli::fetch() returns bad data - 64bit problem). (Andrey) +- Fixed bug #32282 (Segfault in mysqli_fetch_array on 64-bit). (Georg) +- Fixed bug #32296 (get_class_methods() output has changed between 5.0.2 and + 5.0.3). (Dmitry) +- Fixed bug #32245 (xml_parser_free() in a function assigned to the xml parser + gives a segfault). (Rob) +- Fixed bug #32171 (Userspace stream wrapper crashes PHP). (Tony, Dmitry) +- Fixed bug #32080 (segfault when assigning object to itself with + zend.ze1_compatibility_mode=On). (Dmitry) +- Fixed bug #32013 (ext/mysqli bind_result causes fatal error: memory + limit). (Andrey) +- Fixed bug #31887 (ISAPI: Custom 5xx error does not return correct HTTP + response message). (Jani) +- Fixed bug #31828 (Crash with zend.ze1_compatibility_mode=On). (Dmitry) +- Fixed bug #31668 (multi_query works exactly every other time - multi query + d/e flag global and not per connection). (Andrey) +- Fixed bug #31636 (another crash when echoing a COM object). (Wez) +- Fixed bug #31583 (php_std_date() uses short day names in non-y2k_compliance + mode). (mike at php dot net) +- Fixed bug #31525 (object reference being dropped. $this getting lost). + (Stas, Dmitry) +- Fixed bug #31502 (Wrong deserialization from session when using WDDX + serializer). (Dmitry) +- Fixed bug #31465 (False warning in unpack() when working with *). (Ilia) +- Fixed bug #31363 (broken non-blocking flock()). ian at snork dot net +- Fixed bug #31213 (Sideeffects caused by fix of bug #29493). (Dmitry) +- Fixed bug #31158 (array_splice on $GLOBALS crashes). (Dmitry) +- Fixed bug #30961 (Wrong linenumber in ReflectionClass getStartLine()). + (Dmitry) +- Fixed bug #30889 (Conflict between __get/__set and ++ operator). (Dmitry) +- Fixed bug #30833 (array_count_values() modifying input array). (Tony) +- Fixed bug #30828 (debug_backtrace() reports incorrect class in overridden + methods). (Dmitry) +- Fixed bug #30820 (static member conflict with $this->member silently + ignored). (Dmitry) +- Fixed bug #30819 (Better support for LDAP SASL bind). (Jani) +- Fixed bug #30791 (magic methods (__sleep/__wakeup/__toString) call __call if + object is overloaded). (Dmitry) +- Fixed bug #30707 (Segmentation fault on exception in method). (Stas, Dmitry) +- Fixed bug #30702 (cannot initialize class variable from class constant). + (Dmitry) +- Fixed bug #30519 (Interface not existing says Class not found). (Dmitry) +- Fixed bug #30394 (Assignment operators yield wrong result with __get/__set). + (Dmitry) +- Fixed bug #30332 (zend.ze1_compatibility_mode isnt fully compatable with + array_push()). (Dmitry) +- Fixed bug #30162 (Catching exception in constructor causes lose of $this). + (Dmitry) +- Fixed bug #30140 (Problem with array in static properties). (Dmitry) +- Fixed bug #30126 (Enhancement for error message for abstract classes). + (Marcus) +- Fixed bug #30080 (Passing array or non array of objects). (Dmitry) +- Fixed bug #29975 (memory leaks when set_error_handler() is used inside error + handler). (Tony) +- Fixed bug #29971 (variables_order behaviour). (Dmitry) +- Fixed bug #29944 (Function defined in switch, crashes). (Dmitry) +- Fixed bug #29896 (Backtrace argument list out of sync). (Dmitry) +- Fixed bug #29683 (headers_list() returns empty array). (Tony) +- Fixed bug #29583 (crash when echoing a COM object). (M.Sisolak, Wez) +- Fixed bug #29338 (unencoded spaces get ignored after certain tags). (Ilia) +- Fixed bug #29210 (Function: is_callable - no support for private and + protected classes). (Dmitry) +- Fixed bug #29104 (Function declaration in method doesn't work). (Dmitry) +- Fixed bug #29015 (Incorrect behavior of member vars(non string ones)-numeric + mem vars und others). (Dmitry) +- Fixed bug #28839 (SIGSEGV in interactive mode (php -a)). + (kameshj at fastmail dot fm) +- Fixed bug #28605 (Need to use -[m]ieee option for Alpha CPUs). (Jani) +- Fixed bug #28377 (debug_backtrace is intermittently passing args). (Dmitry) +- Fixed bug #27598 (list() array key assignment causes HUGE memory leak). + (Dmitry) +- Fixed bug #26456 (Wrong results from Reflection-API getDocComment() when + called via STDIN). (Dmitry) +- Fixed bug #25922 (In error handler, modifying 5th arg (errcontext) may result + in seg fault). (Dmitry) +- Fixed bug #22836 (returning reference to uninitialized variable). (Dmitry) +- Fixed bug #29689 (default value of protected member overrides default value of private) + and other private variable problems in inherited classes (Stas) +- Fixed bug #29253 (array_diff with $GLOBALS argument fails). (Dmitry) +- Abstract private methods are no longer allowed (Stas) + +31 Mar 2005, PHP 5.0.4 +- Added SNMPv2 support. (harrie) +- Added Oracle Instant Client support. (cjbj at hotmail dot com, Tony) +- Added length and charsetnr for field array and object in mysqli. (Georg) +- Added checks for negative values to gmp_sqrt(), gmp_powm(), gmp_sqrtrem() + and gmp_fact() to prevent SIGFPE. (Tony) +- Changed foreach() to throw an exception if IteratorAggregate::getIterator() + does not return an Iterator. (Marcus) +- Changed phpize not to require libtool. (Jani) +- Updated bundled oniguruma library (used for multibyte regular expression) + to 3.7.0. (Moriyoshi) +- Updated bundled libmbfl library (used for multibyte functions). (Moriyoshi) + Fixed bugs: + . Bug #32311 (mb_encode_mimeheader() does not properly escape characters) + . Bug #32063 (mb_convert_encoding ignores named entity 'alpha') + . Bug #31911 (mb_decode_mimeheader() is case-sensitive to hex escapes) + . bug #30573 (compiler warnings in libmbfl due to invalid type cast) + . Bug #30549 (incorrect character translations for some ISO8859 charsets). +- Fixed bug preventing from building oci8 as shared. + (stanislav dot voroniy at portavita dot nl, Tony) +- Fixed a bug in mysql_affected_rows and mysql_stmt_affected_rows when the + api function returns -1 (Georg) +- Fixed several leaks in ext/browscap and sapi/embed. (Andrei) +- Fixed several leaks in ext/filepro. (Tony) +- Fixed build system to always use bundled libtool files. (Jani) +- Fixed a bug in mysqli_stmt_execute() (type conversion with NULL values). + (Georg) +- Fixed segfault in mysqli_fetch_field_direct() when invalid field offset + is passed. (Tony) +- Fixed posix_getsid() & posix_getpgid() to return sid & pgid instead + of true. (Tony) +- Fixed bug #32394 (offsetUnset() segfaults in a foreach). (Marcus) +- Fixed bug #32373 (segfault in bzopen() if supplied path to non-existent + file). (Tony) +- Fixed bug #32326 (Check values of Connection/Transfer-Encoding + case-incentively in SOAP extension). (Ilia) +- Fixed bug #32290 (call_user_func_array() calls wrong class method within + child class). (Marcus) +- Fixed bug #32238 (spl_array.c: void function cannot return value). (Johannes) +- Fixed bug #32210 (proc_get_status() sets "running" always to true). (Ilia) +- Fixed bug #32200 (Prevent using both --with-apxs2 and --with-apxs2filter). + (Jani) +- Fixed bug #32134 (Overloading offsetGet/offsetSet). (Marcus) +- Fixed bug #32130 (ArrayIterator::seek() does not throw an Exception on + invalid index). (Marcus) +- Fixed bug #32115 (dateTime SOAP encoding of timezone incorrect). (Dmitry) +- Fixed bug #32081 (in mysqli default socket value is not being used). (Ilia) +- Fixed bug #32021 (Crash caused by range('', 'z')). (Derick) +- Fixed bug #32011 (Fragments which replaced Nodes are not globaly useable). + (Rob) +- Fixed bug #32001 (xml_parse_into_struct() function exceeds maximum + execution time). (Rob, Moriyoshi) +- Fixed bug #31980 (Unicode exif data not available on Windows). (Edin) +- Fixed bug #31960 (msql_fetch_row() and msql_fetch_array() dropping columns + with NULL values). (Daniel Convissor) +- Fixed bug #31878 (Segmentation fault using clone keyword on nodes). (Rob) +- Fixed bug #31858 (--disable-cli does not force --without-pear). (Jani) +- Fixed bug #31842 (*date('r') does not return RFC2822 conforming date string). + (Jani) +- Fixed bug #31832 (SOAP encoding problem with complex types in WSDL mode with + multiple parts). (Dmitry) +- Fixed bug #31797 (exif_read_data() uses too low nesting limit). (Ilia) +- Fixed bug #31796 (readline completion handler does not handle empty return + values). (Ilia) +- Fixed bug #31792 (getrusage() does not provide ru_nswap value). (Ilia) +- Fixed bug #31755 (Cannot create SOAP header in no namespace). (Dmitry) +- Fixed bug #31754 (dbase_open() fails for mode = 1). (Mehdi, Derick) +- Fixed bug #31751 (pg_parameter_status() missing on Windows). (Edin) +- Fixed bug #31747 (SOAP Digest Authentication doesn't work with + "HTTP/1.1 100 Continue" response). (Dmitry) +- Fixed bug #31732 (mb_get_info() causes segfault when no parameters + specified). (Tony) +- Fixed bug #31710 (Wrong return values for mysqli_autocommit/commit/rollback). + (Georg) +- Fixed bug #31705 (parse_url() does not recognize http://foo.com#bar). (Ilia) +- Fixed bug #31695 (Cannot redefine endpoint when using WSDL). (Dmitry) +- Fixed bug #31684 (dio_tcsetattr(): misconfigured termios settings). + (elod at itfais dot com) +- Fixed bug #31683 (changes to $name in __get($name) override future + parameters). (Dmitry) +- Fixed bug #31699 (unserialize() float problem on non-English locales). (Ilia) +- Fixed bug #31562 (__autoload() problem with static variables). (Marcus) +- Fixed bug #31651 (ReflectionClass::getDefaultProperties segfaults with arrays). + (Marcus) +- Fixed bug #31623 (OCILogin does not support password grace period). + (daniel dot beet at accuratesoftware dot com, Tony) +- Fixed bug #31527 (crash in msg_send() when non-string is stored without + being serialized). (Ilia) +- Fixed bug #31515 (Improve performance of scandir() by factor of 10 or so). (Ilia) +- Fixed bug #31514 (open_basedir uses path_translated rather then cwd for . + translation). (Ilia) +- Fixed bug #31480 (Possible infinite loop in imap_mail_compose()). (Ilia) +- Fixed bug #31479 (Fixed crash in chunk_split(), when chunklen > strlen). (Ilia) +- Fixed bug #31454 (session_set_save_handler crashes PHP when supplied + non-existent object ref). (Tony) +- Fixed bug #31444 (Memory leak in zend_language_scanner.c). + (hexer at studentcenter dot org) +- Fixed bug #31442 (unserialize broken on 64-bit systems). (Marcus) +- Fixed bug #31440 ($GLOBALS can be overwritten via GPC when register_globals + is enabled). (Ilia) +- Fixed bug #31422 (No Error-Logging on SoapServer-Side). (Dmitry) +- Fixed bug #31413 (curl POSTFIELDS crashes on 64-bit platforms). (Joe) +- Fixed bug #31396 (compile fails with gd 2.0.33 without freetype). (Jani) +- Fixed bug #31371 (highlight_file() trims new line after heredoc). (Ilia) +- Fixed bug #31361 (simplexml/domxml segfault when adding node twice). (Rob) +- Fixed bug #31348 (CachingIterator::rewind() leaks). (Marcus) +- Fixed bug #31346 (ArrayIterator::next segfaults). (Marcus) +- Fixed bug #31190 (Unexpected warning then exception is thrown from + call_user_func_array()). (phpbugs at domain51 dot net, Dmitry) +- Fixed bug #31142 (imap_mail_compose() fails to generate correct output). (Ilia) +- Fixed bug #31139 (XML Parser Functions seem to drop & when parsing). (Rob) +- Fixed bug #31398 (When magic_guotes_gpc are enabled filenames with ' get cutoff). + (Ilia) +- Fixed bug #31288 (Possible crash in mysql_fetch_field(), if mysql_list_fields() + was not called previously). (Ilia) +- Fixed bug #31107, #31110, #31111, #31249 (Compile failure of zend_strtod.c). + (Jani) +- Fixed bug #31110 (PHP 4.3.10 does not compile on Tru64 UNIX 5.1B). (Derick) +- Fixed bug #31107 (Compile failure on Solaris 9 (Intel) and gcc 3.4.3). (Derick) +- Fixed bug #31103 (Better error message when c-client cannot be found). (Ilia) +- Fixed bug #31101 (missing kerberos header file path with --with-openssl). (Jani) +- Fixed bug #31098 (isset() / empty() incorrectly return true in dereference of + a string type). (Moriyoshi) +- Fixed bug #31087 (broken php_url_encode_hash macro). (Ilia) +- Fixed bug #31072 (var_export() does not output an array element with an empty + string key). (Derick) +- Fixed bug #31060 (imageftbbox() does not use linespacing parameter). (Jani) +- Fixed bug #31056 (php_std_date() returns invalid formatted date if + y2k_compliance is On). (Ilia) +- Fixed bug #31055 (apache2filter: per request leak proportional to the full + path of the request URI). (kameshj at fastmail dot fm) +- Fixed bug #30901 (can't send cookies with soap envelop). (Dmitry) +- Fixed bug #30871 (Misleading warning message for array_combine()). (Andrey) +- Fixed bug #30868 (evaluated pointer comparison in mbregex causes compile + failure). (Moriyoshi) +- Fixed bug #30862 (Static array with boolean indexes). (Marcus) +- Fixed bug #30726 (-.1 like numbers are not being handled correctly). (Ilia) +- Fixed bug #30725 (PHP segfaults when an exception is thrown in getIterator() + within foreach). (Marcus) +- Fixed bug #30609 (cURL functions bypass open_basedir). (Jani) +- Fixed bug #30446 (apache2handler: virtual() includes files out of sequence) +- Fixed bug #30430 (odbc_next_result() doesn't bind values and that results + in segfault). (pdan-php at esync dot org, Tony) +- Fixed bug #30266 (Invalid opcode 137/1/8). (Marcus) +- Fixed bug #30120 (imagettftext() and imagettfbbox() accept too many + parameters). (Jani) +- Fixed bug #30106 (SOAP cannot not parse 'ref' element. Causes Uncaught + SoapFault exception). (Dmitry) +- Fixed bug #29989 (type re_registers redefined in oniguruma.h). (Moriyoshi) +- Fixed bug #28803 (enabled debug causes bailout errors with CLI on AIX + because of fflush() called on already closed filedescriptor). (Tony) +- Fixed bug #29767 (Weird behaviour of __set($name, $value)). (Dmitry) +- Fixed bug #29733 (printf() handles repeated placeholders wrong). + (bugs dot php dot net at bluetwanger dot de, Ilia) +- Fixed bug #29424 (width and height inverted for JPEG2000 files). (Ilia) +- Fixed bug #29329 (configure for mysqli with shared doesn't work). (Georg) +- Fixed bug #29136 (make test - libtool failure on MacOSX). (Jani) +- Fixed bug #28976 (mail(): use "From:" from headers if sendmail_from is empty). + (Jani) +- Fixed bug #28930 (PHP sources pick wrong header files generated by bison). + (eggert at gnu dot org, Jani) +- Fixed bug #28840 (__destruct of a class that extends mysqli not called). + (Marcus) +- Fixed bug #28804 (ini-file section parsing pattern is buggy). + (wendland at scan-plus dot de) +- Fixed bug #28451 (corrupt EXIF headers have unlimited recursive IFD directory + entries). (Andrei) +- Fixed bug #28444 (Cannot access undefined property for object with overloaded + property access). (Dmitry) +- Fixed bug #28442 (Changing a static variables in a class changes it across + sub/super classes.) (Marcus) +- Fixed bug #28324 (HTTP_SESSION_VARS appear when register_long_arrays is + Off). (Tony) +- Fixed bug #28074 (FastCGI: stderr should be written in a FCGI stderr stream). + (chris at ex-parrot dot com) +- Fixed bug #28067 (partially incorrect utf8 to htmlentities mapping). (Derick, + Benjamin Greiner) +- Fixed bug #28041 (SOAP HTTP Digest Access Authentication). (Dmitry) +- Fixed bug #27633 (Double \r problem on ftp_get in ASCII mode on Win32). (Ilia) +- Fixed bug #18613 (Multiple OUs in x509 certificate not handled properly). + (Jani) + +15 Dec 2004, PHP 5.0.3 +- Added the %F modifier to *printf to render a non-locale-aware representation + of a float with the . as decimal seperator. (Derick) +- Fixed error handling in mysqli_multi_query. (Georg) +- Extended the functionality of is_subclass_of() to accept either a class name + or an object as first parameter. (Andrey) +- Fixed potential problems with unserializing invalid serialize data. (Marcus) +- Fixed bug #32076 (ReflectionMethod::isDestructor() always return true). + (Derick, Tony) +- Fixed bug #31034 (Problem with non-existing iconv header file). (Derick) +- Fixed bug #30995 (snmp extension does not build with net-snmp 5.2). (Ilia) +- Fixed bug #30994 (SOAP server unable to handle request with references). + (Dmitry) +- Fixed bug #30990 (allow popen() on *NIX to accept 'b' flag). (Ilia) +- Fixed bug #30967 (properties in extended mysqli classes don't work). (Georg) +- Fixed bug #30928 (When Using WSDL, SoapServer doesn't handle private or + protected properties). (Dmitry) +- Fixed bug #30922 (reflective functions crash PHP when interfaces extend + themselves). (Tony, Dmitry) +- Fixed bug #30904 (segfault when recording soapclient into session). (Tony, + Dmitry) +- Fixed bug #30890 (MySQLi testsuite) +- Fixed bug #30856 (ReflectionClass::getStaticProperties segfaults). (Marcus) +- Fixed bug #30832 ("!" stripped off comments in xml parser). (Rob) +- Fixed bug #30799 (SoapServer doesn't handle private or protected properties). + (Dmitry) +- Fixed bug #30783 (Apache crash when using ReflectionFunction:: + getStaticVariables()). (Marcus) +- Fixed bug #30750 (Meaningful error message when upload directory is not + accessible). (Ilia) +- Fixed bug #30685 (Malformed SOAPClient http header reequest). (Dmitry) +- Fixed bug #30672 (Problem handling exif data in jpeg images at unusual + places). (Marcus) +- Fixed bug #30658 (Ensure that temporary files created by GD are removed). + (Ilia) +- Fixed bug #30645 (def. multi result set support for mysql_connect). (Georg) +- Fixed bug #30637 (compile with pear error). (Antony) +- Fixed bug #30587 (array_multisort doesn't separate zvals before + changing them). (Tony) +- Fixed bug #30572 (crash when comparing SimpleXML attribute to a boolean). + (Andi) +- Fixed bug #30566 (attribute namespace URIs are inconsistent when parsing). + (Rob) +- Fixed bug #30490 (PEAR installation fails). (Antony) +- Fixed bug #30475 (curl_getinfo() may crash in some situations). (Ilia) +- Fixed bug #30442 (segfault when parsing ?getvariable[][ ). (Tony) +- Fixed bug #30388 (rename across filesystems loses ownership and + permission info). (Tony) +- Fixed bug #30387 (stream_socket_client async connect was broken). + (vnegrier at esds dot com, Wez). +- Fixed bug #30381 (Strange results with get_class_vars()). (Marcus) +- Fixed bug #30375 (cal_info() does not work without a parameter). (Ilia) +- Fixed bug #30362 (stream_get_line() not handling end string correctly). + (Ilia) +- Fixed bug #30359 (SOAP client requests have no port in "Host" field). + (Dmitry) +- Fixed bug #30356 (str_ireplace() does not work on all strings). (Ilia) +- Fixed bug #30344 (Reflection::getModifierNames() returns too long strings). + (Marcus) +- Fixed bug #30329 (Error Fetching http body, No Content-Length, connection + closed or chunked data). (Dmitry) +- Fixed bug #30282 (segfault when using unknown/unsupported + session.save_handler and/or session.serialize_handler). (Tony) +- Fixed bug #30281 (Prevent non-wbmp images from being detected as such). + (Ilia) +- Fixed bug #30276 (Possible crash in ctype_digit on large numbers). (Ilia) +- Fixed bug #30230 (exception handler not working with objects). (Marcus) +- Fixed bug #30224 (Sybase date strings are sometimes not null terminated). + (Ilia) +- Fixed bug #30175 (SOAP results aren't parsed correctly). (Dmitry) +- Fixed bug #30147 (OO sqlite_fetch_object did not reset error handler). (Wez) +- Fixed bug #30133 (get_current_user() crashes on Windows). (Edin) +- Fixed bug #30061 (xml_set_start_namespace_decl_handler not called). (Rob) +- Fixed bug #30057 (did not detect IPV6 on FreeBSD 4.1). (Wez) +- Fixed bug #30042 (strtotime does not use second param). (Derick) +- Fixed bug #30027 (Possible crash inside ftp_get()). + (cfield at affinitysolutions dot com) +- Fixed bug #29954 (array_reduce segfaults when initial value is array). (Tony) +- Fixed bug #29883 (isset gives invalid values on strings). (Tony, Dmitry) +- Fixed bug #29801 (Set limit on the size of mmapable data). (Ilia) +- Fixed bug #29557 (strtotime error). (Derick) +- Fixed bug #29418 (double free when openssl_csr_new fails). + (Kamesh Jayachandran). +- Fixed bug #29385 (Soapserver always uses std class). (David, Dmitry) +- Fixed bug #29211 (SoapClient doesn't request wsdl through proxy). (Rob) +- Fixed bug #28817 (Var problem when extending domDocument). (Georg) +- Fixed bug #28599 (strtotime fails with zero base time). (Derick) +- Fixed bug #28598 (Lost support for MS Symbol fonts). (Pierre) +- Fixed bug #28220 (mb_strwidth() returns wrong width values for some hangul + characters). (Moriyoshi) +- Fixed bug #28228 (NULL decimal separator is not being handled correctly). + (Ilia) +- Fixed bug #28209 (strtotime("now")). (Derick) +- Fixed bug #27798 (private / protected variables not exposed by + get_object_vars() inside class). (Marcus) +- Fixed bug #27728 (Can't return within a zend_try {} block or the previous + bailout state isn't restored. (Andi) +- Fixed bug #27183 (Userland stream wrapper segfaults on stream_write). + (Christian) + +23 Sep 2004, PHP 5.0.2 +- Added new boolean (fourth) parameter to array_slice() that turns on the + preservation of keys in the returned array. (Derick) +- Added the sorting flag SORT_LOCALE_STRING to the sort() functions which makes + them sort based on the current locale. (Derick) +- Added interface_exists() and make class_exists() only return true for real + classes. (Andrey) +- Added PHP_EOL constant that contains the OS way of representing newlines. + (Paul Hudson, Derick) +- Implemented periodic PCRE compiled regexp cache cleanup, to avoid memory + exhaustion. (Andrei) +- Renamed SoapClient->__call() to SoapClinet->__soapCall(). (Dmitry) +- Fixed bug with raw_post_data not getting set (Brian) +- Fixed a file-descriptor leak with phpinfo() and other 'special' URLs (Zeev) +- Fixed bug #30209 (ReflectionClass::getMethod() lowercases attribute). + (Marcus) +- Fixed bug #30182 (SOAP module processing WSDL file dumps core). (Dmitry) +- Fixed bug #30045 (Cannot pass big integers (> 2147483647) in SOAP requests). + (Dmitry) +- Fixed bug #29985 (unserialize()/ __PHP_Incomplete_class does not report + correctly class name). (Marcus, Tony) +- Fixed bug #29945 (simplexml_load_file URL limitation 255 char). (Rob) +- Fixed bug #29873 (No defines around pcntl_*priority definitions). (Derick) +- Fixed bug #29844 (SOAP doesn't return the result of a valid SOAP request). + (Dmitry) +- Fixed bug #29842 (soapclient return null value). (Dmitry) +- Fixed bug #29839 (incorrect convert (xml:lang to lang)). (Dmitry) +- Fixed bug #29830 (SoapServer::setClass() should not export non-public + methods). (Dmitry) +- Fixed bug #29828 (Interfaces no longer work). (Marcus) +- Fixed bug #29821 (Fixed possible crashes in convert_uudecode() on invalid + data). (Ilia) +- Fixed bug #29808 (array_count_values() breaks with numeric strings). (Ilia) +- Fixed bug #29805 (HTTP Authentication Issues). (Uwe Schindler) +- Fixed bug #29795 (SegFault with Soap and Amazon's Web Services). (Dmitry) +- Fixed bug #29737 (ip2long should return -1 if IP is 255.255.255.255 and FALSE + on error). (Tony) +- Fixed bug #29711 (Changed ext/xml to default to UTF-8 output). (Rob) +- Fixed bug #29678 (opendir() with ftp:// wrapper segfaults if path does not + have trailing slash). (Ilia) +- Fixed bug #29657 (xml_* functions throw non descriptive error). + (Christian, Rob) +- Fixed bug #29656 (segfault on result and statement properties). (Georg) +- Fixed bug #29566 (foreach/string handling strangeness (crash)). (Dmitry) +- Fixed bug #29447 (Reflection API issues). (Marcus) +- Fixed bug #29296 (Added sslv2 and sslv3 transports). (Wez) +- Fixed bug #29283 (Invalid statement handle in mysqli on execute). (Georg) +- Fixed bug #29913 (parse_url() is now binary safe). (Ilia) +- Fixed bug #27994 (segfault with Soapserver when WSDL-Cache is enabled). + (Dmitry) +- Fixed bug #27791 (Apache 2.0 SAPI build against Apache 2 HEAD). (Joe Orton, + Derick) +- Fixed bug #26737 (private/protected properties not serialized when user + declared method __sleep() exists). E_NOTICE thrown when __sleep() returns + name of non-existing member. (Andrey, Curt) + +12 Aug 2004, PHP 5.0.1 +- Changed destructor mechanism so that destructors are called prior to request + shutdown. (Marcus) +- Rewritten UNIX and Windows install help files. (Documentation Team) +- Updated several libraries bundled with the windows release which now + includes libxml2-2.6.11, libxslt-1.1.7 and iconv-1.9.1. (Rob, Edin) +- Improved and moved ActiveScript SAPI to PECL. (Wez) +- Fixed bug #29606 (php_strip_whitespace() prints to stdout rather then + returning the value). (Ilia) +- Fixed bug #29577 (MYSQLI_CLIENT_FOUND_ROWS undefined) (Georg) +- Fixed bug #29573 (Segmentation fault, when exception thrown within + PHP function called from XSLT). (Christian) +- Fixed bug #29522 (accessing properties without connection) (Georg) +- Fixed bug #29505 (get_class_vars() severely broken when used with arrays). + (Marcus) +- Fixed bug #29490 (.Net object instantiation failed). (Michael Sisolak). +- Fixed bug #29474 (win32: usleep() doesn't work). (Wez) +- Fixed bug #29449 (win32: feof() hangs on empty tcp stream). (Wez) +- Fixed bug #29437 (Possible crash inside array_walk_recursive()). (Ilia) +- Fixed bug #29431 (crash when parsing invalid address; invalid address + returned by stream_socket_recvfrom(), stream_socket_getname()). (Wez) +- Fixed bug #29409 (Segfault in PHP functions called from XSLT). (Rob) +- Fixed unloading of dynamically loaded extensions. + (Marcus, kameshj at fastmail dot fm) +- Fixed bug #29395 (sqlite_escape_string() returns bogus data on empty + strings). (Ilia, Tony) +- Fixed bug #29392 (com_dotnet crashes when echo'ing an object). (Wez) +- Fixed bug #29368 (The destructor is called when an exception is thrown from + the constructor). (Marcus) +- Fixed bug #29354 (Exception constructor marked as both public and protected). + (Marcus) +- Fixed bug #29342 (strtotime() does not handle empty date string properly). + (Ilia) +- Fixed bug #29340 (win32 build produces invalid php_ifx.dll). (Edin) +- Fixed bug #29335 (fetch functions now use MYSQLI_BOTH as default) (Georg) +- Fixed bug #29291 (get_class_vars() return names with NULLs). (Marcus) +- Fixed bug #29264 (gettext extension not working). (Edin) +- Fixed bug #29258 (variant_date_from_timestamp() does not honour + timezone). (Wez) +- Fixed bug #29256 (error when sending large packets on a socket). (Dmitry) +- Fixed bug #29236 (memory error when wsdl-cache is enabled). (Dmitry) +- Fixed bug #29147 (Compile Error in mnoGoSearch functions). (Sergey, Antony) +- Fixed bug #29132 ($_SERVER["PHP_AUTH_USER"] isn't defined). (Stefan) +- Fixed bug #29119 (html_entity_decode() misbehaves with UTF-8). (Moriyoshi) +- Fixed bug #29109 (SoapFault exception: [WSDL] Out of memory). (Dmitry) +- Fixed bug #29061 (soap extension segfaults). (Dmitry) +- Fixed bug #28985 (__getTypes() returning nothing on complex WSDL). (Dmitry) +- Fixed bug #28969 (Wrong data encoding of special characters). (Dmitry) +- Fixed bug #28895 (ReflectionClass::isAbstract always returns false). (Marcus) - Fixed bug #28829 (Thread-unsafety in bcmath elementary values). (Sara) +- Fixed bug #28464 (catch() does not catch exceptions by interfaces). (Marcus) +- Fixed bug #27669 (PHP 5 didn't support all possibilities for calling static + methods dynamically). (Dmitry) +- Fixed ReflectionClass::getMethod() and ReflectionClass::getProperty() to + raise an ReflectionException instead of returning NULL on failure. + (Sebastian) +- Fixed convert.* filters to consume remaining buckets_in on flush. (Sara) +- Fixed bug in mysqli->client_version. (Georg) 13 Jul 2004, PHP 5.0.0 - Updated PCRE to provide better error handling in certain cases. (Andrei) @@ -10,7 +642,6 @@ PHP NEWS - Fixed bug #29008 (array_combine() does not handle non-numeric/string keys). (Ilia) - Fixed bug #28999 (fixed behaviour of exec() to work as it did in 4.X). (Ilia) -- Fixed bug #28895 (ReflectionClass::isAbstract always returns false). (Marcus) - Fixed bug #28868 (Internal filter registry not thread safe). (Sara) - Fixed bug #28851 (call_user_func_array has typo in error message). (Marcus) - Fixed bug #28831 (ArrayObject::offsetGet() does the work of offsetUnset()). @@ -27,7 +658,6 @@ PHP NEWS - Fixed bug #28699 (Reflection api bugs). (Marcus) - Fixed bug #28694 (ReflectionExtension::getFunctions() crashes PHP). (Marcus) - Fixed bug #28512 (Allocate enough space to store MSSQL data). (Frank) -- Fixed bug #28325 (Circular references not properly serialised). (Moriyoshi) - Fixed strip_tags() to correctly handle '\0' characters. (Stefan) 7 Jun 2004, PHP 5 Release Candidate 3 @@ -112,7 +742,6 @@ PHP NEWS - Fixed bug #27619 (filters not applied to pre-buffered stream data). (Sara) - Fixed bug #27519 (Reflection_Function constructor crashes with non-existant function's name). (Marcus) -- Fixed bug #27469 (serialize() objects of incomplete class). (Dmitry) - Fixed bug #27457 (handling of numeric indexes in strtr()). (Dmitry) - Fixed bug #27397 (debug_backtrace() not showing function arguments). (Zeev) - Fixed bug #27283 (The last catch statement was sometimes skipped). (Andi) diff --git a/README.CVS-RULES b/README.CVS-RULES index d661edd4f440..8e3641b28bf4 100644 --- a/README.CVS-RULES +++ b/README.CVS-RULES @@ -29,7 +29,14 @@ Having said that, here are the organizational rules: 5. If you don't know how to do something, ask first! 6. Test your changes before committing them. We mean it. Really. - + +Currently we have the following branches in use: +HEAD Will become PHP 5.1. This CVS branch is for active development. +PHP_5_0 Is used to release the PHP 5.0.x series. Only minor feature + enhancements may go in here, but please keep that as infrequent as + possible. +PHP_4_3 Is used to release the PHP 4.3.x series. Only bugfixes are permitted + on this branch. The next few rules are more of a technical nature. @@ -37,8 +44,11 @@ The next few rules are more of a technical nature. messages every day. Woe be to those who attempt to mess with it. 2. All news updates intended for public viewing, such as new features, - bug fixes, improvements, etc., should go into the NEWS file. Also see - the note below about automatically updating NEWS in your commit message. + bug fixes, improvements, etc., should go into the NEWS file. + + NB! Lines, starting with @ will go automagically into NEWS file, but + this is NOT recommended, though. Please, add news entries directly to + NEWS file and don't forget to keep them adjusted and sorted. 3. Do not commit multiple file and dump all messages in one commit. If you modified several unrelated files, commit each group separately and @@ -58,37 +68,29 @@ The next few rules are more of a technical nature. The format of the commit messages is pretty simple. +Use a - to start a new item in your commit message. + If a line begins with #, it is taken to be a comment and will not appear -in the ChangeLog. If the line begins with @, it will be redirected to the -NEWS file. Everything else goes into the ChangeLog. +in the ChangeLog. Everything else goes into the ChangeLog. It is important to note that if your comment or news logline spans multiple -lines, you have to put # or @ at the beginning of _every_ such line. Every -entry in NEWS has to have a name after it, so if you did it with someone's -help, put both your names there. Your name WILL NOT be automatically put -at the end of the NEWS entry - so, please provide it yourself. - -Example. Say you modified two files, datetime.c and string.c. In datetime.c -you added a new format option for date() function, and in string.c you fixed -a memory leak in php_trim(). Don't commit both of these at once. Commit them +lines, you have to put # at the beginning of _every_ such line. + +Example. Say you modified two files, datetime.c and string.c. In datetime.c you +added a new format option for the date() function, and in string.c you fixed a +memory leak in php_trim(). Don't commit both of these at once. Commit them separately and try to make sure your commit messages look something like the following. For datetime.c: - -(PHP date) Added new 'K' format modifier for printing out number of - days until New Year's Eve. -@- Added new 'K' format modifier that will output the number of days -@ until New Year's Eve. (Bob) +- Added new 'K' format modifier to date() for printing out number of days until + New Year's Eve. For string.c: -(php_trim) Fixed a memory leak resulting from improper use of zval_dtor(). -# Man, that thing was leaking all over the place! -@- Fixed memory leak in trim(). (Bob) +- Fixed a memory leak in php_trim() resulting from improper use of zval_dtor(). +#- Man, that thing was leaking all over the place! -The lines above marked with @ will go into NEWS file automagically, and the -# lines will be omitted from the ChangeLog. Alternatively, you might want -to modify NEWS file directly and not use the @ lines. +The # lines will be omitted from the ChangeLog automagically. If you fix some bugs, you should note the bug ID numbers in your commit message. Bug ID should be prefixed by "#" for easier access to @@ -96,13 +98,11 @@ bug report when developers are browsing CVS via. LXR or Bonsai. Example: -Fixed pgsql notice handler double free crash bug. Bug #14016 -@ Fixed pgsql notice handler double free crash bug. Bug #14016 +Fixed bug #14016 (pgsql notice handler double free crash bug.) -If you don't see your messages in ChangeLog and NEWS right away, don't worry! +If you don't see your messages in ChangeLog right away, don't worry! These files are updated once a day, so your stuff will not show up until -somewhat later. Don't go adding stuff to NEWS by hand if you already put @ -lines in the commit message. +somewhat later. You can use LXR (http://lxr.php.net/) and Bonsai (http://bonsai.php.net/) to look at PHP CVS repository in various ways. diff --git a/README.PHP4-TO-PHP5-THIN-CHANGES b/README.PHP4-TO-PHP5-THIN-CHANGES index 149772f2e5d6..0a2c6d665713 100644 --- a/README.PHP4-TO-PHP5-THIN-CHANGES +++ b/README.PHP4-TO-PHP5-THIN-CHANGES @@ -77,20 +77,24 @@ 9. get_class() starting PHP 5 returns the name of the class as it was declared which may lead to problems in older scripts that rely on - the previous behaviour - the class name is lowercased. + the previous behaviour - the class name is lowercased. Expect the + same behaviour from get_parent_class() when applicable. Example : Output (PHP 4): string(6) "foobar" + string(9) "extfoobar" Output (PHP 5): string(6) "FooBar" + string(9) "ExtFooBar" ---------------------------------------------------------------------- Example code that will break : //.... @@ -101,7 +105,51 @@ //... } //... - Possible solution is to search for get_class() in all your scripts and - use strtolower(). + Possible solution is to search for get_class() and get_parent_class() in + all your scripts and use strtolower(). + +10. get_class_methods() returns the names of the methods of a class as they + declared. In PHP4 the names are all lowercased. + Example code : + + Output (PHP4): + array(2) { + [0]=> + string(5) "dofoo" + [1]=> + string(6) "hasfoo" + } + Output (PHP5): + array(2) { + [0]=> + string(5) "doFoo" + [1]=> + string(6) "hasFoo" + } + +11. Assignment $this is impossible. Starting PHP 5.0.0 $this has special + meaning in class methods and is recognized by the PHP parser. The latter + will generate a parse error when assignment to $this is found + Example code : + assignNew($b); + echo "I was executed\n"; + ?> + Output (PHP 4): + I was executed + Output (PHP 5): + PHP Fatal error: Cannot re-assign $this in /tmp/this_ex.php on line 4 - \ No newline at end of file diff --git a/TSRM/TSRM.c b/TSRM/TSRM.c index 8dd1c98e4563..cbbf060101d3 100644 --- a/TSRM/TSRM.c +++ b/TSRM/TSRM.c @@ -296,11 +296,11 @@ static void allocate_new_resource(tsrm_tls_entry **thread_resources_ptr, THREAD_ } } - tsrm_mutex_unlock(tsmm_mutex); - if (tsrm_new_thread_end_handler) { tsrm_new_thread_end_handler(thread_id, &((*thread_resources_ptr)->storage)); } + + tsrm_mutex_unlock(tsmm_mutex); } @@ -481,13 +481,6 @@ TSRM_API THREAD_T tsrm_thread_id(void) { #ifdef TSRM_WIN32 return GetCurrentThreadId(); -#elif defined(NETWARE) - /* There seems to be some problem with the LibC call: NXThreadGetId(). - * Due to this, the PHPMyAdmin application is abending in PHP calls. - * Used the call, kCurrentThread instead and it works fine. - */ -/* return NXThreadGetId(); */ - return kCurrentThread(); #elif defined(GNUPTH) return pth_self(); #elif defined(PTHREADS) @@ -508,24 +501,9 @@ TSRM_API THREAD_T tsrm_thread_id(void) TSRM_API MUTEX_T tsrm_mutex_alloc(void) { MUTEX_T mutexp; -#ifdef NETWARE -#ifndef USE_MPK - /* To use the Recursive Mutex Locking of LibC */ - long flags = NX_MUTEX_RECURSIVE; - NXHierarchy_t order = 0; - NX_LOCK_INFO_ALLOC (lockInfo, "PHP-TSRM", 0); -#endif -#endif - #ifdef TSRM_WIN32 mutexp = malloc(sizeof(CRITICAL_SECTION)); InitializeCriticalSection(mutexp); -#elif defined(NETWARE) -#ifdef USE_MPK - mutexp = kMutexAlloc((BYTE*)"PHP-TSRM"); -#else - mutexp = NXMutexAlloc(flags, order, &lockInfo); -#endif #elif defined(GNUPTH) mutexp = (MUTEX_T) malloc(sizeof(*mutexp)); pth_mutex_init(mutexp); @@ -557,12 +535,6 @@ TSRM_API void tsrm_mutex_free(MUTEX_T mutexp) #ifdef TSRM_WIN32 DeleteCriticalSection(mutexp); free(mutexp); -#elif defined(NETWARE) -#ifdef USE_MPK - kMutexFree(mutexp); -#else - NXMutexFree(mutexp); -#endif #elif defined(GNUPTH) free(mutexp); #elif defined(PTHREADS) @@ -592,12 +564,6 @@ TSRM_API int tsrm_mutex_lock(MUTEX_T mutexp) #ifdef TSRM_WIN32 EnterCriticalSection(mutexp); return 1; -#elif defined(NETWARE) -#ifdef USE_MPK - return kMutexLock(mutexp); -#else - return NXLock(mutexp); -#endif #elif defined(GNUPTH) return pth_mutex_acquire(mutexp, 0, NULL); #elif defined(PTHREADS) @@ -623,12 +589,6 @@ TSRM_API int tsrm_mutex_unlock(MUTEX_T mutexp) #ifdef TSRM_WIN32 LeaveCriticalSection(mutexp); return 1; -#elif defined(NETWARE) -#ifdef USE_MPK - return kMutexUnlock(mutexp); -#else - return NXUnlock(mutexp); -#endif #elif defined(GNUPTH) return pth_mutex_release(mutexp); #elif defined(PTHREADS) diff --git a/TSRM/TSRM.h b/TSRM/TSRM.h index 87f5ad94b745..a66353b88f9a 100644 --- a/TSRM/TSRM.h +++ b/TSRM/TSRM.h @@ -14,8 +14,8 @@ #define TSRM_H /* #ifndef WIN32 */ -#if !defined(WIN32) && !defined(NETWARE) -# include "tsrm_config.h" +#ifndef WIN32 +# include #endif #ifdef WIN32 @@ -42,13 +42,6 @@ # endif # include # include -#elif defined(NETWARE) -# include -#ifdef USE_MPK -# include -#else -# include -#endif #elif defined(GNUPTH) # include #elif defined(PTHREADS) @@ -66,13 +59,6 @@ typedef int ts_rsrc_id; #ifdef TSRM_WIN32 # define THREAD_T DWORD # define MUTEX_T CRITICAL_SECTION * -#elif defined(NETWARE) -# define THREAD_T NXThreadId_t -#ifdef USE_MPK -# define MUTEX_T MUTEX -#else -# define MUTEX_T NXMutex_t * -#endif #elif defined(GNUPTH) # define THREAD_T pth_t # define MUTEX_T pth_mutex_t * diff --git a/TSRM/acinclude.m4 b/TSRM/acinclude.m4 index 1953172aef48..fcf97fd352ee 100644 --- a/TSRM/acinclude.m4 +++ b/TSRM/acinclude.m4 @@ -1,5 +1,5 @@ -AC_DEFUN(AM_SET_LIBTOOL_VARIABLE,[ +AC_DEFUN([AM_SET_LIBTOOL_VARIABLE],[ LIBTOOL='$(SHELL) $(top_builddir)/libtool $1' ]) diff --git a/TSRM/threads.m4 b/TSRM/threads.m4 index 790579656e86..d38841ddfa71 100644 --- a/TSRM/threads.m4 +++ b/TSRM/threads.m4 @@ -30,7 +30,7 @@ dnl PTHREADS_FLAGS dnl dnl Set some magic defines to achieve POSIX threads conformance dnl -AC_DEFUN(PTHREADS_FLAGS,[ +AC_DEFUN([PTHREADS_FLAGS],[ if test -z "$host_alias" && test -n "$host"; then host_alias=$host fi @@ -65,7 +65,7 @@ dnl PTHREADS_CHECK_COMPILE dnl dnl Check whether the current setup can use POSIX threads calls dnl -AC_DEFUN(PTHREADS_CHECK_COMPILE, [ +AC_DEFUN([PTHREADS_CHECK_COMPILE], [ AC_TRY_RUN( [ #include #include @@ -84,7 +84,15 @@ int main() { pthreads_working=yes ], [ pthreads_working=no - ], pthreads_working=no ) ] )dnl + ], [ + dnl For cross compiling running this test is of no use. NetWare supports pthreads + pthreads_working=no + case $host_alias in + *netware*) + pthreads_working=yes + esac +] +) ] )dnl dnl dnl PTHREADS_CHECK() dnl @@ -100,7 +108,7 @@ dnl -pthreads gcc (Solaris) dnl -qthreaded AIX cc V5 dnl -threads gcc (HP-UX) dnl -AC_DEFUN(PTHREADS_CHECK,[ +AC_DEFUN([PTHREADS_CHECK],[ if test "$beos_threads" = "1"; then pthreads_working="yes" @@ -154,7 +162,7 @@ fi ])dnl dnl dnl -AC_DEFUN(PTHREADS_ASSIGN_VARS,[ +AC_DEFUN([PTHREADS_ASSIGN_VARS],[ if test -n "$ac_cv_pthreads_lib"; then LIBS="$LIBS -l$ac_cv_pthreads_lib" fi diff --git a/TSRM/tsrm.m4 b/TSRM/tsrm.m4 index 291b7f2e4ef4..a06c2a694d55 100644 --- a/TSRM/tsrm.m4 +++ b/TSRM/tsrm.m4 @@ -1,6 +1,6 @@ dnl TSRM_CHECK_GCC_ARG(ARG, ACTION-IF-FOUND, ACTION-IF-NOT_FOUND) -AC_DEFUN(TSRM_CHECK_GCC_ARG,[ +AC_DEFUN([TSRM_CHECK_GCC_ARG],[ gcc_arg_name=[ac_cv_gcc_arg]translit($1,A-Z-,a-z_) AC_CACHE_CHECK([whether $CC supports $1], [ac_cv_gcc_arg]translit($1,A-Z-,a-z_), [ echo 'void somefunc() { };' > conftest.c @@ -21,7 +21,7 @@ AC_DEFUN(TSRM_CHECK_GCC_ARG,[ fi ]) -AC_DEFUN(TSRM_BASIC_CHECKS,[ +AC_DEFUN([TSRM_BASIC_CHECKS],[ AC_REQUIRE([AC_PROG_CC])dnl dnl AC_REQUIRE([AM_PROG_CC_STDC])dnl @@ -33,7 +33,7 @@ AC_CHECK_HEADERS(stdarg.h) ]) -AC_DEFUN(TSRM_CHECK_PTH,[ +AC_DEFUN([TSRM_CHECK_PTH],[ AC_MSG_CHECKING(for GNU Pth) PTH_PREFIX="`$1 --prefix`" @@ -50,7 +50,7 @@ AC_MSG_RESULT(yes - installed in $PTH_PREFIX) ]) -AC_DEFUN(TSRM_CHECK_ST,[ +AC_DEFUN([TSRM_CHECK_ST],[ if test -r "$1/include/st.h"; then CPPFLAGS="$CPPFLAGS -I$1/include" LDFLAGS="$LDFLAGS -L$1/lib" @@ -70,7 +70,7 @@ AC_DEFUN(TSRM_CHECK_ST,[ sinclude(threads.m4) sinclude(TSRM/threads.m4) -AC_DEFUN(TSRM_CHECK_PTHREADS,[ +AC_DEFUN([TSRM_CHECK_PTHREADS],[ PTHREADS_CHECK @@ -89,7 +89,7 @@ fi ]) -AC_DEFUN(TSRM_THREADS_CHECKS,[ +AC_DEFUN([TSRM_THREADS_CHECKS],[ dnl For the thread implementations, we always use --with-* dnl to maintain consistency diff --git a/TSRM/tsrm_config_common.h b/TSRM/tsrm_config_common.h index 9930a51a69b1..bdd171e61904 100644 --- a/TSRM/tsrm_config_common.h +++ b/TSRM/tsrm_config_common.h @@ -7,10 +7,8 @@ #ifdef TSRM_WIN32 # include "tsrm_config.w32.h" -#elif defined(NETWARE) -# include "tsrm_config.nw.h" #else -# include "tsrm_config.h" +# include # include #endif diff --git a/TSRM/tsrm_virtual_cwd.c b/TSRM/tsrm_virtual_cwd.c index d0c741faaeb0..4059992fb0df 100644 --- a/TSRM/tsrm_virtual_cwd.c +++ b/TSRM/tsrm_virtual_cwd.c @@ -42,8 +42,7 @@ #endif #ifdef NETWARE -/*#include "pipe.h"*/ -#include "tsrm_nw.h" +#include #endif #ifndef HAVE_REALPATH @@ -142,15 +141,9 @@ static int php_check_dots(const char *element, int n) static int php_is_dir_ok(const cwd_state *state) { -#if !(defined(NETWARE) && defined(CLIB_STAT_PATCH)) struct stat buf; if (stat(state->cwd, &buf) == 0 && S_ISDIR(buf.st_mode)) -#else - struct stat_libc buf; - - if (stat(state->cwd, (struct stat*)(&buf)) == 0 && S_ISDIR(buf.st_mode)) -#endif return (0); return (1); @@ -158,15 +151,9 @@ static int php_is_dir_ok(const cwd_state *state) static int php_is_file_ok(const cwd_state *state) { -#if !(defined(NETWARE) && defined(CLIB_STAT_PATCH)) struct stat buf; if (stat(state->cwd, &buf) == 0 && S_ISREG(buf.st_mode)) -#else - struct stat_libc buf; - - if (stat(state->cwd, (struct stat*)(&buf)) == 0 && S_ISREG(buf.st_mode)) -#endif return (0); return (1); @@ -202,7 +189,20 @@ CWD_API void virtual_cwd_startup(void) char cwd[MAXPATHLEN]; char *result; +#ifdef NETWARE + result = getcwdpath(cwd, NULL, 1); + if(result) + { + char *c=cwd; + while(c = strchr(c, '\\')) + { + *c='/'; + ++c; + } + } +#else result = getcwd(cwd, sizeof(cwd)); +#endif if (!result) { cwd[0] = '\0'; } @@ -308,15 +308,22 @@ CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func if (path_length == 0) return (0); + if (path_length >= MAXPATHLEN) + return (1); #if !defined(TSRM_WIN32) && !defined(NETWARE) /* cwd_length can be 0 when getcwd() fails. * This can happen under solaris when a dir does not have read permissions * but *does* have execute permissions */ if (IS_ABSOLUTE_PATH(path, path_length) || (state->cwd_length < 1)) { - if (use_realpath && realpath(path, resolved_path)) { - path = resolved_path; - path_length = strlen(path); + if (use_realpath) { + if (realpath(path, resolved_path)) { + path = resolved_path; + path_length = strlen(path); + } else { + /* disable for now + return 1; */ + } } } else { /* Concat current directory with relative path and then run realpath() on it */ char *tmp; @@ -332,9 +339,19 @@ CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func memcpy(ptr, path, path_length); ptr += path_length; *ptr = '\0'; - if (use_realpath && realpath(tmp, resolved_path)) { - path = resolved_path; - path_length = strlen(path); + if (strlen(tmp) >= MAXPATHLEN) { + free(tmp); + return 1; + } + if (use_realpath) { + if (realpath(tmp, resolved_path)) { + path = resolved_path; + path_length = strlen(path); + } else { + /* disable for now + free(tmp); + return 1; */ + } } free(tmp); } @@ -428,8 +445,19 @@ CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func state->cwd[state->cwd_length++] = DEFAULT_SLASH; } #elif defined(NETWARE) - /* If the token is a volume name, it will have colon at the end -- so, no slash before it */ - if (ptr[ptr_length-1] != ':') { + /* + Below code keeps appending to state->cwd a File system seperator + cases where this appending should not happen is given below, + a) sys: should just be left as it is + b) sys:system should just be left as it is, + Colon is allowed only in the first token as volume names alone can have the : in their names. + Files and Directories cannot have : in their names + So the check goes like this, + For second token and above simply append the DEFAULT_SLASH to the state->cwd. + For first token check for the existence of : + if it exists don't append the DEFAULT_SLASH to the state->cwd. + */ + if(((state->cwd_length == 0) && (strchr(ptr, ':') == NULL)) || (state->cwd_length > 0)) { state->cwd[state->cwd_length++] = DEFAULT_SLASH; } #else @@ -699,7 +727,6 @@ CWD_API int virtual_rename(char *oldname, char *newname TSRMLS_DC) return retval; } -#if !(defined(NETWARE) && defined(CLIB_STAT_PATCH)) CWD_API int virtual_stat(const char *path, struct stat *buf TSRMLS_DC) { cwd_state new_state; @@ -713,23 +740,8 @@ CWD_API int virtual_stat(const char *path, struct stat *buf TSRMLS_DC) CWD_STATE_FREE(&new_state); return retval; } -#else -CWD_API int virtual_stat(const char *path, struct stat_libc *buf TSRMLS_DC) -{ - cwd_state new_state; - int retval; - - CWD_STATE_COPY(&new_state, &CWDG(cwd)); - virtual_file_ex(&new_state, path, NULL, 1); - - retval = stat(new_state.cwd, (struct stat*)buf); - - CWD_STATE_FREE(&new_state); - return retval; -} -#endif -#if !defined(TSRM_WIN32) && !defined(NETWARE) +#ifndef TSRM_WIN32 CWD_API int virtual_lstat(const char *path, struct stat *buf TSRMLS_DC) { cwd_state new_state; @@ -851,13 +863,24 @@ CWD_API FILE *virtual_popen(const char *command, const char *type TSRMLS_DC) CWD_API FILE *virtual_popen(const char *command, const char *type TSRMLS_DC) { int command_length; + int dir_length, extra = 0; char *command_line; - char *ptr; + char *ptr, *dir; FILE *retval; command_length = strlen(command); - ptr = command_line = (char *) malloc(command_length + sizeof("cd ; ") + CWDG(cwd).cwd_length+1); + dir_length = CWDG(cwd).cwd_length; + dir = CWDG(cwd).cwd; + while (dir_length > 0) { + if (*dir == '\'') extra+=3; + dir++; + dir_length--; + } + dir_length = CWDG(cwd).cwd_length; + dir = CWDG(cwd).cwd; + + ptr = command_line = (char *) malloc(command_length + sizeof("cd '' ; ") + dir_length +extra+1+1); if (!command_line) { return NULL; } @@ -867,8 +890,21 @@ CWD_API FILE *virtual_popen(const char *command, const char *type TSRMLS_DC) if (CWDG(cwd).cwd_length == 0) { *ptr++ = DEFAULT_SLASH; } else { - memcpy(ptr, CWDG(cwd).cwd, CWDG(cwd).cwd_length); - ptr += CWDG(cwd).cwd_length; + *ptr++ = '\''; + while (dir_length > 0) { + switch (*dir) { + case '\'': + *ptr++ = '\''; + *ptr++ = '\\'; + *ptr++ = '\''; + /* fall-through */ + default: + *ptr++ = *dir; + } + dir++; + dir_length--; + } + *ptr++ = '\''; } *ptr++ = ' '; diff --git a/TSRM/tsrm_virtual_cwd.h b/TSRM/tsrm_virtual_cwd.h index bcfb9a08a7c3..33220896435b 100644 --- a/TSRM/tsrm_virtual_cwd.h +++ b/TSRM/tsrm_virtual_cwd.h @@ -74,10 +74,8 @@ typedef unsigned short mode_t; #define DEFAULT_DIR_SEPARATOR ';' #define IS_SLASH(c) ((c) == '/' || (c) == '\\') #define IS_SLASH_P(c) IS_SLASH(*(c)) -#define COPY_WHEN_ABSOLUTE(path) \ - (strchr(path, ':') - path + 1) /* Take the volume name which ends with a colon */ #define IS_ABSOLUTE_PATH(path, len) \ - (strchr(path, ':') != NULL) /* Colon indicates volume name */ + ((strchr(path, ':') != NULL) || ((len >= 1) && ((path[0] == '/') || (path[0] == '\\')))) #else #ifdef HAVE_DIRENT_H @@ -141,11 +139,7 @@ CWD_API FILE *virtual_fopen(const char *path, const char *mode TSRMLS_DC); CWD_API int virtual_open(const char *path TSRMLS_DC, int flags, ...); CWD_API int virtual_creat(const char *path, mode_t mode TSRMLS_DC); CWD_API int virtual_rename(char *oldname, char *newname TSRMLS_DC); -#if !(defined(NETWARE) && defined(CLIB_STAT_PATCH)) CWD_API int virtual_stat(const char *path, struct stat *buf TSRMLS_DC); -#else -CWD_API int virtual_stat(const char *path, struct stat_libc *buf TSRMLS_DC); -#endif #if !defined(TSRM_WIN32) && !defined(NETWARE) CWD_API int virtual_lstat(const char *path, struct stat *buf TSRMLS_DC); #endif @@ -229,7 +223,7 @@ typedef struct _virtual_cwd_globals { #define VCWD_REALPATH(path, real_path) virtual_realpath(path, real_path TSRMLS_CC) #define VCWD_RENAME(oldname, newname) virtual_rename(oldname, newname TSRMLS_CC) #define VCWD_STAT(path, buff) virtual_stat(path, buff TSRMLS_CC) -#if !defined(TSRM_WIN32) && !defined(NETWARE) +#ifndef TSRM_WIN32 #define VCWD_LSTAT(path, buff) virtual_lstat(path, buff TSRMLS_CC) #endif #define VCWD_UNLINK(path) virtual_unlink(path TSRMLS_CC) diff --git a/Zend/ChangeLog b/Zend/ChangeLog index aad5fccf8eff..20598f9d185e 100644 --- a/Zend/ChangeLog +++ b/Zend/ChangeLog @@ -6446,13 +6446,13 @@ 2003-02-08 Ilia Alshanetsky * zend_builtin_functions.c: - The string.h is already avaliable through zend.h, so the manual inclusion + The string.h is already available through zend.h, so the manual inclusion is not necessary. 2003-02-07 Ilia Alshanetsky * zend_builtin_functions.c: - Added a check to ensure that string.h is avaliable before trying to use it. + Added a check to ensure that string.h is available before trying to use it. Thanks Andi. diff --git a/Zend/Makefile.am b/Zend/Makefile.am index deff8aa15228..42ae4d542495 100644 --- a/Zend/Makefile.am +++ b/Zend/Makefile.am @@ -16,7 +16,8 @@ libZend_la_SOURCES=\ zend_ini.c zend_qsort.c zend_objects.c zend_object_handlers.c \ zend_objects_API.c zend_ts_hash.c zend_stream.c zend_mm.c \ zend_default_classes.c zend_reflection_api.c \ - zend_iterators.c zend_interfaces.c zend_exceptions.c + zend_iterators.c zend_interfaces.c zend_exceptions.c \ + zend_strtod.c zend_multibyte.c libZend_la_LDFLAGS = libZend_la_LIBADD = @ZEND_EXTRA_LIBS@ diff --git a/Zend/ZEND_CHANGES b/Zend/ZEND_CHANGES index 6508ccf91fc8..5208ce162392 100644 --- a/Zend/ZEND_CHANGES +++ b/Zend/ZEND_CHANGES @@ -545,7 +545,7 @@ Changes in the Zend Engine 2.0 message = $message; } @@ -890,6 +890,47 @@ Changes in the Zend Engine 2.0 the use of all abstract methods declared in the interfaces Iterator and IteratorAggregate respectively. + * Array overloading + + Objects can be used with Array notation when they implement the + interface ArrayAccess. You cannot use such objects in standard + array functions, however you have full control over the array + notation. This allows lazy initialization or read only array. + + Note that setting [] results in a call to offsetSet() with + index being NULL. That means that as with standard arrays you + cannot store NULL keys. + + Example: + + a); + } + function offsetGet($index) { + return $this->a[$index]; + } + function offsetSet($index, $newval) { + return $this->a[$index] = $newval; + } + function offsetUnset($index) { + unset($this->a[$index]); + } + } + + $obj = new ArrayClass; + + $obj[0] = 'bla'; // calls offsetSet(0,'bla') + $obj[] = 42; // calls offsetSet(NULL, 42) + $x = $obj[0]; // calls offsetGet(0) + $b = isset($obj[0]); // calls offsetExists(0) + unset($obj[0]); // calls offsetUnset(0) + ?> + + * __METHOD__ The pseudo constant __METHOD__ shows the current class and method diff --git a/Zend/Zend.dsp b/Zend/Zend.dsp index 6bf9b4341619..83791c0c4aef 100644 --- a/Zend/Zend.dsp +++ b/Zend/Zend.dsp @@ -7,20 +7,20 @@ CFG=Zend - Win32 Release_inline !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run -!MESSAGE +!MESSAGE !MESSAGE NMAKE /f "Zend.mak". -!MESSAGE +!MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE +!MESSAGE !MESSAGE NMAKE /f "Zend.mak" CFG="Zend - Win32 Release_inline" -!MESSAGE +!MESSAGE !MESSAGE Possible choices for configuration are: -!MESSAGE +!MESSAGE !MESSAGE "Zend - Win32 Release" (based on "Win32 (x86) Static Library") !MESSAGE "Zend - Win32 Debug" (based on "Win32 (x86) Static Library") !MESSAGE "Zend - Win32 Release_inline" (based on "Win32 (x86) Static Library") -!MESSAGE +!MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 @@ -95,7 +95,7 @@ LIB32=link.exe -lib # ADD BASE LIB32 /nologo # ADD LIB32 /nologo -!ENDIF +!ENDIF # Begin Target @@ -135,10 +135,6 @@ SOURCE=.\zend_default_classes.c # End Source File # Begin Source File -SOURCE=.\zend_interfaces.c -# End Source File -# Begin Source File - SOURCE=.\zend_dynamic_array.c # End Source File # Begin Source File @@ -179,6 +175,10 @@ SOURCE=.\zend_ini_scanner.c # End Source File # Begin Source File +SOURCE=.\zend_interfaces.c +# End Source File +# Begin Source File + SOURCE=".\zend_language_parser.c" # End Source File # Begin Source File @@ -243,6 +243,10 @@ SOURCE=.\zend_stream.c # End Source File # Begin Source File +SOURCE=.\zend_strtod.c +# End Source File +# Begin Source File + SOURCE=.\zend_ts_hash.c # End Source File # Begin Source File @@ -291,10 +295,6 @@ SOURCE=.\zend_default_classes.h # End Source File # Begin Source File -SOURCE=.\zend_interfaces.h -# End Source File -# Begin Source File - SOURCE=.\zend_dynamic_array.h # End Source File # Begin Source File @@ -351,6 +351,10 @@ SOURCE=.\zend_ini_scanner.h # End Source File # Begin Source File +SOURCE=.\zend_interfaces.h +# End Source File +# Begin Source File + SOURCE=.\zend_istdiostream.h # End Source File # Begin Source File @@ -415,6 +419,10 @@ SOURCE=.\zend_stream.h # End Source File # Begin Source File +SOURCE=.\zend_strtod.h +# End Source File +# Begin Source File + SOURCE=.\zend_ts_hash.h # End Source File # Begin Source File @@ -449,7 +457,7 @@ BuildCmds= \ !ELSEIF "$(CFG)" == "Zend - Win32 Release_inline" -!ENDIF +!ENDIF # End Source File # Begin Source File @@ -504,7 +512,7 @@ BuildCmds= \ $(BuildCmds) # End Custom Build -!ENDIF +!ENDIF # End Source File # End Group @@ -533,7 +541,7 @@ InputPath=.\zend_ini_scanner.l !ELSEIF "$(CFG)" == "Zend - Win32 Release_inline" -!ENDIF +!ENDIF # End Source File # Begin Source File @@ -570,7 +578,7 @@ InputPath=".\zend_language_scanner.l" # End Custom Build -!ENDIF +!ENDIF # End Source File # End Group diff --git a/Zend/Zend.m4 b/Zend/Zend.m4 index 83c764a05801..5140d1733e91 100644 --- a/Zend/Zend.m4 +++ b/Zend/Zend.m4 @@ -4,7 +4,7 @@ dnl dnl This file contains Zend specific autoconf functions. dnl -AC_DEFUN(LIBZEND_BISON_CHECK,[ +AC_DEFUN([LIBZEND_BISON_CHECK],[ if test "$YACC" != "bison -y"; then AC_MSG_WARN(You will need bison if you want to regenerate the Zend parser.) @@ -19,7 +19,29 @@ fi ]) -AC_DEFUN(LIBZEND_BASIC_CHECKS,[ +AC_DEFUN([LIBZEND_CHECK_INT_TYPE],[ +AC_MSG_CHECKING(for $1) +AC_TRY_COMPILE([ +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_INTTYPES_H +#include +#elif HAVE_STDINT_H +#include +#endif], +[if (($1 *) 0) + return 0; +if (sizeof ($1)) + return 0; +],[ + AC_DEFINE_UNQUOTED([HAVE_]translit($1,a-z_-,A-Z__), 1,[Define if $1 type is present. ]) + AC_MSG_RESULT(yes) +], AC_MSG_RESULT(no) +)dnl +]) + +AC_DEFUN([LIBZEND_BASIC_CHECKS],[ AC_REQUIRE([AC_PROG_YACC]) AC_REQUIRE([AC_PROG_CC]) @@ -42,6 +64,8 @@ if test "$ac_cv_prog_gcc" = "yes" -a "`uname -s`" = "Rhapsody"; then fi AC_CHECK_HEADERS( +inttypes.h \ +stdint.h \ limits.h \ malloc.h \ string.h \ @@ -58,12 +82,12 @@ dlfcn.h) AC_TYPE_SIZE_T AC_TYPE_SIGNAL -AC_DEFUN(LIBZEND_LIBDL_CHECKS,[ +AC_DEFUN([LIBZEND_LIBDL_CHECKS],[ AC_CHECK_LIB(dl, dlopen, [LIBS="-ldl $LIBS"]) AC_CHECK_FUNC(dlopen,[AC_DEFINE(HAVE_LIBDL, 1,[ ])]) ]) -AC_DEFUN(LIBZEND_DLSYM_CHECK,[ +AC_DEFUN([LIBZEND_DLSYM_CHECK],[ dnl dnl Ugly hack to check if dlsym() requires a leading underscore in symbol name. dnl @@ -82,6 +106,10 @@ dnl This is required for QNX and may be some BSD derived systems AC_CHECK_TYPE( uint, unsigned int ) AC_CHECK_TYPE( ulong, unsigned long ) +dnl Check if int32_t and uint32_t are defined +LIBZEND_CHECK_INT_TYPE(int32_t) +LIBZEND_CHECK_INT_TYPE(uint32_t) + dnl Checks for library functions. AC_FUNC_VPRINTF AC_FUNC_MEMCMP @@ -95,7 +123,7 @@ ZEND_FP_EXCEPT ]) -AC_DEFUN(LIBZEND_ENABLE_DEBUG,[ +AC_DEFUN([LIBZEND_ENABLE_DEBUG],[ AC_ARG_ENABLE(debug, [ --enable-debug Compile with debugging symbols],[ @@ -106,7 +134,16 @@ AC_ARG_ENABLE(debug, ]) -AC_DEFUN(LIBZEND_OTHER_CHECKS,[ +AC_DEFUN([LIBZEND_OTHER_CHECKS],[ + +AC_ARG_ENABLE(zend-memory-manager, +[ --disable-zend-memory-manager + Disable the Zend memory manager - FOR DEVELOPERS ONLY!!], +[ + ZEND_USE_ZEND_ALLOC=$enableval +], [ + ZEND_USE_ZEND_ALLOC=yes +]) AC_ARG_ENABLE(maintainer-zts, [ --enable-maintainer-zts Enable thread safety - for code maintainers only],[ @@ -137,6 +174,9 @@ AC_ARG_ENABLE(zend-multibyte, ZEND_MULTIBYTE=no ]) +AC_MSG_CHECKING(whether to enable the Zend memory manager) +AC_MSG_RESULT($ZEND_USE_ZEND_ALLOC) + AC_MSG_CHECKING(whether to enable thread-safety) AC_MSG_RESULT($ZEND_MAINTAINER_ZTS) @@ -167,6 +207,12 @@ fi test -n "$DEBUG_CFLAGS" && CFLAGS="$CFLAGS $DEBUG_CFLAGS" +if test "$ZEND_USE_ZEND_ALLOC" = "yes"; then + AC_DEFINE(USE_ZEND_ALLOC,1,[Use Zend memory manager]) +else + AC_DEFINE(USE_ZEND_ALLOC,0,[Use Zend memory manager]) +fi + if test "$ZEND_MAINTAINER_ZTS" = "yes"; then AC_DEFINE(ZTS,1,[ ]) CFLAGS="$CFLAGS -DZTS" @@ -237,6 +283,9 @@ int main() LIBZEND_MM_ALIGN_LOG2=`cat conftest.zend | cut -d ' ' -f 2` AC_DEFINE_UNQUOTED(ZEND_MM_ALIGNMENT, $LIBZEND_MM_ALIGN, [ ]) AC_DEFINE_UNQUOTED(ZEND_MM_ALIGNMENT_LOG2, $LIBZEND_MM_ALIGN_LOG2, [ ]) +], [], [ + dnl cross-compile needs something here + LIBZEND_MM_ALIGN=8 ]) AC_MSG_RESULT(done) @@ -244,7 +293,7 @@ AC_MSG_RESULT(done) ]) -AC_DEFUN(LIBZEND_CPLUSPLUS_CHECKS,[ +AC_DEFUN([LIBZEND_CPLUSPLUS_CHECKS],[ ]) diff --git a/Zend/ZendTS.dsp b/Zend/ZendTS.dsp index 76b4e46e5f4a..830f97efd2cb 100644 --- a/Zend/ZendTS.dsp +++ b/Zend/ZendTS.dsp @@ -276,6 +276,10 @@ SOURCE=.\zend_stream.c # End Source File # Begin Source File +SOURCE=.\zend_strtod.c +# End Source File +# Begin Source File + SOURCE=.\zend_ts_hash.c # End Source File # Begin Source File @@ -452,6 +456,10 @@ SOURCE=.\zend_stream.h # End Source File # Begin Source File +SOURCE=.\zend_strtod.h +# End Source File +# Begin Source File + SOURCE=.\zend_ts_hash.h # End Source File # Begin Source File diff --git a/Zend/acconfig.h b/Zend/acconfig.h index a273b95748aa..03de27104e6b 100644 --- a/Zend/acconfig.h +++ b/Zend/acconfig.h @@ -23,9 +23,7 @@ #define ZEND_DLEXPORT #define ZEND_DLIMPORT -#ifndef NETWARE @TOP@ -#endif #undef uint #undef ulong @@ -33,9 +31,7 @@ /* Define if you want to enable memory limit support */ #define MEMORY_LIMIT 0 -#ifndef NETWARE @BOTTOM@ -#endif #ifndef ZEND_ACCONFIG_H_NO_C_PROTOS @@ -47,6 +43,10 @@ # include #endif +#ifdef HAVE_SYS_SELECT_H +#include +#endif + #ifdef HAVE_IEEEFP_H # include #endif @@ -98,6 +98,13 @@ int zend_sprintf(char *buffer, const char *format, ...); #endif /* ifndef ZEND_ACCONFIG_H_NO_C_PROTOS */ +#ifdef NETWARE +#ifdef USE_WINSOCK +#/*This detection against winsock is of no use*/ undef HAVE_SOCKLEN_T +#/*This detection against winsock is of no use*/ undef HAVE_SYS_SOCKET_H +#endif +#endif + /* * Local variables: * tab-width: 4 diff --git a/Zend/acinclude.m4 b/Zend/acinclude.m4 index 395f7220db4e..480e24e0b11e 100644 --- a/Zend/acinclude.m4 +++ b/Zend/acinclude.m4 @@ -2,7 +2,7 @@ dnl $Id$ dnl dnl This file contains local autoconf functions. -AC_DEFUN(ZEND_FP_EXCEPT,[ +AC_DEFUN([ZEND_FP_EXCEPT],[ AC_CACHE_CHECK(whether fp_except is defined, ac_cv_type_fp_except,[ AC_TRY_COMPILE([ #include @@ -23,7 +23,7 @@ fp_except x = (fp_except) 0; dnl dnl Check for broken sprintf() dnl -AC_DEFUN(AC_ZEND_BROKEN_SPRINTF,[ +AC_DEFUN([AC_ZEND_BROKEN_SPRINTF],[ AC_CACHE_CHECK(whether sprintf is broken, ac_cv_broken_sprintf,[ AC_TRY_RUN([main() {char buf[20];exit(sprintf(buf,"testing 123")!=11); }],[ ac_cv_broken_sprintf=no @@ -41,7 +41,34 @@ AC_DEFUN(AC_ZEND_BROKEN_SPRINTF,[ AC_DEFINE_UNQUOTED(ZEND_BROKEN_SPRINTF, $ac_result, [Whether sprintf is broken]) ]) -AC_DEFUN(AM_SET_LIBTOOL_VARIABLE,[ - LIBTOOL='$(SHELL) $(top_builddir)/libtool $1' +dnl +dnl AC_ZEND_C_BIGENDIAN +dnl Replacement macro for AC_C_BIGENDIAN +dnl +AC_DEFUN([AC_ZEND_C_BIGENDIAN], +[AC_CACHE_CHECK([whether byte ordering is bigendian], ac_cv_c_bigendian_php, + [ + ac_cv_c_bigendian_php=unknown + AC_TRY_RUN( + [ +int main(void) +{ + short one = 1; + char *cp = (char *)&one; + + if (*cp == 0) { + return(0); + } else { + return(1); + } +} + ], [ac_cv_c_bigendian_php=yes], [ac_cv_c_bigendian_php=no], [ac_cv_c_bigendian_php=unknown]) + ]) + if test $ac_cv_c_bigendian_php = yes; then + AC_DEFINE(WORDS_BIGENDIAN, [], [Define if processor uses big-endian word]) + fi ]) +AC_DEFUN([AM_SET_LIBTOOL_VARIABLE],[ + LIBTOOL='$(SHELL) $(top_builddir)/libtool $1' +]) diff --git a/Zend/configure.in b/Zend/configure.in index fd13fd9800f3..9cbd1e11cee0 100644 --- a/Zend/configure.in +++ b/Zend/configure.in @@ -10,10 +10,14 @@ AC_PROG_CC AM_PROG_LEX AM_PROG_CC_STDC ZEND_VERSION=$VERSION +AC_ZEND_C_BIGENDIAN dnl We want this one before the checks, so the checks can modify CFLAGS. test -z "$CFLAGS" && auto_cflags=1 +AC_CHECK_SIZEOF(long, 8) +AC_CHECK_SIZEOF(int, 4) + sinclude(Zend.m4) LIBZEND_BASIC_CHECKS diff --git a/Zend/tests/bug20240.phpt b/Zend/tests/bug20240.phpt index acf673a277b7..43950440067a 100755 --- a/Zend/tests/bug20240.phpt +++ b/Zend/tests/bug20240.phpt @@ -39,5 +39,5 @@ echo "Done\n"; 2 3 Done -test::destructor test::__destruct +test::destructor diff --git a/Zend/tests/bug22836.phpt b/Zend/tests/bug22836.phpt index 1edcaa5c17a3..3cbc95493ed2 100644 --- a/Zend/tests/bug22836.phpt +++ b/Zend/tests/bug22836.phpt @@ -19,56 +19,48 @@ for ($i = 0; $i < 8; $i++) { string(3) "foo" 'foo' -Notice: Undefined variable: a in %s on line %d +Notice: Undefined variable: a in %s on line %d Strict Standards: Only variable references should be returned by reference in %s on line %d string(3) "foo" 'foo' -Notice: Undefined variable: a in %s on line %d +Notice: Undefined variable: a in %s on line %d Strict Standards: Only variable references should be returned by reference in %s on line %d string(3) "foo" 'foo' -Notice: Undefined variable: a in %s on line %d +Notice: Undefined variable: a in %s on line %d Strict Standards: Only variable references should be returned by reference in %s on line %d string(3) "foo" 'foo' -Notice: Undefined variable: a in %s on line %d +Notice: Undefined variable: a in %s on line %d Strict Standards: Only variable references should be returned by reference in %s on line %d string(3) "foo" 'foo' -Notice: Undefined variable: a in %s on line %d +Notice: Undefined variable: a in %s on line %d Strict Standards: Only variable references should be returned by reference in %s on line %d string(3) "foo" 'foo' -Notice: Undefined variable: a in %s on line %d +Notice: Undefined variable: a in %s on line %d Strict Standards: Only variable references should be returned by reference in %s on line %d string(3) "foo" 'foo' -Notice: Undefined variable: a in %s on line %d +Notice: Undefined variable: a in %s on line %d Strict Standards: Only variable references should be returned by reference in %s on line %d string(3) "foo" 'foo' -Notice: Undefined variable: a in %s on line %d +Notice: Undefined variable: a in %s on line %d Strict Standards: Only variable references should be returned by reference in %s on line %d -string(3) "foo" -'foo' - -Notice: Undefined variable: a in %s on line %d - -Strict Standards: Only variable references should be returned by reference in %s on line %d - - diff --git a/Zend/tests/bug26229.phpt b/Zend/tests/bug26229.phpt index 1e03bb2c4953..347eb5557158 100755 --- a/Zend/tests/bug26229.phpt +++ b/Zend/tests/bug26229.phpt @@ -11,11 +11,19 @@ class array_iterator implements IteratorAggregate { $obj = new array_iterator; -foreach ($obj as $property => $value) { - var_dump($value); +try +{ + foreach ($obj as $property => $value) + { + var_dump($value); + } +} +catch(Exception $e) +{ + echo $e->getMessage() . "\n"; } ?> ===DONE=== --EXPECTF-- -Warning: Objects returned by array_iterator::getIterator() must be traversable or implement interface Iterator in %sbug26229.php on line %d -===DONE=== \ No newline at end of file +Objects returned by array_iterator::getIterator() must be traversable or implement interface Iterator +===DONE=== diff --git a/Zend/tests/bug27145.phpt b/Zend/tests/bug27145.phpt deleted file mode 100755 index f2f6dd637853..000000000000 --- a/Zend/tests/bug27145.phpt +++ /dev/null @@ -1,13 +0,0 @@ ---TEST-- -Bug #27145 (Errors messages print unmangled PPP property names) ---FILE-- - ---EXPECTF-- -Fatal error: Cannot redeclare property static protected a::$v in class b in %s on line %d \ No newline at end of file diff --git a/Zend/tests/bug27268.phpt b/Zend/tests/bug27268.phpt new file mode 100755 index 000000000000..a86e8d0297a8 --- /dev/null +++ b/Zend/tests/bug27268.phpt @@ -0,0 +1,28 @@ +--TEST-- +Bug #27268 (Bad references accentuated by clone) +--FILE-- +a; + } +} + +$A = new A; +$A->a = array(1); +$x = $A->getA(); +$clone = clone $A; +$clone->a = array(); +print_r($A); +?> +--EXPECT-- +A Object +( + [a] => Array + ( + [0] => 1 + ) + +) diff --git a/Zend/tests/bug27304.phpt b/Zend/tests/bug27304.phpt new file mode 100755 index 000000000000..51e392d59b8d --- /dev/null +++ b/Zend/tests/bug27304.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #27304 +--FILE-- +test(); + +?> +===DONE=== +--EXPECT-- +bool(false) +bool(false) +===DONE=== diff --git a/Zend/tests/bug27598.phpt b/Zend/tests/bug27598.phpt new file mode 100755 index 000000000000..534e8cf85702 --- /dev/null +++ b/Zend/tests/bug27598.phpt @@ -0,0 +1,12 @@ +--TEST-- +Bug #27598 (list() array key assignment causes HUGE memory leak) +--FILE-- + +--EXPECT-- +array(1) { + [0]=> + int(1) +} diff --git a/Zend/tests/bug27798.phpt b/Zend/tests/bug27798.phpt new file mode 100755 index 000000000000..f0d1cd5e99e4 --- /dev/null +++ b/Zend/tests/bug27798.phpt @@ -0,0 +1,72 @@ +--TEST-- +Bug #27798 (private / protected variables not exposed by get_object_vars() inside class) +--FILE-- + +===DONE=== +--EXPECT-- +Base::__construct +array(3) { + ["Foo"]=> + int(1) + ["Bar"]=> + int(2) + ["Baz"]=> + int(3) +} +array(1) { + ["Foo"]=> + int(1) +} +Base::__construct +array(3) { + ["Baz"]=> + int(4) + ["Foo"]=> + int(1) + ["Bar"]=> + int(2) +} +Child::__construct +array(3) { + ["Baz"]=> + int(4) + ["Foo"]=> + int(1) + ["Bar"]=> + int(2) +} +array(1) { + ["Foo"]=> + int(1) +} +===DONE=== diff --git a/Zend/tests/bug28377.phpt b/Zend/tests/bug28377.phpt new file mode 100755 index 000000000000..9d1b43472c10 --- /dev/null +++ b/Zend/tests/bug28377.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #28377 (debug_backtrace is intermittently passing args) +--FILE-- + +--EXPECT-- +dereferenced -- args: 2 +direct -- args: 2 diff --git a/Zend/tests/bug28442.phpt b/Zend/tests/bug28442.phpt new file mode 100755 index 000000000000..1237357ccaf9 --- /dev/null +++ b/Zend/tests/bug28442.phpt @@ -0,0 +1,65 @@ +--TEST-- +Bug #28442 (Changing a static variables in a class changes it across sub/super classes.) +--FILE-- + +===DONE=== +--EXPECTF-- +===INIT=== +string(1) "A" +string(1) "C" +string(1) "C" +===SetA=== +string(2) "A2" +string(1) "C" +string(1) "C" +===SetB=== +string(2) "A2" +string(2) "B2" +string(2) "B2" +===SetC=== +string(2) "A2" +string(2) "C2" +string(2) "C2" +===DONE=== diff --git a/Zend/tests/bug28444.phpt b/Zend/tests/bug28444.phpt new file mode 100755 index 000000000000..f8a5513e0b9c --- /dev/null +++ b/Zend/tests/bug28444.phpt @@ -0,0 +1,74 @@ +--TEST-- +Bug #28444 (Cannot access undefined property for object with overloaded property access) +--FILE-- +x = $x; + } +} + +class Overloaded +{ + public $props = array(); + public $x; + + function __construct($x) + { + $this->x = new Object($x); + } + + function __get($prop) + { + echo __METHOD__ . "($prop)\n"; + return $this->props[$prop]; + } + + function __set($prop, $val) + { + echo __METHOD__ . "($prop,$val)\n"; + $this->props[$prop] = $val; + } +} +$y = new Overloaded(2); +var_dump($y->x); +var_dump($y->x->x); +var_dump($y->x->x = 3); +var_dump($y->y = 3); +var_dump($y->y); +var_dump($y->z = new Object(4)); +var_dump($y->z->x); +$t = $y->z; +var_dump($t->x = 5); +var_dump($y->z->x = 6); + +?> +===DONE=== +--EXPECTF-- +object(Object)#%d (1) { + ["x"]=> + int(2) +} +int(2) +int(3) +Overloaded::__set(y,3) +int(3) +Overloaded::__get(y) +int(3) +Overloaded::__set(z,Object id #3) +object(Object)#%d (1) { + ["x"]=> + int(4) +} +Overloaded::__get(z) +int(4) +Overloaded::__get(z) +int(5) +Overloaded::__get(z) +int(6) +===DONE=== diff --git a/Zend/tests/bug29015.phpt b/Zend/tests/bug29015.phpt new file mode 100644 index 000000000000..6c18ab8a0996 --- /dev/null +++ b/Zend/tests/bug29015.phpt @@ -0,0 +1,11 @@ +--TEST-- +Bug #29015 (Incorrect behavior of member vars(non string ones)-numeric mem vars und others) +--FILE-- +$x = "string('')"; +var_dump($a); +?> +--EXPECTF-- +Fatal error: Cannot access empty property in %sbug29015.php on line 4 diff --git a/Zend/tests/bug29104.phpt b/Zend/tests/bug29104.phpt new file mode 100644 index 000000000000..c7afbee07357 --- /dev/null +++ b/Zend/tests/bug29104.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #29104 Function declaration in method doesn't work +--FILE-- +g(); +f(); +?> +--EXPECT-- +function g - begin +function g - end +function f diff --git a/Zend/tests/bug29210.phpt b/Zend/tests/bug29210.phpt new file mode 100644 index 000000000000..294685499c6d --- /dev/null +++ b/Zend/tests/bug29210.phpt @@ -0,0 +1,104 @@ +--TEST-- +Bug #29210 Function: is_callable - no support for private and protected classes +--FILE-- +test_func1(); + } else { + echo "test_func1 isn't callable from inside\n"; + } + if (is_callable(array($this,'test_func2'))) { + $this->test_func2(); + } else { + echo "test_func2 isn't callable from inside\n"; + } + if (is_callable(array('test_class','test_func3'))) { + test_class::test_func3(); + } else { + echo "test_func3 isn't callable from inside\n"; + } + if (is_callable(array('test_class','test_func4'))) { + test_class::test_func4(); + } else { + echo "test_func4 isn't callable from inside\n"; + } + } +} + +class foo extends test_class { + function test() { + if (is_callable(array($this,'test_func1'))) { + $this->test_func1(); + } else { + echo "test_func1 isn't callable from child\n"; + } + if (is_callable(array($this,'test_func2'))) { + $this->test_func2(); + } else { + echo "test_func2 isn't callable from child\n"; + } + if (is_callable(array('test_class','test_func3'))) { + test_class::test_func3(); + } else { + echo "test_func3 isn't callable from child\n"; + } + if (is_callable(array('test_class','test_func4'))) { + test_class::test_func4(); + } else { + echo "test_func4 isn't callable from child\n"; + } + } +} + +$object = new test_class; +$object->test(); +if (is_callable(array($object,'test_func1'))) { + $object->test_func1(); +} else { + echo "test_func1 isn't callable from outside\n"; +} +if (is_callable(array($object,'test_func2'))) { + $object->test_func2(); +} else { + echo "test_func2 isn't callable from outside\n"; +} +if (is_callable(array('test_class','test_func3'))) { + test_class::test_func3(); +} else { + echo "test_func3 isn't callable from outside\n"; +} +if (is_callable(array('test_class','test_func4'))) { + test_class::test_func4(); +} else { + echo "test_func4 isn't callable from outside\n"; +} +$object = new foo(); +$object->test(); +?> +--EXPECT-- +test_func1 +test_func2 +test_func3 +test_func4 +test_func1 isn't callable from outside +test_func2 isn't callable from outside +test_func3 isn't callable from outside +test_func4 isn't callable from outside +test_func1 isn't callable from child +test_func2 +test_func3 isn't callable from child +test_func4 diff --git a/Zend/tests/bug29368.phpt b/Zend/tests/bug29368.phpt new file mode 100755 index 000000000000..4c5a1252401e --- /dev/null +++ b/Zend/tests/bug29368.phpt @@ -0,0 +1,34 @@ +--TEST-- +Bug #29368 (The destructor is called when an exception is thrown from the constructor) +--FILE-- + +===DONE=== +--EXPECTF-- +Foo::__construct +Caught exception! +===DONE=== diff --git a/Zend/tests/bug29505.phpt b/Zend/tests/bug29505.phpt new file mode 100755 index 000000000000..4d7c05351679 --- /dev/null +++ b/Zend/tests/bug29505.phpt @@ -0,0 +1,31 @@ +--TEST-- +Bug #29505 (get_class_vars() severely broken when used with arrays) +--FILE-- +"c", 3=>array()); +} + +var_dump(get_class_vars('Test')); + +?> +===DONE=== +--EXPECT-- +array(2) { + ["empty"]=> + array(0) { + } + ["three"]=> + array(3) { + [0]=> + int(1) + ["b"]=> + string(1) "c" + [3]=> + array(0) { + } + } +} +===DONE=== diff --git a/Zend/tests/bug29689.phpt b/Zend/tests/bug29689.phpt new file mode 100644 index 000000000000..74dabc159041 --- /dev/null +++ b/Zend/tests/bug29689.phpt @@ -0,0 +1,62 @@ +--TEST-- +Bug #29689 (default value of protected member overrides default value of private) +--FILE-- +foo, " ", $this->foo2, "\n"; + } +} + +class bar extends foo { + protected $foo = 'bar'; + + function printFoo() + { + parent::printFoo(); + echo __CLASS__, ': ', $this->foo, " ", $this->foo2, "\n"; + } +} + +class baz extends bar { + protected $foo = 'baz'; + protected $foo2 = 'baz2'; +} + +class bar2 extends foo { + function printFoo() + { + parent::printFoo(); + echo __CLASS__, ': ', $this->foo, " ", $this->foo2, "\n"; + } +} + +class baz2 extends bar2 { + protected $foo = 'baz2'; + protected $foo2 = 'baz22'; +} + +$bar = new bar; +$bar->printFoo(); +echo "---baz--\n"; +$baz = new baz(); +$baz->printFoo(); +echo "---baz2--\n"; +$baz = new baz2(); +$baz->printFoo(); +?> +--EXPECTF-- +foo: foo foo2 +bar: bar +Notice: Undefined property: bar::$foo2 in %s on line %d + +---baz-- +foo: foo foo2 +bar: baz baz2 +---baz2-- +foo: foo foo2 +bar2: baz2 baz22 diff --git a/Zend/tests/bug29883.phpt b/Zend/tests/bug29883.phpt new file mode 100644 index 000000000000..c92f147ff7a7 --- /dev/null +++ b/Zend/tests/bug29883.phpt @@ -0,0 +1,13 @@ +--TEST-- +Bug #29883 (isset gives invalid values on strings) +--FILE-- + +--EXPECT-- +bool(false) +bool(true) +u diff --git a/Zend/tests/bug29890.phpt b/Zend/tests/bug29890.phpt new file mode 100644 index 000000000000..32e8e1bd5dba --- /dev/null +++ b/Zend/tests/bug29890.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #29890 (crash if error handler fails) +--FILE-- + +--EXPECT-- +error :Constant TEST already defined diff --git a/Zend/tests/bug29896.phpt b/Zend/tests/bug29896.phpt new file mode 100755 index 000000000000..1e2eb0b067eb --- /dev/null +++ b/Zend/tests/bug29896.phpt @@ -0,0 +1,28 @@ +--TEST-- +Bug #29896 (Backtrace argument list out of sync) +--FILE-- + +--EXPECTF-- +#0 userErrorHandler(8, Undefined variable: b, %sbug29896.php, 11, Array ([A1] => Test1)) called at [%sbug29896.php:11] +#1 GenerateError1(Test1) called at [%sbug29896.php:16] +#2 GenerateError2(Test2) called at [%sbug29896.php:19] + diff --git a/Zend/tests/bug29944.phpt b/Zend/tests/bug29944.phpt new file mode 100644 index 000000000000..6c0cf1ec7a6d --- /dev/null +++ b/Zend/tests/bug29944.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug #29944 (Function defined in switch, crashes) +--FILE-- + +--EXPECT-- +ok + diff --git a/Zend/tests/bug30080.phpt b/Zend/tests/bug30080.phpt new file mode 100755 index 000000000000..bd8401e1bed6 --- /dev/null +++ b/Zend/tests/bug30080.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug #30080 (Passing array or non array of objects) +--FILE-- + +--EXPECT-- +array(1) { + [0]=> + object(stdClass)#2 (0) { + } +} diff --git a/Zend/tests/bug30140.phpt b/Zend/tests/bug30140.phpt new file mode 100755 index 000000000000..1dfb83500f31 --- /dev/null +++ b/Zend/tests/bug30140.phpt @@ -0,0 +1,30 @@ +--TEST-- +Bug #30140 (Problem with array in static properties) +--FILE-- + +--EXPECT-- +string(1) "x" +string(1) "y" +string(1) "z" +string(1) "x" +string(1) "y" +string(1) "z" diff --git a/Zend/tests/bug30162.phpt b/Zend/tests/bug30162.phpt new file mode 100755 index 000000000000..ae11f8ff8b71 --- /dev/null +++ b/Zend/tests/bug30162.phpt @@ -0,0 +1,52 @@ +--TEST-- +Bug #30162 (Catching exception in constructor couses lose of $this) +--FILE-- +x = "x"; + throw new Exception; + } + +} + +class hariCow extends FIIFO { + + public function __construct() { + try { + parent::__construct(); + } catch(Exception $e) { + } + $this->y = "y"; + try { + $this->z = new FIIFO; + } catch(Exception $e) { + } + } + + public function __toString() { + return "Rusticus in asino sedet."; + } + +} + +try { + $db = new FIIFO(); +} catch(Exception $e) { +} +var_dump($db); + +$db = new hariCow; + +var_dump($db); +?> +--EXPECTF-- +Notice: Undefined variable: db in %sbug30162.php on line 35 +NULL +object(hariCow)#1 (2) { + ["x"]=> + string(1) "x" + ["y"]=> + string(1) "y" +} diff --git a/Zend/tests/bug30332.phpt b/Zend/tests/bug30332.phpt new file mode 100644 index 000000000000..e2478498cdb5 --- /dev/null +++ b/Zend/tests/bug30332.phpt @@ -0,0 +1,40 @@ +--TEST-- +Bug #30332 (zend.ze1_compatibility_mode isnt fully compatable with array_push()) +--INI-- +zend.ze1_compatibility_mode=on +error_reporting=4095 +--FILE-- +first = " im in the first"; + +print_r($first); +print_r($second); +print_r($container); +?> +--EXPECTF-- +Strict Standards: Implicit cloning object of class 'x' because of 'zend.ze1_compatibility_mode' in %sbug30332.php on line 4 + +Strict Standards: Implicit cloning object of class 'x' because of 'zend.ze1_compatibility_mode' in %sbug30332.php on line 5 + +Strict Standards: Implicit cloning object of class 'x' because of 'zend.ze1_compatibility_mode' in %sbug30332.php on line 7 +x Object +( + [first] => im in the first +) +x Object +( +) +Array +( + [0] => x Object + ( + ) + +) diff --git a/Zend/tests/bug30394.phpt b/Zend/tests/bug30394.phpt new file mode 100755 index 000000000000..b69eda4fef74 --- /dev/null +++ b/Zend/tests/bug30394.phpt @@ -0,0 +1,30 @@ +--TEST-- +Bug #30394 (Assignment operators yield wrong result with __get/__set) +--FILE-- +_p[ $what ]; + } + + public function __set( $what, $value ) + { + $this->_p[ $what ] = $value; + } + + private $_p = array(); +} + +$c = new Container(); +$c->a = 1; +$c->a += 1; +print $c->a; // --> 2 + +print " - "; +$c->a += max( 0, 1 ); +print $c->a; // --> 4 (!) +?> +--EXPECT-- +2 - 3 diff --git a/Zend/tests/bug30451.phpt b/Zend/tests/bug30451.phpt new file mode 100644 index 000000000000..210f087574ff --- /dev/null +++ b/Zend/tests/bug30451.phpt @@ -0,0 +1,36 @@ +--TEST-- +Bug #30451 (static properties permissions broken) +--FILE-- + +--EXPECT-- +bool(true) +bool(true) +bool(true) +bool(true) diff --git a/Zend/tests/bug30519.phpt b/Zend/tests/bug30519.phpt new file mode 100755 index 000000000000..185d21aef7a4 --- /dev/null +++ b/Zend/tests/bug30519.phpt @@ -0,0 +1,10 @@ +--TEST-- +Bug #30519 Interface not existing says Class not found +--FILE-- + +--EXPECTF-- +Fatal error: Interface 'a' not found in %sbug30519.php on line 2 + diff --git a/Zend/tests/bug30702.phpt b/Zend/tests/bug30702.phpt new file mode 100644 index 000000000000..17e44a389569 --- /dev/null +++ b/Zend/tests/bug30702.phpt @@ -0,0 +1,39 @@ +--TEST-- +Bug #30702 cannot initialize class variable from class constant +--FILE-- + +--EXPECT-- +object(bar)#1 (6) { + ["c1"]=> + int(1) + ["c2"]=> + int(2) + ["c3"]=> + int(1) + ["c4"]=> + int(2) + ["c5"]=> + int(1) + ["c6"]=> + int(1) +} diff --git a/Zend/tests/bug30707.phpt b/Zend/tests/bug30707.phpt new file mode 100755 index 000000000000..d37d32974ea2 --- /dev/null +++ b/Zend/tests/bug30707.phpt @@ -0,0 +1,29 @@ +--TEST-- +Bug #30707 (Segmentation fault on exception in method) +--FILE-- +plap($this->plop()); + } catch(Exception $e) { + } + } + + function plap($a) { + } + + function plop() { + throw new Exception; + } +} + +$x = new C; +$x->byePHP($x->plip()); +?> +--EXPECT-- +ok diff --git a/Zend/tests/bug30725.phpt b/Zend/tests/bug30725.phpt new file mode 100755 index 000000000000..ce6c9a50a260 --- /dev/null +++ b/Zend/tests/bug30725.phpt @@ -0,0 +1,32 @@ +--TEST-- +Bug #30725 (PHP segfaults when an exception is thrown in getIterator() within foreach) +--FILE-- + +===DONE=== +--EXPECT-- +Caught +===DONE=== diff --git a/Zend/tests/bug30791.phpt b/Zend/tests/bug30791.phpt new file mode 100755 index 000000000000..f56bcfb6e7bd --- /dev/null +++ b/Zend/tests/bug30791.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #30791 magic methods (__sleep/__wakeup/__toString) call __call if object is overloaded +--FILE-- + +--EXPECT-- +Object id #1 +Object id #2 +object(a)#2 (1) { + ["a"]=> + int(4) +} diff --git a/Zend/tests/bug30820.phpt b/Zend/tests/bug30820.phpt new file mode 100755 index 000000000000..97e46e9287b5 --- /dev/null +++ b/Zend/tests/bug30820.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #30820 (static member conflict with $this->member silently ignored) +--INI-- +error_reporting=4095 +--FILE-- +x = 5; // no warning, but refers to different variable + + echo 'Blah::$x = '. Blah::$x ."\n"; + echo '$this->x = '. $this->x ."\n"; + } +} + +$b = new Blah(); +$b->show(); +?> +--EXPECTF-- +Strict Standards: Accessing static property Blah::$x as non static in %sbug30820.php on line 7 +Blah::$x = 1 + +Strict Standards: Accessing static property Blah::$x as non static in %sbug30820.php on line 10 +$this->x = 5 diff --git a/Zend/tests/bug30828.phpt b/Zend/tests/bug30828.phpt new file mode 100755 index 000000000000..d05dbb606dcd --- /dev/null +++ b/Zend/tests/bug30828.phpt @@ -0,0 +1,61 @@ +--TEST-- +Bug #30828 (debug_backtrace() reports incorrect class in overridden methods) +--FILE-- +foo(); +B::bar(); +?> +--EXPECTF-- +#0 A->__construct() called at [%sbug30828.php:30] +#1 B->__construct() called at [%sbug30828.php:42] +A->__construct +B->__construct +#0 A->foo() called at [%sbug30828.php:34] +#1 B->foo() called at [%sbug30828.php:43] +A->foo +B->foo +#0 A::bar() called at [%sbug30828.php:38] +#1 B::bar() called at [%sbug30828.php:44] +A::bar +B::bar diff --git a/Zend/tests/bug30889.phpt b/Zend/tests/bug30889.phpt new file mode 100644 index 000000000000..4f58cbf5a5dc --- /dev/null +++ b/Zend/tests/bug30889.phpt @@ -0,0 +1,31 @@ +--TEST-- +Bug #30889 Conflict between __get/__set and ++ operator +--FILE-- +values = array('a' => 0); + } + function __set($name, $value) + { + print "set $name = $value ($name was ".$this->values[$name].")\n"; + $this->values[$name] = $value; + } + function __get($name) + { + print "get $name (returns ".$this->values[$name].")\n"; + return $this->values[$name]; + } +} +$test = new overloaded(); +$test->a++; // __get(), then __set() +++$test->a; +?> +--EXPECT-- +get a (returns 0) +set a = 1 (a was 0) +get a (returns 1) +set a = 2 (a was 1) diff --git a/Zend/tests/bug30922.phpt b/Zend/tests/bug30922.phpt new file mode 100644 index 000000000000..24d79171be21 --- /dev/null +++ b/Zend/tests/bug30922.phpt @@ -0,0 +1,13 @@ +--TEST-- +Bug #30922 (reflective functions crash PHP when interfaces extend themselves) +--FILE-- + +--EXPECTF-- +Fatal error: Interface RecurisiveFooFar cannot not implement itself in %sbug30922.php on line %d diff --git a/Zend/tests/bug31098.phpt b/Zend/tests/bug31098.phpt new file mode 100644 index 000000000000..fa753678eee8 --- /dev/null +++ b/Zend/tests/bug31098.phpt @@ -0,0 +1,53 @@ +--TEST-- +Bug #31098 (isset() / empty() incorrectly returns true in dereference of a wrong type) +--FILE-- +b)); +$a = 'a'; +var_dump(isset($a->b)); +$a = '0'; +var_dump(isset($a->b)); +$a = ''; +var_dump(isset($a{'b'})); +$a = 'a'; +var_dump(isset($a{'b'})); +$a = '0'; +var_dump(isset($a{'b'})); + +$simpleString = "Bogus String Text"; +echo isset($simpleString->wrong)?"bug\n":"ok\n"; +echo isset($simpleString["wrong"])?"ok\n":"bug\n"; +echo isset($simpleString[-1])?"bug\n":"ok\n"; +echo isset($simpleString[0])?"ok\n":"bug\n"; +echo isset($simpleString["0"])?"ok\n":"bug\n"; +echo isset($simpleString["16"])?"ok\n":"bug\n"; +echo isset($simpleString["17"])?"bug\n":"ok\n"; +echo isset($simpleString["wrong"][0])?"bug\n":"ok\n"; +echo $simpleString->wrong === null?"ok\n":"bug\n"; +echo $simpleString["wrong"] === "B"?"ok\n":"bug\n"; +echo $simpleString["0"] === "B"?"ok\n":"bug\n"; +$simpleString["wrong"] = "f"; +echo $simpleString["0"] === "f"?"ok\n":"bug\n"; +?> +--EXPECTF-- +bool(false) +bool(false) +bool(false) +bool(false) +bool(true) +bool(true) +ok +ok +ok +ok +ok +ok +ok +ok + +Notice: Trying to get property of non-object in %sbug31098.php on line %d +ok +ok +ok +ok diff --git a/Zend/tests/bug31177.phpt b/Zend/tests/bug31177.phpt new file mode 100755 index 000000000000..5e84573624e9 --- /dev/null +++ b/Zend/tests/bug31177.phpt @@ -0,0 +1,44 @@ +--TEST-- +Bug #31177 (Memory leak) +--FILE-- +query()); + } + + public function select2() { + new DbGowRecordSet($this->query()); + } + +} + +class DbGowRecordSet { + + public function __construct($resource) { + } + +} + +$db = new DbGow; + +try { + $rs = $db->select(); +} catch(Exception $e) { + echo "ok\n"; +} + +try { + $db->select2(); +} catch(Exception $e) { + echo "ok\n"; +} +?> +--EXPECT-- +ok +ok diff --git a/Zend/tests/bug31525.phpt b/Zend/tests/bug31525.phpt new file mode 100755 index 000000000000..b1a01b61efcb --- /dev/null +++ b/Zend/tests/bug31525.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #31525 (object reference being dropped. $this getting lost) +--INI-- +error_reporting=4095 +--FILE-- +getThis(); + } +} +$bar = new Foo(); +$bar->destroyThis(); +var_dump($bar); +?> +--EXPECTF-- +Strict Standards: Only variables should be assigned by reference in %sbug31525.php on line 7 +object(Foo)#1 (0) { +} diff --git a/Zend/tests/bug31683.phpt b/Zend/tests/bug31683.phpt new file mode 100644 index 000000000000..4e0159d6c210 --- /dev/null +++ b/Zend/tests/bug31683.phpt @@ -0,0 +1,97 @@ +--TEST-- +Bug #31683 (changes to $name in __get($name) override future parameters) +--SKIPIF-- + +--FILE-- +ok("ok"); + $foo->ok; + $foo->ok = "ok"; + $x = $foo["ok"]; + $foo["ok"] = "ok"; + isset($foo["ok"]); + unset($foo["ok"]); +// $foo[]; + $foo[] = "ok"; +// isset($foo[]); +// unset($foo[]); + $foo->$a; + echo "---\n"; +} +?> +--EXPECT-- +string(2) "ok" +string(2) "ok" +string(2) "ok" +string(2) "ok" +string(2) "ok" +string(2) "ok" +string(2) "ok" +string(2) "ok" +string(2) "ok" +NULL +string(2) "ok" +string(2) "ok" +--- +string(2) "ok" +string(2) "ok" +string(2) "ok" +string(2) "ok" +string(2) "ok" +string(2) "ok" +string(2) "ok" +string(2) "ok" +string(2) "ok" +NULL +string(2) "ok" +string(2) "ok" +--- diff --git a/Zend/tests/bug31720.phpt b/Zend/tests/bug31720.phpt new file mode 100644 index 000000000000..be57ca2c454a --- /dev/null +++ b/Zend/tests/bug31720.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug #31720 (Invalid object callbacks not caught in array_walk()) +--FILE-- + +===DONE=== +--EXPECTF-- +Notice: Undefined variable: nonesuchvar in %s on line %d + +Notice: Non-callable array passed to zend_call_function() in %s on line %d + +Warning: array_walk(): Unable to call Array() - function does not exist in %s on line %d +===DONE=== diff --git a/Zend/tests/bug31828.phpt b/Zend/tests/bug31828.phpt new file mode 100644 index 000000000000..a3cc4542fd70 --- /dev/null +++ b/Zend/tests/bug31828.phpt @@ -0,0 +1,25 @@ +--TEST-- +Bug #31828 (Crash with zend.ze1_compatibility_mode=On) +--INI-- +zend.ze1_compatibility_mode=on +error_reporting=4095 +--FILE-- +id = 77; +$o->name = "Aerospace"; +$a[] = $o; +$a = $a[0]; +print_r($a); +?> +--EXPECTF-- +Strict Standards: Implicit cloning object of class 'stdClass' because of 'zend.ze1_compatibility_mode' in %sbug31828.php on line 2 + +Strict Standards: Implicit cloning object of class 'stdClass' because of 'zend.ze1_compatibility_mode' in %sbug31828.php on line 5 + +Strict Standards: Implicit cloning object of class 'stdClass' because of 'zend.ze1_compatibility_mode' in %sbug31828.php on line 6 +stdClass Object +( + [id] => 77 + [name] => Aerospace +) diff --git a/Zend/tests/bug32080.phpt b/Zend/tests/bug32080.phpt new file mode 100644 index 000000000000..a96c8bf26273 --- /dev/null +++ b/Zend/tests/bug32080.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug #32080 (segfault when assigning object to itself with zend.ze1_compatibility_mode=On) +--INI-- +zend.ze1_compatibility_mode=on +error_reporting=4095 +--FILE-- + +--EXPECTF-- +Strict Standards: Implicit cloning object of class 'test' because of 'zend.ze1_compatibility_mode' in %sbug32080.php on line 3 + +Strict Standards: Implicit cloning object of class 'test' because of 'zend.ze1_compatibility_mode' in %sbug32080.php on line 5 +object(test)#%d (0) { +} diff --git a/Zend/tests/bug32226.phpt b/Zend/tests/bug32226.phpt new file mode 100755 index 000000000000..b2bd754c2898 --- /dev/null +++ b/Zend/tests/bug32226.phpt @@ -0,0 +1,36 @@ +--TEST-- +Bug # 32226 (SEGV with exception handler on non existing instance) +--FILE-- + +===DONE=== +--EXPECT-- +Caught +===DONE=== diff --git a/Zend/tests/bug32252.phpt b/Zend/tests/bug32252.phpt new file mode 100755 index 000000000000..706da18cfb4d --- /dev/null +++ b/Zend/tests/bug32252.phpt @@ -0,0 +1,47 @@ +--TEST-- +Bug #32252 (Segfault when offsetSet throws an Exception (only without debug)) +--FILE-- + +===DONE=== +--EXPECT-- +Test::offsetSet(-1, 123) +CAUGHT +===DONE=== diff --git a/Zend/tests/bug32290.phpt b/Zend/tests/bug32290.phpt new file mode 100755 index 000000000000..f754275ccff4 --- /dev/null +++ b/Zend/tests/bug32290.phpt @@ -0,0 +1,35 @@ +--TEST-- +Bug #32290 (calling call_user_func_array() ends in infinite loop within child class) +--FILE-- += 5) return 5; + return call_user_func_array(array("TestA","doSomething"), array($i)); + } +} + +$x = new TestB(); +var_dump($x->doSomething(1)); + +?> +===DONE=== +--EXPECTF-- +TestB::doSomething(Object id #%d) +TestA::doSomething(Object id #%d) +int(1) +===DONE=== diff --git a/Zend/tests/bug32296.phpt b/Zend/tests/bug32296.phpt new file mode 100755 index 000000000000..81fe25df8bd3 --- /dev/null +++ b/Zend/tests/bug32296.phpt @@ -0,0 +1,60 @@ +--TEST-- +Bug #32296 get_class_methods output has changed between 5.0.2 and 5.0.3 +--FILE-- +buggy(); +print_r(get_class_methods("square")); +print_r(get_class_methods($a)); +?> +--EXPECT-- +square +a:Array +( + [0] => x2 + [1] => buggy + [2] => unfold + [3] => __construct +) +b:Array +( + [0] => x2 + [1] => buggy + [2] => unfold + [3] => __construct +) +Array +( + [0] => buggy + [1] => __construct +) +Array +( + [0] => buggy + [1] => __construct +) diff --git a/Zend/tests/bug32322.phpt b/Zend/tests/bug32322.phpt new file mode 100755 index 000000000000..f69c5259e84a --- /dev/null +++ b/Zend/tests/bug32322.phpt @@ -0,0 +1,80 @@ +--TEST-- +Bug #32322 (Return values by reference broken( using self::),example singleton instance) +--INI-- +error_reporting=4095 +--FILE-- + myname = $value; + } + private function __clone() {} + static public function getInstance() + { + if ( self::$instance == null ) + { + self::$instance = new test('Singleton1'); + } + else { + echo "Using old class " . self::$instance -> myname . "\n"; + } + return self::$instance; + } + static public function getInstance2() + { + static $instance2 = null; + if ( $instance2 == null ) + { + $instance2 = new test('Singleton2'); + } + else { + echo "Using old class " . $instance2 -> myname . "\n"; + } + return $instance2; + } + public function __destruct() + { + if ( defined('SCRIPT_END') ) + { + echo "Class " . $this -> myname . " destroyed at script end\n"; + } else { + echo "Class " . $this -> myname . " destroyed beforce script end\n"; + } + } +} +echo "Try static instance inside class :\n"; +$getCopyofSingleton = test::getInstance(); +$getCopyofSingleton = null; +$getCopyofSingleton = &test::getInstance(); +$getCopyofSingleton = null; +$getCopyofSingleton = test::getInstance(); +echo "Try static instance inside function :\n"; +$getCopyofSingleton2 = test::getInstance2(); +$getCopyofSingleton2 = null; +$getCopyofSingleton2 = &test::getInstance2(); +$getCopyofSingleton2 = null; +$getCopyofSingleton2 = test::getInstance2(); + +define('SCRIPT_END',1); +?> +--EXPECTF-- +Try static instance inside class : +New class Singleton1 created +Using old class Singleton1 + +Strict Standards: Only variables should be assigned by reference in %sbug32322.php on line 49 +Using old class Singleton1 +Try static instance inside function : +New class Singleton2 created +Using old class Singleton2 + +Strict Standards: Only variables should be assigned by reference in %sbug32322.php on line 55 +Using old class Singleton2 +Class Singleton1 destroyed at script end +Class Singleton2 destroyed at script end diff --git a/Zend/tests/bug32596.phpt b/Zend/tests/bug32596.phpt new file mode 100755 index 000000000000..2dd0cfe9f003 --- /dev/null +++ b/Zend/tests/bug32596.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #32596 (Segfault/Memory Leak by getClass (etc) in __destruct) +--FILE-- +error; + } +} + + +BUG::instance()->error; +echo "this is still executed\n"; +?> +--EXPECT-- +BUG +please fix this thing, it wasted a nice part of my life! +this is still executed + diff --git a/Zend/tests/bug32660.phpt b/Zend/tests/bug32660.phpt new file mode 100755 index 000000000000..f173b287e1b6 --- /dev/null +++ b/Zend/tests/bug32660.phpt @@ -0,0 +1,36 @@ +--TEST-- +Bug #32660 Assignment by reference causes crash when field access is overloaded (__get) +--FILE-- +q = 3;//array(); + } + + function __get($name) + { + return $this->q; + } +} + +$a = new A; + +$b = "short"; +$c =& $a->whatever; +$c = "long"; +print_r($a); +$a->whatever =& $b; +$b = "much longer"; +print_r($a); +?> +--EXPECTF-- +A Object +( + [q] => long +) + +Fatal error: Cannot assign by reference to overloaded object in %sbug32660.php on line 23 diff --git a/Zend/tests/bug32674.phpt b/Zend/tests/bug32674.phpt new file mode 100644 index 000000000000..547bcec096e5 --- /dev/null +++ b/Zend/tests/bug32674.phpt @@ -0,0 +1,62 @@ +--TEST-- +Bug #32674 exception in iterator causes crash +--FILE-- +_elements); + } + + public function count() { + return count($this->_elements); + } + + public function current() { + $element = current($this->_elements); + return $element; + } + + public function next() { + $element = next($this->_elements); + return $element; + } + + public function key() { + $this->_fillCollection(); + $element = key($this->_elements); + return $element; + } + + public function valid() { + throw new Exception('shit happend'); + + return ($this->current() !== false); + } +} + +class class2 { + public $dummy; +} + +$obj = new class2(); +$col = new collection(); + +try { + foreach($col as $co) { + //irrelevant + } + echo 'shouldn`t get here'; + //$dummy = 'this will not crash'; + $obj->dummy = 'this will crash'; +} catch (Exception $e) { + echo "ok\n"; +} +?> +--EXPECT-- +ok diff --git a/Zend/tests/bug32799.phpt b/Zend/tests/bug32799.phpt new file mode 100755 index 000000000000..7b09a5027467 --- /dev/null +++ b/Zend/tests/bug32799.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug #32799 (crash: calling the corresponding global var during the destruct) +--FILE-- +c++; // no warning + print $GLOBALS['p']->c."\n"; // segfault + var_dump($GLOBALS['p']); + } +} +$p=new test; +$p=null; //destroy the object by a new assignment (segfault) +?> +--EXPECT-- +2 +object(test)#1 (1) { + ["c"]=> + int(2) +} diff --git a/Zend/tests/bug32852.phpt b/Zend/tests/bug32852.phpt new file mode 100644 index 000000000000..38cea6f145d9 --- /dev/null +++ b/Zend/tests/bug32852.phpt @@ -0,0 +1,38 @@ +--TEST-- +Bug #32852 (Crash with singleton and __destruct when zend.ze1_compatibility_mode = On) +--INI-- +zend.ze1_compatibility_mode=on +error_reporting=4095 +--FILE-- + +--EXPECTF-- +Strict Standards: Implicit cloning object of class 'crashme' because of 'zend.ze1_compatibility_mode' in %sbug32852.php on line 6 +i'm called + +Strict Standards: Implicit cloning object of class 'crashme' because of 'zend.ze1_compatibility_mode' in %sbug32852.php on line 15 +i'm called + +Strict Standards: Implicit cloning object of class 'crashme' because of 'zend.ze1_compatibility_mode' in %sbug32852.php on line 17 +i'm called +i'm called diff --git a/Zend/tests/bug32993.phpt b/Zend/tests/bug32993.phpt new file mode 100755 index 000000000000..88fb0230b6bd --- /dev/null +++ b/Zend/tests/bug32993.phpt @@ -0,0 +1,29 @@ +--TEST-- +Bug #32993 (implemented Iterator function current() don't throw exception) +--FILE-- +arr); } + public function current() { throw new Exception(); } + public function key() { return key($this->arr); } + public function next() { return next($this->arr); } + public function valid() { return (current($this->arr) !== false); } +} + +$t = new Test(); +$t->arr = array(1, 2, 3); + +try { + foreach ($t as $v) { + echo "$v\n"; + } +} catch (Exception $e) { + ; // handle exception +} +echo "ok\n"; +?> +--EXPECT-- +ok diff --git a/Zend/tests/bug33116.phpt b/Zend/tests/bug33116.phpt new file mode 100755 index 000000000000..aa714a1f85a8 --- /dev/null +++ b/Zend/tests/bug33116.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #33116 (crash when assigning class name to global variable in __autoload) +--FILE-- + +--EXPECT-- +DefClass Object +( +) +Array +( + [0] => DefClass +) diff --git a/Zend/tests/bug33171.phpt b/Zend/tests/bug33171.phpt new file mode 100755 index 000000000000..27f5264bada5 --- /dev/null +++ b/Zend/tests/bug33171.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #33171 (foreach enumerates private fields declared in base classes) +--FILE-- + $val) + { + echo "$key => $val\n"; + } + } +}; + +$x = new B; +$x->go(); +?> +--EXPECT-- +c => B's c diff --git a/Zend/tests/bug33243.phpt b/Zend/tests/bug33243.phpt new file mode 100755 index 000000000000..bb5d77c7bf6a --- /dev/null +++ b/Zend/tests/bug33243.phpt @@ -0,0 +1,25 @@ +--TEST-- +Bug #33243 (ze1_compatibility_mode does not work as expected) +--INI-- +zend.ze1_compatibility_mode=1 +error_reporting=4095 +--FILE-- +y->z = 0; +$b = $a; // should perform deep copy of $a +$b->y->z = 1; // hence this should have no effect on $a +var_dump($a); +?> +--EXPECTF-- +Strict Standards: Creating default object from empty value in %sbug33243.php on line 2 + +Strict Standards: Implicit cloning object of class 'stdClass' because of 'zend.ze1_compatibility_mode' in %sbug33243.php on line 3 + +Strict Standards: Implicit cloning object of class 'stdClass' because of 'zend.ze1_compatibility_mode' in %sbug33243.php on line 5 +object(stdClass)#%d (1) { + ["y"]=> + object(stdClass)#%d (1) { + ["z"]=> + int(0) + } +} diff --git a/Zend/tests/bug33257.phpt b/Zend/tests/bug33257.phpt new file mode 100755 index 000000000000..b3e98003a391 --- /dev/null +++ b/Zend/tests/bug33257.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #33257 array_splice() inconsistent when passed function instead of variable +--FILE-- + +--EXPECTF-- +Fatal error: Only variables can be passed by reference in %sbug33257.php on line 10 diff --git a/Zend/tests/bug33277.phpt b/Zend/tests/bug33277.phpt new file mode 100644 index 000000000000..17e6337f6f3f --- /dev/null +++ b/Zend/tests/bug33277.phpt @@ -0,0 +1,28 @@ +--TEST-- +Bug #33277 (private method accessed by child class) +--FILE-- +bar(); + } +} + +class foo2son extends fooson { + + function bar() { + echo "public!\n"; + } +} + +$b = new foo2son(); +$b->barson(); +?> +--EXPECT-- +public! diff --git a/Zend/tests/bug33558.phpt b/Zend/tests/bug33558.phpt new file mode 100755 index 000000000000..9c87fc6017f5 --- /dev/null +++ b/Zend/tests/bug33558.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug #33558 (warning with nested calls to functions returning by reference) +--INI-- +error_reporting=4095 +--FILE-- + +--EXPECT-- +ok + diff --git a/Zend/tests/bug33802.phpt b/Zend/tests/bug33802.phpt new file mode 100755 index 000000000000..d2f8cd736e39 --- /dev/null +++ b/Zend/tests/bug33802.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #33802 (throw Exception in error handler causes crash) +--FILE-- + +ok +--EXPECT-- +ok diff --git a/Zend/tests/bug34064.phpt b/Zend/tests/bug34064.phpt new file mode 100755 index 000000000000..84208a54f865 --- /dev/null +++ b/Zend/tests/bug34064.phpt @@ -0,0 +1,35 @@ +--TEST-- +Bug #34064 (arr[] as param to function in class gives invalid opcode) +--FILE-- +test_ref($ar[]); + var_dump($ar); + $this->test($ar[]); + } +} + +$o = new XmlTest(); +$o->run(); +?> +--EXPECTF-- +array(1) { + [0]=> + string(2) "ok" +} + +Fatal error: Cannot use [] for reading in %sbug34064.php on line 18 + diff --git a/Zend/tests/bug34137.phpt b/Zend/tests/bug34137.phpt new file mode 100755 index 000000000000..5856333332e6 --- /dev/null +++ b/Zend/tests/bug34137.phpt @@ -0,0 +1,10 @@ +--TEST-- +Bug #34137 (assigning array element by reference causes binary mess) +--FILE-- + array('alfa' => 'ok')); +$arr1 =& $arr1['a1']; +echo '-'.$arr1['alfa']."-\n"; +?> +--EXPECT-- +-ok- diff --git a/Zend/tests/bug34260.phpt b/Zend/tests/bug34260.phpt new file mode 100755 index 000000000000..fa393d065c2a --- /dev/null +++ b/Zend/tests/bug34260.phpt @@ -0,0 +1,36 @@ +--TEST-- +Bug #34260 (Segfault with callbacks (array_map) + overloading) +--FILE-- + +--EXPECT-- +I hate me +I hate me +I heart me +I heart me diff --git a/Zend/tests/bug_debug_backtrace.phpt b/Zend/tests/bug_debug_backtrace.phpt new file mode 100755 index 000000000000..3e4a0ec94667 --- /dev/null +++ b/Zend/tests/bug_debug_backtrace.phpt @@ -0,0 +1,28 @@ +--TEST-- +Bug - crash in debug_backtrace when trace starts in eval +--FILE-- + +===DONE=== +--EXPECTF-- +#0 boo() called at [%s:%d] +#1 bar() called at [%s:%d] +#2 foo() called at [%s(%d) : eval()'d code:1] +#3 eval() called at [%s:%d] +Done +===DONE=== diff --git a/Zend/tests/object_handlers.phpt b/Zend/tests/object_handlers.phpt new file mode 100755 index 000000000000..905646ba8f26 --- /dev/null +++ b/Zend/tests/object_handlers.phpt @@ -0,0 +1,171 @@ +--TEST-- +Magic object handlers segfault and memory errors +--FILE-- +const_get; +echo $y,"\n"; +$x->const_set = 1; +echo $y,"\n"; +$x->const_call(); +echo $y,"\n"; +$z = $x["const_dim_get"]; +echo $y,"\n"; +$x["const_dim_set"] = 1; +echo $y,"\n"; +isset($x["const_dim_isset"]); +echo $y,"\n"; +unset($x["const_dim_unset"]); +echo $y,"\n"; + +// IS_CONST + conversion +$z = $x->{1}; +echo $y,"\n"; +$x->{2} = 1; +echo $y,"\n"; + +// IS_TMP_VAR +$c = "tmp"; +$z = $x->{$c."_get"}; +echo $y,"\n"; +$x->{$c."_set"} = 1; +echo $y,"\n"; +$x->{$c."_call"}(); +echo $y,"\n"; +$z = $x[$c."_dim_get"]; +echo $y,"\n"; +$x[$c."_dim_set"] = 1; +echo $y,"\n"; +isset($x[$c."_dim_isset"]); +echo $y,"\n"; +unset($x[$c."_dim_unset"]); +echo $y,"\n"; + +// IS_TMP_VAR + conversion +$c = 0; +$z = $x->{$c+3}; +echo $y,"\n"; +$x->{$c+4} = 1; +echo $y,"\n"; + +// IS_CV +$c = "cv_get"; +$z = $x->{$c}; +echo $y,"\n"; +$c = "cv_set"; +$x->{$c} = 1; +echo $y,"\n"; +$c = "cv_call"; +$x->{$c}(); +echo $y,"\n"; +$c = "cv_dim_get"; +$z = $x[$c]; +echo $y,"\n"; +$c = "cv_dim_set"; +$x[$c] = 1; +echo $y,"\n"; +$c = "cv_dim_isset"; +isset($x[$c]); +echo $y,"\n"; +$c = "cv_dim_unset"; +unset($x[$c]); +echo $y,"\n"; + +// IS_CV + conversion +$c = 5; +$z = $x->{$c}; +echo $y,"\n"; +$c = 6; +$x->{$c} = 1; +echo $y,"\n"; + +// IS_VAR +$z = $x->{f("var_get")}; +echo $y,"\n"; +$x->{f("var_set")} = 1; +echo $y,"\n"; +$x->{f("var_call")}(); +echo $y,"\n"; +$z = $x[f("var_dim_get")]; +echo $y,"\n"; +$x[f("var_dim_set")] = 1; +echo $y,"\n"; +isset($x[f("var_dim_isset")]); +echo $y,"\n"; +unset($x[f("var_dim_unset")]); +echo $y,"\n"; + +// IS_VAR + conversion +$z = $x->{f(7)}; +echo $y,"\n"; +$x->{f(8)} = 1; +echo $y,"\n"; +?> +--EXPECT-- +const_get +const_set +const_call +const_dim_get +const_dim_set +const_dim_isset +const_dim_unset +1 +2 +tmp_get +tmp_set +tmp_call +tmp_dim_get +tmp_dim_set +tmp_dim_isset +tmp_dim_unset +3 +4 +cv_get +cv_set +cv_call +cv_dim_get +cv_dim_set +cv_dim_isset +cv_dim_unset +5 +6 +var_get +var_set +var_call +var_dim_get +var_dim_set +var_dim_isset +var_dim_unset +7 +8 diff --git a/Zend/zend.c b/Zend/zend.c index 22af4592ae85..bc2e6b517f13 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -83,7 +83,6 @@ ZEND_INI_END() ZEND_API int compiler_globals_id; ZEND_API int executor_globals_id; ZEND_API int alloc_globals_id; -zend_class_entry global_main_class; HashTable *global_function_table; HashTable *global_class_table; HashTable *global_constants_table; @@ -495,21 +494,19 @@ static void zend_new_thread_end_handler(THREAD_T thread_id TSRMLS_DC) zend_ini_refresh_caches(ZEND_INI_STAGE_STARTUP TSRMLS_CC); } -#endif - -static void alloc_globals_ctor(zend_alloc_globals *alloc_globals_p TSRMLS_DC) +static void alloc_globals_dtor(zend_alloc_globals *alloc_globals_p TSRMLS_DC) { - start_memory_manager(TSRMLS_C); + shutdown_memory_manager(0, 1 TSRMLS_CC); } +#endif -#ifdef ZTS -static void alloc_globals_dtor(zend_alloc_globals *alloc_globals_p TSRMLS_DC) + +static void alloc_globals_ctor(zend_alloc_globals *alloc_globals_p TSRMLS_DC) { - shutdown_memory_manager(0, 1 TSRMLS_CC); + start_memory_manager(TSRMLS_C); } -#endif #if defined(__FreeBSD__) || defined(__DragonFly__) @@ -706,6 +703,7 @@ void zend_shutdown(TSRMLS_D) zend_hash_destroy(GLOBAL_AUTO_GLOBALS_TABLE); free(GLOBAL_AUTO_GLOBALS_TABLE); + zend_shutdown_extensions(TSRMLS_C); free(zend_version_info); @@ -805,6 +803,13 @@ void zend_deactivate_modules(TSRMLS_D) } zend_end_try(); } +void zend_call_destructors(TSRMLS_D) +{ + zend_try { + shutdown_destructors(TSRMLS_C); + } zend_end_try(); +} + void zend_deactivate(TSRMLS_D) { /* we're no longer executing anything */ @@ -822,6 +827,8 @@ void zend_deactivate(TSRMLS_D) shutdown_compiler(TSRMLS_C); } zend_end_try(); + zend_destroy_rsrc_list(&EG(regular_list) TSRMLS_CC); + zend_try { zend_ini_deactivate(TSRMLS_C); } zend_end_try(); @@ -840,6 +847,7 @@ static int exec_done_cb(zend_module_entry *module TSRMLS_DC) void zend_post_deactivate_modules(TSRMLS_D) { zend_hash_apply(&module_registry, (apply_func_t) exec_done_cb TSRMLS_CC); + zend_hash_apply(&module_registry, (apply_func_t) module_registry_unload_temp TSRMLS_CC); } @@ -866,14 +874,13 @@ ZEND_API int zend_get_configuration_directive(char *name, uint name_length, zval ZEND_API void zend_error(int type, const char *format, ...) { va_list args; + va_list usr_copy; zval ***params; zval *retval; zval *z_error_type, *z_error_message, *z_error_filename, *z_error_lineno, *z_context; char *error_filename; uint error_lineno; zval *orig_user_error_handler; - zval *orig_garbage[2]; - int orig_garbage_ptr; TSRMLS_FETCH(); /* Obtain relevant filename and lineno */ @@ -937,7 +944,15 @@ ZEND_API void zend_error(int type, const char *format, ...) ALLOC_INIT_ZVAL(z_error_lineno); ALLOC_INIT_ZVAL(z_context); - z_error_message->value.str.len = zend_vspprintf(&z_error_message->value.str.val, 0, format, args); +#if defined(va_copy) + va_copy(usr_copy, args); +#else + usr_copy = args; +#endif + z_error_message->value.str.len = zend_vspprintf(&z_error_message->value.str.val, 0, format, usr_copy); +#if defined(va_copy) + va_end(usr_copy); +#endif z_error_message->type = IS_STRING; z_error_type->value.lval = type; @@ -954,7 +969,7 @@ ZEND_API void zend_error(int type, const char *format, ...) z_context->value.ht = EG(active_symbol_table); z_context->type = IS_ARRAY; - ZVAL_ADDREF(z_context); /* we don't want this one to be freed */ + zval_copy_ctor(z_context); params = (zval ***) emalloc(sizeof(zval **)*5); params[0] = &z_error_type; @@ -966,12 +981,6 @@ ZEND_API void zend_error(int type, const char *format, ...) orig_user_error_handler = EG(user_error_handler); EG(user_error_handler) = NULL; - orig_garbage_ptr = EG(garbage_ptr); - EG(garbage_ptr) = 0; - if (orig_garbage_ptr > 0) { - memcpy(&orig_garbage, &EG(garbage), sizeof(zval*)*orig_garbage_ptr); - } - if (call_user_function_ex(CG(function_table), NULL, orig_user_error_handler, &retval, 5, params, 1, NULL TSRMLS_CC)==SUCCESS) { if (retval) { if (Z_TYPE_P(retval) == IS_BOOL && Z_LVAL_P(retval) == 0) { @@ -984,24 +993,18 @@ ZEND_API void zend_error(int type, const char *format, ...) zend_error_cb(type, error_filename, error_lineno, format, args); } - if (orig_garbage_ptr > 0) { - while (EG(garbage_ptr)) { - zval_ptr_dtor(&EG(garbage)[--EG(garbage_ptr)]); - } - EG(garbage_ptr) = orig_garbage_ptr; - memcpy(&EG(garbage), &orig_garbage, sizeof(zval*)*orig_garbage_ptr); + if (!EG(user_error_handler)) { + EG(user_error_handler) = orig_user_error_handler; + } else { + zval_ptr_dtor(&orig_user_error_handler); } - EG(user_error_handler) = orig_user_error_handler; - efree(params); zval_ptr_dtor(&z_error_message); zval_ptr_dtor(&z_error_type); zval_ptr_dtor(&z_error_filename); zval_ptr_dtor(&z_error_lineno); - if (ZVAL_REFCOUNT(z_context) == 2) { - FREE_ZVAL(z_context); - } + zval_ptr_dtor(&z_context); break; } diff --git a/Zend/zend.h b/Zend/zend.h index c9b58779b56e..1785889107cb 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -22,7 +22,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "2.0.1-dev" +#define ZEND_VERSION "2.0.5" #define ZEND_ENGINE_2 @@ -44,13 +44,13 @@ # include "zend_config.w32.h" # define ZEND_PATHS_SEPARATOR ';' #elif defined(NETWARE) -# include "zend_config.nw.h" -# include "acconfig.h" +# include +# define ZEND_PATHS_SEPARATOR ';' #elif defined(__riscos__) -# include "zend_config.h" +# include # define ZEND_PATHS_SEPARATOR ';' #else -# include "zend_config.h" +# include # define ZEND_PATHS_SEPARATOR ':' #endif @@ -91,7 +91,7 @@ const char *zend_mh_bundle_error(void); #endif /* HAVE_MACH_O_DYLD_H */ -#if defined(HAVE_LIBDL) +#if defined(HAVE_LIBDL) && !defined(HAVE_MACH_O_DYLD_H) # ifndef RTLD_LAZY # define RTLD_LAZY 1 /* Solaris 1, FreeBSD's (2.1.7.1 and older) */ @@ -103,6 +103,8 @@ const char *zend_mh_bundle_error(void); # if defined(RTLD_GROUP) && defined(RTLD_WORLD) && defined(RTLD_PARENT) # define DL_LOAD(libname) dlopen(libname, RTLD_LAZY | RTLD_GLOBAL | RTLD_GROUP | RTLD_WORLD | RTLD_PARENT) +# elif defined(RTLD_DEEPBIND) +# define DL_LOAD(libname) dlopen(libname, RTLD_LAZY | RTLD_GLOBAL | RTLD_DEEPBIND) # else # define DL_LOAD(libname) dlopen(libname, RTLD_LAZY | RTLD_GLOBAL) # endif @@ -117,7 +119,7 @@ const char *zend_mh_bundle_error(void); # define ZEND_EXTENSIONS_SUPPORT 1 #elif defined(HAVE_MACH_O_DYLD_H) # define DL_LOAD(libname) zend_mh_bundle_load(libname) -# define DL_UNLOAD(handle) zend_mh_bundle_unload(handle) +# define DL_UNLOAD zend_mh_bundle_unload # define DL_FETCH_SYMBOL(h,s) zend_mh_bundle_symbol(h,s) # define DL_ERROR zend_mh_bundle_error # define DL_HANDLE void * @@ -450,6 +452,7 @@ END_EXTERN_C() void zend_activate(TSRMLS_D); void zend_deactivate(TSRMLS_D); +void zend_call_destructors(TSRMLS_D); void zend_activate_modules(TSRMLS_D); void zend_deactivate_modules(TSRMLS_D); void zend_post_deactivate_modules(TSRMLS_D); @@ -601,6 +604,20 @@ END_EXTERN_C() (*ppzv_dest)->refcount = refcount; \ } +#define SEPARATE_ARG_IF_REF(varptr) \ + if (PZVAL_IS_REF(varptr)) { \ + zval *original_var = varptr; \ + ALLOC_ZVAL(varptr); \ + varptr->value = original_var->value; \ + varptr->type = original_var->type; \ + varptr->is_ref = 0; \ + varptr->refcount = 1; \ + zval_copy_ctor(varptr); \ + } else { \ + varptr->refcount++; \ + } + + #define ZEND_MAX_RESERVED_RESOURCES 4 diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 793727900c11..4f4fcfa18c02 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -152,7 +152,29 @@ ZEND_API int _zend_get_parameters_array_ex(int param_count, zval ***argument_arr } while (param_count-->0) { - *(argument_array++) = (zval **) p-(arg_count--); + zval **value = (zval**)(p-arg_count); + + if (EG(ze1_compatibility_mode) && Z_TYPE_PP(value) == IS_OBJECT) { + zval *value_ptr; + char *class_name; + zend_uint class_name_len; + int dup; + + dup = zend_get_object_classname(*value, &class_name, &class_name_len TSRMLS_CC); + + ALLOC_ZVAL(value_ptr); + *value_ptr = **value; + INIT_PZVAL(value_ptr); + zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name); + if(!dup) { + efree(class_name); + } + value_ptr->value.obj = Z_OBJ_HANDLER_PP(value, clone_obj)(*value TSRMLS_CC); + zval_ptr_dtor(value); + *value = value_ptr; + } + *(argument_array++) = value; + arg_count--; } return SUCCESS; @@ -161,7 +183,10 @@ ZEND_API int _zend_get_parameters_array_ex(int param_count, zval ***argument_arr ZEND_API void zend_wrong_param_count(TSRMLS_D) { - zend_error(E_WARNING, "Wrong parameter count for %s()", get_active_function_name(TSRMLS_C)); + char *space; + char *class_name = get_active_class_name(&space TSRMLS_CC); + + zend_error(E_WARNING, "Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name(TSRMLS_C)); } @@ -209,6 +234,20 @@ ZEND_API zend_class_entry *zend_get_class_entry(zval *zobject TSRMLS_DC) } } +/* returns 1 if you need to copy result, 0 if it's already a copy */ +ZEND_API int zend_get_object_classname(zval *object, char **class_name, zend_uint *class_name_len TSRMLS_DC) +{ + if (Z_OBJ_HT_P(object)->get_class_name == NULL || + Z_OBJ_HT_P(object)->get_class_name(object, class_name, class_name_len, 0 TSRMLS_CC) != SUCCESS) { + zend_class_entry *ce = Z_OBJCE_P(object); + + *class_name = ce->name; + *class_name_len = ce->name_length; + return 1; + } + return 0; +} + static char *zend_parse_arg_impl(zval **arg, va_list *va, char **spec TSRMLS_DC) { @@ -316,11 +355,13 @@ static char *zend_parse_arg_impl(zval **arg, va_list *va, char **spec TSRMLS_DC) *pl = Z_STRLEN_PP(arg); break; case IS_OBJECT: { - if (Z_OBJ_HANDLER_PP(arg, cast_object) - && Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, IS_STRING, 0 TSRMLS_CC) == SUCCESS) { - *pl = Z_STRLEN_PP(arg); - *p = Z_STRVAL_PP(arg); - break; + if (Z_OBJ_HANDLER_PP(arg, cast_object)) { + SEPARATE_ZVAL_IF_NOT_REF(arg); + if (Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, IS_STRING, 0 TSRMLS_CC) == SUCCESS) { + *pl = Z_STRLEN_PP(arg); + *p = Z_STRVAL_PP(arg); + break; + } } } @@ -450,8 +491,10 @@ static int zend_parse_arg(int arg_num, zval **arg, va_list *va, char **spec, int expected_type = zend_parse_arg_impl(arg, va, spec TSRMLS_CC); if (expected_type) { if (!quiet) { - zend_error(E_WARNING, "%s() expects parameter %d to be %s, %s given", - get_active_function_name(TSRMLS_C), arg_num, expected_type, + char *space; + char *class_name = get_active_class_name(&space TSRMLS_CC); + zend_error(E_WARNING, "%s%s%s() expects parameter %d to be %s, %s given", + class_name, space, get_active_function_name(TSRMLS_C), arg_num, expected_type, zend_zval_type_name(*arg)); } return FAILURE; @@ -685,6 +728,21 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destro } +ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC) +{ + if (!class_type->constants_updated) { + zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry); + zend_class_entry *old_scope = *scope; + + *scope = class_type; + zend_hash_apply_with_argument(&class_type->default_properties, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC); + zend_hash_apply_with_argument(class_type->static_members, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC); + *scope = old_scope; + class_type->constants_updated = 1; + } +} + + /* This function requires 'properties' to contain all props declared in the * class and all props being public. If only a subset is given or the class * has protected members then you need to merge the properties seperately by @@ -699,11 +757,7 @@ ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type zend_error(E_ERROR, "Cannot instantiate %s %s", what, class_type->name); } - if (!class_type->constants_updated) { - zend_hash_apply_with_argument(&class_type->default_properties, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC); - zend_hash_apply_with_argument(class_type->static_members, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC); - class_type->constants_updated = 1; - } + zend_update_class_constants(class_type TSRMLS_CC); arg->type = IS_OBJECT; if (class_type->create_object == NULL) { @@ -1216,6 +1270,29 @@ ZEND_API int zend_startup_module(zend_module_entry *module) return zend_register_module_ex(module TSRMLS_CC); } +void zend_check_magic_method_implementation(zend_class_entry *ce, zend_function *fptr, int error_type TSRMLS_DC) +{ + char lcname[16]; + int name_len; + + /* we don't care if the function name is longer, in fact lowercasing only + * the beginning of the name speeds up the check process */ + name_len = strlen(fptr->common.function_name); + zend_str_tolower_copy(lcname, fptr->common.function_name, MIN(name_len, sizeof(lcname)-1)); + lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */ + + if (name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)) && fptr->common.num_args != 0) { + zend_error(error_type, "Destuctor %s::%s() cannot take arguments", ce->name, ZEND_DESTRUCTOR_FUNC_NAME); + } else if (name_len == sizeof(ZEND_CLONE_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)) && fptr->common.num_args != 0) { + zend_error(error_type, "Method %s::%s() cannot accept any arguments", ce->name, ZEND_CLONE_FUNC_NAME); + } else if (name_len == sizeof(ZEND_GET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)) && fptr->common.num_args != 1) { + zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_GET_FUNC_NAME); + } else if (name_len == sizeof(ZEND_SET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)) && fptr->common.num_args != 2) { + zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_SET_FUNC_NAME); + } else if (name_len == sizeof(ZEND_CALL_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)) && fptr->common.num_args != 2) { + zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_CALL_FUNC_NAME); + } +} /* registers all functions in *library_functions in the function hash */ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC) @@ -1226,9 +1303,11 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr int count=0, unload=0; HashTable *target_function_table = function_table; int error_type; - zend_function *ctor = NULL, *dtor = NULL, *clone = NULL; + zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__call = NULL; char *lowercase_name; int fname_len; + char *lc_class_name; + int class_name_len; if (type==MODULE_PERSISTENT) { error_type = E_CORE_WARNING; @@ -1240,6 +1319,11 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr target_function_table = CG(function_table); } internal_function->type = ZEND_INTERNAL_FUNCTION; + + if (scope) { + class_name_len = strlen(scope->name); + lc_class_name = zend_str_tolower_dup(scope->name, class_name_len); + } while (ptr->fname) { internal_function->handler = ptr->handler; @@ -1267,7 +1351,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr if (ptr->flags) { if (!(ptr->flags & ZEND_ACC_PPP_MASK)) { zend_error(error_type, "Invalid access level for %s%s%s() - access must be exactly one of public, protected or private", scope ? scope->name : "", scope ? "::" : "", ptr->fname); - internal_function->fn_flags |= ZEND_ACC_PUBLIC; + internal_function->fn_flags = ZEND_ACC_PUBLIC; } else { internal_function->fn_flags = ptr->flags; } @@ -1309,18 +1393,28 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr * If it's an old-style constructor, store it only if we don't have * a constructor already. */ - if (!strcmp(ptr->fname, scope->name) && !ctor) { + if ((fname_len == class_name_len) && !memcmp(lowercase_name, lc_class_name, class_name_len+1) && !ctor) { ctor = reg_function; - } else if (!strcmp(ptr->fname, ZEND_CONSTRUCTOR_FUNC_NAME)) { + } else if ((fname_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME))) { ctor = reg_function; - } else if (!strcmp(ptr->fname, ZEND_DESTRUCTOR_FUNC_NAME)) { + } else if ((fname_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME))) { dtor = reg_function; if (internal_function->num_args) { zend_error(error_type, "Destructor %s::%s() cannot take arguments", scope->name, ptr->fname); } - - } else if (!strcmp(ptr->fname, ZEND_CLONE_FUNC_NAME)) { + } else if ((fname_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME))) { clone = reg_function; + } else if ((fname_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME))) { + __call = reg_function; + } else if ((fname_len == sizeof(ZEND_GET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME))) { + __get = reg_function; + } else if ((fname_len == sizeof(ZEND_SET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME))) { + __set = reg_function; + } else { + reg_function = NULL; + } + if (reg_function) { + zend_check_magic_method_implementation(scope, reg_function, error_type TSRMLS_CC); } } ptr++; @@ -1328,9 +1422,12 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr free_alloca(lowercase_name); } if (unload) { /* before unloading, display all remaining bad function in the module */ + if (scope) { + efree(lc_class_name); + } while (ptr->fname) { if (zend_hash_exists(target_function_table, ptr->fname, strlen(ptr->fname)+1)) { - zend_error(error_type, "Function registration failed - duplicate name - %s", ptr->fname); + zend_error(error_type, "Function registration failed - duplicate name - %s%s%s", scope ? scope->name : "", scope ? "::" : "", ptr->fname); } ptr++; } @@ -1341,27 +1438,49 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr scope->constructor = ctor; scope->destructor = dtor; scope->clone = clone; + scope->__call = __call; + scope->__get = __get; + scope->__set = __set; if (ctor) { ctor->common.fn_flags |= ZEND_ACC_CTOR; if (ctor->common.fn_flags & ZEND_ACC_STATIC) { - zend_error(error_type, "Constructor %s::%s cannot be static", ctor->common.scope->name, ctor->common.function_name); + zend_error(error_type, "Constructor %s::%s() cannot be static", scope->name, ctor->common.function_name); } ctor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (dtor) { dtor->common.fn_flags |= ZEND_ACC_DTOR; if (dtor->common.fn_flags & ZEND_ACC_STATIC) { - zend_error(error_type, "Destructor %s::%s cannot be static", dtor->common.scope->name, dtor->common.function_name); + zend_error(error_type, "Destructor %s::%s() cannot be static", scope->name, dtor->common.function_name); } dtor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (clone) { clone->common.fn_flags |= ZEND_ACC_CLONE; if (clone->common.fn_flags & ZEND_ACC_STATIC) { - zend_error(error_type, "Constructor %s::%s cannot be static", clone->common.scope->name, clone->common.function_name); + zend_error(error_type, "Constructor %s::%s() cannot be static", scope->name, clone->common.function_name); } clone->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } + if (__call) { + if (__call->common.fn_flags & ZEND_ACC_STATIC) { + zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __call->common.function_name); + } + __call->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; + } + if (__get) { + if (__get->common.fn_flags & ZEND_ACC_STATIC) { + zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __get->common.function_name); + } + __get->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; + } + if (__set) { + if (__set->common.fn_flags & ZEND_ACC_STATIC) { + zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __set->common.function_name); + } + __set->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; + } + efree(lc_class_name); } return SUCCESS; } @@ -1415,9 +1534,6 @@ void module_destructor(zend_module_entry *module) if (module->type == MODULE_TEMPORARY) { zend_clean_module_rsrc_dtors(module->module_number TSRMLS_CC); clean_module_constants(module->module_number TSRMLS_CC); - if (module->request_shutdown_func) { - module->request_shutdown_func(module->type, module->module_number TSRMLS_CC); - } } if (module->module_started && module->module_shutdown_func) { @@ -1431,9 +1547,9 @@ void module_destructor(zend_module_entry *module) zend_unregister_functions(module->functions, -1, NULL TSRMLS_CC); } -#if HAVE_LIBDL +#if HAVE_LIBDL || defined(HAVE_MACH_O_DYLD_H) if (module->handle) { - dlclose(module->handle); + DL_UNLOAD(module->handle); } #endif } @@ -1455,24 +1571,23 @@ int module_registry_request_startup(zend_module_entry *module TSRMLS_DC) } -/* for persistent modules - call request shutdown and flag NOT to erase - * for temporary modules - do nothing, and flag to erase - */ +/* call request shutdown for all modules */ int module_registry_cleanup(zend_module_entry *module TSRMLS_DC) { - switch (module->type) { - case MODULE_PERSISTENT: - if (module->request_shutdown_func) { + if (module->request_shutdown_func) { #if 0 - zend_printf("%s: Request shutdown\n", module->name); + zend_printf("%s: Request shutdown\n", module->name); #endif - module->request_shutdown_func(module->type, module->module_number TSRMLS_CC); - } - return 0; - break; + module->request_shutdown_func(module->type, module->module_number TSRMLS_CC); + } + return 0; +} + +int module_registry_unload_temp(zend_module_entry *module TSRMLS_DC) +{ + switch (module->type) { case MODULE_TEMPORARY: return 1; - break; } return 0; } @@ -1534,7 +1649,9 @@ ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *cla ZEND_API void zend_class_implements(zend_class_entry *class_entry TSRMLS_DC, int num_interfaces, ...) { zend_class_entry *interface_entry; + int ce_num = class_entry->num_interfaces, impl_num; va_list interface_list; + va_start(interface_list, num_interfaces); if (class_entry->type & ZEND_INTERNAL_CLASS) { class_entry->interfaces = realloc(class_entry->interfaces, sizeof(zend_class_entry*) * (class_entry->num_interfaces+num_interfaces)); @@ -1542,11 +1659,13 @@ ZEND_API void zend_class_implements(zend_class_entry *class_entry TSRMLS_DC, int class_entry->interfaces = erealloc(class_entry->interfaces, sizeof(zend_class_entry*) * (class_entry->num_interfaces+num_interfaces)); } - va_start(interface_list, num_interfaces); while (num_interfaces--) { interface_entry = va_arg(interface_list, zend_class_entry *); class_entry->interfaces[class_entry->num_interfaces++] = interface_entry; - zend_do_implement_interface(class_entry, interface_entry TSRMLS_CC); + } + impl_num = class_entry->num_interfaces; + while(ce_num < impl_num) { + zend_do_implement_interface(class_entry, class_entry->interfaces[ce_num++] TSRMLS_CC); } va_end(interface_list); } @@ -1639,7 +1758,7 @@ ZEND_API int zend_disable_class(char *class_name, uint class_name_length TSRMLS_ return 1; } -ZEND_API zend_bool zend_is_callable(zval *callable, zend_bool syntax_only, char **callable_name) +ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **callable_name) { char *lcname; zend_bool retval = 0; @@ -1650,7 +1769,7 @@ ZEND_API zend_bool zend_is_callable(zval *callable, zend_bool syntax_only, char if (callable_name) { *callable_name = estrndup(Z_STRVAL_P(callable), Z_STRLEN_P(callable)); } - if (syntax_only) { + if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) { return 1; } @@ -1687,7 +1806,7 @@ ZEND_API zend_bool zend_is_callable(zval *callable, zend_bool syntax_only, char memcpy(ptr, Z_STRVAL_PP(method), Z_STRLEN_PP(method) + 1); } - if (syntax_only) + if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) return 1; lcname = zend_str_tolower_dup(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj)); @@ -1716,14 +1835,27 @@ ZEND_API zend_bool zend_is_callable(zval *callable, zend_bool syntax_only, char memcpy(ptr, Z_STRVAL_PP(method), Z_STRLEN_PP(method) + 1); } - if (syntax_only) + if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) return 1; } if (ce) { + zend_function *fbc; + lcname = zend_str_tolower_dup(Z_STRVAL_PP(method), Z_STRLEN_PP(method)); - if (zend_hash_exists(&ce->function_table, lcname, Z_STRLEN_PP(method)+1)) { + if (zend_hash_find(&ce->function_table, lcname, Z_STRLEN_PP(method)+1, (void **)&fbc) == SUCCESS) { retval = 1; + if ((check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0) { + if (fbc->op_array.fn_flags & ZEND_ACC_PRIVATE) { + if (!zend_check_private(fbc, (Z_TYPE_PP(obj) == IS_STRING)?EG(scope):(*obj)->value.obj.handlers->get_class_entry(*obj TSRMLS_CC), lcname, Z_STRLEN_PP(method) TSRMLS_CC)) { + retval = 0; + } + } else if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) { + if (!zend_check_protected(fbc->common.scope, EG(scope))) { + retval = 0; + } + } + } } /* check for __call too */ if (retval == 0 && ce->__call != 0) { @@ -1755,8 +1887,10 @@ ZEND_API zend_bool zend_is_callable(zval *callable, zend_bool syntax_only, char ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRMLS_DC) { - char *lcname, *func; + char *lcname, *func, *class_name; zend_bool retval = 0; + zend_class_entry **pce; + int class_name_len; if (zend_is_callable(callable, 0, callable_name)) { return 1; @@ -1766,12 +1900,18 @@ ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRML lcname = zend_str_tolower_dup(Z_STRVAL_P(callable), Z_STRLEN_P(callable)); if ((func = strstr(lcname, "::")) != NULL) { - zval_dtor(callable); - array_init(callable); - add_next_index_stringl(callable, lcname, func - lcname, 1); - func += 2; - add_next_index_stringl(callable, func, strlen(func), 1); - retval = 1; + *func = '\0'; + class_name_len = func - lcname; + class_name = estrndup(Z_STRVAL_P(callable), class_name_len); + if (zend_lookup_class(class_name, class_name_len, &pce TSRMLS_CC) == SUCCESS) { + zval_dtor(callable); + array_init(callable); + add_next_index_stringl(callable, lcname, class_name_len, 1); + func += 2; + add_next_index_stringl(callable, func, strlen(func), 1); + retval = 1; + } + efree(class_name); } efree(lcname); break; @@ -1911,7 +2051,12 @@ ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, char * EG(scope) = scope; if (!Z_OBJ_HT_P(object)->write_property) { - zend_error(E_CORE_ERROR, "Property %s of class %s cannot be updated", Z_OBJCE_P(object)->name, name); + char *class_name; + zend_uint class_name_len; + + zend_get_object_classname(object, &class_name, &class_name_len TSRMLS_CC); + + zend_error(E_CORE_ERROR, "Property %s of class %s cannot be updated", name, class_name); } ZVAL_STRINGL(&property, name, name_length, 0); Z_OBJ_HT_P(object)->write_property(object, &property, value TSRMLS_CC); @@ -1960,7 +2105,11 @@ ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *n EG(scope) = scope; if (!Z_OBJ_HT_P(object)->read_property) { - zend_error(E_CORE_ERROR, "Property %s of class %s cannot be read", Z_OBJCE_P(object)->name, name); + char *class_name; + zend_uint class_name_len; + + zend_get_object_classname(object, &class_name, &class_name_len TSRMLS_CC); + zend_error(E_CORE_ERROR, "Property %s of class %s cannot be read", name, class_name); } ZVAL_STRINGL(&property, name, name_length, 0); value = Z_OBJ_HT_P(object)->read_property(object, &property, silent TSRMLS_CC); diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 353b9385a48e..0e226421b218 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -168,6 +168,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr ZEND_API void zend_unregister_functions(zend_function_entry *functions, int count, HashTable *function_table TSRMLS_DC); ZEND_API int zend_register_module(zend_module_entry *module_entry); ZEND_API int zend_register_module_ex(zend_module_entry *module TSRMLS_DC); +void zend_check_magic_method_implementation(zend_class_entry *ce, zend_function *fptr, int error_type TSRMLS_DC); ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *class_entry TSRMLS_DC); ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce, char *parent_name TSRMLS_DC); @@ -178,7 +179,11 @@ ZEND_API int zend_disable_function(char *function_name, uint function_name_lengt ZEND_API int zend_disable_class(char *class_name, uint class_name_length TSRMLS_DC); ZEND_API void zend_wrong_param_count(TSRMLS_D); -ZEND_API zend_bool zend_is_callable(zval *callable, zend_bool syntax_only, char **callable_name); + +#define IS_CALLABLE_CHECK_SYNTAX_ONLY (1<<0) +#define IS_CALLABLE_CHECK_NO_ACCESS (1<<1) + +ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **callable_name); ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRMLS_DC); ZEND_API char *zend_get_module_version(char *module_name); ZEND_API int zend_get_module_started(char *module_name); @@ -187,6 +192,7 @@ ZEND_API int zend_declare_property_null(zend_class_entry *ce, char *name, int na ZEND_API int zend_declare_property_long(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC); ZEND_API int zend_declare_property_string(zend_class_entry *ce, char *name, int name_length, char *value, int access_type TSRMLS_DC); +ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC); ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, char *name, int name_length, zval *value TSRMLS_DC); ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, char *name, int name_length TSRMLS_DC); ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC); @@ -195,6 +201,7 @@ ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *name, int name_length, zend_bool silent TSRMLS_DC); ZEND_API zend_class_entry *zend_get_class_entry(zval *zobject TSRMLS_DC); +ZEND_API int zend_get_object_classname(zval *object, char **class_name, zend_uint *class_name_len TSRMLS_DC); #define getThis() (this_ptr) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index ff80a702b1a0..d0e42461fa8c 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -23,6 +23,7 @@ #include "zend_alloc.h" #include "zend_globals.h" #include "zend_fast_cache.h" +#include "zend_execute.h" #ifdef HAVE_SIGNAL_H # include #endif @@ -36,6 +37,41 @@ ZEND_API zend_alloc_globals alloc_globals; #endif +ZEND_API void zend_mm_safe_error_ex(const char *format, ...) +{ + char *error_filename; + uint error_lineno; + char buf[1024]; + va_list args; + TSRMLS_FETCH(); + + if (zend_is_compiling(TSRMLS_C)) { + error_filename = zend_get_compiled_filename(TSRMLS_C); + error_lineno = zend_get_compiled_lineno(TSRMLS_C); + } else if (zend_is_executing(TSRMLS_C)) { + error_filename = zend_get_executed_filename(TSRMLS_C); + error_lineno = zend_get_executed_lineno(TSRMLS_C); + } else { + error_filename = NULL; + error_lineno = 0; + } + if (!error_filename) { + error_filename = "Unknown"; + } + + va_start(args, format); + vsnprintf(buf, sizeof(buf), format, args); + va_end(args); + + fprintf(stderr, "\nFatal error: %s in %s on line %d\n", buf, error_filename, error_lineno); +/* See http://support.microsoft.com/kb/190351 */ +#ifdef ZEND_WIN32 + fflush(stderr); +#endif + + _exit(1); +} + #ifdef ZEND_MM #define ZEND_DISABLE_MEMORY_CACHE 0 @@ -75,20 +111,11 @@ static long mem_block_end_magic = MEM_BLOCK_END_MAGIC; #define _CHECK_MEMORY_LIMIT(s, rs, file, lineno) { AG(allocated_memory) += rs;\ if (AG(memory_limit) AG(allocated_memory) - rs) { \ - AG(memory_limit) = AG(allocated_memory) + 1048576; \ - if (file) { \ - zend_error(E_ERROR,"Allowed memory size of %d bytes exhausted at %s:%d (tried to allocate %d bytes)", php_mem_limit, file, lineno, s); \ - } else { \ - zend_error(E_ERROR,"Allowed memory size of %d bytes exhausted (tried to allocate %d bytes)", php_mem_limit, s); \ - } \ + AG(allocated_memory) -= rs; \ + if (file) { \ + zend_mm_safe_error_ex("Allowed memory size of %d bytes exhausted at %s:%d (tried to allocate %zu bytes)", php_mem_limit, (const char *) (file), lineno, (size_t) (s)); \ } else { \ - if (file) { \ - fprintf(stderr, "Allowed memory size of %d bytes exhausted at %s:%d (tried to allocate %d bytes)\n", php_mem_limit, file, lineno, s); \ - } else { \ - fprintf(stderr, "Allowed memory size of %d bytes exhausted (tried to allocate %d bytes)\n", php_mem_limit, s); \ - } \ - exit(1); \ + zend_mm_safe_error_ex("Allowed memory size of %d bytes exhausted (tried to allocate %zu bytes)", php_mem_limit, (size_t) (s)); \ } \ } \ } @@ -191,7 +218,7 @@ ZEND_API void *_emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) #if ZEND_DEBUG && defined(HAVE_KILL) && defined(HAVE_GETPID) kill(getpid(), SIGSEGV); #else - exit(1); + _exit(1); #endif HANDLE_UNBLOCK_INTERRUPTIONS(); return (void *)p; @@ -239,7 +266,7 @@ ZEND_API void *_safe_emalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_ } } - zend_error(E_ERROR, "Possible integer overflow in memory allocation (%zd * %zd + %zd)", nmemb, size, offset); + zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zd * %zd + %zd)", nmemb, size, offset); return 0; } @@ -349,7 +376,7 @@ ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LIN #if ZEND_DEBUG && HAVE_KILL && HAVE_GETPID kill(getpid(), SIGSEGV); #else - exit(1); + _exit(1); #endif } ADD_POINTER_TO_LIST(orig); @@ -388,7 +415,6 @@ ZEND_API char *_estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) return p; } - ZEND_API char *_estrndup(const char *s, uint length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { char *p; @@ -481,7 +507,7 @@ ZEND_API void shutdown_memory_manager(int silent, int full_shutdown TSRMLS_DC) unsigned int i, j; zend_mem_header *ptr; - for (i=1; i +#undef _GNU_SOURCE + +/* Standard wrapper macros */ +#define emalloc(size) malloc(size) +#define safe_emalloc(nmemb, size, offset) malloc((nmemb) * (size) + (offset)) +#define efree(ptr) free(ptr) +#define ecalloc(nmemb, size) calloc((nmemb), (size)) +#define erealloc(ptr, size) realloc((ptr), (size)) +#define erealloc_recoverable(ptr, size) realloc((ptr), (size)) +#define estrdup(s) strdup(s) +#define estrndup(s, length) zend_strndup((s), (length)) + +/* Relay wrapper macros */ +#define emalloc_rel(size) malloc(size) +#define safe_emalloc_rel(nmemb, size, offset) malloc((nmemb) * (size) + (offset)) +#define efree_rel(ptr) free(ptr) +#define ecalloc_rel(nmemb, size) calloc((nmemb), (size)) +#define erealloc_rel(ptr, size) realloc((ptr), (size)) +#define erealloc_recoverable_rel(ptr, size) realloc((ptr), (size)) +#define estrdup_rel(s) strdup(s) +#define estrndup_rel(s, length) zend_strndup((s), (length)) + +/* Selective persistent/non persistent allocation macros */ +#define pemalloc(size, persistent) malloc(size) +#define pefree(ptr, persistent) free(ptr) +#define pecalloc(nmemb, size, persistent) calloc((nmemb), (size)) +#define perealloc(ptr, size, persistent) realloc((ptr), (size)) +#define perealloc_recoverable(ptr, size, persistent) realloc((ptr), (size)) +#define pestrdup(s, persistent) strdup(s) + +#define pemalloc_rel(size, persistent) malloc(size) +#define pefree_rel(ptr, persistent) free(ptr) +#define pecalloc_rel(nmemb, size, persistent) calloc((nmemb), (size)) +#define perealloc_rel(ptr, size, persistent) realloc((ptr), (size)) +#define perealloc_recoverable_rel(ptr, size, persistent) realloc((ptr), (size)) +#define pestrdup_rel(s, persistent) strdup(s) +#endif /* !USE_ZEND_ALLOC */ + #define safe_estrdup(ptr) ((ptr)?(estrdup(ptr)):(empty_string)) #define safe_estrndup(ptr, len) ((ptr)?(estrndup((ptr), (len))):(empty_string)) @@ -139,6 +183,11 @@ void zend_debug_alloc_output(char *format, ...); #define full_mem_check(silent) #endif +#if defined(__GNUC__) && __GNUC__ >= 3 +ZEND_API void zend_mm_safe_error_ex(const char *format, ...) __attribute__ ((noreturn, format(printf, 1, 2))); +#else +ZEND_API void zend_mm_safe_error_ex(const char *format, ...); +#endif END_EXTERN_C() diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index eb6729145396..7513e62f9afe 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -44,6 +44,7 @@ static ZEND_FUNCTION(get_class); static ZEND_FUNCTION(get_parent_class); static ZEND_FUNCTION(method_exists); static ZEND_FUNCTION(class_exists); +static ZEND_FUNCTION(interface_exists); static ZEND_FUNCTION(function_exists); #if ZEND_DEBUG static ZEND_FUNCTION(leak); @@ -102,6 +103,7 @@ static zend_function_entry builtin_functions[] = { ZEND_FE(get_parent_class, NULL) ZEND_FE(method_exists, NULL) ZEND_FE(class_exists, NULL) + ZEND_FE(interface_exists, NULL) ZEND_FE(function_exists, NULL) #if ZEND_DEBUG ZEND_FE(leak, NULL) @@ -431,7 +433,7 @@ ZEND_FUNCTION(error_reporting) /* }}} */ -/* {{{ proto bool define(string constant_name, mixed value, case_sensitive=true) +/* {{{ proto bool define(string constant_name, mixed value, boolean case_sensitive=true) Define a new constant */ ZEND_FUNCTION(define) { @@ -521,6 +523,7 @@ ZEND_FUNCTION(get_class) zval **arg; char *name = ""; zend_uint name_len = 0; + int dup; if (!ZEND_NUM_ARGS()) { if (EG(scope)) { @@ -536,19 +539,9 @@ ZEND_FUNCTION(get_class) RETURN_FALSE; } - if (Z_OBJ_HT_PP(arg)->get_class_name == NULL || - Z_OBJ_HT_PP(arg)->get_class_name(*arg, &name, &name_len, 0 TSRMLS_CC) != SUCCESS) { - zend_class_entry *ce; + dup = zend_get_object_classname(*arg, &name, &name_len TSRMLS_CC); - ce = zend_get_class_entry(*arg TSRMLS_CC); - if (!ce) { - RETURN_FALSE; - } - - RETURN_STRINGL(ce->name, ce->name_length, 1); - } - - RETURN_STRINGL(name, name_len, 0); + RETURN_STRINGL(name, name_len, dup); } /* }}} */ @@ -601,12 +594,21 @@ static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass) ZEND_WRONG_PARAM_COUNT(); } - if (Z_TYPE_PP(obj) != IS_OBJECT) { + if (only_subclass && Z_TYPE_PP(obj) == IS_STRING) { + zend_class_entry **the_ce; + if (zend_lookup_class(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), &the_ce TSRMLS_CC) == FAILURE) { + zend_error(E_WARNING, "Unknown class passed as parameter"); + RETURN_FALSE; + } + instance_ce = *the_ce; + } else if (Z_TYPE_PP(obj) != IS_OBJECT) { RETURN_FALSE; + } else { + instance_ce = NULL; } /* TBI!! new object handlers */ - if (!HAS_CLASS_ENTRY(**obj)) { + if (Z_TYPE_PP(obj) == IS_OBJECT && !HAS_CLASS_ENTRY(**obj)) { RETURN_FALSE; } @@ -616,7 +618,11 @@ static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass) retval = 0; } else { if (only_subclass) { - instance_ce = Z_OBJCE_PP(obj)->parent; + if (!instance_ce) { + instance_ce = Z_OBJCE_PP(obj)->parent; + } else { + instance_ce = instance_ce->parent; + } } else { instance_ce = Z_OBJCE_PP(obj); } @@ -655,30 +661,72 @@ ZEND_FUNCTION(is_a) /* }}} */ +/* {{{ add_class_vars */ +static void add_class_vars(zend_class_entry *ce, HashTable *properties, zval *return_value TSRMLS_DC) +{ + int instanceof = EG(scope) && instanceof_function(EG(scope), ce TSRMLS_CC); + + if (zend_hash_num_elements(properties) > 0) { + HashPosition pos; + zval **prop; + + zend_hash_internal_pointer_reset_ex(properties, &pos); + while (zend_hash_get_current_data_ex(properties, (void **) &prop, &pos) == SUCCESS) { + char *key, *class_name, *prop_name; + uint key_len; + ulong num_index; + zval *prop_copy; + + zend_hash_get_current_key_ex(properties, &key, &key_len, &num_index, 0, &pos); + zend_hash_move_forward_ex(properties, &pos); + zend_unmangle_property_name(key, &class_name, &prop_name); + if (class_name) { + if (class_name[0] != '*' && strcmp(class_name, ce->name)) { + /* filter privates from base classes */ + continue; + } else if (!instanceof) { + /* filter protected if not inside class */ + continue; + } + } + + /* copy: enforce read only access */ + ALLOC_ZVAL(prop_copy); + *prop_copy = **prop; + zval_copy_ctor(prop_copy); + INIT_PZVAL(prop_copy); + + /* this is necessary to make it able to work with default array + * properties, returned to user */ + if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || Z_TYPE_P(prop_copy) == IS_CONSTANT) { + zval_update_constant(&prop_copy, 0 TSRMLS_CC); + } + + add_assoc_zval(return_value, prop_name, prop_copy); + } + } +} +/* }}} */ + + /* {{{ proto array get_class_vars(string class_name) - Returns an array of default properties of the class */ + Returns an array of default properties of the class. */ ZEND_FUNCTION(get_class_vars) { - zval **class_name; - zend_class_entry *ce, **pce; - zval *tmp; + char *class_name; + int class_name_len; + zend_class_entry **pce; - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &class_name)==FAILURE) { - ZEND_WRONG_PARAM_COUNT(); + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &class_name, &class_name_len) == FAILURE) { + return; } - convert_to_string_ex(class_name); - - if (zend_lookup_class(Z_STRVAL_PP(class_name), Z_STRLEN_PP(class_name), &pce TSRMLS_CC) == FAILURE) { + if (zend_lookup_class(class_name, class_name_len, &pce TSRMLS_CC) == FAILURE) { RETURN_FALSE; } else { - ce = *pce; array_init(return_value); - if (!ce->constants_updated) { - zend_hash_apply_with_argument(&ce->default_properties, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC); - ce->constants_updated = 1; - } - zend_hash_copy(return_value->value.ht, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); + add_class_vars(*pce, &(*pce)->default_properties, return_value TSRMLS_CC); + add_class_vars(*pce, (*pce)->static_members, return_value TSRMLS_CC); } } /* }}} */ @@ -692,9 +740,10 @@ ZEND_FUNCTION(get_object_vars) zval **value; HashTable *properties; HashPosition pos; - char *key; + char *key, *prop_name, *class_name; uint key_len; ulong num_index; + int instanceof; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &obj) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); @@ -707,16 +756,27 @@ ZEND_FUNCTION(get_object_vars) RETURN_FALSE; } + instanceof = EG(This) && instanceof_function(Z_OBJCE_P(EG(This)), Z_OBJCE_PP(obj) TSRMLS_CC); + array_init(return_value); properties = Z_OBJ_HT_PP(obj)->get_properties(*obj TSRMLS_CC); zend_hash_internal_pointer_reset_ex(properties, &pos); while (zend_hash_get_current_data_ex(properties, (void **) &value, &pos) == SUCCESS) { - if (zend_hash_get_current_key_ex(properties, &key, &key_len, &num_index, 0, &pos) == HASH_KEY_IS_STRING && key[0]) { + if (zend_hash_get_current_key_ex(properties, &key, &key_len, &num_index, 0, &pos) == HASH_KEY_IS_STRING) { + if (key[0]) { /* Not separating references */ (*value)->refcount++; add_assoc_zval_ex(return_value, key, key_len, *value); + } else if (instanceof) { + zend_unmangle_property_name(key, &class_name, &prop_name); + if (!memcmp(class_name, "*", 2) || (Z_OBJCE_P(EG(This)) == Z_OBJCE_PP(obj) && !strcmp(Z_OBJCE_P(EG(This))->name, class_name))) { + /* Not separating references */ + (*value)->refcount++; + add_assoc_zval_ex(return_value, prop_name, strlen(prop_name)+1, *value); + } + } } zend_hash_move_forward_ex(properties, &pos); } @@ -758,14 +818,20 @@ ZEND_FUNCTION(get_class_methods) zend_hash_internal_pointer_reset_ex(&ce->function_table, &pos); while (zend_hash_get_current_data_ex(&ce->function_table, (void **) &mptr, &pos) == SUCCESS) { - MAKE_STD_ZVAL(method_name); - ZVAL_STRING(method_name, mptr->common.function_name, 1); - zend_hash_next_index_insert(return_value->value.ht, &method_name, sizeof(zval *), NULL); + if ((mptr->common.fn_flags & ZEND_ACC_PUBLIC) + || (EG(scope) && + (((mptr->common.fn_flags & ZEND_ACC_PROTECTED) && + instanceof_function(EG(scope), mptr->common.scope TSRMLS_CC)) + || ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) && + EG(scope) == mptr->common.scope)))) { + MAKE_STD_ZVAL(method_name); + ZVAL_STRING(method_name, mptr->common.function_name, 1); + zend_hash_next_index_insert(return_value->value.ht, &method_name, sizeof(zval *), NULL); + } zend_hash_move_forward_ex(&ce->function_table, &pos); } } /* }}} */ -\ /* {{{ proto bool method_exists(object object, string method) @@ -819,11 +885,42 @@ ZEND_FUNCTION(class_exists) found = zend_hash_find(EG(class_table), lc_name, class_name_len+1, (void **) &ce); free_alloca(lc_name); - RETURN_BOOL(found == SUCCESS); + RETURN_BOOL(found == SUCCESS && !((*ce)->ce_flags & ZEND_ACC_INTERFACE)); } if (zend_lookup_class(class_name, class_name_len, &ce TSRMLS_CC) == SUCCESS) { - RETURN_TRUE; + RETURN_BOOL(((*ce)->ce_flags & ZEND_ACC_INTERFACE) == 0); + } else { + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ proto bool interface_exists(string classname [, bool autoload]) + Checks if the class exists */ +ZEND_FUNCTION(interface_exists) +{ + char *iface_name, *lc_name; + zend_class_entry **ce; + int iface_name_len; + zend_bool autoload = 1; + int found; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &iface_name, &iface_name_len, &autoload) == FAILURE) { + return; + } + + if (!autoload) { + lc_name = do_alloca(iface_name_len + 1); + zend_str_tolower_copy(lc_name, iface_name, iface_name_len); + + found = zend_hash_find(EG(class_table), lc_name, iface_name_len+1, (void **) &ce); + free_alloca(lc_name); + RETURN_BOOL(found == SUCCESS && (*ce)->ce_flags & ZEND_ACC_INTERFACE); + } + + if (zend_lookup_class(iface_name, iface_name_len, &ce TSRMLS_CC) == SUCCESS) { + RETURN_BOOL(((*ce)->ce_flags & ZEND_ACC_INTERFACE) > 0); } else { RETURN_FALSE; } @@ -1035,13 +1132,15 @@ ZEND_FUNCTION(set_exception_handler) ZEND_WRONG_PARAM_COUNT(); } - if (!zend_is_callable(*exception_handler, 0, &exception_handler_name)) { - zend_error(E_WARNING, "%s() expects the argument (%s) to be a valid callback", - get_active_function_name(TSRMLS_C), exception_handler_name?exception_handler_name:"unknown"); + if (Z_TYPE_PP(exception_handler) != IS_NULL) { /* NULL == unset */ + if (!zend_is_callable(*exception_handler, 0, &exception_handler_name)) { + zend_error(E_WARNING, "%s() expects the argument (%s) to be a valid callback", + get_active_function_name(TSRMLS_C), exception_handler_name?exception_handler_name:"unknown"); + efree(exception_handler_name); + return; + } efree(exception_handler_name); - return; } - efree(exception_handler_name); if (EG(user_exception_handler)) { had_orig_exception_handler = 1; @@ -1051,7 +1150,7 @@ ZEND_FUNCTION(set_exception_handler) } ALLOC_ZVAL(EG(user_exception_handler)); - if (Z_STRLEN_PP(exception_handler)==0) { /* unset user-defined handler */ + if (Z_TYPE_PP(exception_handler) == IS_NULL) { /* unset user-defined handler */ FREE_ZVAL(EG(user_exception_handler)); EG(user_exception_handler) = NULL; RETURN_TRUE; @@ -1421,6 +1520,12 @@ static zval *debug_backtrace_get_args(void ***curpos TSRMLS_DC) (*arg)->refcount++; add_next_index_zval(arg_array, *arg); } + + /* skip args from incomplete frames */ + while ((((*curpos)-1) > EG(argument_stack).elements) && *((*curpos)-1)) { + (*curpos)--; + } + return arg_array; } @@ -1443,7 +1548,7 @@ void debug_print_backtrace_args(zval *arg_array TSRMLS_DC) /* {{{ proto void debug_print_backtrace(void) */ ZEND_FUNCTION(debug_print_backtrace) { - zend_execute_data *ptr; + zend_execute_data *ptr, *skip; int lineno; char *function_name; char *filename; @@ -1468,6 +1573,11 @@ ZEND_FUNCTION(debug_print_backtrace) args -= *(ulong*)args; frames_on_stack++; + /* skip args from incomplete frames */ + while (((args-1) > EG(argument_stack).elements) && *(args-1)) { + args--; + } + if ((args-1) == EG(argument_stack).elements) { arg_stack_consistent = 1; break; @@ -1481,13 +1591,35 @@ ZEND_FUNCTION(debug_print_backtrace) cur_arg_pos -= 2; frames_on_stack--; + if (arg_stack_consistent) { + /* skip args from incomplete frames */ + while (((cur_arg_pos-1) > EG(argument_stack).elements) && *(cur_arg_pos-1)) { + cur_arg_pos--; + } + } + array_init(return_value); while (ptr) { - class_name = call_type = NULL; - if (ptr->op_array) { - filename = ptr->op_array->filename; - lineno = ptr->opline->lineno; + char *free_class_name = NULL; + + class_name = call_type = NULL; + arg_array = NULL; + + skip = ptr; + /* skip internal handler */ + if (!skip->op_array && + skip->prev_execute_data && + skip->prev_execute_data->opline && + skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL && + skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME && + skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) { + skip = skip->prev_execute_data; + } + + if (skip->op_array) { + filename = skip->op_array->filename; + lineno = skip->opline->lineno; } else { filename = NULL; lineno = 0; @@ -1497,7 +1629,18 @@ ZEND_FUNCTION(debug_print_backtrace) if (function_name) { if (ptr->object) { - class_name = Z_OBJCE(*ptr->object)->name; + if (ptr->function_state.function->common.scope) { + class_name = ptr->function_state.function->common.scope->name; + } else { + zend_uint class_name_len; + int dup; + + dup = zend_get_object_classname(ptr->object, &class_name, &class_name_len TSRMLS_CC); + if(!dup) { + free_class_name = class_name; + } + } + call_type = "->"; } else if (ptr->function_state.function->common.scope) { class_name = ptr->function_state.function->common.scope->name; @@ -1516,6 +1659,11 @@ ZEND_FUNCTION(debug_print_backtrace) /* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */ zend_bool build_filename_arg = 1; + if (!ptr->opline || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) { + /* can happen when calling eval from a custom sapi */ + function_name = "unknown"; + build_filename_arg = 0; + } else switch (ptr->opline->op2.u.constant.value.lval) { case ZEND_EVAL: function_name = "eval"; @@ -1560,8 +1708,11 @@ ZEND_FUNCTION(debug_print_backtrace) } zend_printf(") called at [%s:%d]\n", filename, lineno); include_filename = filename; - ptr = ptr->prev_execute_data; + ptr = skip->prev_execute_data; ++indent; + if (free_class_name) { + efree(free_class_name); + } } } @@ -1569,12 +1720,11 @@ ZEND_FUNCTION(debug_print_backtrace) ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last TSRMLS_DC) { - zend_execute_data *ptr; + zend_execute_data *ptr, *skip; int lineno; char *function_name; char *filename; char *class_name; - char *call_type; char *include_filename = NULL; zval *stack_frame; void **cur_arg_pos = EG(argument_stack).top_element; @@ -1589,6 +1739,11 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last TSRML args -= *(ulong*)args; frames_on_stack++; + /* skip args from incomplete frames */ + while (((args-1) > EG(argument_stack).elements) && *(args-1)) { + args--; + } + if ((args-1) == EG(argument_stack).elements) { arg_stack_consistent = 1; break; @@ -1597,12 +1752,24 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last TSRML ptr = EG(current_execute_data); + /* skip "new Exception()" */ + if ((skip_last == 0) && ptr->opline && (ptr->opline->opcode == ZEND_NEW)) { + ptr = ptr->prev_execute_data; + } + /* skip debug_backtrace() */ - ptr = ptr->prev_execute_data; if (skip_last--) { int arg_count = *((ulong*)(cur_arg_pos - 2)); cur_arg_pos -= (arg_count + 2); frames_on_stack--; + ptr = ptr->prev_execute_data; + + if (arg_stack_consistent) { + /* skip args from incomplete frames */ + while (((cur_arg_pos-1) > EG(argument_stack).elements) && *(cur_arg_pos-1)) { + cur_arg_pos--; + } + } } array_init(return_value); @@ -1611,9 +1778,20 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last TSRML MAKE_STD_ZVAL(stack_frame); array_init(stack_frame); - if (ptr->op_array) { - filename = ptr->op_array->filename; - lineno = ptr->opline->lineno; + skip = ptr; + /* skip internal handler */ + if (!skip->op_array && + skip->prev_execute_data && + skip->prev_execute_data->opline && + skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL && + skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME && + skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) { + skip = skip->prev_execute_data; + } + + if (skip->op_array) { + filename = skip->op_array->filename; + lineno = skip->opline->lineno; add_assoc_string_ex(stack_frame, "file", sizeof("file"), filename, 1); add_assoc_long_ex(stack_frame, "line", sizeof("line"), lineno); @@ -1629,20 +1807,21 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last TSRML if (function_name) { add_assoc_string_ex(stack_frame, "function", sizeof("function"), function_name, 1); - if (ptr->object) { - class_name = Z_OBJCE(*ptr->object)->name; - call_type = "->"; + if (ptr->object && Z_TYPE_P(ptr->object) == IS_OBJECT) { + if (ptr->function_state.function->common.scope) { + add_assoc_string_ex(stack_frame, "class", sizeof("class"), ptr->function_state.function->common.scope->name, 1); + } else { + zend_uint class_name_len; + int dup; + + dup = zend_get_object_classname(ptr->object, &class_name, &class_name_len TSRMLS_CC); + add_assoc_string_ex(stack_frame, "class", sizeof("class"), class_name, dup); + + } + add_assoc_string_ex(stack_frame, "type", sizeof("type"), "->", 1); } else if (ptr->function_state.function->common.scope) { - class_name = ptr->function_state.function->common.scope->name; - call_type = "::"; - } else { - class_name = NULL; - call_type = NULL; - } - - if (class_name) { - add_assoc_string_ex(stack_frame, "class", sizeof("class"), class_name, 1); - add_assoc_string_ex(stack_frame, "type", sizeof("type"), call_type, 1); + add_assoc_string_ex(stack_frame, "class", sizeof("class"), ptr->function_state.function->common.scope->name, 1); + add_assoc_string_ex(stack_frame, "type", sizeof("type"), "::", 1); } if ((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL))) { @@ -1655,6 +1834,11 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last TSRML /* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */ zend_bool build_filename_arg = 1; + if (!ptr->opline || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) { + /* can happen when calling eval from a custom sapi */ + function_name = "unknown"; + build_filename_arg = 0; + } else switch (ptr->opline->op2.u.constant.value.lval) { case ZEND_EVAL: function_name = "eval"; @@ -1701,7 +1885,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last TSRML include_filename = filename; - ptr = ptr->prev_execute_data; + ptr = skip->prev_execute_data; } } /* }}} */ @@ -1756,10 +1940,13 @@ ZEND_FUNCTION(get_extension_funcs) convert_to_string_ex(extension_name); if (strncasecmp(Z_STRVAL_PP(extension_name), "zend", sizeof("zend"))) { - if (zend_hash_find(&module_registry, Z_STRVAL_PP(extension_name), + char *lcname = zend_str_tolower_dup(Z_STRVAL_PP(extension_name), Z_STRLEN_PP(extension_name)); + if (zend_hash_find(&module_registry, lcname, Z_STRLEN_PP(extension_name)+1, (void**)&module) == FAILURE) { + efree(lcname); RETURN_FALSE; } + efree(lcname); if (!(func = module->functions)) { RETURN_FALSE; @@ -1777,7 +1964,6 @@ ZEND_FUNCTION(get_extension_funcs) } /* }}} */ - /* * Local variables: * tab-width: 4 diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 91310655d385..26a98a9d83e0 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -19,7 +19,7 @@ /* $Id$ */ -#include "zend_language_parser.h" +#include #include "zend.h" #include "zend_compile.h" #include "zend_constants.h" @@ -68,7 +68,7 @@ static void build_runtime_defined_function_key(zval *result, char *name, int nam uint char_pos_len; char *filename; - char_pos_len = zend_sprintf(char_pos_buf, "%x", (unsigned int) LANG_SCNG(_yy_last_accepting_cpos)); + char_pos_len = zend_sprintf(char_pos_buf, "%p", LANG_SCNG(_yy_last_accepting_cpos)); if (CG(active_op_array)->filename) { filename = CG(active_op_array)->filename; } else { @@ -418,6 +418,9 @@ void zend_do_abstract_method(znode *function_name, znode *modifiers, znode *body } if (modifiers->u.constant.value.lval & ZEND_ACC_ABSTRACT) { + if(modifiers->u.constant.value.lval & ZEND_ACC_PRIVATE) { + zend_error(E_COMPILE_ERROR, "%s function %s::%s() cannot be declared private", method_type, CG(active_class_entry)->name, function_name->u.constant.value.str.val); + } if (body->u.constant.value.lval == ZEND_ACC_ABSTRACT) { zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); @@ -483,6 +486,12 @@ void zend_do_assign(znode *result, znode *variable, znode *value TSRMLS_DC) } } +static inline zend_bool zend_is_function_or_method_call(znode *variable) +{ + zend_uint type = variable->u.EA.type; + + return ((type & ZEND_PARSED_METHOD_CALL) || (type == ZEND_PARSED_FUNCTION_CALL)); +} void zend_do_assign_ref(znode *result, znode *lvar, znode *rvar TSRMLS_DC) { @@ -494,6 +503,11 @@ void zend_do_assign_ref(znode *result, znode *lvar, znode *rvar TSRMLS_DC) if (opline_is_fetch_this(last_op TSRMLS_CC)) { zend_error(E_COMPILE_ERROR, "Cannot re-assign $this"); } + if (zend_is_function_or_method_call(rvar)) { + opline->extended_value = ZEND_RETURNS_FUNCTION; + } else { + opline->extended_value = 0; + } if (result) { opline->result.op_type = IS_VAR; opline->result.u.EA.type = 0; @@ -717,13 +731,6 @@ void zend_check_writable_variable(znode *variable) } } -static inline zend_bool zend_is_function_or_method_call(znode *variable) -{ - zend_uint type = variable->u.EA.type; - - return ((type & ZEND_PARSED_METHOD_CALL) || (type == ZEND_PARSED_FUNCTION_CALL)); -} - void zend_do_begin_variable_parse(TSRMLS_D) { zend_llist fetch_list; @@ -738,48 +745,53 @@ void zend_do_end_variable_parse(int type, int arg_offset TSRMLS_DC) zend_llist *fetch_list_ptr; zend_llist_element *le; zend_op *opline, *opline_ptr=NULL; - int num_of_created_opcodes = 0; zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr); le = fetch_list_ptr->head; - while (le) { + if (le) { opline_ptr = (zend_op *)le->data; - opline = get_next_op(CG(active_op_array) TSRMLS_CC); - memcpy(opline, opline_ptr, sizeof(zend_op)); - switch (type) { - case BP_VAR_R: - if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) { - zend_error(E_COMPILE_ERROR, "Cannot use [] for reading"); - } - opline->opcode -= 3; - break; - case BP_VAR_W: - break; - case BP_VAR_RW: - opline->opcode += 3; - break; - case BP_VAR_IS: - opline->opcode += 6; /* 3+3 */ - break; - case BP_VAR_FUNC_ARG: - opline->opcode += 9; /* 3+3+3 */ - opline->extended_value = arg_offset; - break; - case BP_VAR_UNSET: - if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) { - zend_error(E_COMPILE_ERROR, "Cannot use [] for unsetting"); - } - opline->opcode += 12; /* 3+3+3+3 */ - break; + if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) { + CG(active_op_array)->uses_this = 1; } - le = le->next; - num_of_created_opcodes++; - } - if (num_of_created_opcodes == 1 && opline_is_fetch_this(opline_ptr TSRMLS_CC)) { - CG(active_op_array)->uses_this = 1; + while (1) { + opline = get_next_op(CG(active_op_array) TSRMLS_CC); + memcpy(opline, opline_ptr, sizeof(zend_op)); + switch (type) { + case BP_VAR_R: + if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) { + zend_error(E_COMPILE_ERROR, "Cannot use [] for reading"); + } + opline->opcode -= 3; + break; + case BP_VAR_W: + break; + case BP_VAR_RW: + opline->opcode += 3; + break; + case BP_VAR_IS: + if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) { + zend_error(E_COMPILE_ERROR, "Cannot use [] for reading"); + } + opline->opcode += 6; /* 3+3 */ + break; + case BP_VAR_FUNC_ARG: + opline->opcode += 9; /* 3+3+3 */ + opline->extended_value = arg_offset; + break; + case BP_VAR_UNSET: + if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) { + zend_error(E_COMPILE_ERROR, "Cannot use [] for unsetting"); + } + opline->opcode += 12; /* 3+3+3+3 */ + break; + } + le = le->next; + if (le == NULL) break; + opline_ptr = (zend_op *)le->data; + } } zend_llist_destroy(fetch_list_ptr); @@ -891,7 +903,8 @@ void zend_do_free(znode *op1 TSRMLS_DC) * Find JMP_NO_CTOR, mark the preceding ASSIGN and the * proceeding INIT_FCALL_BY_NAME as unused */ - if (opline->opcode == ZEND_JMP_NO_CTOR) { + if (opline->opcode == ZEND_JMP_NO_CTOR && + opline->op1.u.var == op1->u.var) { opline->op1.u.EA.type |= EXT_TYPE_UNUSED; (opline-1)->result.u.EA.type |= EXT_TYPE_UNUSED; (opline+1)->op1.u.EA.type |= EXT_TYPE_UNUSED; @@ -962,7 +975,7 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n op_array.fn_flags = fn_flags; op_array.pass_rest_by_reference = 0; - op_array.scope = CG(active_class_entry); + op_array.scope = is_method?CG(active_class_entry):NULL; op_array.prototype = NULL; op_array.line_start = zend_get_compiled_lineno(TSRMLS_C); @@ -992,35 +1005,37 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n fn_flags |= ZEND_ACC_PUBLIC; } - short_class_name = do_alloca(short_class_name_length + 1); - zend_str_tolower_copy(short_class_name, CG(active_class_entry)->name, short_class_name_length); - /* Improve after RC: cache the lowercase class name */ - - if ((short_class_name_length == name_len) && (!memcmp(short_class_name, lcname, name_len))) { - if (CG(active_class_entry)->constructor) { - zend_error(E_STRICT, "Redefining already defined constructor for class %s", CG(active_class_entry)->name); - } else { + if (!(CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)) { + short_class_name = do_alloca(short_class_name_length + 1); + zend_str_tolower_copy(short_class_name, CG(active_class_entry)->name, short_class_name_length); + /* Improve after RC: cache the lowercase class name */ + + if ((short_class_name_length == name_len) && (!memcmp(short_class_name, lcname, name_len))) { + if (CG(active_class_entry)->constructor) { + zend_error(E_STRICT, "Redefining already defined constructor for class %s", CG(active_class_entry)->name); + } else { + CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array); + } + } else if ((name_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)))) { + if (CG(active_class_entry)->constructor) { + zend_error(E_STRICT, "Redefining already defined constructor for class %s", CG(active_class_entry)->name); + } CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array); + } else if ((name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)))) { + CG(active_class_entry)->destructor = (zend_function *) CG(active_op_array); + } else if ((name_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)))) { + CG(active_class_entry)->clone = (zend_function *) CG(active_op_array); + } else if ((name_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)))) { + CG(active_class_entry)->__call = (zend_function *) CG(active_op_array); + } else if ((name_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)))) { + CG(active_class_entry)->__get = (zend_function *) CG(active_op_array); + } else if ((name_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)))) { + CG(active_class_entry)->__set = (zend_function *) CG(active_op_array); + } else if (!(fn_flags & ZEND_ACC_STATIC)) { + CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC; } - } else if ((name_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)))) { - if (CG(active_class_entry)->constructor) { - zend_error(E_STRICT, "Redefining already defined constructor for class %s", CG(active_class_entry)->name); - } - CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array); - } else if ((name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)))) { - CG(active_class_entry)->destructor = (zend_function *) CG(active_op_array); - } else if ((name_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)))) { - CG(active_class_entry)->clone = (zend_function *) CG(active_op_array); - } else if ((name_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)))) { - CG(active_class_entry)->__call = (zend_function *) CG(active_op_array); - } else if ((name_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)))) { - CG(active_class_entry)->__get = (zend_function *) CG(active_op_array); - } else if ((name_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)))) { - CG(active_class_entry)->__set = (zend_function *) CG(active_op_array); - } else if (!(fn_flags & ZEND_ACC_STATIC)) { - CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC; - } - free_alloca(short_class_name); + free_alloca(short_class_name); + } efree(lcname); } else { @@ -1069,9 +1084,10 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n } if (CG(doc_comment)) { - CG(active_op_array)->doc_comment = estrndup(CG(doc_comment), CG(doc_comment_len)); + CG(active_op_array)->doc_comment = CG(doc_comment); CG(active_op_array)->doc_comment_len = CG(doc_comment_len); - RESET_DOC_COMMENT(); + CG(doc_comment) = NULL; + CG(doc_comment_len) = 0; } } @@ -1087,16 +1103,26 @@ void zend_do_handle_exception(TSRMLS_D) void zend_do_end_function_declaration(znode *function_token TSRMLS_DC) { + char lcname[16]; + int name_len; + zend_do_extended_info(TSRMLS_C); zend_do_return(NULL, 0 TSRMLS_CC); zend_do_handle_exception(TSRMLS_C); pass_two(CG(active_op_array) TSRMLS_CC); - if (CG(active_class_entry) - && !strcmp(CG(active_op_array)->function_name, ZEND_CLONE_FUNC_NAME) - && CG(active_op_array)->num_args != 0) { - zend_error(E_COMPILE_ERROR, "The clone method cannot accept any arguments"); + if (CG(active_class_entry)) { + zend_check_magic_method_implementation(CG(active_class_entry), (zend_function*)CG(active_op_array), E_COMPILE_ERROR TSRMLS_CC); + } else { + /* we don't care if the function name is longer, in fact lowercasing only + * the beginning of the name speeds up the check process */ + name_len = strlen(CG(active_op_array)->function_name); + zend_str_tolower_copy(lcname, CG(active_op_array)->function_name, MIN(name_len, sizeof(lcname)-1)); + lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */ + if (name_len == sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME)) && CG(active_op_array)->num_args != 1) { + zend_error(E_COMPILE_ERROR, "%s() must take exactly 1 argument", ZEND_AUTOLOAD_FUNC_NAME); + } } CG(active_op_array)->line_end = zend_get_compiled_lineno(TSRMLS_C); @@ -1114,10 +1140,6 @@ void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initia zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); zend_arg_info *cur_arg_info; - if (CG(active_class_entry) && CG(active_class_entry)->destructor == (zend_function *) CG(active_op_array)) - { - zend_error(E_COMPILE_ERROR, "Destuctor %s::%s() cannot take arguments", CG(active_class_entry)->name, CG(active_op_array)->function_name); - } CG(active_op_array)->num_args++; opline->opcode = op; opline->result = *var; @@ -1193,7 +1215,7 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) last_op_number = get_next_op_number(CG(active_op_array))-1; last_op = &CG(active_op_array)->opcodes[last_op_number]; - if ((last_op->op2.op_type == IS_CONST) && (last_op->op2.u.constant.value.str.len == sizeof(ZEND_CLONE_FUNC_NAME)-1) + if ((last_op->op2.op_type == IS_CONST) && (last_op->op2.u.constant.type == IS_STRING) && (last_op->op2.u.constant.value.str.len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && !zend_binary_strcasecmp(last_op->op2.u.constant.value.str.val, last_op->op2.u.constant.value.str.len, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)-1)) { zend_error(E_COMPILE_ERROR, "Cannot call __clone() method on objects - use 'clone $obj' instead"); } @@ -1275,6 +1297,7 @@ void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC) opline->op2 = *class_name; } opline->result.u.var = get_temporary_variable(CG(active_op_array)); + opline->result.u.EA.type = opline->extended_value; opline->result.op_type = IS_CONST; /* FIXME: Hack so that INIT_FCALL_BY_NAME still knows this is a class */ *result = opline->result; } @@ -1298,36 +1321,27 @@ void zend_do_fetch_class_name(znode *result, znode *class_name_entry, znode *cla result->u.constant.value.str.len = length; } -void zend_do_begin_class_member_function_call(TSRMLS_D) +void zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC) { unsigned char *ptr = NULL; - long fetch_const_op_number = get_next_op_number(CG(active_op_array)); - zend_op *last_op = &CG(active_op_array)->opcodes[fetch_const_op_number-1]; - - if (last_op->opcode == ZEND_FETCH_CONSTANT) { /* regular method call */ - /* a tmp var is leaked here */ - last_op->opcode = ZEND_INIT_STATIC_METHOD_CALL; - if(last_op->op2.op_type == IS_CONST && - (sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == Z_STRLEN(last_op->op2.u.constant) && - memcmp(Z_STRVAL(last_op->op2.u.constant), ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == 0) { - zval_dtor(&last_op->op2.u.constant); - SET_UNUSED(last_op->op2); + zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); + + opline->opcode = ZEND_INIT_STATIC_METHOD_CALL; + opline->op1 = *class_name; + opline->op2 = *method_name; + + if (opline->op2.op_type == IS_CONST) { + if ((sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == Z_STRLEN(opline->op2.u.constant) && + memcmp(Z_STRVAL(opline->op2.u.constant), ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == 0) { + zval_dtor(&opline->op2.u.constant); + SET_UNUSED(opline->op2); } else { - zend_lowercase_znode_if_const(&last_op->op2); + zend_str_tolower(opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len); } - } else if (last_op->opcode == ZEND_FETCH_R) { /* indirect method call */ - zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); - - last_op->op2.u.EA.type = ZEND_FETCH_LOCAL; - opline->opcode = ZEND_INIT_STATIC_METHOD_CALL; - opline->op1 = last_op->op2; - opline->op2 = last_op->result; - } else { - zend_error(E_COMPILE_ERROR, "Internal compiler error - please report!"); } - zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *)); + zend_do_extended_fcall_begin(TSRMLS_C); } @@ -1368,6 +1382,7 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) int original_op=op; zend_function **function_ptr_ptr, *function_ptr; int send_by_reference; + int send_function = 0; zend_stack_top(&CG(function_call_stack), (void **) &function_ptr_ptr); function_ptr = *function_ptr_ptr; @@ -1392,6 +1407,7 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) if (op == ZEND_SEND_VAR && zend_is_function_or_method_call(param)) { /* Method call */ op = ZEND_SEND_VAR_NO_REF; + send_function = ZEND_ARG_SEND_FUNCTION; } else if (op == ZEND_SEND_VAL && param->op_type == IS_VAR) { op = ZEND_SEND_VAR_NO_REF; } @@ -1430,9 +1446,9 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) if (op == ZEND_SEND_VAR_NO_REF) { if (function_ptr) { - opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND | send_by_reference; + opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND | send_by_reference | send_function; } else { - opline->extended_value = 0; + opline->extended_value = send_function; } } else { if (function_ptr) { @@ -1453,7 +1469,7 @@ static int generate_free_switch_expr(zend_switch_entry *switch_entry TSRMLS_DC) zend_op *opline; if (switch_entry->cond.op_type != IS_VAR && switch_entry->cond.op_type != IS_TMP_VAR) { - return 0; + return (switch_entry->cond.op_type == IS_UNUSED); } opline = get_next_op(CG(active_op_array) TSRMLS_CC); @@ -1675,9 +1691,11 @@ static void do_inherit_parent_constructor(zend_class_entry *ce) if (!zend_hash_exists(&ce->function_table, lc_class_name, ce->name_length+1)) { lc_parent_class_name = zend_str_tolower_dup(ce->parent->name, ce->parent->name_length); if (zend_hash_find(&ce->parent->function_table, lc_parent_class_name, ce->parent->name_length+1, (void **)&function)==SUCCESS) { - /* inherit parent's constructor */ - zend_hash_update(&ce->function_table, lc_class_name, ce->name_length+1, function, sizeof(zend_function), NULL); - function_add_ref(function); + if (function->common.fn_flags & ZEND_ACC_CTOR) { + /* inherit parent's constructor */ + zend_hash_update(&ce->function_table, lc_class_name, ce->name_length+1, function, sizeof(zend_function), NULL); + function_add_ref(function); + } } efree(lc_parent_class_name); } @@ -1850,9 +1868,18 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro zend_property_info *child_info; zend_class_entry *parent_ce = ce->parent; - if (parent_info->flags & ZEND_ACC_PRIVATE) { + if (parent_info->flags & (ZEND_ACC_PRIVATE|ZEND_ACC_SHADOW)) { if (zend_hash_quick_find(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) { child_info->flags |= ZEND_ACC_CHANGED; + } else { + zend_hash_quick_update(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, parent_info, sizeof(zend_property_info), (void **) &child_info); + if(ce->type & ZEND_INTERNAL_CLASS) { + zend_duplicate_property_info_internal(child_info); + } else { + zend_duplicate_property_info(child_info); + } + child_info->flags &= ~ZEND_ACC_PRIVATE; /* it's not private anymore */ + child_info->flags |= ZEND_ACC_SHADOW; /* but it's a shadow of private */ } return 0; /* don't copy access information to child */ } @@ -1864,6 +1891,11 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro (child_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", ce->name, hash_key->arKey); } + + if(parent_info->flags & ZEND_ACC_CHANGED) { + child_info->flags |= ZEND_ACC_CHANGED; + } + if ((child_info->flags & ZEND_ACC_PPP_MASK) > (parent_info->flags & ZEND_ACC_PPP_MASK)) { zend_error(E_COMPILE_ERROR, "Access level to %s::$%s must be %s (as in class %s)%s", ce->name, hash_key->arKey, zend_visibility_string(parent_info->flags), parent_ce->name, (parent_info->flags&ZEND_ACC_PUBLIC) ? "" : " or weaker"); } else if (child_info->flags & ZEND_ACC_IMPLICIT_PUBLIC) { @@ -1904,12 +1936,6 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro zend_hash_del(&ce->default_properties, prot_name, prot_name_length+1); } pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS); - } else if (!(child_info->flags & ZEND_ACC_PRIVATE) && (child_info->flags & ZEND_ACC_STATIC)) { - char *prop_name, *tmp; - - zend_unmangle_property_name(child_info->name, &tmp, &prop_name); - zend_error(E_COMPILE_ERROR, "Cannot redeclare property static %s %s::$%s in class %s", - zend_visibility_string(child_info->flags), parent_ce->name, prop_name, ce->name); } return 0; /* Don't copy from parent */ } else { @@ -1924,6 +1950,9 @@ static inline void do_implement_interface(zend_class_entry *ce, zend_class_entry if (!(ce->ce_flags & ZEND_ACC_INTERFACE) && iface->interface_gets_implemented && iface->interface_gets_implemented(iface, ce TSRMLS_CC) == FAILURE) { zend_error(E_CORE_ERROR, "Class %s could not implement interface %s", ce->name, iface->name); } + if (ce == iface) { + zend_error(E_ERROR, "Interface %s cannot not implement itself", ce->name); + } } @@ -1993,6 +2022,8 @@ void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce TSRML zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, (void (*)(void *)) zval_add_ref, NULL, sizeof(zval *), 0); zend_hash_merge_ex(&ce->function_table, &parent_ce->function_table, (copy_ctor_func_t) do_inherit_method, sizeof(zend_function), (merge_checker_func_t) do_inherit_method_check, ce); do_inherit_parent_constructor(ce); + + zend_verify_abstract_class(ce TSRMLS_CC); } @@ -2100,6 +2131,10 @@ ZEND_API zend_class_entry *do_bind_inherited_class(zend_op *opline, HashTable *c ce = *pce; } + if (parent_ce->ce_flags & ZEND_ACC_INTERFACE) { + zend_error(E_COMPILE_ERROR, "Class %s cannot extend from interface %s", ce->name, parent_ce->name); + } + zend_do_inheritance(ce, parent_ce TSRMLS_CC); ce->refcount++; @@ -2160,6 +2195,19 @@ void zend_do_early_binding(TSRMLS_D) if (do_bind_inherited_class(opline, CG(class_table), *pce, 1 TSRMLS_CC) == NULL) { return; } + /* clear unnecessary ZEND_FETCH_CLASS opcode */ + if (opline > CG(active_op_array)->opcodes && + (opline-1)->opcode == ZEND_FETCH_CLASS) { + zend_op *fetch_class_opline = opline-1; + + zval_dtor(&fetch_class_opline->op2.u.constant); + fetch_class_opline->opcode = ZEND_NOP; + memset(&fetch_class_opline->op1, 0, sizeof(znode)); + memset(&fetch_class_opline->op2, 0, sizeof(znode)); + SET_UNUSED(fetch_class_opline->op1); + SET_UNUSED(fetch_class_opline->op2); + SET_UNUSED(fetch_class_opline->result); + } } else { /* We currently don't early-bind classes that implement interfaces */ return; @@ -2489,10 +2537,20 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod zend_initialize_class_data(new_class_entry, 1 TSRMLS_CC); new_class_entry->filename = zend_get_compiled_filename(TSRMLS_C); - new_class_entry->line_start = zend_get_compiled_lineno(TSRMLS_C); - new_class_entry->ce_flags |= class_token->u.constant.value.lval; + new_class_entry->line_start = class_token->u.opline_num; + new_class_entry->ce_flags |= class_token->u.EA.type; if (parent_class_name && parent_class_name->op_type != IS_UNUSED) { + switch (parent_class_name->u.EA.type) { + case ZEND_FETCH_CLASS_SELF: + zend_error(E_COMPILE_ERROR, "Cannot use 'self' as class name as it is reserved"); + break; + case ZEND_FETCH_CLASS_PARENT: + zend_error(E_COMPILE_ERROR, "Cannot use 'parent' as class name as it is reserved"); + break; + default: + break; + } doing_inheritance = 1; } @@ -2522,9 +2580,10 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod CG(implementing_class) = opline->result; if (CG(doc_comment)) { - CG(active_class_entry)->doc_comment = estrndup(CG(doc_comment), CG(doc_comment_len)); + CG(active_class_entry)->doc_comment = CG(doc_comment); CG(active_class_entry)->doc_comment_len = CG(doc_comment_len); - RESET_DOC_COMMENT(); + CG(doc_comment) = NULL; + CG(doc_comment_len) = 0; } } @@ -2568,7 +2627,8 @@ void zend_do_end_class_declaration(znode *class_token, znode *parent_token TSRML /* Inherit interfaces */ if (ce->num_interfaces > 0) { - ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *)*ce->num_interfaces); + ce->interfaces = (zend_class_entry **) emalloc(sizeof(zend_class_entry *)*ce->num_interfaces); + memset(ce->interfaces, 0, sizeof(zend_class_entry *)*ce->num_interfaces); } if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) && ((parent_token->op_type != IS_UNUSED) || (ce->num_interfaces > 0))) { @@ -2583,8 +2643,26 @@ void zend_do_end_class_declaration(znode *class_token, znode *parent_token TSRML void zend_do_implements_interface(znode *interface_znode TSRMLS_DC) { - zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); + zend_op *opline; + switch (interface_znode->u.EA.type) { + case ZEND_FETCH_CLASS_SELF: + zend_error(E_COMPILE_ERROR, "Cannot use 'self' as interface name as it is reserved"); + break; + case ZEND_FETCH_CLASS_PARENT: + zend_error(E_COMPILE_ERROR, "Cannot use 'parent' as interface name as it is reserved"); + break; + default: + if (CG(active_op_array)->last > 0) { + opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1]; + if (opline->opcode == ZEND_FETCH_CLASS) { + opline->extended_value = ZEND_FETCH_CLASS_INTERFACE; + } + } + break; + } + + opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline->opcode = ZEND_ADD_INTERFACE; opline->op1 = CG(implementing_class); opline->op2 = *interface_znode; @@ -2951,9 +3029,16 @@ void zend_do_add_static_array_element(znode *result, znode *offset, znode *expr) zend_symtable_update(result->u.constant.value.ht, offset->u.constant.value.str.val, offset->u.constant.value.str.len+1, &element, sizeof(zval *), NULL); zval_dtor(&offset->u.constant); break; + case IS_NULL: + zend_symtable_update(result->u.constant.value.ht, "", 1, &element, sizeof(zval *), NULL); + break; case IS_LONG: + case IS_BOOL: zend_hash_index_update(result->u.constant.value.ht, offset->u.constant.value.lval, &element, sizeof(zval *), NULL); break; + case IS_DOUBLE: + zend_hash_index_update(result->u.constant.value.ht, (long)offset->u.constant.value.dval, &element, sizeof(zval *), NULL); + break; } } else { zend_hash_next_index_insert(result->u.constant.value.ht, &element, sizeof(zval *), NULL); @@ -3006,7 +3091,6 @@ void zend_do_list_end(znode *result, znode *expr TSRMLS_DC) zend_llist_element *dimension; zend_op *opline; znode last_container; - int opcode_index; int last_op_number; zend_op *last_op; @@ -3048,14 +3132,10 @@ void zend_do_list_end(znode *result, znode *expr TSRMLS_DC) ((list_llist_element *) le->data)->value = last_container; zend_llist_destroy(&((list_llist_element *) le->data)->dimensions); zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); - opcode_index = - 1; last_op_number = get_next_op_number(CG(active_op_array))-1; last_op = &CG(active_op_array)->opcodes[last_op_number]; - if (last_op->opcode == ZEND_FETCH_OBJ_W) { - opcode_index = - 2; - } zend_do_assign(result, &((list_llist_element *) le->data)->var, &((list_llist_element *) le->data)->value TSRMLS_CC); - CG(active_op_array)->opcodes[CG(active_op_array)->last + opcode_index].result.u.EA.type |= EXT_TYPE_UNUSED; + zend_do_free(result TSRMLS_CC); le = le->next; } zend_llist_destroy(&CG(dimension_llist)); diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 69fc099b708e..7eda6b9e6a52 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -41,10 +41,13 @@ #define DEC_BPC(op_array) if (CG(interactive)) { ((op_array)->backpatch_count--); } #define HANDLE_INTERACTIVE() if (CG(interactive)) { execute_new_code(TSRMLS_C); } -#define RESET_DOC_COMMENT() \ - { \ - CG(doc_comment) = NULL; \ - CG(doc_comment_len) = 0; \ +#define RESET_DOC_COMMENT() \ + { \ + if (CG(doc_comment)) { \ + efree(CG(doc_comment)); \ + CG(doc_comment) = NULL; \ + } \ + CG(doc_comment_len) = 0; \ } typedef struct _zend_op_array zend_op_array; @@ -131,6 +134,9 @@ typedef struct _zend_try_catch_element { /* method flag (bc only), any method that has this flag can be used statically and non statically. */ #define ZEND_ACC_ALLOW_STATIC 0x10000 +/* shadow of parent's private method/property */ +#define ZEND_ACC_SHADOW 0x20000 + char *zend_visibility_string(zend_uint fn_flags); @@ -375,7 +381,7 @@ void zend_do_clone(znode *result, znode *expr TSRMLS_DC); void zend_do_begin_dynamic_function_call(znode *function_name TSRMLS_DC); void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC); void zend_do_fetch_class_name(znode *result, znode *class_entry, znode *class_name TSRMLS_DC); -void zend_do_begin_class_member_function_call(TSRMLS_D); +void zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC); void zend_do_end_function_call(znode *function_name, znode *result, znode *argument_list, int is_method, int is_dynamic_fcall TSRMLS_DC); void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC); void zend_do_handle_exception(TSRMLS_D); @@ -738,6 +744,7 @@ int zendlex(znode *zendlval TSRMLS_DC); #define ZEND_FETCH_CLASS_MAIN 3 #define ZEND_FETCH_CLASS_GLOBAL 4 #define ZEND_FETCH_CLASS_AUTO 5 +#define ZEND_FETCH_CLASS_INTERFACE 6 /* variable parsing type (compile-time) */ @@ -798,6 +805,7 @@ int zendlex(znode *zendlval TSRMLS_DC); #define ZEND_ARG_SEND_BY_REF (1<<0) #define ZEND_ARG_COMPILE_TIME_BOUND (1<<1) +#define ZEND_ARG_SEND_FUNCTION (1<<2) #define AI_USE_PTR(ai) \ if ((ai).ptr_ptr) { \ @@ -840,6 +848,7 @@ END_EXTERN_C() #define ZEND_GET_FUNC_NAME "__get" #define ZEND_SET_FUNC_NAME "__set" #define ZEND_CALL_FUNC_NAME "__call" +#define ZEND_AUTOLOAD_FUNC_NAME "__autoload" #endif /* ZEND_COMPILE_H */ diff --git a/Zend/zend_config.w32.h b/Zend/zend_config.w32.h index 84d85c7d85d4..af51889db6bf 100644 --- a/Zend/zend_config.w32.h +++ b/Zend/zend_config.w32.h @@ -22,6 +22,7 @@ #ifndef ZEND_CONFIG_W32_H #define ZEND_CONFIG_W32_H +#define USE_ZEND_ALLOC 1 #define HAVE_ALLOCA 1 #define HAVE_LIMITS_H 1 #define _CRTDBG_MAP_ALLOC @@ -55,6 +56,7 @@ typedef unsigned int uint; #define HAVE_STDARG_H 1 #define HAVE_SNPRINTF 1 #define HAVE_VSNPRINTF 1 +#define HAVE_STRCOLL 1 #define snprintf _snprintf #define vsnprintf _vsnprintf diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index ff0f31370067..2a9d0c082527 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -50,7 +50,8 @@ void zend_throw_exception_internal(zval *exception TSRMLS_DC) zend_throw_exception_hook(exception TSRMLS_CC); } - if ((EG(current_execute_data)->opline+1)->opcode == ZEND_HANDLE_EXCEPTION) { + if (EG(current_execute_data)->opline == NULL || + (EG(current_execute_data)->opline+1)->opcode == ZEND_HANDLE_EXCEPTION) { /* no need to rethrow the exception */ return; } @@ -99,12 +100,15 @@ static zend_object_value zend_default_exception_new(zend_class_entry *class_type return obj.value.obj; } + ZEND_METHOD(exception, __clone) { /* Should never be executable */ zend_throw_exception(NULL, "Cannot clone object using __clone()", 0 TSRMLS_CC); } +/* {{{ proto Exception::__construct() + Exception constructor */ ZEND_METHOD(exception, __construct) { char *message = NULL; @@ -126,6 +130,7 @@ ZEND_METHOD(exception, __construct) zend_update_property_long(default_exception_ce, object, "code", sizeof("code")-1, code TSRMLS_CC); } } +/* }}} */ #define DEFAULT_0_PARAMS \ if (ZEND_NUM_ARGS() > 0) { \ @@ -142,40 +147,61 @@ static void _default_exception_get_entry(zval *object, char *name, int name_len, zval_copy_ctor(return_value); } + +/* {{{ proto Exception::getFile() + Obtain the file name in which the exception occurred */ ZEND_METHOD(exception, getFile) { DEFAULT_0_PARAMS; _default_exception_get_entry(getThis(), "file", sizeof("file")-1, return_value TSRMLS_CC); } +/* }}} */ + +/* {{{ proto Exception::getLine() + Obtain the line number in which the exception occurred */ ZEND_METHOD(exception, getLine) { DEFAULT_0_PARAMS; _default_exception_get_entry(getThis(), "line", sizeof("line")-1, return_value TSRMLS_CC); } +/* }}} */ + +/* {{{ proto Exception::getMessage() + Obtain the exception message */ ZEND_METHOD(exception, getMessage) { DEFAULT_0_PARAMS; _default_exception_get_entry(getThis(), "message", sizeof("message")-1, return_value TSRMLS_CC); } +/* }}} */ + +/* {{{ proto Exception::getCode() + Obtain the user-defined exception code */ ZEND_METHOD(exception, getCode) { DEFAULT_0_PARAMS; _default_exception_get_entry(getThis(), "code", sizeof("code")-1, return_value TSRMLS_CC); } +/* }}} */ + +/* {{{ proto Exception::getTrace() + Obtain a stack trace for the location in which the exception occurred */ ZEND_METHOD(exception, getTrace) { DEFAULT_0_PARAMS; _default_exception_get_entry(getThis(), "trace", sizeof("trace")-1, return_value TSRMLS_CC); } +/* }}} */ + /* {{{ ZEND_METHOD(exception, gettraceasstring) */ #define TRACE_APPEND_CHR(chr) \ @@ -272,10 +298,20 @@ static int _build_trace_args(zval **arg, int num_args, va_list args, zend_hash_k TRACE_APPEND_STR("Array, "); break; case IS_OBJECT: { + char *class_name; + zend_uint class_name_len; + int dup; TSRMLS_FETCH(); TRACE_APPEND_STR("Object("); - TRACE_APPEND_STRL(Z_OBJCE_PP(arg)->name, strlen(Z_OBJCE_PP(arg)->name)); + + dup = zend_get_object_classname(*arg, &class_name, &class_name_len TSRMLS_CC); + + TRACE_APPEND_STRL(class_name, class_name_len); + if(!dup) { + efree(class_name); + } + TRACE_APPEND_STR("), "); break; } @@ -427,9 +463,15 @@ ZEND_METHOD(exception, __toString) * And never try to change the state of exceptions and never implement anything * that gives the user anything to accomplish this. */ +static +ZEND_BEGIN_ARG_INFO(arginfo_exception___construct, 0) + ZEND_ARG_INFO(0, message) + ZEND_ARG_INFO(0, code) +ZEND_END_ARG_INFO(); + static zend_function_entry default_exception_functions[] = { ZEND_ME(exception, __clone, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL) - ZEND_ME(exception, __construct, NULL, 0) + ZEND_ME(exception, __construct, arginfo_exception___construct, ZEND_ACC_PUBLIC) ZEND_ME(exception, getMessage, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) ZEND_ME(exception, getCode, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) ZEND_ME(exception, getFile, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 026b635a9536..b1056dfbfc10 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -52,6 +52,18 @@ static void zend_extension_fcall_end_handler(zend_extension *extension, zend_op_ #define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset)) #define T(offset) (*(temp_variable *)((char *) Ts + offset)) +#define TEMP_VAR_STACK_LIMIT 2000 + +#define MAKE_REAL_ZVAL_PTR(val) \ + do { \ + zval *_tmp; \ + ALLOC_ZVAL(_tmp); \ + _tmp->value = (val)->value; \ + _tmp->type = (val)->type; \ + _tmp->refcount = 1; \ + _tmp->is_ref = 0; \ + val = _tmp; \ + } while (0) /* former zend_execute_locks.h */ static inline void zend_pzval_lock_func(zval *z) @@ -153,30 +165,23 @@ static inline zval **_get_zval_ptr_ptr(znode *node, temp_variable *Ts TSRMLS_DC) static inline void zend_fetch_property_address_inner(zval *object, znode *op2, znode *result, temp_variable *Ts, int type TSRMLS_DC) { zval *prop_ptr = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R); - zval tmp; - - switch (op2->op_type) { - case IS_CONST: - /* already a constant string */ - break; - case IS_VAR: - tmp = *prop_ptr; - zval_copy_ctor(&tmp); - convert_to_string(&tmp); - prop_ptr = &tmp; - break; - case IS_TMP_VAR: - convert_to_string(prop_ptr); - break; + if (EG(free_op2)) { + MAKE_REAL_ZVAL_PTR(prop_ptr); } if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { zval **ptr_ptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, prop_ptr TSRMLS_CC); if(NULL == ptr_ptr) { - zend_error(E_ERROR, "Cannot access undefined property for object with overloaded property access"); + if (Z_OBJ_HT_P(object)->read_property && + (T(result->u.var).var.ptr = Z_OBJ_HT_P(object)->read_property(object, prop_ptr, BP_VAR_W TSRMLS_CC)) != NULL) { + T(result->u.var).var.ptr_ptr = &T(result->u.var).var.ptr; + } else { + zend_error(E_ERROR, "Cannot access undefined property for object with overloaded property access"); + } + } else { + T(result->u.var).var.ptr_ptr = ptr_ptr; } - T(result->u.var).var.ptr_ptr = ptr_ptr; } else if (Z_OBJ_HT_P(object)->read_property) { T(result->u.var).var.ptr = Z_OBJ_HT_P(object)->read_property(object, prop_ptr, BP_VAR_W TSRMLS_CC); T(result->u.var).var.ptr_ptr = &T(result->u.var).var.ptr; @@ -185,10 +190,9 @@ static inline void zend_fetch_property_address_inner(zval *object, znode *op2, z T(result->u.var).var.ptr_ptr = &EG(error_zval_ptr); } - if (prop_ptr == &tmp) { - zval_dtor(prop_ptr); + if (EG(free_op2)) { + zval_ptr_dtor(&prop_ptr); } - FREE_OP(Ts, op2, EG(free_op2)); } @@ -233,12 +237,6 @@ void zend_assign_to_variable_reference(znode *result, zval **variable_ptr_ptr, z if (variable_ptr == EG(error_zval_ptr) || value_ptr==EG(error_zval_ptr)) { variable_ptr_ptr = &EG(uninitialized_zval_ptr); } else if (variable_ptr != value_ptr) { - variable_ptr->refcount--; - if (variable_ptr->refcount==0) { - zendi_zval_dtor(*variable_ptr); - FREE_ZVAL(variable_ptr); - } - if (!PZVAL_IS_REF(value_ptr)) { /* break it away */ value_ptr->refcount--; @@ -251,9 +249,14 @@ void zend_assign_to_variable_reference(znode *result, zval **variable_ptr_ptr, z value_ptr->refcount = 1; value_ptr->is_ref = 1; } - *variable_ptr_ptr = value_ptr; value_ptr->refcount++; + + variable_ptr->refcount--; + if (variable_ptr->refcount==0) { + zendi_zval_dtor(*variable_ptr); + FREE_ZVAL(variable_ptr); + } } else if (!variable_ptr->is_ref) { if (variable_ptr_ptr == value_ptr_ptr) { SEPARATE_ZVAL(variable_ptr_ptr); @@ -377,7 +380,7 @@ static inline void zend_assign_to_object(znode *result, zval **object_ptr, znode *retval = EG(uninitialized_zval_ptr); SELECTIVE_PZVAL_LOCK(*retval, result); - PZVAL_UNLOCK(value); + FREE_OP(Ts, value_op, free_value); return; } @@ -386,15 +389,27 @@ static inline void zend_assign_to_object(znode *result, zval **object_ptr, znode /* separate our value if necessary */ if (EG(ze1_compatibility_mode) && Z_TYPE_P(value) == IS_OBJECT) { zval *orig_value = value; - + char *class_name; + zend_uint class_name_len; + int dup; + ALLOC_ZVAL(value); *value = *orig_value; value->is_ref = 0; value->refcount = 0; + + dup = zend_get_object_classname(orig_value, &class_name, &class_name_len TSRMLS_CC); + if (Z_OBJ_HANDLER_P(value, clone_obj) == NULL) { - zend_error(E_ERROR, "Trying to clone an uncloneable object of class %s", Z_OBJCE_P(orig_value)->name); + zend_error(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name); } - zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", Z_OBJCE_P(orig_value)->name); + + zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name); + + if(!dup) { + efree(class_name); + } + value->value.obj = Z_OBJ_HANDLER_P(orig_value, clone_obj)(orig_value TSRMLS_CC); } else if (value_op->op_type == IS_TMP_VAR) { zval *orig_value = value; @@ -416,40 +431,29 @@ static inline void zend_assign_to_object(znode *result, zval **object_ptr, znode value->refcount++; if (opcode == ZEND_ASSIGN_OBJ) { - zval tmp; - - switch (op2->op_type) { - case IS_CONST: - /* already a constant string */ - break; - case IS_VAR: - tmp = *property_name; - zval_copy_ctor(&tmp); - convert_to_string(&tmp); - property_name = &tmp; - break; - case IS_TMP_VAR: - convert_to_string(property_name); - break; + if (EG(free_op2)) { + MAKE_REAL_ZVAL_PTR(property_name); } Z_OBJ_HT_P(object)->write_property(object, property_name, value TSRMLS_CC); - if (property_name == &tmp) { - zval_dtor(property_name); - } } else { /* Note: property_name in this case is really the array index! */ if (!Z_OBJ_HT_P(object)->write_dimension) { zend_error(E_ERROR, "Cannot use object as array"); } + if (EG(free_op2)) { + MAKE_REAL_ZVAL_PTR(property_name); + } Z_OBJ_HT_P(object)->write_dimension(object, property_name, value TSRMLS_CC); } - FREE_OP(Ts, op2, EG(free_op2)); if (result) { T(result->u.var).var.ptr = value; T(result->u.var).var.ptr_ptr = &T(result->u.var).var.ptr; /* this is so that we could use it in FETCH_DIM_R, etc. - see bug #27876 */ SELECTIVE_PZVAL_LOCK(value, result); } + if (EG(free_op2)) { + zval_ptr_dtor(&property_name); + } zval_ptr_dtor(&value); } @@ -559,40 +563,60 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2 } if (EG(ze1_compatibility_mode) && Z_TYPE_P(value) == IS_OBJECT) { + char *class_name; + zend_uint class_name_len; + int dup; + + dup = zend_get_object_classname(value, &class_name, &class_name_len TSRMLS_CC); + if (Z_OBJ_HANDLER_P(value, clone_obj) == NULL) { - zend_error(E_ERROR, "Trying to clone an uncloneable object of class %s", Z_OBJCE_P(value)->name); + zend_error(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name); } else if (PZVAL_IS_REF(variable_ptr)) { - if (variable_ptr != value) { + if (variable_ptr != value) { zend_uint refcount = variable_ptr->refcount; zval garbage; - + if (type != IS_TMP_VAR) { value->refcount++; } + garbage = *variable_ptr; *variable_ptr = *value; variable_ptr->refcount = refcount; variable_ptr->is_ref = 1; - zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", Z_OBJCE_P(value)->name); + + zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name); + variable_ptr->value.obj = Z_OBJ_HANDLER_P(value, clone_obj)(value TSRMLS_CC); + if (type != IS_TMP_VAR) { value->refcount--; } + zendi_zval_dtor(garbage); } } else { - variable_ptr->refcount--; - if (variable_ptr->refcount == 0) { - zendi_zval_dtor(*variable_ptr); - } else { - ALLOC_ZVAL(variable_ptr); - *variable_ptr_ptr = variable_ptr; + if (variable_ptr != value) { + value->refcount++; + variable_ptr->refcount--; + if (variable_ptr->refcount == 0) { + zendi_zval_dtor(*variable_ptr); + } else { + ALLOC_ZVAL(variable_ptr); + *variable_ptr_ptr = variable_ptr; + } + *variable_ptr = *value; + INIT_PZVAL(variable_ptr); + zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name); + variable_ptr->value.obj = Z_OBJ_HANDLER_P(value, clone_obj)(value TSRMLS_CC); + zval_ptr_dtor(&value); } - *variable_ptr = *value; - INIT_PZVAL(variable_ptr); - zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", Z_OBJCE_P(value)->name); - variable_ptr->value.obj = Z_OBJ_HANDLER_P(value, clone_obj)(value TSRMLS_CC); } + + if(!dup) { + efree(class_name); + } + } else if (PZVAL_IS_REF(variable_ptr)) { if (variable_ptr!=value) { zend_uint refcount = variable_ptr->refcount; @@ -762,13 +786,13 @@ static void zend_fetch_var_address(zend_op *opline, temp_variable *Ts, int type if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &retval) == FAILURE) { switch (type) { case BP_VAR_R: - zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val); + zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val); /* break missing intentionally */ case BP_VAR_IS: retval = &EG(uninitialized_zval_ptr); break; case BP_VAR_RW: - zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val); + zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val); /* break missing intentionally */ case BP_VAR_W: { zval *new_zval = &EG(uninitialized_zval); @@ -938,7 +962,7 @@ static void zend_fetch_dimension_address(znode *result, znode *op1, znode *op2, new_zval->refcount++; if (zend_hash_next_index_insert(container->value.ht, &new_zval, sizeof(zval *), (void **) retval) == FAILURE) { zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); - *retval = &EG(uninitialized_zval_ptr); + *retval = &EG(error_zval_ptr); new_zval->refcount--; } } else { @@ -996,8 +1020,12 @@ static void zend_fetch_dimension_address(znode *result, znode *op1, znode *op2, zend_error(E_ERROR, "Cannot use object as array"); } else { zval *dim = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R); - zval *overloaded_result = Z_OBJ_HT_P(container)->read_dimension(container, dim, type TSRMLS_CC); + zval *overloaded_result; + if (EG(free_op2)) { + MAKE_REAL_ZVAL_PTR(dim); + } + overloaded_result = Z_OBJ_HT_P(container)->read_dimension(container, dim, type TSRMLS_CC); if (overloaded_result) { switch (type) { case BP_VAR_RW: @@ -1014,8 +1042,10 @@ static void zend_fetch_dimension_address(znode *result, znode *op1, znode *op2, *retval = &EG(error_zval_ptr); } AI_USE_PTR(T(result->u.var).var); - FREE_OP(Ts, op2, EG(free_op2)); SELECTIVE_PZVAL_LOCK(**retval, result); + if (EG(free_op2)) { + zval_ptr_dtor(&dim); + } } break; default: { @@ -1133,41 +1163,29 @@ static void zend_fetch_property_address_read(znode *result, znode *op1, znode *o } else { *retval = EG(error_zval_ptr); } + SELECTIVE_PZVAL_LOCK(*retval, result); } else { zval *offset; - zval tmp; offset = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R); - switch (op2->op_type) { - case IS_CONST: - /* already a constant string */ - break; - case IS_VAR: - tmp = *offset; - zval_copy_ctor(&tmp); - convert_to_string(&tmp); - offset = &tmp; - break; - case IS_TMP_VAR: - convert_to_string(offset); - break; + if (EG(free_op2)) { + MAKE_REAL_ZVAL_PTR(offset); } /* here we are sure we are dealing with an object */ *retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); - if (offset == &tmp) { - zval_dtor(offset); - } - FREE_OP(Ts, op2, EG(free_op2)); if (RETURN_VALUE_UNUSED(result) && ((*retval)->refcount == 0)) { zval_dtor(*retval); FREE_ZVAL(*retval); - return; /* no need for locking */ + } else { + SELECTIVE_PZVAL_LOCK(*retval, result); + } + + if (EG(free_op2)) { + zval_ptr_dtor(&offset); } } - - SELECTIVE_PZVAL_LOCK(*retval, result); } static void zend_pre_incdec_property(znode *result, znode *op1, znode *op2, temp_variable * Ts, int (*incdec_op)(zval *) TSRMLS_DC) @@ -1190,6 +1208,10 @@ static void zend_pre_incdec_property(znode *result, znode *op1, znode *op2, temp return; } + if (EG(free_op2)) { + MAKE_REAL_ZVAL_PTR(property); + } + /* here we are sure we are dealing with an object */ if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { @@ -1225,7 +1247,9 @@ static void zend_pre_incdec_property(znode *result, znode *op1, znode *op2, temp zval_ptr_dtor(&z); } - FREE_OP(Ts, op2, EG(free_op2)); + if (EG(free_op2)) { + zval_ptr_dtor(&property); + } } static void zend_post_incdec_property(znode *result, znode *op1, znode *op2, temp_variable * Ts, int (*incdec_op)(zval *) TSRMLS_DC) @@ -1246,6 +1270,10 @@ static void zend_post_incdec_property(znode *result, znode *op1, znode *op2, tem return; } + if (EG(free_op2)) { + MAKE_REAL_ZVAL_PTR(property); + } + /* here we are sure we are dealing with an object */ if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { @@ -1264,6 +1292,7 @@ static void zend_post_incdec_property(znode *result, znode *op1, znode *op2, tem if (!have_get_ptr) { zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_RW TSRMLS_CC); + zval *z_copy; if (z->type == IS_OBJECT && Z_OBJ_HT_P(z)->get) { zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC); @@ -1276,13 +1305,22 @@ static void zend_post_incdec_property(znode *result, znode *op1, znode *op2, tem } *retval = *z; zendi_zval_copy_ctor(*retval); - incdec_op(z); + ALLOC_ZVAL(z_copy); + *z_copy = *z; + zendi_zval_copy_ctor(*z_copy); + INIT_PZVAL(z_copy); + incdec_op(z_copy); z->refcount++; - Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); + Z_OBJ_HT_P(object)->write_property(object, property, z_copy TSRMLS_CC); + zval_ptr_dtor(&z_copy); + /* this would destroy z if it was returned with refcount == 0 and undo + recount++ above otherwise */ zval_ptr_dtor(&z); } - FREE_OP(Ts, op2, EG(free_op2)); + if (EG(free_op2)) { + zval_ptr_dtor(&property); + } } @@ -1321,7 +1359,7 @@ static int zend_check_symbol(zval **pz TSRMLS_DC) #define SET_OPCODE(new_op) \ CHECK_SYMBOL_TABLES() \ - EX(opline) = new_op; + EX(opline) = new_op; \ #define INC_OPCODE() \ if (!EG(exception)) { \ @@ -1330,7 +1368,11 @@ static int zend_check_symbol(zval **pz TSRMLS_DC) } #define RETURN_FROM_EXECUTE_LOOP(execute_data) \ - efree(EX(Ts)); \ + if (EX(op_array)->T < TEMP_VAR_STACK_LIMIT) { \ + free_alloca(EX(Ts)); \ + } else { \ + efree(EX(Ts)); \ + } \ EG(in_execution) = EX(original_in_execution); \ EG(current_execute_data) = EX(prev_execute_data); \ return 1; /* CHECK_ME */ @@ -1349,7 +1391,11 @@ ZEND_API void execute(zend_op_array *op_array TSRMLS_DC) /* Initialize execute_data */ EX(fbc) = NULL; EX(object) = NULL; - EX(Ts) = (temp_variable *) safe_emalloc(sizeof(temp_variable), op_array->T, 0); + if (op_array->T < TEMP_VAR_STACK_LIMIT) { + EX(Ts) = (temp_variable *) do_alloca(sizeof(temp_variable) * op_array->T); + } else { + EX(Ts) = (temp_variable *) safe_emalloc(sizeof(temp_variable), op_array->T, 0); + } EX(op_array) = op_array; EX(original_in_execution) = EG(in_execution); EX(prev_execute_data) = EG(current_execute_data); @@ -1623,7 +1669,6 @@ static inline int zend_binary_assign_op_obj_helper(int (*binary_op)(zval *result zval *property = get_zval_ptr(&opline->op2, EX(Ts), &EG(free_op2), BP_VAR_R); zval *free_value; zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_value, BP_VAR_R); - zval tmp; znode *result = &opline->result; zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; @@ -1642,19 +1687,8 @@ static inline int zend_binary_assign_op_obj_helper(int (*binary_op)(zval *result SELECTIVE_PZVAL_LOCK(*retval, result); } else { /* here we are sure we are dealing with an object */ - switch (opline->op2.op_type) { - case IS_CONST: - /* already a constant string */ - break; - case IS_VAR: - tmp = *property; - zval_copy_ctor(&tmp); - convert_to_string(&tmp); - property = &tmp; - break; - case IS_TMP_VAR: - convert_to_string(property); - break; + if (EG(free_op2)) { + MAKE_REAL_ZVAL_PTR(property); } /* here property is a string */ @@ -1707,11 +1741,9 @@ static inline int zend_binary_assign_op_obj_helper(int (*binary_op)(zval *result zval_ptr_dtor(&z); } - if (property == &tmp) { - zval_dtor(property); + if (EG(free_op2)) { + zval_ptr_dtor(&property); } - - FREE_OP(Ts, op2, EG(free_op2)); FREE_OP(Ts, value, free_value); } @@ -1766,6 +1798,9 @@ static inline int zend_binary_assign_op_helper(int (*binary_op)(zval *result, zv EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); SELECTIVE_PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &opline->result); AI_USE_PTR(EX_T(opline->result.u.var).var); + if (increment_opline) { + INC_OPCODE(); + } NEXT_OPCODE(); } @@ -1899,10 +1934,20 @@ static inline int zend_incdec_op_helper(incdec_t incdec_op_arg, ZEND_OPCODE_HAND zend_error(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } if (*var_ptr == EG(error_zval_ptr)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - SELECTIVE_PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); - NEXT_OPCODE(); + switch (opline->opcode) { + case ZEND_PRE_INC: + case ZEND_PRE_DEC: + EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); + SELECTIVE_PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &opline->result); + AI_USE_PTR(EX_T(opline->result.u.var).var); + NEXT_OPCODE(); + break; + case ZEND_POST_INC: + case ZEND_POST_DEC: + EX_T(opline->result.u.var).tmp_var = *EG(uninitialized_zval_ptr); + NEXT_OPCODE(); + break; + } } switch (opline->opcode) { @@ -2086,6 +2131,9 @@ int zend_fetch_dim_func_arg_handler(ZEND_OPCODE_HANDLER_ARGS) /* Behave like FETCH_DIM_W */ zend_fetch_dimension_address(&opline->result, &opline->op1, &opline->op2, EX(Ts), BP_VAR_W TSRMLS_CC); } else { + if (opline->op2.op_type == IS_UNUSED) { + zend_error(E_ERROR, "Cannot use [] for reading"); + } /* Behave like FETCH_DIM_R, except for locking used for list() */ zend_fetch_dimension_address(&opline->result, &opline->op1, &opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); AI_USE_PTR(EX_T(opline->result.u.var).var); @@ -2218,7 +2266,7 @@ int zend_assign_dim_handler(ZEND_OPCODE_HANDLER_ARGS) zend_fetch_dimension_address(&op_data->op2, &opline->op1, &opline->op2, EX(Ts), BP_VAR_W TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &EG(free_op1), BP_VAR_R); - zend_assign_to_variable(&opline->result, &op_data->op2, &op_data->op1, value, (EG(free_op1)?IS_TMP_VAR:opline->op1.op_type), EX(Ts) TSRMLS_CC); + zend_assign_to_variable(&opline->result, &op_data->op2, &op_data->op1, value, (EG(free_op1)?IS_TMP_VAR:op_data->op1.op_type), EX(Ts) TSRMLS_CC); } /* assign_dim has two opcodes! */ INC_OPCODE(); @@ -2242,6 +2290,19 @@ int zend_assign_ref_handler(ZEND_OPCODE_HANDLER_ARGS) { zval **value_ptr_ptr = get_zval_ptr_ptr(&opline->op2, EX(Ts), BP_VAR_W); + if (opline->op2.op_type == IS_VAR && + value_ptr_ptr && + !(*value_ptr_ptr)->is_ref && + opline->extended_value == ZEND_RETURNS_FUNCTION && + !EX_T(opline->op2.u.var).var.fcall_returned_reference) { + PZVAL_LOCK(*value_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */ + zend_error(E_STRICT, "Only variables should be assigned by reference"); + return zend_assign_handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } + if (opline->op1.op_type == IS_VAR && EX_T(opline->op1.u.var).var.ptr_ptr == &EX_T(opline->op1.u.var).var.ptr) { + zend_error(E_ERROR, "Cannot assign by reference to overloaded object"); + } + zend_assign_to_variable_reference(&opline->result, get_zval_ptr_ptr(&opline->op1, EX(Ts), BP_VAR_W), value_ptr_ptr, EX(Ts) TSRMLS_CC); NEXT_OPCODE(); @@ -2437,7 +2498,7 @@ int zend_fetch_class_handler(ZEND_OPCODE_HANDLER_ARGS) EX_T(opline->result.u.var).class_entry = Z_OBJCE_P(class_name); break; case IS_STRING: - EX_T(opline->result.u.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC); + EX_T(opline->result.u.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC); break; default: zend_error(E_ERROR, "Class name must be a valid object or a string"); @@ -2777,7 +2838,12 @@ int zend_do_fcall_common_helper(ZEND_OPCODE_HANDLER_ARGS) if (EG(This)) { if (EG(exception) && EX(fbc) && EX(fbc)->common.fn_flags&ZEND_ACC_CTOR) { EG(This)->refcount--; - zval_ptr_dtor(&EG(This)); + if (EG(This)->refcount == 1) { + zend_object_store_ctor_failed(EG(This) TSRMLS_CC); + } + if (should_change_scope && EG(This) != current_this) { + zval_ptr_dtor(&EG(This)); + } } else if (should_change_scope) { zval_ptr_dtor(&EG(This)); } @@ -2848,10 +2914,11 @@ int zend_return_handler(ZEND_OPCODE_HANDLER_ARGS) } if (!(*retval_ptr_ptr)->is_ref) { - if (EX_T(opline->op1.u.var).var.ptr_ptr == &EX_T(opline->op1.u.var).var.ptr - || (opline->extended_value == ZEND_RETURNS_FUNCTION && !EX_T(opline->op1.u.var).var.fcall_returned_reference)) { - zend_error(E_STRICT, "Only variable references should be returned by reference"); + if (opline->extended_value == ZEND_RETURNS_FUNCTION && + EX_T(opline->op1.u.var).var.fcall_returned_reference) { + } else if (EX_T(opline->op1.u.var).var.ptr_ptr == &EX_T(opline->op1.u.var).var.ptr) { PZVAL_LOCK(*retval_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */ + zend_error(E_STRICT, "Only variable references should be returned by reference"); goto return_by_value; } } @@ -2865,16 +2932,27 @@ int zend_return_handler(ZEND_OPCODE_HANDLER_ARGS) retval_ptr = get_zval_ptr(&opline->op1, EX(Ts), &EG(free_op1), BP_VAR_R); if (EG(ze1_compatibility_mode) && Z_TYPE_P(retval_ptr) == IS_OBJECT) { + char *class_name; + zend_uint class_name_len; + int dup; + + dup = zend_get_object_classname(retval_ptr, &class_name, &class_name_len TSRMLS_CC); + ALLOC_ZVAL(*(EG(return_value_ptr_ptr))); **EG(return_value_ptr_ptr) = *retval_ptr; INIT_PZVAL(*EG(return_value_ptr_ptr)); if (Z_OBJ_HT_P(retval_ptr)->clone_obj == NULL) { - zend_error(E_ERROR, "Trying to clone an uncloneable object of class %s", Z_OBJCE_P(retval_ptr)->name); + zend_error(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name); } - zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", Z_OBJCE_P(retval_ptr)->name); + zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name); (*EG(return_value_ptr_ptr))->value.obj = Z_OBJ_HT_P(retval_ptr)->clone_obj(retval_ptr TSRMLS_CC); + + if(!dup) { + efree(class_name); + } } else if (!EG(free_op1)) { /* Not a temp var */ - if (PZVAL_IS_REF(retval_ptr) && retval_ptr->refcount > 0) { + if (EG(active_op_array)->return_reference == ZEND_RETURN_REF || + (PZVAL_IS_REF(retval_ptr) && retval_ptr->refcount > 0)) { ALLOC_ZVAL(*(EG(return_value_ptr_ptr))); **EG(return_value_ptr_ptr) = *retval_ptr; (*EG(return_value_ptr_ptr))->is_ref = 0; @@ -2929,21 +3007,16 @@ int zend_catch_handler(ZEND_OPCODE_HANDLER_ARGS) } ce = Z_OBJCE_P(EG(exception)); if (ce != EX_T(opline->op1.u.var).class_entry) { - while (ce->parent) { - if (ce->parent == EX_T(opline->op1.u.var).class_entry) { - goto exception_should_be_taken; + if (!instanceof_function(ce, EX_T(opline->op1.u.var).class_entry TSRMLS_CC)) { + if (opline->op1.u.EA.type) { + zend_throw_exception_internal(NULL TSRMLS_CC); + NEXT_OPCODE(); } - ce = ce->parent; - } - if (opline->op1.u.EA.type) { - zend_throw_exception_internal(NULL TSRMLS_CC); - NEXT_OPCODE(); + SET_OPCODE(&op_array->opcodes[opline->extended_value]); + return 0; /* CHECK_ME */ } - SET_OPCODE(&op_array->opcodes[opline->extended_value]); - return 0; /* CHECK_ME */ } -exception_should_be_taken: zend_hash_update(EG(active_symbol_table), opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, &EG(exception), sizeof(zval *), (void **) NULL); EG(exception) = NULL; @@ -3010,7 +3083,10 @@ int zend_send_var_no_ref_handler(ZEND_OPCODE_HANDLER_ARGS) } else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) { return zend_send_by_var_helper(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - { + if ((opline->extended_value & ZEND_ARG_SEND_FUNCTION) && + !EX_T(opline->op1.u.var).var.fcall_returned_reference) { + zend_error(E_ERROR, "Only variables can be passed by reference"); + } else { zval *varptr; varptr = get_zval_ptr(&opline->op1, EX(Ts), &EG(free_op1), BP_VAR_R); @@ -3265,7 +3341,7 @@ int zend_clone_handler(ZEND_OPCODE_HANDLER_ARGS) NEXT_OPCODE(); } - ce = Z_OBJCE_P(obj); + ce = (Z_OBJ_HT_P(obj)->get_class_entry) ? Z_OBJCE_P(obj) : NULL; clone = ce ? ce->clone : NULL; clone_call = Z_OBJ_HT_P(obj)->clone_obj; if (!clone_call) { @@ -3628,62 +3704,70 @@ int zend_unset_dim_obj_handler(ZEND_OPCODE_HANDLER_ARGS) long index; if (container) { - HashTable *ht; - if (opline->extended_value == ZEND_UNSET_DIM) { switch (Z_TYPE_PP(container)) { - case IS_ARRAY: - ht = Z_ARRVAL_PP(container); + case IS_ARRAY: { + HashTable *ht = Z_ARRVAL_PP(container); + switch (offset->type) { + case IS_DOUBLE: + case IS_RESOURCE: + case IS_BOOL: + case IS_LONG: + if (offset->type == IS_DOUBLE) { + index = (long) offset->value.dval; + } else { + index = offset->value.lval; + } + + zend_hash_index_del(ht, index); + break; + case IS_STRING: + zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1); + break; + case IS_NULL: + zend_hash_del(ht, "", sizeof("")); + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; + } + FREE_OP(EX(Ts), &opline->op2, EG(free_op2)); break; + } case IS_OBJECT: - ht = NULL; if (!Z_OBJ_HT_P(*container)->unset_dimension) { zend_error(E_ERROR, "Cannot use object as array"); } + if (EG(free_op2)) { + MAKE_REAL_ZVAL_PTR(offset); + } Z_OBJ_HT_P(*container)->unset_dimension(*container, offset TSRMLS_CC); + if (EG(free_op2)) { + zval_ptr_dtor(&offset); + } break; case IS_STRING: zend_error(E_ERROR, "Cannot unset string offsets"); return 0; /* bailed out before */ default: - ht = NULL; + FREE_OP(EX(Ts), &opline->op2, EG(free_op2)); break; } } else { /* ZEND_UNSET_OBJ */ - ht = NULL; if (Z_TYPE_PP(container) == IS_OBJECT) { + if (EG(free_op2)) { + MAKE_REAL_ZVAL_PTR(offset); + } Z_OBJ_HT_P(*container)->unset_property(*container, offset TSRMLS_CC); - } - } - if (ht) { - switch (offset->type) { - case IS_DOUBLE: - case IS_RESOURCE: - case IS_BOOL: - case IS_LONG: - if (offset->type == IS_DOUBLE) { - index = (long) offset->value.dval; - } else { - index = offset->value.lval; - } - - zend_hash_index_del(ht, index); - break; - case IS_STRING: - zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1); - break; - case IS_NULL: - zend_hash_del(ht, "", sizeof("")); - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; + if (EG(free_op2)) { + zval_ptr_dtor(&offset); + } } } } else { /* overloaded element */ + FREE_OP(EX(Ts), &opline->op2, EG(free_op2)); } - FREE_OP(EX(Ts), &opline->op2, EG(free_op2)); NEXT_OPCODE(); } @@ -3699,8 +3783,14 @@ int zend_fe_reset_handler(ZEND_OPCODE_HANDLER_ARGS) if (opline->extended_value) { array_ptr_ptr = get_zval_ptr_ptr(&opline->op1, EX(Ts), BP_VAR_R); if (array_ptr_ptr == NULL) { - MAKE_STD_ZVAL(array_ptr); + ALLOC_INIT_ZVAL(array_ptr); } else if (Z_TYPE_PP(array_ptr_ptr) == IS_OBJECT) { + if(Z_OBJ_HT_PP(array_ptr_ptr)->get_class_entry == NULL) { + zend_error(E_WARNING, "foreach() can not iterate over objects without PHP class"); + opline++; + SET_OPCODE(op_array->opcodes+opline->op2.u.opline_num); + return 0; + } ce = Z_OBJCE_PP(array_ptr_ptr); if (!ce || ce->get_iterator == NULL) { SEPARATE_ZVAL_IF_NOT_REF(array_ptr_ptr); @@ -3721,7 +3811,7 @@ int zend_fe_reset_handler(ZEND_OPCODE_HANDLER_ARGS) *tmp = *array_ptr; INIT_PZVAL(tmp); array_ptr = tmp; - } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { + } else if (Z_TYPE_P(array_ptr) == IS_OBJECT && Z_OBJ_HT_P(array_ptr)->get_class_entry) { ce = Z_OBJCE_P(array_ptr); } else { array_ptr->refcount++; @@ -3731,10 +3821,16 @@ int zend_fe_reset_handler(ZEND_OPCODE_HANDLER_ARGS) if (ce && ce->get_iterator) { iter = ce->get_iterator(ce, array_ptr TSRMLS_CC); - if (iter) { + if (iter && !EG(exception)) { array_ptr = zend_iterator_wrap(iter TSRMLS_CC); } else { - array_ptr->refcount++; + FREE_OP(Ts, op1, EG(free_op1)); + if (!EG(exception)) { + zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %s did not create an Iterator", ce->name); + } + zend_throw_exception_internal(NULL TSRMLS_CC); + NEXT_OPCODE(); + return 0; } } @@ -3746,6 +3842,11 @@ int zend_fe_reset_handler(ZEND_OPCODE_HANDLER_ARGS) iter->index = 0; if (iter->funcs->rewind) { iter->funcs->rewind(iter TSRMLS_CC); + if (EG(exception)) { + array_ptr->refcount--; + zval_ptr_dtor(&array_ptr); + NEXT_OPCODE(); + } } } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { /* probably redundant */ @@ -3822,13 +3923,28 @@ int zend_fe_fetch_handler(ZEND_OPCODE_HANDLER_ARGS) /* This could cause an endless loop if index becomes zero again. * In case that ever happens we need an additional flag. */ iter->funcs->move_forward(iter TSRMLS_CC); + if (EG(exception)) { + array->refcount--; + zval_ptr_dtor(&array); + NEXT_OPCODE(); + } } if (!iter || iter->funcs->valid(iter TSRMLS_CC) == FAILURE) { /* reached end of iteration */ + if (EG(exception)) { + array->refcount--; + zval_ptr_dtor(&array); + NEXT_OPCODE(); + } SET_OPCODE(op_array->opcodes+opline->op2.u.opline_num); return 0; /* CHECK_ME */ } iter->funcs->get_current_data(iter, &value TSRMLS_CC); + if (EG(exception)) { + array->refcount--; + zval_ptr_dtor(&array); + NEXT_OPCODE(); + } if (!value) { /* failure in get_current_data */ SET_OPCODE(op_array->opcodes+opline->op2.u.opline_num); @@ -3836,6 +3952,11 @@ int zend_fe_fetch_handler(ZEND_OPCODE_HANDLER_ARGS) } if (iter->funcs->get_current_key) { key_type = iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC); + if (EG(exception)) { + array->refcount--; + zval_ptr_dtor(&array); + NEXT_OPCODE(); + } } else { key_type = HASH_KEY_IS_LONG; int_key = iter->index; @@ -3958,12 +4079,13 @@ int zend_isset_isempty_var_handler(ZEND_OPCODE_HANDLER_ARGS) static int zend_isset_isempty_dim_prop_obj_handler(int prop_dim, ZEND_OPCODE_HANDLER_ARGS) { zval **container = get_obj_zval_ptr_ptr(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC); - zval *offset = get_zval_ptr(&opline->op2, EX(Ts), &EG(free_op2), BP_VAR_R); zval **value = NULL; int result = 0; long index; if (container) { + zval *offset = get_zval_ptr(&opline->op2, EX(Ts), &EG(free_op2), BP_VAR_R); + if ((*container)->type == IS_ARRAY) { HashTable *ht; int isset = 0; @@ -4016,28 +4138,46 @@ static int zend_isset_isempty_dim_prop_obj_handler(int prop_dim, ZEND_OPCODE_HAN } break; } + FREE_OP(EX(Ts), &opline->op2, EG(free_op2)); } else if ((*container)->type == IS_OBJECT) { + if (EG(free_op2)) { + MAKE_REAL_ZVAL_PTR(offset); + } if (prop_dim) { result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC); } else { result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC); } - } else if ((*container)->type == IS_STRING) { /* string offsets */ + if (EG(free_op2)) { + zval_ptr_dtor(&offset); + } + } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */ + zval tmp; + + if (offset->type != IS_LONG) { + tmp = *offset; + zval_copy_ctor(&tmp); + convert_to_long(&tmp); + offset = &tmp; + } switch (opline->extended_value) { case ZEND_ISSET: - if (offset->value.lval <= Z_STRLEN_PP(container)) { + if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) { result = 1; } break; case ZEND_ISEMPTY: - if (offset->value.lval <= Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') { + if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') { result = 1; } break; } + FREE_OP(EX(Ts), &opline->op2, EG(free_op2)); + } else { + FREE_OP(EX(Ts), &opline->op2, EG(free_op2)); } } - + EX_T(opline->result.u.var).tmp_var.type = IS_BOOL; switch (opline->extended_value) { @@ -4049,8 +4189,6 @@ static int zend_isset_isempty_dim_prop_obj_handler(int prop_dim, ZEND_OPCODE_HAN break; } - FREE_OP(EX(Ts), &opline->op2, EG(free_op2)); - NEXT_OPCODE(); } @@ -4193,7 +4331,7 @@ int zend_instanceof_handler(ZEND_OPCODE_HANDLER_ARGS) zval *expr = get_zval_ptr(&opline->op1, EX(Ts), &EG(free_op1), BP_VAR_R); zend_bool result; - if (Z_TYPE_P(expr) == IS_OBJECT) { + if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->get_class_entry) { result = instanceof_function(Z_OBJCE_P(expr), EX_T(opline->op2.u.var).class_entry TSRMLS_CC); } else { result = 0; @@ -4243,6 +4381,7 @@ int zend_handle_exception_handler(ZEND_OPCODE_HANDLER_ARGS) while (*stack_zval_pp != NULL) { zval_ptr_dtor(stack_zval_pp); EG(argument_stack).top_element--; + EG(argument_stack).top--; stack_zval_pp--; } @@ -4257,6 +4396,13 @@ int zend_handle_exception_handler(ZEND_OPCODE_HANDLER_ARGS) } } + while (EX(fbc)) { + if (EX(object)) { + zval_ptr_dtor(&EX(object)); + } + zend_ptr_stack_n_pop(&EG(arg_types_stack), 3, &EX(calling_scope), &EX(object), &EX(fbc)); + } + if (encapsulating_block == -1) { RETURN_FROM_EXECUTE_LOOP(execute_data); } else { @@ -4275,7 +4421,7 @@ int zend_verify_abstract_class_handler(ZEND_OPCODE_HANDLER_ARGS) void zend_init_opcodes_handlers() { - memset(zend_opcode_handlers, sizeof(zend_opcode_handlers), 0); + memset(zend_opcode_handlers, 0, sizeof(zend_opcode_handlers)); zend_opcode_handlers[ZEND_NOP] = zend_nop_handler; zend_opcode_handlers[ZEND_ADD] = zend_add_handler; zend_opcode_handlers[ZEND_SUB] = zend_sub_handler; diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index d4d02a49e70a..2ff6ba25eb48 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -49,6 +49,7 @@ ZEND_API extern void (*zend_execute_internal)(zend_execute_data *execute_data_pt void init_executor(TSRMLS_D); void shutdown_executor(TSRMLS_D); +void shutdown_destructors(TSRMLS_D); ZEND_API void execute(zend_op_array *op_array TSRMLS_DC); ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC); ZEND_API int zend_is_true(zval *op); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 0cee71deb1d9..90f12d35a478 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -183,8 +183,15 @@ void init_executor(TSRMLS_D) EG(scope) = NULL; EG(This) = NULL; +} - EG(float_separator)[0] = '.'; +void shutdown_destructors(TSRMLS_D) { + zend_try { + zend_objects_store_call_destructors(&EG(objects_store) TSRMLS_CC); + } zend_catch { + /* if we couldn't destruct cleanly, mark all objects as destructed anyway */ + zend_objects_store_mark_destructed(&EG(objects_store) TSRMLS_CC); + } zend_end_try(); } void shutdown_executor(TSRMLS_D) @@ -206,8 +213,10 @@ void shutdown_executor(TSRMLS_D) } */ zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_deactivator TSRMLS_CC); - zend_objects_store_call_destructors(&EG(objects_store) TSRMLS_CC); zend_hash_graceful_reverse_destroy(&EG(symbol_table)); + } zend_catch { + /* if we couldn't destruct cleanly, mark all objects as destructed anyway */ + zend_objects_store_mark_destructed(&EG(objects_store) TSRMLS_CC); } zend_end_try(); zend_try { @@ -276,11 +285,6 @@ void shutdown_executor(TSRMLS_D) clean_non_persistent_constants(TSRMLS_C); } zend_end_try(); - /* The regular list must be destroyed after the main symbol table, - * op arrays, and constants are destroyed. - */ - zend_destroy_rsrc_list(&EG(regular_list) TSRMLS_CC); - zend_try { #if ZEND_DEBUG signal(SIGSEGV, original_sigsegv_handler); @@ -298,6 +302,16 @@ void shutdown_executor(TSRMLS_D) FREE_HASHTABLE(EG(in_autoload)); } } zend_end_try(); + + /* may be used by zend_error before init_executor */ + EG(user_error_handler) = NULL; + EG(user_exception_handler) = NULL; + memset(&EG(user_error_handlers_error_reporting), 0, sizeof(EG(user_error_handlers_error_reporting))); + memset(&EG(user_error_handlers), 0, sizeof(EG(user_error_handlers))); + memset(&EG(user_exception_handlers), 0, sizeof(EG(user_exception_handlers))); + EG(objects_store).object_buckets = NULL; + EG(objects_store).top = 1; + EG(exception) = NULL; } @@ -383,15 +397,17 @@ ZEND_API zend_bool zend_is_executing(TSRMLS_D) ZEND_API void _zval_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC) { + zval *zv = *zval_ptr; + #if DEBUG_ZEND>=2 printf("Reducing refcount for %x (%x): %d->%d\n", *zval_ptr, zval_ptr, (*zval_ptr)->refcount, (*zval_ptr)->refcount-1); #endif - (*zval_ptr)->refcount--; - if ((*zval_ptr)->refcount==0) { - zval_dtor(*zval_ptr); - safe_free_zval_ptr_rel(*zval_ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC); - } else if ((*zval_ptr)->refcount == 1) { - (*zval_ptr)->is_ref = 0; + zv->refcount--; + if (zv->refcount==0) { + zval_dtor(zv); + safe_free_zval_ptr_rel(zv ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC); + } else if (zv->refcount == 1) { + zv->is_ref = 0; } } @@ -426,11 +442,13 @@ ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC) if (p->type == IS_CONSTANT) { int refcount; + zend_uchar is_ref; - SEPARATE_ZVAL(pp); + SEPARATE_ZVAL_IF_NOT_REF(pp); p = *pp; refcount = p->refcount; + is_ref = p->is_ref; if (!zend_get_constant(p->value.str.val, p->value.str.len, &const_value TSRMLS_CC)) { zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", @@ -447,15 +465,15 @@ ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC) *p = const_value; } - INIT_PZVAL(p); p->refcount = refcount; + p->is_ref = is_ref; } else if (p->type == IS_CONSTANT_ARRAY) { zval **element, *new_val; char *str_index; uint str_index_len; ulong num_index; - SEPARATE_ZVAL(pp); + SEPARATE_ZVAL_IF_NOT_REF(pp); p = *pp; p->type = IS_ARRAY; @@ -498,6 +516,7 @@ ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC) case IS_STRING: zend_symtable_update(p->value.ht, const_value.value.str.val, const_value.value.str.len+1, &new_val, sizeof(zval *), NULL); break; + case IS_BOOL: case IS_LONG: zend_hash_index_update(p->value.ht, const_value.value.lval, &new_val, sizeof(zval *), NULL); break; @@ -560,6 +579,8 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS zend_op_array *original_op_array; zend_op **original_opline_ptr; zval *orig_free_op1, *orig_free_op2; + zval *orig_garbage[2]; + int orig_garbage_ptr; int (*orig_unary_op)(zval *result, zval *op1); int (*orig_binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC); zend_class_entry *current_scope; @@ -570,6 +591,10 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS zval *params_array; int call_via_handler = 0; + if (EG(exception)) { + return FAILURE; /* we would result in an instable executor otherwise */ + } + switch (fci->size) { case sizeof(zend_fcall_info): break; /* nothing to do currently */ @@ -581,6 +606,8 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS /* Initialize execute_data */ if (EG(current_execute_data)) { execute_data = *EG(current_execute_data); + EX(op_array) = NULL; + EX(opline) = NULL; } else { /* This only happens when we're called outside any execute()'s * It shouldn't be strictly necessary to NULL execute_data out, @@ -668,6 +695,9 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS fci->function_table = &(*ce)->function_table; calling_scope = *ce; + } else { + zend_error(E_NOTICE, "Non-callable array passed to zend_call_function()"); + return FAILURE; } if (fci->function_table == NULL) { @@ -684,7 +714,15 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS zend_error(E_ERROR, "Object does not support method calls"); } EX(function_state).function = - Z_OBJ_HT_PP(fci->object_pp)->get_method(*fci->object_pp, Z_STRVAL_P(fci->function_name), Z_STRLEN_P(fci->function_name) TSRMLS_CC); + Z_OBJ_HT_PP(fci->object_pp)->get_method(*fci->object_pp, Z_STRVAL_P(fci->function_name), Z_STRLEN_P(fci->function_name) TSRMLS_CC); + if (EX(function_state).function && calling_scope != EX(function_state).function->common.scope) { + char *function_name_lc = zend_str_tolower_dup(Z_STRVAL_P(fci->function_name), Z_STRLEN_P(fci->function_name)); + if (zend_hash_find(&calling_scope->function_table, function_name_lc, fci->function_name->value.str.len+1, (void **) &EX(function_state).function)==FAILURE) { + efree(function_name_lc); + zend_error(E_ERROR, "Cannot call method %s::%s() or method does not exist", calling_scope->name, Z_STRVAL_P(fci->function_name)); + } + efree(function_name_lc); + } } else if (calling_scope) { char *function_name_lc = zend_str_tolower_dup(Z_STRVAL_P(fci->function_name), Z_STRLEN_P(fci->function_name)); @@ -715,7 +753,9 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS return FAILURE; } } - if (fci_cache) { + if (fci_cache && + (EX(function_state).function->type != ZEND_INTERNAL_FUNCTION || + ((zend_internal_function*)EX(function_state).function)->handler != zend_std_call_user_call)) { fci_cache->function_handler = EX(function_state).function; fci_cache->object_pp = fci->object_pp; fci_cache->calling_scope = calling_scope; @@ -736,6 +776,11 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS zval *new_zval; if (fci->no_separation) { + if(i) { + /* hack to clean up the stack */ + zend_ptr_stack_n_push(&EG(argument_stack), 2, (void *) (long) i, NULL); + zend_ptr_stack_clear_multiple(TSRMLS_C); + } return FAILURE; } ALLOC_ZVAL(new_zval); @@ -806,7 +851,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS } else { severity = E_ERROR; } - zend_error(E_STRICT, "Non-static method %s::%s() cannot be called statically", calling_scope->name, EX(function_state).function->common.function_name); + zend_error(severity, "Non-static method %s::%s() cannot be called statically", calling_scope->name, EX(function_state).function->common.function_name); } } @@ -832,6 +877,11 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS orig_free_op2 = EG(free_op2); orig_unary_op = EG(unary_op); orig_binary_op = EG(binary_op); + orig_garbage_ptr = EG(garbage_ptr); + EG(garbage_ptr) = 0; + if (orig_garbage_ptr > 0) { + memcpy(&orig_garbage, &EG(garbage), sizeof(zval*)*orig_garbage_ptr); + } zend_execute(EG(active_op_array) TSRMLS_CC); if (!fci->symbol_table) { zend_hash_destroy(EG(active_symbol_table)); @@ -845,6 +895,13 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS EG(free_op2) = orig_free_op2; EG(unary_op) = orig_unary_op; EG(binary_op) = orig_binary_op; + if (orig_garbage_ptr > 0) { + while (EG(garbage_ptr)) { + zval_ptr_dtor(&EG(garbage)[--EG(garbage_ptr)]); + } + EG(garbage_ptr) = orig_garbage_ptr; + memcpy(&EG(garbage), &orig_garbage, sizeof(zval*)*orig_garbage_ptr); + } } else { ALLOC_INIT_ZVAL(*fci->retval_ptr_ptr); if (EX(function_state).function->common.scope) { @@ -878,13 +935,17 @@ ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry *** { zval **args[1]; zval autoload_function; - zval class_name, *class_name_ptr = &class_name; + zval *class_name_ptr; zval *retval_ptr; int retval; char *lc_name; zval *exception; char dummy = 1; + if (name == NULL) { + return FAILURE; + } + lc_name = do_alloca(name_length + 1); zend_str_tolower_copy(lc_name, name, name_length); @@ -911,10 +972,11 @@ ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry *** return FAILURE; } - ZVAL_STRINGL(&autoload_function, "__autoload", sizeof("__autoload")-1, 0); + ZVAL_STRINGL(&autoload_function, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME)-1, 0); + ALLOC_ZVAL(class_name_ptr); INIT_PZVAL(class_name_ptr); - ZVAL_STRINGL(class_name_ptr, name, name_length, 0); + ZVAL_STRINGL(class_name_ptr, name, name_length, 1); args[0] = &class_name_ptr; @@ -922,6 +984,8 @@ ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry *** EG(exception) = NULL; retval = call_user_function_ex(EG(function_table), NULL, &autoload_function, &retval_ptr, 1, args, 0, NULL TSRMLS_CC); + zval_ptr_dtor(&class_name_ptr); + zend_hash_del(EG(in_autoload), lc_name, name_length+1); if (retval == FAILURE) { @@ -932,7 +996,7 @@ ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry *** if (EG(exception)) { free_alloca(lc_name); - zend_error(E_ERROR, "__autoload(%s) threw an exception of type '%s'", name, Z_OBJCE_P(EG(exception))->name); + zend_error(E_ERROR, "Function %s(%s) threw an exception of type '%s'", ZEND_AUTOLOAD_FUNC_NAME, name, Z_OBJCE_P(EG(exception))->name); return FAILURE; } EG(exception) = exception; @@ -1060,6 +1124,17 @@ void execute_new_code(TSRMLS_D) opline->op2.u.constant.is_ref = 1; opline->op2.u.constant.refcount = 2; } + switch (opline->opcode) { + case ZEND_JMP: + opline->op1.u.jmp_addr = &CG(active_op_array)->opcodes[opline->op1.u.opline_num]; + break; + case ZEND_JMPZ: + case ZEND_JMPNZ: + case ZEND_JMPZ_EX: + case ZEND_JMPNZ_EX: + opline->op2.u.jmp_addr = &CG(active_op_array)->opcodes[opline->op2.u.opline_num]; + break; + } opline->handler = zend_opcode_handlers[opline->opcode]; opline++; } @@ -1217,10 +1292,17 @@ void zend_set_timeout(long seconds) t_r.it_value.tv_sec = seconds; t_r.it_value.tv_usec = t_r.it_interval.tv_sec = t_r.it_interval.tv_usec = 0; +# ifdef __CYGWIN__ + setitimer(ITIMER_REAL, &t_r, NULL); + signal(SIGALRM, zend_timeout); + sigemptyset(&sigset); + sigaddset(&sigset, SIGALRM); +# else setitimer(ITIMER_PROF, &t_r, NULL); signal(SIGPROF, zend_timeout); sigemptyset(&sigset); sigaddset(&sigset, SIGPROF); +# endif sigprocmask(SIG_UNBLOCK, &sigset, NULL); } # endif @@ -1239,7 +1321,11 @@ void zend_unset_timeout(TSRMLS_D) no_timeout.it_value.tv_sec = no_timeout.it_value.tv_usec = no_timeout.it_interval.tv_sec = no_timeout.it_interval.tv_usec = 0; +#ifdef __CYGWIN__ + setitimer(ITIMER_REAL, &no_timeout, NULL); +#else setitimer(ITIMER_PROF, &no_timeout, NULL); +#endif } # endif #endif @@ -1275,7 +1361,11 @@ zend_class_entry *zend_fetch_class(char *class_name, uint class_name_len, int fe } if (zend_lookup_class(class_name, class_name_len, &pce TSRMLS_CC)==FAILURE) { - zend_error(E_ERROR, "Class '%s' not found", class_name); + if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) { + zend_error(E_ERROR, "Interface '%s' not found", class_name); + } else { + zend_error(E_ERROR, "Class '%s' not found", class_name); + } } return *pce; } @@ -1318,8 +1408,9 @@ void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC) zend_hash_apply_with_argument(&ce->function_table, (apply_func_arg_t) zend_verify_abstract_class_function, &ai TSRMLS_CC); if (ai.cnt) { - zend_error(E_ERROR, "Class %s contains %d abstract methods and must therefore be declared abstract (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")", + zend_error(E_ERROR, "Class %s contains %d abstract method%s and must therefore be declared abstract or implement the remaining methods (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")", ce->name, ai.cnt, + ai.cnt > 1 ? "s" : "", DISPLAY_ABSTRACT_FN(0), DISPLAY_ABSTRACT_FN(1), DISPLAY_ABSTRACT_FN(2) diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 1ce4c39295b9..41063f433071 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -237,9 +237,6 @@ struct _zend_executor_globals { zend_property_info std_property_info; - /* locale stuff */ - char float_separator[1]; - void *reserved[ZEND_MAX_RESERVED_RESOURCES]; }; diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 065c9b46805b..0c668ee20daa 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -1054,7 +1054,7 @@ ZEND_API int zend_hash_get_current_key_ex(HashTable *ht, char **str_index, uint if (p) { if (p->nKeyLength) { if (duplicate) { - *str_index = estrndup(p->arKey, p->nKeyLength); + *str_index = estrndup(p->arKey, p->nKeyLength-1); } else { *str_index = p->arKey; } diff --git a/Zend/zend_highlight.c b/Zend/zend_highlight.c index 757a4a128419..7eec296b5a2f 100644 --- a/Zend/zend_highlight.c +++ b/Zend/zend_highlight.c @@ -20,7 +20,7 @@ /* $Id$ */ #include "zend.h" -#include "zend_language_parser.h" +#include #include "zend_compile.h" #include "zend_highlight.h" #include "zend_ptr_stack.h" @@ -71,17 +71,9 @@ ZEND_API void zend_html_puts(const char *s, uint len TSRMLS_DC) while (ptrhighlight_html; char *next_color; - int in_string=0; + int in_string=0, post_heredoc = 0; zend_printf(""); zend_printf("\n", last_color); @@ -159,9 +151,14 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini switch (token_type) { case T_END_HEREDOC: zend_html_puts(token.value.str.val, token.value.str.len TSRMLS_CC); + post_heredoc = 1; break; default: zend_html_puts(LANG_SCNG(yy_text), LANG_SCNG(yy_leng) TSRMLS_CC); + if (post_heredoc) { + zend_html_putc('\n'); + post_heredoc = 0; + } break; } @@ -203,7 +200,7 @@ ZEND_API void zend_strip(TSRMLS_D) switch (token_type) { case T_WHITESPACE: if (!prev_space) { - putchar(' '); + zend_write(" ", sizeof(" ") - 1); prev_space = 1; } /* lack of break; is intentional */ @@ -215,9 +212,9 @@ ZEND_API void zend_strip(TSRMLS_D) case T_END_HEREDOC: { char *ptr = LANG_SCNG(yy_text); - fwrite(ptr, LANG_SCNG(yy_leng) - 1, 1, stdout); + zend_write(ptr, LANG_SCNG(yy_leng) - 1); /* The ensure that we only write one ; and that it followed by the required newline */ - putchar('\n'); + zend_write("\n", sizeof("\n") - 1); if (ptr[LANG_SCNG(yy_leng) - 1] == ';') { lex_scan(&token TSRMLS_CC); } @@ -226,7 +223,7 @@ ZEND_API void zend_strip(TSRMLS_D) break; default: - fwrite(LANG_SCNG(yy_text), LANG_SCNG(yy_leng), 1, stdout); + zend_write(LANG_SCNG(yy_text), LANG_SCNG(yy_leng)); break; } diff --git a/Zend/zend_indent.c b/Zend/zend_indent.c index 80198c8a7a92..8e120b4d6285 100644 --- a/Zend/zend_indent.c +++ b/Zend/zend_indent.c @@ -23,7 +23,7 @@ #include "zend.h" -#include "zend_language_parser.h" +#include #include "zend_compile.h" #include "zend_indent.h" diff --git a/Zend/zend_ini.c b/Zend/zend_ini.c index 5128a0f8a435..3d6b873b08dc 100644 --- a/Zend/zend_ini.c +++ b/Zend/zend_ini.c @@ -24,6 +24,7 @@ #include "zend_ini.h" #include "zend_alloc.h" #include "zend_operators.h" +#include "zend_strtod.h" static HashTable *registered_zend_ini_directives; @@ -47,7 +48,12 @@ static int zend_restore_ini_entry_cb(zend_ini_entry *ini_entry, int stage TSRMLS { if (ini_entry->modified) { if (ini_entry->on_modify) { - ini_entry->on_modify(ini_entry, ini_entry->orig_value, ini_entry->orig_value_length, ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage TSRMLS_CC); + zend_try { + /* even if on_modify bails out, we have to continue on with restoring, + since there can be allocated variables that would be freed on MM shutdown + and would lead to memory corruption later ini entry is modified again */ + ini_entry->on_modify(ini_entry, ini_entry->orig_value, ini_entry->orig_value_length, ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage TSRMLS_CC); + } zend_end_try(); } efree(ini_entry->value); ini_entry->value = ini_entry->orig_value; @@ -147,10 +153,27 @@ ZEND_API int zend_register_ini_entries(zend_ini_entry *ini_entry, int module_num zend_ini_entry *p = ini_entry; zend_ini_entry *hashed_ini_entry; zval default_value; + HashTable *directives = registered_zend_ini_directives; + zend_bool config_directive_success = 0; + +#ifdef ZTS + /* if we are called during the request, eg: from dl(), + * then we should not touch the global directives table, + * and should update the per-(request|thread) version instead. + * This solves two problems: one is that ini entries for dl()'d + * extensions will now work, and the second is that updating the + * global hash here from dl() is not mutex protected and can + * lead to death. + */ + if (directives != EG(ini_directives)) { + directives = EG(ini_directives); + } +#endif while (p->name) { p->module_number = module_number; - if (zend_hash_add(registered_zend_ini_directives, p->name, p->name_length, p, sizeof(zend_ini_entry), (void **) &hashed_ini_entry)==FAILURE) { + config_directive_success = 0; + if (zend_hash_add(directives, p->name, p->name_length, p, sizeof(zend_ini_entry), (void **) &hashed_ini_entry)==FAILURE) { zend_unregister_ini_entries(module_number TSRMLS_CC); return FAILURE; } @@ -159,11 +182,12 @@ ZEND_API int zend_register_ini_entries(zend_ini_entry *ini_entry, int module_num || hashed_ini_entry->on_modify(hashed_ini_entry, default_value.value.str.val, default_value.value.str.len, hashed_ini_entry->mh_arg1, hashed_ini_entry->mh_arg2, hashed_ini_entry->mh_arg3, ZEND_INI_STAGE_STARTUP TSRMLS_CC)==SUCCESS) { hashed_ini_entry->value = default_value.value.str.val; hashed_ini_entry->value_length = default_value.value.str.len; + config_directive_success = 1; } - } else { - if (hashed_ini_entry->on_modify) { - hashed_ini_entry->on_modify(hashed_ini_entry, hashed_ini_entry->value, hashed_ini_entry->value_length, hashed_ini_entry->mh_arg1, hashed_ini_entry->mh_arg2, hashed_ini_entry->mh_arg3, ZEND_INI_STAGE_STARTUP TSRMLS_CC); - } + } + + if (!config_directive_success && hashed_ini_entry->on_modify) { + hashed_ini_entry->on_modify(hashed_ini_entry, hashed_ini_entry->value, hashed_ini_entry->value_length, hashed_ini_entry->mh_arg1, hashed_ini_entry->mh_arg2, hashed_ini_entry->mh_arg3, ZEND_INI_STAGE_STARTUP TSRMLS_CC); } p++; } @@ -283,9 +307,9 @@ ZEND_API double zend_ini_double(char *name, uint name_length, int orig) if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry)==SUCCESS) { if (orig && ini_entry->modified) { - return (double) (ini_entry->orig_value ? strtod(ini_entry->orig_value, NULL) : 0.0); + return (double) (ini_entry->orig_value ? zend_strtod(ini_entry->orig_value, NULL) : 0.0); } else if (ini_entry->value) { - return (double) strtod(ini_entry->value, NULL); + return (double) zend_strtod(ini_entry->value, NULL); } } @@ -471,7 +495,7 @@ ZEND_API ZEND_INI_MH(OnUpdateReal) p = (double *) (base+(size_t) mh_arg1); - *p = strtod(new_value, NULL); + *p = zend_strtod(new_value, NULL); return SUCCESS; } diff --git a/Zend/zend_ini.h b/Zend/zend_ini.h index 1eb97b6666ef..e7bdd76be26a 100644 --- a/Zend/zend_ini.h +++ b/Zend/zend_ini.h @@ -192,7 +192,7 @@ END_EXTERN_C() /* INI parsing engine */ typedef void (*zend_ini_parser_cb_t)(zval *arg1, zval *arg2, int callback_type, void *arg); BEGIN_EXTERN_C() -int zend_parse_ini_file(zend_file_handle *fh, zend_bool unbuffered_errors, zend_ini_parser_cb_t ini_parser_cb, void *arg); +ZEND_API int zend_parse_ini_file(zend_file_handle *fh, zend_bool unbuffered_errors, zend_ini_parser_cb_t ini_parser_cb, void *arg); END_EXTERN_C() #define ZEND_INI_PARSER_ENTRY 1 diff --git a/Zend/zend_ini_parser.y b/Zend/zend_ini_parser.y index 1d90e34f5f59..8a70c665a18d 100644 --- a/Zend/zend_ini_parser.y +++ b/Zend/zend_ini_parser.y @@ -139,7 +139,7 @@ static void ini_error(char *str) } -int zend_parse_ini_file(zend_file_handle *fh, zend_bool unbuffered_errors, zend_ini_parser_cb_t ini_parser_cb, void *arg) +ZEND_API int zend_parse_ini_file(zend_file_handle *fh, zend_bool unbuffered_errors, zend_ini_parser_cb_t ini_parser_cb, void *arg) { int retval; zend_ini_parser_param ini_parser_param; diff --git a/Zend/zend_ini_scanner.l b/Zend/zend_ini_scanner.l index f2da5998e33c..7eadf74a08e9 100644 --- a/Zend/zend_ini_scanner.l +++ b/Zend/zend_ini_scanner.l @@ -32,7 +32,7 @@ #include #include "zend.h" #include "zend_globals.h" -#include "zend_ini_parser.h" +#include #include "zend_ini_scanner.h" #undef YYSTYPE @@ -53,13 +53,13 @@ static char *ini_filename; void init_ini_scanner(TSRMLS_D) { - SCNG(lineno)=1; + SCNG(lineno)=1; } int zend_ini_scanner_get_lineno(TSRMLS_D) { - return SCNG(lineno); + return SCNG(lineno); } @@ -116,10 +116,10 @@ NEWLINE ("\r"|"\n"|"\r\n") return CFG_FALSE; } -[[][^[]+[\]][ ]*{NEWLINE}? { +[[][^\]\n]+[\]][ ]*{NEWLINE}? { /* SECTION */ - /* eat trailng and spaces ] */ + /* eat trailing ] and spaces */ while (yyleng>0 && (yytext[yyleng-1]=='\n' || yytext[yyleng-1]=='\r' || yytext[yyleng-1]==']' || yytext[yyleng-1]==' ')) { yyleng--; yytext[yyleng]=0; diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c index 69a546de6078..44bdccec9b81 100755 --- a/Zend/zend_interfaces.c +++ b/Zend/zend_interfaces.c @@ -21,6 +21,7 @@ #include "zend.h" #include "zend_API.h" #include "zend_interfaces.h" +#include "zend_exceptions.h" ZEND_API zend_class_entry *zend_ce_traversable; ZEND_API zend_class_entry *zend_ce_aggregate; @@ -35,6 +36,7 @@ ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend zend_fcall_info fci; zval z_fname; zval *retval; + HashTable *function_table; zval **params[2]; @@ -61,12 +63,17 @@ ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend fcic.initialized = 1; if (!obj_ce) { - obj_ce = Z_OBJCE_PP(object_pp); + obj_ce = object_pp ? Z_OBJCE_PP(object_pp) : NULL; + } + if (obj_ce) { + function_table = &obj_ce->function_table; + } else { + function_table = EG(function_table); } if (!fn_proxy || !*fn_proxy) { - if (zend_hash_find(&obj_ce->function_table, function_name, function_name_len+1, (void **) &fcic.function_handler) == FAILURE) { + if (zend_hash_find(function_table, function_name, function_name_len+1, (void **) &fcic.function_handler) == FAILURE) { /* error at c-level */ - zend_error(E_CORE_ERROR, "Couldn't find implementation for method %s::%s", obj_ce->name, function_name); + zend_error(E_CORE_ERROR, "Couldn't find implementation for method %s%s%s", obj_ce ? obj_ce->name : "", obj_ce ? "::" : "", function_name); } if (fn_proxy) { *fn_proxy = fcic.function_handler; @@ -81,9 +88,9 @@ ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend if (result == FAILURE) { /* error at c-level */ if (!obj_ce) { - obj_ce = Z_OBJCE_PP(object_pp); + obj_ce = object_pp ? Z_OBJCE_PP(object_pp) : NULL; } - zend_error(E_CORE_ERROR, "Couldn't execute method %s::%s", obj_ce->name, function_name); + zend_error(E_CORE_ERROR, "Couldn't execute method %s%s%s", obj_ce ? obj_ce->name : "", obj_ce ? "::" : "", function_name); } if (!retval_ptr_ptr) { if (retval) { @@ -270,11 +277,17 @@ static zend_object_iterator *zend_user_it_get_new_iterator(zend_class_entry *ce, zval *iterator = zend_user_it_new_iterator(ce, object TSRMLS_CC); zend_object_iterator *new_iterator; - zend_class_entry *ce_it = Z_TYPE_P(iterator) == IS_OBJECT ? Z_OBJCE_P(iterator) : NULL; + zend_class_entry *ce_it = iterator && Z_TYPE_P(iterator) == IS_OBJECT ? Z_OBJCE_P(iterator) : NULL; - if (!ce || !ce_it || !ce_it->get_iterator) { - zend_error(E_WARNING, "Objects returned by %s::getIterator() must be traversable or implement interface Iterator", ce->name); - zval_ptr_dtor(&iterator); + if (!ce || !ce_it || !ce_it->get_iterator || (ce_it->get_iterator == zend_user_it_get_new_iterator && iterator == object)) { + if (!EG(exception)) + { + zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Objects returned by %s::getIterator() must be traversable or implement interface Iterator", ce->name); + } + if (iterator) + { + zval_ptr_dtor(&iterator); + } return NULL; } new_iterator = ce_it->get_iterator(ce_it, iterator TSRMLS_CC); @@ -287,7 +300,7 @@ static zend_object_iterator *zend_user_it_get_new_iterator(zend_class_entry *ce, static int zend_implement_traversable(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC) { /* check that class_type is traversable at c-level or implements at least one of 'aggregate' and 'Iterator' */ - int i; + zend_uint i; if (class_type->get_iterator || (class_type->parent && class_type->parent->get_iterator)) { return SUCCESS; diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 6d85f8be7a87..f26406b26863 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -291,9 +291,9 @@ unticked_class_declaration_statement: class_entry_type: - T_CLASS { $$.u.constant.value.lval = 0; } - | T_ABSTRACT T_CLASS { $$.u.constant.value.lval = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; } - | T_FINAL T_CLASS { $$.u.constant.value.lval = ZEND_ACC_FINAL_CLASS; } + T_CLASS { $$.u.opline_num = CG(zend_lineno); $$.u.EA.type = 0; } + | T_ABSTRACT T_CLASS { $$.u.opline_num = CG(zend_lineno); $$.u.EA.type = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; } + | T_FINAL T_CLASS { $$.u.opline_num = CG(zend_lineno); $$.u.EA.type = ZEND_ACC_FINAL_CLASS; } ; extends_from: @@ -302,7 +302,7 @@ extends_from: ; interface_entry: - T_INTERFACE { $$.u.constant.value.lval = ZEND_ACC_INTERFACE; } + T_INTERFACE { $$.u.opline_num = CG(zend_lineno); $$.u.EA.type = ZEND_ACC_INTERFACE; } ; interface_extends_list: @@ -614,12 +614,12 @@ function_call: T_STRING '(' { $2.u.opline_num = zend_do_begin_function_call(&$1 TSRMLS_CC); } function_call_parameter_list ')' { zend_do_end_function_call(&$1, &$$, &$4, 0, $2.u.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); } - | class_constant '(' { zend_do_begin_class_member_function_call(TSRMLS_C); zend_do_extended_fcall_begin(TSRMLS_C); } + | fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' { zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); } function_call_parameter_list - ')' { zend_do_end_function_call(NULL, &$$, &$4, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} - | static_member '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(TSRMLS_C); zend_do_extended_fcall_begin(TSRMLS_C); } + ')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} + | fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); } function_call_parameter_list - ')' { zend_do_end_function_call(NULL, &$$, &$4, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} + ')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} | variable_without_objects '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1 TSRMLS_CC); } function_call_parameter_list ')' { zend_do_end_function_call(&$1, &$$, &$4, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index e6efbcc8270e..1f07062e7cb6 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -50,13 +50,14 @@ #include #include "zend.h" #include "zend_alloc.h" -#include "zend_language_parser.h" +#include #include "zend_compile.h" #include "zend_language_scanner.h" #include "zend_highlight.h" #include "zend_constants.h" #include "zend_variables.h" #include "zend_operators.h" +#include "zend_strtod.h" #ifdef HAVE_STDARG_H # include @@ -124,14 +125,20 @@ void startup_scanner(TSRMLS_D) { CG(heredoc) = NULL; CG(heredoc_len)=0; - RESET_DOC_COMMENT(); + CG(doc_comment) = NULL; + CG(doc_comment_len) = 0; SCNG(yy_start_stack_ptr) = 0; SCNG(yy_start_stack_depth) = 0; + SCNG(current_buffer) = NULL; #ifdef ZEND_MULTIBYTE SCNG(script_org) = NULL; SCNG(script_org_size) = 0; SCNG(script_filtered) = NULL; SCNG(script_filtered_size) = 0; + SCNG(input_filter) = NULL; + SCNG(output_filter) = NULL; + SCNG(script_encoding) = NULL; + SCNG(internal_encoding) = NULL; #endif /* ZEND_MULTIBYTE */ } @@ -142,6 +149,10 @@ void shutdown_scanner(TSRMLS_D) efree(CG(heredoc)); CG(heredoc_len)=0; } + if (SCNG(yy_start_stack)) { + yy_flex_free(SCNG(yy_start_stack)); + SCNG(yy_start_stack) = NULL; + } RESET_DOC_COMMENT(); #ifdef ZEND_MULTIBYTE @@ -153,6 +164,12 @@ void shutdown_scanner(TSRMLS_D) efree(SCNG(script_filtered)); SCNG(script_filtered) = NULL; } + SCNG(script_org_size) = 0; + SCNG(script_filtered_size) = 0; + SCNG(input_filter) = NULL; + SCNG(output_filter) = NULL; + SCNG(script_encoding) = NULL; + SCNG(internal_encoding) = NULL; #endif /* ZEND_MULTIBYTE */ } END_EXTERN_C() @@ -1160,6 +1177,7 @@ NEWLINE ("\r"|"\n"|"\r\n") "}" { + RESET_DOC_COMMENT(); /* This is a temporary fix which is dependant on flex and it's implementation */ if (yy_start_stack_ptr) { yy_pop_state(TSRMLS_C); @@ -1188,7 +1206,7 @@ NEWLINE ("\r"|"\n"|"\r\n") errno = 0; zendlval->value.lval = strtol(yytext, NULL, 0); if (errno == ERANGE) { /* overflow */ - zendlval->value.dval = strtod(yytext, NULL); + zendlval->value.dval = zend_strtod(yytext, NULL); zendlval->type = IS_DOUBLE; return T_DNUMBER; } else { @@ -1225,7 +1243,7 @@ NEWLINE ("\r"|"\n"|"\r\n") } {DNUM}|{EXPONENT_DNUM} { - zendlval->value.dval = strtod(yytext, NULL); + zendlval->value.dval = zend_strtod(yytext, NULL); zendlval->type = IS_DOUBLE; return T_DNUMBER; } @@ -1447,6 +1465,7 @@ NEWLINE ("\r"|"\n"|"\r\n") "/**"{WHITESPACE} { CG(comment_start_line) = CG(zend_lineno); + RESET_DOC_COMMENT(); BEGIN(ST_DOC_COMMENT); yymore(); } @@ -1463,7 +1482,7 @@ NEWLINE ("\r"|"\n"|"\r\n") } "*/" { - CG(doc_comment) = yytext; /* no copying - intentional */ + CG(doc_comment) = estrndup(yytext, yyleng); CG(doc_comment_len) = yyleng; HANDLE_NEWLINES(yytext, yyleng); BEGIN(ST_IN_SCRIPTING); diff --git a/Zend/zend_list.c b/Zend/zend_list.c index bd88e44c761e..398cbb241153 100644 --- a/Zend/zend_list.c +++ b/Zend/zend_list.c @@ -114,16 +114,20 @@ ZEND_API void *zend_fetch_resource(zval **passed_id TSRMLS_DC, int default_id, c void *resource; va_list resource_types; int i; - + char *space; + char *class_name; + if (default_id==-1) { /* use id */ if (!passed_id) { if (resource_type_name) { - zend_error(E_WARNING, "%s(): no %s resource supplied", get_active_function_name(TSRMLS_C), resource_type_name); + class_name = get_active_class_name(&space TSRMLS_CC); + zend_error(E_WARNING, "%s%s%s(): no %s resource supplied", class_name, space, get_active_function_name(TSRMLS_C), resource_type_name); } return NULL; } else if ((*passed_id)->type != IS_RESOURCE) { if (resource_type_name) { - zend_error(E_WARNING, "%s(): supplied argument is not a valid %s resource", get_active_function_name(TSRMLS_C), resource_type_name); + class_name = get_active_class_name(&space TSRMLS_CC); + zend_error(E_WARNING, "%s%s%s(): supplied argument is not a valid %s resource", class_name, space, get_active_function_name(TSRMLS_C), resource_type_name); } return NULL; } @@ -135,7 +139,8 @@ ZEND_API void *zend_fetch_resource(zval **passed_id TSRMLS_DC, int default_id, c resource = zend_list_find(id, &actual_resource_type); if (!resource) { if (resource_type_name) { - zend_error(E_WARNING, "%s(): %d is not a valid %s resource", get_active_function_name(TSRMLS_C), id, resource_type_name); + class_name = get_active_class_name(&space TSRMLS_CC); + zend_error(E_WARNING, "%s%s%s(): %d is not a valid %s resource", class_name, space, get_active_function_name(TSRMLS_C), id, resource_type_name); } return NULL; } @@ -153,7 +158,8 @@ ZEND_API void *zend_fetch_resource(zval **passed_id TSRMLS_DC, int default_id, c va_end(resource_types); if (resource_type_name) { - zend_error(E_WARNING, "%s(): supplied resource is not a valid %s resource", get_active_function_name(TSRMLS_C), resource_type_name); + class_name = get_active_class_name(&space TSRMLS_CC); + zend_error(E_WARNING, "%s%s%s(): supplied resource is not a valid %s resource", class_name, space, get_active_function_name(TSRMLS_C), resource_type_name); } return NULL; diff --git a/Zend/zend_llist.c b/Zend/zend_llist.c index 88fb026c7c79..7b40dddb384e 100644 --- a/Zend/zend_llist.c +++ b/Zend/zend_llist.c @@ -117,6 +117,8 @@ ZEND_API void zend_llist_destroy(zend_llist *l) current = next; } + l->head = NULL; + l->tail = NULL; l->count = 0; } diff --git a/Zend/zend_mm.c b/Zend/zend_mm.c index 71a24c11eaa0..d1d432e46062 100644 --- a/Zend/zend_mm.c +++ b/Zend/zend_mm.c @@ -319,12 +319,12 @@ void *zend_mm_alloc(zend_mm_heap *heap, size_t size) if (true_size > (heap->block_size - ZEND_MM_ALIGNED_SEGMENT_SIZE - ZEND_MM_ALIGNED_HEADER_SIZE)) { /* Make sure we add a memory block which is big enough */ if (zend_mm_add_memory_block(heap, true_size + ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE)) { - zend_error(E_ERROR, "Out of memory: cannot allocate %d bytes!", true_size); + zend_mm_safe_error_ex("Out of memory: cannot allocate %zd bytes!", true_size); return NULL; } } else { if (zend_mm_add_memory_block(heap, heap->block_size)) { - zend_error(E_ERROR, "Out of memory: cannot allocate %d bytes!", heap->block_size); + zend_mm_safe_error_ex("Out of memory: cannot allocate %zd bytes!", heap->block_size); return NULL; } } diff --git a/Zend/zend_modules.h b/Zend/zend_modules.h index 536269eb958c..213d74328e17 100644 --- a/Zend/zend_modules.h +++ b/Zend/zend_modules.h @@ -23,6 +23,7 @@ #define MODULES_H #include "zend.h" +#include "zend_compile.h" #define INIT_FUNC_ARGS int type, int module_number TSRMLS_DC #define INIT_FUNC_ARGS_PASSTHRU type, module_number TSRMLS_CC @@ -37,7 +38,7 @@ extern struct _zend_arg_info third_arg_force_ref[4]; extern struct _zend_arg_info fourth_arg_force_ref[5]; extern struct _zend_arg_info all_args_by_ref[1]; -#define ZEND_MODULE_API_NO 20040412 +#define ZEND_MODULE_API_NO 20041030 #ifdef ZTS #define USING_ZTS 1 #else @@ -88,6 +89,7 @@ extern ZEND_API HashTable module_registry; void module_destructor(zend_module_entry *module); int module_registry_cleanup(zend_module_entry *module TSRMLS_DC); int module_registry_request_startup(zend_module_entry *module TSRMLS_DC); +int module_registry_unload_temp(zend_module_entry *module TSRMLS_DC); #define ZEND_MODULE_DTOR (void (*)(void *)) module_destructor #endif diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 7965bb0eb3f0..493bd113d665 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -72,6 +72,7 @@ static zval *zend_std_call_getter(zval *object, zval *member TSRMLS_DC) INIT_PZVAL(&__get_name); ZVAL_STRINGL(&__get_name, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1, 0); + SEPARATE_ARG_IF_REF(member); call_args[0] = &member; /* go call the __get handler */ @@ -87,11 +88,13 @@ static zval *zend_std_call_getter(zval *object, zval *member TSRMLS_DC) retval returns the value that is received */ - if (call_result == FAILURE) { zend_error(E_ERROR, "Could not call __get handler for class %s", Z_OBJCE_P(object)->name); return NULL; } + + zval_ptr_dtor(&member); + if (retval) { retval->refcount--; } @@ -105,7 +108,7 @@ static int zend_std_call_setter(zval *object, zval *member, zval *value TSRMLS_D zval *retval = NULL; zval __set_name; int call_result; - int ret; + int result; /* __set handler is called with two arguments: property name @@ -116,6 +119,7 @@ static int zend_std_call_setter(zval *object, zval *member, zval *value TSRMLS_D INIT_PZVAL(&__set_name); ZVAL_STRINGL(&__set_name, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1, 0); + SEPARATE_ARG_IF_REF(member); call_args[0] = &member; value->refcount++; call_args[1] = &value; @@ -139,19 +143,16 @@ static int zend_std_call_setter(zval *object, zval *member, zval *value TSRMLS_D return FAILURE; } + zval_ptr_dtor(&member); zval_ptr_dtor(&value); - if (retval && zend_is_true(retval)) { - ret = SUCCESS; - } else { - ret = FAILURE; - } - if (retval) { + result = i_zend_is_true(retval) ? SUCCESS : FAILURE; zval_ptr_dtor(&retval); + return result; + } else { + return FAILURE; } - - return ret; } @@ -161,13 +162,7 @@ static int zend_verify_property_access(zend_property_info *property_info, zend_c case ZEND_ACC_PUBLIC: return 1; case ZEND_ACC_PROTECTED: - while (ce) { - if (ce==EG(scope)) { - return 1; - } - ce = ce->parent; - } - return 0; + return zend_check_protected(ce, EG(scope));; case ZEND_ACC_PRIVATE: if (ce==EG(scope) && EG(scope)) { return 1; @@ -197,22 +192,41 @@ static inline zend_property_info *zend_get_property_info(zend_object *zobj, zval zend_property_info *property_info = NULL; zend_property_info *scope_property_info; zend_bool denied_access = 0; - - ulong h = zend_get_hash_value(Z_STRVAL_P(member), Z_STRLEN_P(member)+1); - if (zend_hash_quick_find(&zobj->ce->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, h, (void **) &property_info)==SUCCESS) { - if (zend_verify_property_access(property_info, zobj->ce TSRMLS_CC)) { - if (property_info->flags & ZEND_ACC_CHANGED - && !(property_info->flags & ZEND_ACC_PRIVATE)) { - /* We still need to make sure that we're not in a context - * where the right property is a different 'statically linked' private - * continue checking below... - */ + ulong h; + + if (Z_STRVAL_P(member)[0] == '\0') { + if (!silent) { + if (Z_STRLEN_P(member) == 0) { + zend_error(E_ERROR, "Cannot access empty property"); } else { - return property_info; + zend_error(E_ERROR, "Cannot access property started with '\\0'"); } + } + return NULL; + } + h = zend_get_hash_value(Z_STRVAL_P(member), Z_STRLEN_P(member) + 1); + if (zend_hash_quick_find(&zobj->ce->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, h, (void **) &property_info)==SUCCESS) { + if(property_info->flags & ZEND_ACC_SHADOW) { + /* if it's a shadow - go to access it's private */ + property_info = NULL; } else { - /* Try to look in the scope instead */ - denied_access = 1; + if (zend_verify_property_access(property_info, zobj->ce TSRMLS_CC)) { + if (property_info->flags & ZEND_ACC_CHANGED + && !(property_info->flags & ZEND_ACC_PRIVATE)) { + /* We still need to make sure that we're not in a context + * where the right property is a different 'statically linked' private + * continue checking below... + */ + } else { + if (!silent && (property_info->flags & ZEND_ACC_STATIC)) { + zend_error(E_STRICT, "Accessing static property %s::$%s as non static", zobj->ce->name, Z_STRVAL_P(member)); + } + return property_info; + } + } else { + /* Try to look in the scope instead */ + denied_access = 1; + } } } if (EG(scope) != zobj->ce @@ -220,6 +234,9 @@ static inline zend_property_info *zend_get_property_info(zend_object *zobj, zval && EG(scope) && zend_hash_quick_find(&EG(scope)->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, h, (void **) &scope_property_info)==SUCCESS && scope_property_info->flags & ZEND_ACC_PRIVATE) { + if (!silent && (scope_property_info->flags & ZEND_ACC_STATIC)) { + zend_error(E_STRICT, "Accessing static property %s::$%s as non static", EG(scope)->name, Z_STRVAL_P(member)); + } return scope_property_info; } else if (property_info) { if (denied_access) { @@ -254,9 +271,14 @@ ZEND_API int zend_check_property_access(zend_object *zobj, char *prop_info_name if (!property_info) { return FAILURE; } - if (prop_info_name[0] == '\0' && prop_info_name[1] != '*' && !(property_info->flags & ZEND_ACC_PRIVATE)) { - /* we we're looking for a private prop but found a non private one of the same name */ - return FAILURE; + if (prop_info_name[0] == '\0' && prop_info_name[1] != '*') { + if (!(property_info->flags & ZEND_ACC_PRIVATE)) { + /* we we're looking for a private prop but found a non private one of the same name */ + return FAILURE; + } else if (strcmp(prop_info_name+1, property_info->name+1)) { + /* we we're looking for a private prop but found a private one of the same name but another class */ + return FAILURE; + } } return zend_verify_property_access(property_info, zobj->ce TSRMLS_CC) ? SUCCESS : FAILURE; } @@ -264,7 +286,7 @@ ZEND_API int zend_check_property_access(zend_object *zobj, char *prop_info_name zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC) { zend_object *zobj; - zval tmp_member; + zval *tmp_member = NULL; zval **retval; zval *rv = NULL; zend_property_info *property_info; @@ -274,10 +296,12 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC) zobj = Z_OBJ_P(object); if (member->type != IS_STRING) { - tmp_member = *member; - zval_copy_ctor(&tmp_member); - convert_to_string(&tmp_member); - member = &tmp_member; + ALLOC_ZVAL(tmp_member); + *tmp_member = *member; + INIT_PZVAL(tmp_member); + zval_copy_ctor(tmp_member); + convert_to_string(tmp_member); + member = tmp_member; } #if DEBUG_OBJECT_HANDLERS @@ -305,8 +329,10 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC) retval = &EG(uninitialized_zval_ptr); } } - if (member == &tmp_member) { - zval_dtor(member); + if (tmp_member) { + (*retval)->refcount++; + zval_ptr_dtor(&tmp_member); + (*retval)->refcount--; } return *retval; } @@ -315,7 +341,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC) static void zend_std_write_property(zval *object, zval *member, zval *value TSRMLS_DC) { zend_object *zobj; - zval tmp_member; + zval *tmp_member = NULL; zval **variable_ptr; int setter_done = 0; zend_property_info *property_info; @@ -323,10 +349,12 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM zobj = Z_OBJ_P(object); if (member->type != IS_STRING) { - tmp_member = *member; - zval_copy_ctor(&tmp_member); - convert_to_string(&tmp_member); - member = &tmp_member; + ALLOC_ZVAL(tmp_member); + *tmp_member = *member; + INIT_PZVAL(tmp_member); + zval_copy_ctor(tmp_member); + convert_to_string(tmp_member); + member = tmp_member; } property_info = zend_get_property_info(zobj, member, 0 TSRMLS_CC); @@ -370,8 +398,8 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM } zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &value, sizeof(zval *), (void **) &foo); } - if (member == &tmp_member) { - zval_dtor(member); + if (tmp_member) { + zval_ptr_dtor(&tmp_member); } } @@ -383,12 +411,14 @@ zval *zend_std_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) { if(offset == NULL) { /* [] construct */ - zval offset_null; - INIT_ZVAL(offset_null); - offset = &offset_null; + ALLOC_INIT_ZVAL(offset); + } else { + SEPARATE_ARG_IF_REF(offset); } zend_call_method_with_1_params(&object, ce, NULL, "offsetget", &retval, offset); + zval_ptr_dtor(&offset); + if (!retval) { if (!EG(exception)) { zend_error(E_ERROR, "Undefined offset for object of type %s used as array", ce->name); @@ -410,14 +440,15 @@ zval *zend_std_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) static void zend_std_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC) { zend_class_entry *ce = Z_OBJCE_P(object); - zval tmp; if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) { if (!offset) { - INIT_ZVAL(tmp); - offset = &tmp; + ALLOC_INIT_ZVAL(offset); + } else { + SEPARATE_ARG_IF_REF(offset); } zend_call_method_with_2_params(&object, ce, NULL, "offsetset", NULL, offset, value); + zval_ptr_dtor(&offset); } else { zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name); } @@ -431,10 +462,16 @@ static int zend_std_has_dimension(zval *object, zval *offset, int check_empty TS int result; if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) { + SEPARATE_ARG_IF_REF(offset); zend_call_method_with_1_params(&object, ce, NULL, "offsetexists", &retval, offset); - result = i_zend_is_true(retval); - zval_ptr_dtor(&retval); - return result; + zval_ptr_dtor(&offset); + if (retval) { + result = i_zend_is_true(retval); + zval_ptr_dtor(&retval); + return result; + } else { + return 0; + } } else { zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name); return 0; @@ -513,11 +550,11 @@ static void zend_std_unset_property(zval *object, zval *member TSRMLS_DC) static void zend_std_unset_dimension(zval *object, zval *offset TSRMLS_DC) { zend_class_entry *ce = Z_OBJCE_P(object); - zval *retval; if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) { - zend_call_method_with_1_params(&object, ce, NULL, "offsetunset", &retval, offset); - zval_ptr_dtor(&retval); + SEPARATE_ARG_IF_REF(offset); + zend_call_method_with_1_params(&object, ce, NULL, "offsetunset", NULL, offset); + zval_ptr_dtor(&offset); } else { zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name); } @@ -528,7 +565,7 @@ ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS) { zval ***args; zend_internal_function *func = (zend_internal_function *)EG(function_state_ptr)->function; - zval method_name, method_args, __call_name; + zval __call_name; zval *method_name_ptr, *method_args_ptr; zval **call_args[2]; zval *method_result_ptr = NULL; @@ -542,11 +579,11 @@ ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS) RETURN_FALSE; } - method_name_ptr = &method_name; + ALLOC_ZVAL(method_name_ptr); INIT_PZVAL(method_name_ptr); ZVAL_STRING(method_name_ptr, func->function_name, 0); /* no dup - it's a copy */ - method_args_ptr = &method_args; + ALLOC_ZVAL(method_args_ptr); INIT_PZVAL(method_args_ptr); array_init(method_args_ptr); @@ -591,8 +628,8 @@ ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS) } /* now destruct all auxiliaries */ - zval_dtor(method_args_ptr); - zval_dtor(method_name_ptr); + zval_ptr_dtor(&method_args_ptr); + zval_ptr_dtor(&method_name_ptr); /* destruct the function also, then - we have allocated it in get_method */ efree(func); @@ -602,7 +639,7 @@ ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS) * Returns the function address that should be called, or NULL * if no such function exists. */ -inline zend_function *zend_check_private(zend_function *fbc, zend_class_entry *ce, int fn_flags, char *function_name_strval, int function_name_strlen TSRMLS_DC) +static inline zend_function *zend_check_private_int(zend_function *fbc, zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC) { if (!ce) { return 0; @@ -637,6 +674,11 @@ inline zend_function *zend_check_private(zend_function *fbc, zend_class_entry *c } +ZEND_API int zend_check_private(zend_function *fbc, zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC) +{ + return zend_check_private_int(fbc, ce, function_name_strval, function_name_strlen TSRMLS_CC) != NULL; +} + /* Ensures that we're allowed to call a protected method. */ ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope) @@ -704,7 +746,8 @@ static union _zend_function *zend_std_get_method(zval *object, char *method_name zend_function *priv_fbc; if (zend_hash_find(&EG(scope)->function_table, lc_method_name, method_len+1, (void **) &priv_fbc)==SUCCESS - && priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE) { + && priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE + && priv_fbc->common.scope == EG(scope)) { fbc = priv_fbc; } } @@ -713,7 +756,7 @@ static union _zend_function *zend_std_get_method(zval *object, char *method_name /* Ensure that if we're calling a private function, we're allowed to do so. */ - updated_fbc = zend_check_private(fbc, object->value.obj.handlers->get_class_entry(object TSRMLS_CC), fbc->common.fn_flags, lc_method_name, method_len TSRMLS_CC); + updated_fbc = zend_check_private_int(fbc, object->value.obj.handlers->get_class_entry(object TSRMLS_CC), lc_method_name, method_len TSRMLS_CC); if (!updated_fbc) { zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : ""); } @@ -751,7 +794,7 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, char *f /* Ensure that if we're calling a private function, we're allowed to do so. */ - updated_fbc = zend_check_private(fbc, EG(scope), fbc->common.fn_flags, function_name_strval, function_name_strlen TSRMLS_CC); + updated_fbc = zend_check_private_int(fbc, EG(scope), function_name_strval, function_name_strlen TSRMLS_CC); if (!updated_fbc) { zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), function_name_strval, EG(scope) ? EG(scope)->name : ""); } @@ -775,7 +818,7 @@ ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char *propert zend_property_info *property_info; zend_property_info std_property_info; - if (zend_hash_find(&ce->properties_info, property_name, property_name_len+1, (void **) &property_info)==FAILURE) { + if (zend_hash_find(&ce->properties_info, property_name, property_name_len+1, (void **) &property_info)==FAILURE || (property_info->flags & ZEND_ACC_SHADOW)) { std_property_info.flags = ZEND_ACC_PUBLIC; std_property_info.name = property_name; std_property_info.name_length = property_name_len; @@ -783,12 +826,15 @@ ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char *propert property_info = &std_property_info; } -#if 1&&DEBUG_OBJECT_HANDLERS +#if DEBUG_OBJECT_HANDLERS zend_printf("Access type for %s::%s is %s\n", ce->name, property_name, zend_visibility_string(property_info->flags)); #endif if (!zend_verify_property_access(property_info, ce TSRMLS_CC)) { - zend_error(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, property_name); + if (!silent) { + zend_error(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, property_name); + } + return NULL; } zend_hash_quick_find(tmp_ce->static_members, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval); @@ -931,6 +977,9 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty switch (type) { case IS_STRING: + if (!zend_hash_exists(&Z_OBJCE_P(readobj)->function_table, "__tostring", sizeof("__tostring"))) { + return FAILURE; + } ZVAL_STRING(&fname, "__tostring", 0); if (call_user_function_ex(NULL, &readobj, &fname, &retval, 0, NULL, 0, NULL TSRMLS_CC) == SUCCESS) { if (retval) { diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h index 4c8d12eda380..f28fb9044bef 100644 --- a/Zend/zend_object_handlers.h +++ b/Zend/zend_object_handlers.h @@ -137,6 +137,8 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty #define IS_ZEND_STD_OBJECT(z) ((z).type == IS_OBJECT && (Z_OBJ_HT((z))->get_class_entry != NULL)) #define HAS_CLASS_ENTRY(z) (Z_OBJ_HT(z)->get_class_entry != NULL) +ZEND_API int zend_check_private(union _zend_function *fbc, zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC); + ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope); ZEND_API int zend_check_property_access(zend_object *zobj, char *prop_info_name TSRMLS_DC); diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c index 85f76302fc4a..baa920226fd9 100644 --- a/Zend/zend_objects.c +++ b/Zend/zend_objects.c @@ -76,10 +76,13 @@ ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handl old_exception = EG(exception); EG(exception) = NULL; zend_call_method_with_0_params(&obj, object->ce, NULL, "__destruct", NULL); - if (EG(exception)) { - zval_ptr_dtor(&EG(exception)); + if (old_exception) { + if (EG(exception)) { + zend_error(E_ERROR, "Ignoring exception from %s::__destruct() while an exception is already active", object->ce->name); + zval_ptr_dtor(&EG(exception)); + } + EG(exception) = old_exception; } - EG(exception) = old_exception; } } @@ -108,9 +111,33 @@ ZEND_API zend_object *zend_objects_get_address(zval *zobject TSRMLS_DC) return (zend_object *)zend_object_store_get_object(zobject TSRMLS_CC); } +static void zval_add_ref_or_clone(zval **p) +{ + if (Z_TYPE_PP(p) == IS_OBJECT && !PZVAL_IS_REF(*p)) { + TSRMLS_FETCH(); + + if (Z_OBJ_HANDLER_PP(p, clone_obj) == NULL) { + zend_error(E_ERROR, "Trying to clone an uncloneable object of class %s", Z_OBJCE_PP(p)->name); + } else { + zval *orig = *p; + + ALLOC_ZVAL(*p); + **p = *orig; + INIT_PZVAL(*p); + (*p)->value.obj = Z_OBJ_HT_PP(p)->clone_obj(orig TSRMLS_CC); + } + } else { + (*p)->refcount++; + } +} + ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object_value new_obj_val, zend_object *old_object, zend_object_handle handle TSRMLS_DC) { - zend_hash_copy(new_object->properties, old_object->properties, (copy_ctor_func_t) zval_add_ref, (void *) NULL /* Not used anymore */, sizeof(zval *)); + if (EG(ze1_compatibility_mode)) { + zend_hash_copy(new_object->properties, old_object->properties, (copy_ctor_func_t) zval_add_ref_or_clone, (void *) NULL /* Not used anymore */, sizeof(zval *)); + } else { + zend_hash_copy(new_object->properties, old_object->properties, (copy_ctor_func_t) zval_add_ref, (void *) NULL /* Not used anymore */, sizeof(zval *)); + } if (old_object->ce->clone) { zval *new_obj; zval *clone_func_name; diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c index a5788bd437c3..d37b4976e828 100644 --- a/Zend/zend_objects_API.c +++ b/Zend/zend_objects_API.c @@ -58,6 +58,16 @@ ZEND_API void zend_objects_store_call_destructors(zend_objects_store *objects TS } } +ZEND_API void zend_objects_store_mark_destructed(zend_objects_store *objects TSRMLS_DC) +{ + zend_uint i = 1; + + for (i = 1; i < objects->top ; i++) { + if (objects->object_buckets[i].valid) { + objects->object_buckets[i].destructor_called = 1; + } + } +} ZEND_API void zend_objects_store_free_object_storage(zend_objects_store *objects TSRMLS_DC) { @@ -141,7 +151,9 @@ ZEND_API void zend_objects_store_del_ref(zval *zobject TSRMLS_DC) EG(objects_store).object_buckets[handle].destructor_called = 1; if (obj->dtor) { + zobject->refcount++; obj->dtor(obj->object, handle TSRMLS_CC); + zobject->refcount--; } } if (obj->refcount == 1) { @@ -207,6 +219,15 @@ ZEND_API void zend_object_store_set_object(zval *zobject, void *object TSRMLS_DC } +/* Called when the ctor was terminated by an exception */ +ZEND_API void zend_object_store_ctor_failed(zval *zobject TSRMLS_DC) +{ + zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); + + EG(objects_store).object_buckets[handle].destructor_called = 1; +} + + /* Proxy objects workings */ typedef struct _zend_proxy_object { zval *object; diff --git a/Zend/zend_objects_API.h b/Zend/zend_objects_API.h index bcca11b0f264..02701941f2d9 100644 --- a/Zend/zend_objects_API.h +++ b/Zend/zend_objects_API.h @@ -57,6 +57,7 @@ typedef struct _zend_objects_store { BEGIN_EXTERN_C() ZEND_API void zend_objects_store_init(zend_objects_store *objects, zend_uint init_size); ZEND_API void zend_objects_store_call_destructors(zend_objects_store *objects TSRMLS_DC); +ZEND_API void zend_objects_store_mark_destructed(zend_objects_store *objects TSRMLS_DC); ZEND_API void zend_objects_store_destroy(zend_objects_store *objects); /* Store API functions */ @@ -68,6 +69,7 @@ ZEND_API zend_object_value zend_objects_store_clone_obj(zval *object TSRMLS_DC); ZEND_API void *zend_object_store_get_object(zval *object TSRMLS_DC); /* See comment in zend_objects_API.c before you use this */ ZEND_API void zend_object_store_set_object(zval *zobject, void *object TSRMLS_DC); +ZEND_API void zend_object_store_ctor_failed(zval *zobject TSRMLS_DC); ZEND_API void zend_objects_store_free_object_storage(zend_objects_store *objects TSRMLS_DC); diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 96217df5b15d..e583ca8ae60b 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -29,6 +29,7 @@ #include "zend_fast_cache.h" #include "zend_API.h" #include "zend_multiply.h" +#include "zend_strtod.h" #define LONG_SIGN_MASK (1L << (8*sizeof(long)-1)) @@ -376,7 +377,7 @@ ZEND_API void convert_to_double(zval *op) case IS_STRING: strval = op->value.str.val; - op->value.dval = strtod(strval, NULL); + op->value.dval = zend_strtod(strval, NULL); STR_FREE(strval); break; case IS_ARRAY: @@ -1117,6 +1118,9 @@ ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* must support result==op1 */ ZEND_API int add_char_to_string(zval *result, zval *op1, zval *op2) { + if (op1->value.str.len > INT_MAX - 1) { + zend_mm_safe_error_ex("String size overflow"); + } result->value.str.len = op1->value.str.len + 1; result->value.str.val = (char *) erealloc(op1->value.str.val, result->value.str.len+1); result->value.str.val[result->value.str.len - 1] = (char) op2->value.lval; @@ -1129,7 +1133,12 @@ ZEND_API int add_char_to_string(zval *result, zval *op1, zval *op2) /* must support result==op1 */ ZEND_API int add_string_to_string(zval *result, zval *op1, zval *op2) { - int length = op1->value.str.len + op2->value.str.len; + int length; + + if (op1->value.str.len > INT_MAX - op2->value.str.len) { + zend_mm_safe_error_ex("String size overflow"); + } + length = op1->value.str.len + op2->value.str.len; if (op1->value.str.val == empty_string) { result->value.str.val = (char *) emalloc(length+1); } else { @@ -1164,6 +1173,9 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) if (use_copy2) { op2 = &op2_copy; } + if (op1->value.str.len > INT_MAX - op2->value.str.len) { + zend_mm_safe_error_ex("String size overflow"); + } if (result==op1) { /* special case, perform operations on result */ uint res_len = op1->value.str.len + op2->value.str.len; @@ -1221,6 +1233,35 @@ ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_D return SUCCESS; } +#if HAVE_STRCOLL +ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) +{ + zval op1_copy, op2_copy; + int use_copy1, use_copy2; + + zend_make_printable_zval(op1, &op1_copy, &use_copy1); + zend_make_printable_zval(op2, &op2_copy, &use_copy2); + + if (use_copy1) { + op1 = &op1_copy; + } + if (use_copy2) { + op2 = &op2_copy; + } + + result->value.lval = strcoll(op1->value.str.val, op2->value.str.val); + result->type = IS_LONG; + + if (use_copy1) { + zval_dtor(op1); + } + if (use_copy2) { + zval_dtor(op2); + } + return SUCCESS; +} +#endif + ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) { zval op1_copy, op2_copy; @@ -1254,24 +1295,26 @@ static inline void zend_free_obj_get_result(zval *op, int free_op) } #define COMPARE_RETURN_AND_FREE(retval) \ - zend_free_obj_get_result(op1, free_op1); \ - zend_free_obj_get_result(op2, free_op2); \ + zend_free_obj_get_result(op1_orig, free_op1); \ + zend_free_obj_get_result(op2_orig, free_op2); \ return retval; ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) { zval op1_copy, op2_copy; zend_bool free_op1 = 0, free_op2 = 0; + zval *op1_orig, *op2_orig; if (op1->type == IS_OBJECT && Z_OBJ_HT_P(op1)->get) { op1 = Z_OBJ_HT_P(op1)->get(op1 TSRMLS_CC); free_op1 = 1; } + op1_orig = op1; if (op2->type == IS_OBJECT && Z_OBJ_HT_P(op2)->get) { op2 = Z_OBJ_HT_P(op2)->get(op2 TSRMLS_CC); free_op2 = 1; } - + op2_orig = op2; if ((op1->type == IS_NULL && op2->type == IS_STRING) || (op2->type == IS_NULL && op1->type == IS_STRING)) { @@ -1867,9 +1910,9 @@ ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2) (ret2=is_numeric_string(s2->value.str.val, s2->value.str.len, &lval2, &dval2, 0))) { if ((ret1==IS_DOUBLE) || (ret2==IS_DOUBLE)) { if (ret1!=IS_DOUBLE) { - dval1 = strtod(s1->value.str.val, NULL); + dval1 = zend_strtod(s1->value.str.val, NULL); } else if (ret2!=IS_DOUBLE) { - dval2 = strtod(s2->value.str.val, NULL); + dval2 = zend_strtod(s2->value.str.val, NULL); } result->value.dval = dval1 - dval2; result->value.lval = ZEND_NORMALIZE_BOOL(result->value.dval); @@ -1922,13 +1965,13 @@ ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC) { result->type = IS_LONG; - if (Z_OBJ_HT_P(o1)->compare_objects == NULL) { - if (Z_OBJ_HANDLE_P(o1) == Z_OBJ_HANDLE_P(o2)) { - result->value.lval = 0; - } else { - result->value.lval = 1; - } + if (Z_OBJ_HANDLE_P(o1) == Z_OBJ_HANDLE_P(o2)) { + result->value.lval = 0; return; + } + + if (Z_OBJ_HT_P(o1)->compare_objects == NULL) { + result->value.lval = 1; } else { result->value.lval = Z_OBJ_HT_P(o1)->compare_objects(o1, o2 TSRMLS_CC); } @@ -1943,13 +1986,6 @@ ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC) op->value.str.val = (char *) emalloc_rel(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1); sprintf(op->value.str.val, "%.*G", (int) EG(precision), dval); op->value.str.len = strlen(op->value.str.val); - - if (EG(float_separator)[0] != '.') { - char *p = op->value.str.val; - if ((p = strchr(p, '.'))) { - *p = EG(float_separator)[0]; - } - } } /* diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index c6182ff6b650..2c3d65d51dbe 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -29,6 +29,7 @@ #include #endif +#include "zend_strtod.h" #if 0&&HAVE_BCMATH #include "ext/bcmath/libbcmath/src/bcmath.h" @@ -87,6 +88,8 @@ static inline zend_bool is_numeric_string(char *str, int length, long *lval, dou *lval = local_lval; } return IS_LONG; + } else if (end_ptr_long == str && *end_ptr_long != '\0' && *str != '.' && *str != '-') { /* ignore partial string matches */ + return 0; } } else { end_ptr_long=NULL; @@ -97,7 +100,7 @@ static inline zend_bool is_numeric_string(char *str, int length, long *lval, dou } errno=0; - local_dval = strtod(str, &end_ptr_double); + local_dval = zend_strtod(str, &end_ptr_double); if (errno != ERANGE) { if (end_ptr_double == str+length) { /* floating point string */ if (!zend_finite(local_dval)) { @@ -177,6 +180,9 @@ ZEND_API int zval_is_true(zval *op); ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); +#if HAVE_STRCOLL +ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); +#endif ZEND_API void zend_str_tolower(char *str, unsigned int length); ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned int length); diff --git a/Zend/zend_reflection_api.c b/Zend/zend_reflection_api.c index 81cde4791ed7..145b579b4f19 100644 --- a/Zend/zend_reflection_api.c +++ b/Zend/zend_reflection_api.c @@ -145,8 +145,10 @@ typedef struct _property_reference { /* Struct for parameters */ typedef struct _parameter_reference { - int offset; + zend_uint offset; + zend_uint required; struct _zend_arg_info *arg_info; + zend_function *fptr; } parameter_reference; /* Struct for reflection objects */ @@ -155,6 +157,7 @@ typedef struct { void *ptr; unsigned int free_ptr:1; zval *obj; + zend_class_entry *ce; } reflection_object; static zend_object_handlers reflection_object_handlers; @@ -213,6 +216,7 @@ static void reflection_objects_clone(void *object, void **object_clone TSRMLS_DC static zend_object_value reflection_objects_new(zend_class_entry *class_type TSRMLS_DC) { + zval tmp; zend_object_value retval; reflection_object *intern; @@ -226,6 +230,7 @@ static zend_object_value reflection_objects_new(zend_class_entry *class_type TSR ALLOC_HASHTABLE(intern->zo.properties); zend_hash_init(intern->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0); + zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); retval.handle = zend_objects_store_put(intern, NULL, reflection_free_objects_storage, reflection_objects_clone TSRMLS_CC); retval.handlers = &reflection_object_handlers; return retval; @@ -252,7 +257,7 @@ static void _extension_string(string *str, zend_module_entry *module, char *inde /* {{{ _class_string */ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *indent TSRMLS_DC) { - int count, count_static_props = 0, count_static_funcs = 0; + int count, count_static_props = 0, count_static_funcs = 0, count_shadow_props = 0; string sub_indent; string_init(&sub_indent); @@ -344,7 +349,9 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos); while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) { - if (prop->flags & ZEND_ACC_STATIC) { + if(prop->flags & ZEND_ACC_SHADOW) { + count_shadow_props++; + } else if (prop->flags & ZEND_ACC_STATIC) { count_static_props++; } zend_hash_move_forward_ex(&ce->properties_info, &pos); @@ -360,9 +367,10 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos); while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) { - if (prop->flags & ZEND_ACC_STATIC) { + if ((prop->flags & ZEND_ACC_STATIC) && !(prop->flags & ZEND_ACC_SHADOW)) { _property_string(str, prop, NULL, sub_indent.string TSRMLS_CC); } + zend_hash_move_forward_ex(&ce->properties_info, &pos); } } @@ -410,7 +418,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in /* Default/Implicit properties */ if (&ce->properties_info) { - count = zend_hash_num_elements(&ce->properties_info) - count_static_props; + count = zend_hash_num_elements(&ce->properties_info) - count_static_props - count_shadow_props; string_printf(str, "\n%s - Properties [%d] {\n", indent, count); if (count > 0) { HashPosition pos; @@ -419,7 +427,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos); while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) { - if (!(prop->flags & ZEND_ACC_STATIC)) { + if (!(prop->flags & (ZEND_ACC_STATIC|ZEND_ACC_SHADOW))) { _property_string(str, prop, NULL, sub_indent.string TSRMLS_CC); } zend_hash_move_forward_ex(&ce->properties_info, &pos); @@ -501,9 +509,14 @@ static void _const_string(string *str, char *name, zval *value, char *indent TSR /* }}} */ /* {{{ _parameter_string */ -static void _parameter_string(string *str, struct _zend_arg_info *arg_info, int offset, char* indent TSRMLS_DC) +static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg_info *arg_info, zend_uint offset, zend_uint required, char* indent TSRMLS_DC) { string_printf(str, "Parameter #%d [ ", offset); + if (offset >= required) { + string_printf(str, " "); + } else { + string_printf(str, " "); + } if (arg_info->class_name) { string_printf(str, "%s ", arg_info->class_name); if (arg_info->allow_null) { @@ -518,6 +531,32 @@ static void _parameter_string(string *str, struct _zend_arg_info *arg_info, int } else { string_printf(str, "$param%d", offset); } + if (fptr->type == ZEND_USER_FUNCTION && offset >= required) { + zend_op *precv = &((zend_op_array*)fptr)->opcodes[offset*2 + 1]; + if (precv->opcode == ZEND_RECV_INIT && precv->op2.op_type != IS_UNUSED) { + zval *zv, zv_copy; + int use_copy; + string_write(str, " = ", sizeof(" = ")-1); + zv_copy = precv->op2.u.constant; + zv = &zv_copy; + zval_update_constant(&zv, (void*)1 TSRMLS_CC); + if (Z_TYPE_P(zv) == IS_NULL) { + string_write(str, "NULL", sizeof("NULL")-1); + } else if (Z_TYPE_P(zv) == IS_STRING) { + string_write(str, "'", sizeof("'")-1); + string_write(str, Z_STRVAL_P(zv), MIN(Z_STRLEN_P(zv), 15)); + if (Z_STRLEN_P(zv) > 15) { + string_write(str, "...", sizeof("...")-1); + } + string_write(str, "'", sizeof("'")-1); + } else { + zend_make_printable_zval(zv, &zv_copy, &use_copy); + string_write(str, Z_STRVAL(zv_copy), Z_STRLEN(zv_copy)); + zval_dtor(&zv_copy); + } + zval_ptr_dtor(&zv); + } + } string_write(str, " ]", sizeof(" ]")-1); } /* }}} */ @@ -525,8 +564,8 @@ static void _parameter_string(string *str, struct _zend_arg_info *arg_info, int /* {{{ _function_parameter_string */ static void _function_parameter_string(string *str, zend_function *fptr, char* indent TSRMLS_DC) { - zend_uint i; struct _zend_arg_info *arg_info = fptr->common.arg_info; + zend_uint i, required = fptr->common.required_num_args; if (!arg_info) { return; @@ -536,7 +575,7 @@ static void _function_parameter_string(string *str, zend_function *fptr, char* i string_printf(str, "%s- Parameters [%d] {\n", indent, fptr->common.num_args); for (i = 0; i < fptr->common.num_args; i++) { string_printf(str, "%s ", indent); - _parameter_string(str, arg_info, i, indent TSRMLS_CC); + _parameter_string(str, fptr, arg_info, i, required, indent TSRMLS_CC); string_write(str, "\n", sizeof("\n")-1); arg_info++; } @@ -586,6 +625,9 @@ static void _function_string(string *str, zend_function *fptr, char* indent TSRM case ZEND_ACC_PROTECTED: string_printf(str, "protected "); break; + default: + string_printf(str, " "); + break; } string_printf(str, fptr->common.scope ? "method " : "function "); @@ -779,8 +821,8 @@ static void _function_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask) } /* }}} */ -/* {{{ reflection_class_factory */ -static void reflection_class_factory(zend_class_entry *ce, zval *object TSRMLS_DC) +/* {{{ zend_reflection_class_factory */ +ZEND_API void zend_reflection_class_factory(zend_class_entry *ce, zval *object TSRMLS_DC) { reflection_object *intern; zval *name; @@ -791,6 +833,7 @@ static void reflection_class_factory(zend_class_entry *ce, zval *object TSRMLS_D intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC); intern->ptr = ce; intern->free_ptr = 0; + intern->ce = ce; zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); } /* }}} */ @@ -818,12 +861,13 @@ static void reflection_extension_factory(zval *object, char *name_str TSRMLS_DC) ZVAL_STRINGL(name, module->name, name_len, 1); intern->ptr = module; intern->free_ptr = 0; + intern->ce = NULL; zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); } /* }}} */ /* {{{ reflection_parameter_factory */ -static void reflection_parameter_factory(struct _zend_arg_info *arg_info, int offset, zval *object TSRMLS_DC) +static void reflection_parameter_factory(zend_function *fptr, struct _zend_arg_info *arg_info, zend_uint offset, zend_uint required, zval *object TSRMLS_DC) { reflection_object *intern; parameter_reference *reference; @@ -840,8 +884,11 @@ static void reflection_parameter_factory(struct _zend_arg_info *arg_info, int of reference = (parameter_reference*) emalloc(sizeof(parameter_reference)); reference->arg_info = arg_info; reference->offset = offset; + reference->required = required; + reference->fptr = fptr; intern->ptr = reference; intern->free_ptr = 1; + intern->ce = fptr->common.scope; zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); } /* }}} */ @@ -859,6 +906,7 @@ static void reflection_function_factory(zend_function *function, zval *object TS intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC); intern->ptr = function; intern->free_ptr = 0; + intern->ce = NULL; zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); } /* }}} */ @@ -878,6 +926,7 @@ static void reflection_method_factory(zend_class_entry *ce, zend_function *metho intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC); intern->ptr = method; intern->free_ptr = 0; + intern->ce = ce; zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL); } @@ -923,6 +972,7 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info reference->prop = prop; intern->ptr = reference; intern->free_ptr = 1; + intern->ce = ce; zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL); } @@ -1051,7 +1101,7 @@ ZEND_METHOD(reflection, export) zval_ptr_dtor(&fname); if (result == FAILURE) { - _DO_THROW("Invokation of method __toString() failed"); + _DO_THROW("Invocation of method __toString() failed"); /* Returns from this function */ } @@ -1084,32 +1134,32 @@ ZEND_METHOD(reflection, getModifierNames) array_init(return_value); if (modifiers & (ZEND_ACC_ABSTRACT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) { - add_next_index_stringl(return_value, "abstract", sizeof("abstract"), 1); + add_next_index_stringl(return_value, "abstract", sizeof("abstract")-1, 1); } if (modifiers & (ZEND_ACC_FINAL | ZEND_ACC_FINAL_CLASS)) { - add_next_index_stringl(return_value, "final", sizeof("final"), 1); + add_next_index_stringl(return_value, "final", sizeof("final")-1, 1); } /* These are mutually exclusive */ switch (modifiers & ZEND_ACC_PPP_MASK) { case ZEND_ACC_PUBLIC: - add_next_index_stringl(return_value, "public", sizeof("public"), 1); + add_next_index_stringl(return_value, "public", sizeof("public")-1, 1); break; case ZEND_ACC_PRIVATE: - add_next_index_stringl(return_value, "private", sizeof("private"), 1); + add_next_index_stringl(return_value, "private", sizeof("private")-1, 1); break; case ZEND_ACC_PROTECTED: - add_next_index_stringl(return_value, "protected", sizeof("protected"), 1); + add_next_index_stringl(return_value, "protected", sizeof("protected")-1, 1); break; } if (modifiers & ZEND_ACC_STATIC) { - add_next_index_stringl(return_value, "static", sizeof("static"), 1); + add_next_index_stringl(return_value, "static", sizeof("static")-1, 1); } } /* }}} */ -/* {{{ proto public static mixed ReflectionFunction::export(string name, [, bool return]) throws ReflectionException +/* {{{ proto public static mixed ReflectionFunction::export(string name [, bool return]) throws ReflectionException Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */ ZEND_METHOD(reflection_function, export) { @@ -1152,6 +1202,7 @@ ZEND_METHOD(reflection_function, __construct) zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); intern->ptr = fptr; intern->free_ptr = 0; + intern->ce = NULL; } /* }}} */ @@ -1283,7 +1334,8 @@ ZEND_METHOD(reflection_function, getStaticVariables) /* Return an empty array in case no static variables exist */ array_init(return_value); - if (fptr->op_array.static_variables != NULL) { + if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.static_variables != NULL) { + zend_hash_apply_with_argument(fptr->op_array.static_variables, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC); zend_hash_copy(Z_ARRVAL_P(return_value), fptr->op_array.static_variables, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *)); } } @@ -1332,7 +1384,7 @@ ZEND_METHOD(reflection_function, invoke) if (result == FAILURE) { zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, - "Invokation of method %s() failed", fptr->common.function_name); + "Invocation of method %s() failed", fptr->common.function_name); return; } @@ -1356,13 +1408,41 @@ ZEND_METHOD(reflection_function, returnsReference) } /* }}} */ +/* {{{ proto public bool ReflectionFunction::getNumberOfParameters() + Gets the number of required parameters */ +ZEND_METHOD(reflection_function, getNumberOfParameters) +{ + reflection_object *intern; + zend_function *fptr; + + METHOD_NOTSTATIC; + GET_REFLECTION_OBJECT_PTR(fptr); + + RETURN_LONG(fptr->common.num_args); +} +/* }}} */ + +/* {{{ proto public bool ReflectionFunction::getNumberOfRequiredParameters() + Gets the number of required parameters */ +ZEND_METHOD(reflection_function, getNumberOfRequiredParameters) +{ + reflection_object *intern; + zend_function *fptr; + + METHOD_NOTSTATIC; + GET_REFLECTION_OBJECT_PTR(fptr); + + RETURN_LONG(fptr->common.required_num_args); +} +/* }}} */ + /* {{{ proto public ReflectionParameter[] Reflection_Function::getParameters() Returns an array of parameter objects for this function */ ZEND_METHOD(reflection_function, getParameters) { reflection_object *intern; zend_function *fptr; - int i; + zend_uint i; struct _zend_arg_info *arg_info; METHOD_NOTSTATIC; @@ -1375,7 +1455,7 @@ ZEND_METHOD(reflection_function, getParameters) zval *parameter; ALLOC_ZVAL(parameter); - reflection_parameter_factory(arg_info, i, parameter TSRMLS_CC); + reflection_parameter_factory(fptr, arg_info, i, fptr->common.required_num_args, parameter TSRMLS_CC); add_next_index_zval(return_value, parameter); arg_info++; @@ -1383,7 +1463,7 @@ ZEND_METHOD(reflection_function, getParameters) } /* }}} */ -/* {{{ proto public static mixed ReflectionParameter::export(mixed function, mixed parameter, [, bool return]) throws ReflectionException +/* {{{ proto public static mixed ReflectionParameter::export(mixed function, mixed parameter [, bool return]) throws ReflectionException Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */ ZEND_METHOD(reflection_parameter, export) { @@ -1403,6 +1483,7 @@ ZEND_METHOD(reflection_parameter, __construct) zend_function *fptr; struct _zend_arg_info *arg_info; int position; + zend_class_entry *ce = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &reference, ¶meter) == FAILURE) { return; @@ -1435,7 +1516,6 @@ ZEND_METHOD(reflection_parameter, __construct) case IS_ARRAY: { zval **classref; zval **method; - zend_class_entry *ce; zend_class_entry **pce; char *lcname; @@ -1479,12 +1559,12 @@ ZEND_METHOD(reflection_parameter, __construct) arg_info = fptr->common.arg_info; if (Z_TYPE_P(parameter) == IS_LONG) { position= Z_LVAL_P(parameter); - if (position < 0 || position >= fptr->common.num_args) { + if (position < 0 || (zend_uint)position >= fptr->common.num_args) { _DO_THROW("The parameter specified by its offset could not be found"); /* returns out of this function */ } } else { - int i; + zend_uint i; position= -1; convert_to_string_ex(¶meter); @@ -1510,9 +1590,12 @@ ZEND_METHOD(reflection_parameter, __construct) ref = (parameter_reference*) emalloc(sizeof(parameter_reference)); ref->arg_info = &arg_info[position]; - ref->offset = position; + ref->offset = (zend_uint)position; + ref->required = fptr->common.required_num_args; + ref->fptr = fptr; intern->ptr = ref; intern->free_ptr = 1; + intern->ce = ce; } /* }}} */ @@ -1527,7 +1610,7 @@ ZEND_METHOD(reflection_parameter, __toString) METHOD_NOTSTATIC_NUMPARAMS(0); GET_REFLECTION_OBJECT_PTR(param); string_init(&str); - _parameter_string(&str, param->arg_info, param->offset, "" TSRMLS_CC); + _parameter_string(&str, param->fptr, param->arg_info, param->offset, param->required, "" TSRMLS_CC); RETURN_STRINGL(str.string, str.len - 1, 0); } /* }}} */ @@ -1541,7 +1624,7 @@ ZEND_METHOD(reflection_parameter, getName) } /* }}} */ -/* {{{ proto public ReflectionClass Reflection_Parameter::getClass() +/* {{{ proto public ReflectionClass ReflectionParameter::getClass() Returns this parameters's class hint or NULL if there is none */ ZEND_METHOD(reflection_parameter, getClass) { @@ -1564,7 +1647,7 @@ ZEND_METHOD(reflection_parameter, getClass) return; } free_alloca(lcname); - reflection_class_factory(*pce, return_value TSRMLS_CC); + zend_reflection_class_factory(*pce, return_value TSRMLS_CC); } } /* }}} */ @@ -1597,7 +1680,81 @@ ZEND_METHOD(reflection_parameter, isPassedByReference) } /* }}} */ -/* {{{ proto public static mixed ReflectionMethod::export(mixed class, string name, [, bool return]) throws ReflectionException +/* {{{ proto public bool ReflectionParameter::isOptional() + Returns whether this parameter is an optional parameter */ +ZEND_METHOD(reflection_parameter, isOptional) +{ + reflection_object *intern; + parameter_reference *param; + + METHOD_NOTSTATIC_NUMPARAMS(0); + GET_REFLECTION_OBJECT_PTR(param); + + RETVAL_BOOL(param->offset >= param->required); +} +/* }}} */ + +/* {{{ proto public bool ReflectionParameter::isDefaultValueAvailable() + Returns whether the default value of this parameter is available */ +ZEND_METHOD(reflection_parameter, isDefaultValueAvailable) +{ + reflection_object *intern; + parameter_reference *param; + zend_op *precv; + + METHOD_NOTSTATIC_NUMPARAMS(0); + GET_REFLECTION_OBJECT_PTR(param); + + if (param->fptr->type != ZEND_USER_FUNCTION) + { + RETURN_FALSE; + } + if (param->offset < param->required) { + RETURN_FALSE; + } + precv = &((zend_op_array*)param->fptr)->opcodes[param->offset*2 + 1]; + if (precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) { + RETURN_FALSE; + } + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto public bool ReflectionParameter::getDefaultValue() + Returns the default value of this parameter or throws an exception */ +ZEND_METHOD(reflection_parameter, getDefaultValue) +{ + reflection_object *intern; + parameter_reference *param; + zend_op *precv; + zval *zv, zv_copy; + + METHOD_NOTSTATIC_NUMPARAMS(0); + GET_REFLECTION_OBJECT_PTR(param); + + if (param->fptr->type != ZEND_USER_FUNCTION) + { + zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Cannot determine default value for internal functions"); + return; + } + if (param->offset < param->required) { + zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Parameter is not optional"); + return; + } + precv = &((zend_op_array*)param->fptr)->opcodes[param->offset*2 + 1]; + if (precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) { + zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Internal error"); + return; + } + + zv_copy = precv->op2.u.constant; + zv = &zv_copy; + zval_update_constant(&zv, (void*)0 TSRMLS_CC); + RETURN_ZVAL(zv, 1, 1); +} +/* }}} */ + +/* {{{ proto public static mixed ReflectionMethod::export(mixed class, string name [, bool return]) throws ReflectionException Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */ ZEND_METHOD(reflection_method, export) { @@ -1669,6 +1826,7 @@ ZEND_METHOD(reflection_method, __construct) zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); intern->ptr = mptr; intern->free_ptr = 0; + intern->ce = ce; } /* }}} */ @@ -1689,7 +1847,7 @@ ZEND_METHOD(reflection_method, __toString) /* }}} */ /* {{{ proto public mixed ReflectionMethod::invoke(mixed object, mixed* args) - Invokes the function. Pass a */ + Invokes the method. */ ZEND_METHOD(reflection_method, invoke) { zval *retval_ptr; @@ -1706,7 +1864,7 @@ ZEND_METHOD(reflection_method, invoke) METHOD_NOTSTATIC; if (argc < 1) { - zend_error(E_WARNING, "%s expects at least one parameter, none given", get_active_function_name(TSRMLS_C)); + zend_error(E_WARNING, "Invoke() expects at least one parameter, none given"); RETURN_FALSE; } @@ -1716,11 +1874,11 @@ ZEND_METHOD(reflection_method, invoke) (mptr->common.fn_flags & ZEND_ACC_ABSTRACT)) { if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) { zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, - "Trying to invoke abstract method %s::%s", + "Trying to invoke abstract method %s::%s()", mptr->common.scope->name, mptr->common.function_name); } else { zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, - "Trying to invoke %s method %s::%s from scope %s", + "Trying to invoke %s method %s::%s() from scope %s", mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private", mptr->common.scope->name, mptr->common.function_name, Z_OBJCE_P(getThis())->name); @@ -1781,7 +1939,7 @@ ZEND_METHOD(reflection_method, invoke) if (result == FAILURE) { zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, - "Invokation of method %s::%s() failed", mptr->common.scope->name, mptr->common.function_name); + "Invocation of method %s::%s() failed", mptr->common.scope->name, mptr->common.function_name); return; } @@ -1848,7 +2006,10 @@ ZEND_METHOD(reflection_method, isConstructor) METHOD_NOTSTATIC_NUMPARAMS(0); GET_REFLECTION_OBJECT_PTR(mptr); - RETURN_BOOL(mptr->common.scope->constructor == mptr); + /* we need to check if the ctor is the ctor of the class level we we + * looking at since we might be looking at an inherited old style ctor + * defined in base class. */ + RETURN_BOOL(mptr->common.fn_flags & ZEND_ACC_CTOR && intern->ce->constructor && intern->ce->constructor->common.scope == mptr->common.scope); } /* }}} */ @@ -1861,7 +2022,7 @@ ZEND_METHOD(reflection_method, isDestructor) METHOD_NOTSTATIC_NUMPARAMS(0); GET_REFLECTION_OBJECT_PTR(mptr); - RETURN_BOOL(mptr->common.scope->destructor == mptr); + RETURN_BOOL(mptr->common.fn_flags & ZEND_ACC_DTOR); } /* }}} */ @@ -1879,7 +2040,7 @@ ZEND_METHOD(reflection_method, getModifiers) } /* }}} */ -/* {{{ proto public ReflectionClass Reflection_Method::getDeclaringClass() +/* {{{ proto public ReflectionClass ReflectionMethod::getDeclaringClass() Get the declaring class */ ZEND_METHOD(reflection_method, getDeclaringClass) { @@ -1889,11 +2050,11 @@ ZEND_METHOD(reflection_method, getDeclaringClass) METHOD_NOTSTATIC; GET_REFLECTION_OBJECT_PTR(mptr); - reflection_class_factory(mptr->common.scope, return_value TSRMLS_CC); + zend_reflection_class_factory(mptr->common.scope, return_value TSRMLS_CC); } /* }}} */ -/* {{{ proto public static mixed ReflectionClass::export(mixed argument, [, bool return]) throws ReflectionException +/* {{{ proto public static mixed ReflectionClass::export(mixed argument [, bool return]) throws ReflectionException Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */ ZEND_METHOD(reflection_class, export) { @@ -1970,6 +2131,9 @@ ZEND_METHOD(reflection_class, getStaticProperties) METHOD_NOTSTATIC_NUMPARAMS(0); GET_REFLECTION_OBJECT_PTR(ce); + + zend_update_class_constants(ce TSRMLS_CC); + array_init(return_value); zend_hash_copy(Z_ARRVAL_P(return_value), ce->static_members, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *)); } @@ -1987,6 +2151,8 @@ ZEND_METHOD(reflection_class, getDefaultProperties) GET_REFLECTION_OBJECT_PTR(ce); array_init(return_value); + zend_update_class_constants(ce TSRMLS_CC); + count = zend_hash_num_elements(&ce->default_properties); if (count > 0) { HashPosition pos; @@ -2134,7 +2300,7 @@ ZEND_METHOD(reflection_class, getDocComment) } /* }}} */ -/* {{{ proto public ReflectionMethod Reflection_Class::getConstructor() +/* {{{ proto public ReflectionMethod ReflectionClass::getConstructor() Returns the class' constructor if there is one, NULL otherwise */ ZEND_METHOD(reflection_class, getConstructor) { @@ -2152,14 +2318,14 @@ ZEND_METHOD(reflection_class, getConstructor) } /* }}} */ -/* {{{ proto public ReflectionMethod Reflection_Class::getMethod(string name) - Returns the class' method specified by it's name */ +/* {{{ proto public ReflectionMethod ReflectionClass::getMethod(string name) throws ReflectionException + Returns the class' method specified by its name */ ZEND_METHOD(reflection_class, getMethod) { reflection_object *intern; zend_class_entry *ce; zend_function *mptr; - char *name; + char *name, *lc_name; int name_len; METHOD_NOTSTATIC; @@ -2168,11 +2334,15 @@ ZEND_METHOD(reflection_class, getMethod) } GET_REFLECTION_OBJECT_PTR(ce); - zend_str_tolower(name, name_len); - if (zend_hash_find(&ce->function_table, name, name_len + 1, (void**) &mptr) == SUCCESS) { + lc_name = zend_str_tolower_dup(name, name_len); + if (zend_hash_find(&ce->function_table, lc_name, name_len + 1, (void**) &mptr) == SUCCESS) { reflection_method_factory(ce, mptr, return_value TSRMLS_CC); + efree(lc_name); } else { - RETURN_NULL(); + efree(lc_name); + zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, + "Method %s does not exist", name); + return; } } /* }}} */ @@ -2195,7 +2365,7 @@ static int _addmethod(zend_function *mptr, int num_args, va_list args, zend_hash } /* }}} */ -/* {{{ proto public ReflectionMethod[] Reflection_Class::getMethods() +/* {{{ proto public ReflectionMethod[] ReflectionClass::getMethods() Returns an array of this class' methods */ ZEND_METHOD(reflection_class, getMethods) { @@ -2221,8 +2391,8 @@ ZEND_METHOD(reflection_class, getMethods) } /* }}} */ -/* {{{ proto public ReflectionProperty Reflection_Class::getProperty(string name) - Returns the class' property specified by it's name */ +/* {{{ proto public ReflectionProperty ReflectionClass::getProperty(string name) throws ReflectionException + Returns the class' property specified by its name */ ZEND_METHOD(reflection_class, getProperty) { reflection_object *intern; @@ -2237,10 +2407,12 @@ ZEND_METHOD(reflection_class, getProperty) } GET_REFLECTION_OBJECT_PTR(ce); - if (zend_hash_find(&ce->properties_info, name, name_len + 1, (void**) &property_info) == SUCCESS) { + if (zend_hash_find(&ce->properties_info, name, name_len + 1, (void**) &property_info) == SUCCESS && (property_info->flags & ZEND_ACC_SHADOW) == 0) { reflection_property_factory(ce, property_info, return_value TSRMLS_CC); } else { - RETURN_NULL(); + zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, + "Property %s does not exist", name); + return; } } /* }}} */ @@ -2253,6 +2425,10 @@ static int _addproperty(zend_property_info *pptr, int num_args, va_list args, ze zval *retval = va_arg(args, zval*); long filter = va_arg(args, long); + if (pptr->flags & ZEND_ACC_SHADOW) { + return 0; + } + if (pptr->flags & filter) { TSRMLS_FETCH(); ALLOC_ZVAL(property); @@ -2263,7 +2439,7 @@ static int _addproperty(zend_property_info *pptr, int num_args, va_list args, ze } /* }}} */ -/* {{{ proto public ReflectionProperty[] Reflection_Class::getProperties() +/* {{{ proto public ReflectionProperty[] ReflectionClass::getProperties() Returns an array of this class' properties */ ZEND_METHOD(reflection_class, getProperties) { @@ -2300,6 +2476,7 @@ ZEND_METHOD(reflection_class, getConstants) METHOD_NOTSTATIC_NUMPARAMS(0); GET_REFLECTION_OBJECT_PTR(ce); array_init(return_value); + zend_hash_apply_with_argument(&ce->constants_table, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC); zend_hash_copy(Z_ARRVAL_P(return_value), &ce->constants_table, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *)); } /* }}} */ @@ -2320,6 +2497,7 @@ ZEND_METHOD(reflection_class, getConstant) } GET_REFLECTION_OBJECT_PTR(ce); + zend_hash_apply_with_argument(&ce->constants_table, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC); if (zend_hash_find(&ce->constants_table, name, name_len + 1, (void **) &value) == FAILURE) { RETURN_FALSE; } @@ -2349,7 +2527,7 @@ ZEND_METHOD(reflection_class, isInstantiable) METHOD_NOTSTATIC_NUMPARAMS(0); GET_REFLECTION_OBJECT_PTR(ce); - if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_ABSTRACT)) { + if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) { RETURN_FALSE; } @@ -2383,7 +2561,7 @@ ZEND_METHOD(reflection_class, isFinal) Returns whether this class is abstract */ ZEND_METHOD(reflection_class, isAbstract) { - _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_IMPLICIT_ABSTRACT_CLASS); + _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS); } /* }}} */ @@ -2467,7 +2645,7 @@ ZEND_METHOD(reflection_class, newInstance) if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) { efree(params); zval_ptr_dtor(&retval_ptr); - zend_error(E_WARNING, "Invokation of %s's constructor failed", ce->name); + zend_error(E_WARNING, "Invocation of %s's constructor failed", ce->name); RETURN_NULL(); } if (retval_ptr) { @@ -2478,7 +2656,7 @@ ZEND_METHOD(reflection_class, newInstance) } /* }}} */ -/* {{{ proto public ReflectionClass[] Reflection_Class::getInterfaces() +/* {{{ proto public ReflectionClass[] ReflectionClass::getInterfaces() Returns an array of interfaces this class implements */ ZEND_METHOD(reflection_class, getInterfaces) { @@ -2497,14 +2675,14 @@ ZEND_METHOD(reflection_class, getInterfaces) for (i=0; i < ce->num_interfaces; i++) { zval *interface; ALLOC_ZVAL(interface); - reflection_class_factory(ce->interfaces[i], interface TSRMLS_CC); + zend_reflection_class_factory(ce->interfaces[i], interface TSRMLS_CC); add_next_index_zval(return_value, interface); } } } /* }}} */ -/* {{{ proto public ReflectionClass Reflection_Class::getParentClass() +/* {{{ proto public ReflectionClass ReflectionClass::getParentClass() Returns the class' parent class, or, if none exists, FALSE */ ZEND_METHOD(reflection_class, getParentClass) { @@ -2515,14 +2693,14 @@ ZEND_METHOD(reflection_class, getParentClass) GET_REFLECTION_OBJECT_PTR(ce); if (ce->parent) { - reflection_class_factory(ce->parent, return_value TSRMLS_CC); + zend_reflection_class_factory(ce->parent, return_value TSRMLS_CC); } else { RETURN_FALSE; } } /* }}} */ -/* {{{ proto public bool ReflectionClass::isSubclassOf(string|reflection_class class) +/* {{{ proto public bool ReflectionClass::isSubclassOf(string|ReflectionClass class) Returns whether this class is a subclass of another class */ ZEND_METHOD(reflection_class, isSubclassOf) { @@ -2541,7 +2719,7 @@ ZEND_METHOD(reflection_class, isSubclassOf) case IS_STRING: if (zend_lookup_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), &pce TSRMLS_CC) == FAILURE) { zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, - "Interface %s doesn't exist", Z_STRVAL_P(class_name)); + "Interface %s does not exist", Z_STRVAL_P(class_name)); return; } class_ce = *pce; @@ -2559,7 +2737,7 @@ ZEND_METHOD(reflection_class, isSubclassOf) /* no break */ default: zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, - "Parameter one must either be a string or a Reflection_Class object"); + "Parameter one must either be a string or a ReflectionClass object"); return; } @@ -2568,7 +2746,7 @@ ZEND_METHOD(reflection_class, isSubclassOf) } /* }}} */ -/* {{{ proto public bool ReflectionClass::implementsInterface(string|reflection_class interface_name) +/* {{{ proto public bool ReflectionClass::implementsInterface(string|ReflectionClass interface_name) Returns whether this class is a subclass of another class */ ZEND_METHOD(reflection_class, implementsInterface) { @@ -2587,7 +2765,7 @@ ZEND_METHOD(reflection_class, implementsInterface) case IS_STRING: if (zend_lookup_class(Z_STRVAL_P(interface), Z_STRLEN_P(interface), &pce TSRMLS_CC) == FAILURE) { zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, - "Interface %s doesn't exist", Z_STRVAL_P(interface)); + "Interface %s does not exist", Z_STRVAL_P(interface)); return; } interface_ce = *pce; @@ -2605,7 +2783,7 @@ ZEND_METHOD(reflection_class, implementsInterface) /* no break */ default: zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, - "Parameter one must either be a string or a Reflection_Class object"); + "Parameter one must either be a string or a ReflectionClass object"); return; } @@ -2632,7 +2810,7 @@ ZEND_METHOD(reflection_class, isIterateable) } /* }}} */ -/* {{{ proto public ReflectionExtension|NULL Reflection_Class::getExtension() +/* {{{ proto public ReflectionExtension|NULL ReflectionClass::getExtension() Returns NULL or the extension the class belongs to */ ZEND_METHOD(reflection_class, getExtension) { @@ -2666,7 +2844,7 @@ ZEND_METHOD(reflection_class, getExtensionName) } /* }}} */ -/* {{{ proto public static mixed ReflectionObject::export(mixed argument, [, bool return]) throws ReflectionException +/* {{{ proto public static mixed ReflectionObject::export(mixed argument [, bool return]) throws ReflectionException Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */ ZEND_METHOD(reflection_object, export) { @@ -2682,7 +2860,7 @@ ZEND_METHOD(reflection_object, __construct) } /* }}} */ -/* {{{ proto public static mixed ReflectionProperty::export(mixed class, string name, [, bool return]) throws ReflectionException +/* {{{ proto public static mixed ReflectionProperty::export(mixed class, string name [, bool return]) throws ReflectionException Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */ ZEND_METHOD(reflection_property, export) { @@ -2695,7 +2873,7 @@ ZEND_METHOD(reflection_property, export) ZEND_METHOD(reflection_property, __construct) { zval *propname, *classname; - char *name_str; + char *name_str, *class_name, *prop_name; int name_len; zval *object; reflection_object *intern; @@ -2734,7 +2912,7 @@ ZEND_METHOD(reflection_property, __construct) /* returns out of this function */ } - if (zend_hash_find(&ce->properties_info, name_str, name_len + 1, (void **) &property_info) == FAILURE) { + if (zend_hash_find(&ce->properties_info, name_str, name_len + 1, (void **) &property_info) == FAILURE || (property_info->flags & ZEND_ACC_SHADOW)) { zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Property %s::$%s does not exist", ce->name, name_str); return; @@ -2760,8 +2938,9 @@ ZEND_METHOD(reflection_property, __construct) ZVAL_STRINGL(classname, ce->name, ce->name_length, 1); zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL); + zend_unmangle_property_name(property_info->name, &class_name, &prop_name); MAKE_STD_ZVAL(propname); - ZVAL_STRING(propname, property_info->name, 1); + ZVAL_STRING(propname, prop_name, 1); zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &propname, sizeof(zval *), NULL); reference = (property_reference*) emalloc(sizeof(property_reference)); @@ -2769,6 +2948,7 @@ ZEND_METHOD(reflection_property, __construct) reference->prop = property_info; intern->ptr = reference; intern->free_ptr = 1; + intern->ce = ce; } /* }}} */ @@ -2861,7 +3041,7 @@ ZEND_METHOD(reflection_property, getModifiers) } /* }}} */ -/* {{{ proto public mixed ReflectionProperty::getValue(stdclass object) +/* {{{ proto public mixed ReflectionProperty::getValue([stdclass object]) Returns this property's value */ ZEND_METHOD(reflection_property, getValue) { @@ -2878,16 +3058,16 @@ ZEND_METHOD(reflection_property, getValue) /* Returns from this function */ } - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &object) == FAILURE) { - return; - } - if ((ref->prop->flags & ZEND_ACC_STATIC)) { - if (zend_hash_quick_find(Z_OBJCE_P(object)->static_members, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) { + zend_update_class_constants(intern->ce TSRMLS_CC); + if (zend_hash_quick_find(intern->ce->static_members, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) { zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name); /* Bails out */ } } else { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &object) == FAILURE) { + return; + } if (zend_hash_quick_find(Z_OBJPROP_P(object), ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) { zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name); /* Bails out */ @@ -2899,7 +3079,7 @@ ZEND_METHOD(reflection_property, getValue) } /* }}} */ -/* {{{ proto public void ReflectionProperty::setValue(stdclass object, mixed value) +/* {{{ proto public void ReflectionProperty::setValue([stdclass object,] mixed value) Sets this property's value */ ZEND_METHOD(reflection_property, setValue) { @@ -2909,38 +3089,48 @@ ZEND_METHOD(reflection_property, setValue) zval *object; zval *value; int setter_done = 0; + zval *tmp; + HashTable *prop_table; METHOD_NOTSTATIC; GET_REFLECTION_OBJECT_PTR(ref); - if (ref->prop->flags & ~ZEND_ACC_PUBLIC) { + if (ref->prop->flags & ~(ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)) { _DO_THROW("Cannot access non-public member"); /* Returns from this function */ } - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "oz", &object, &value) == FAILURE) { - return; - } - - if (zend_hash_quick_find(Z_OBJPROP_P(object), ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &variable_ptr) == SUCCESS) { - if (*variable_ptr == value) { - setter_done = 1; - } else { - if (PZVAL_IS_REF(*variable_ptr)) { - zval_dtor(*variable_ptr); - (*variable_ptr)->type = value->type; - (*variable_ptr)->value = value->value; - if (value->refcount > 0) { - zval_copy_ctor(*variable_ptr); - } - setter_done = 1; + if ((ref->prop->flags & ZEND_ACC_STATIC)) { + if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &tmp, &value) == FAILURE) { + return; } } + prop_table = intern->ce->static_members; } else { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "oz", &object, &value) == FAILURE) { + return; + } + prop_table = Z_OBJPROP_P(object); + } + + if (zend_hash_quick_find(prop_table, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &variable_ptr) == FAILURE) { zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name); /* Bails out */ } - + if (*variable_ptr == value) { + setter_done = 1; + } else { + if (PZVAL_IS_REF(*variable_ptr)) { + zval_dtor(*variable_ptr); + (*variable_ptr)->type = value->type; + (*variable_ptr)->value = value->value; + if (value->refcount > 0) { + zval_copy_ctor(*variable_ptr); + } + setter_done = 1; + } + } if (!setter_done) { zval **foo; @@ -2948,12 +3138,12 @@ ZEND_METHOD(reflection_property, setValue) if (PZVAL_IS_REF(value)) { SEPARATE_ZVAL(&value); } - zend_hash_quick_update(Z_OBJPROP_P(object), ref->prop->name, ref->prop->name_length+1, ref->prop->h, &value, sizeof(zval *), (void **) &foo); + zend_hash_quick_update(prop_table, ref->prop->name, ref->prop->name_length+1, ref->prop->h, &value, sizeof(zval *), (void **) &foo); } } /* }}} */ -/* {{{ proto public ReflectionClass Reflection_Property::getDeclaringClass() +/* {{{ proto public ReflectionClass ReflectionProperty::getDeclaringClass() Get the declaring class */ ZEND_METHOD(reflection_property, getDeclaringClass) { @@ -2963,10 +3153,10 @@ ZEND_METHOD(reflection_property, getDeclaringClass) METHOD_NOTSTATIC_NUMPARAMS(0); GET_REFLECTION_OBJECT_PTR(ref); - reflection_class_factory(ref->ce, return_value TSRMLS_CC); + zend_reflection_class_factory(ref->ce, return_value TSRMLS_CC); } -/* {{{ proto public static mixed ReflectionExtension::export(string name, [, bool return]) throws ReflectionException +/* {{{ proto public static mixed ReflectionExtension::export(string name [, bool return]) throws ReflectionException Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */ ZEND_METHOD(reflection_extension, export) { @@ -3009,6 +3199,7 @@ ZEND_METHOD(reflection_extension, __construct) zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); intern->ptr = module; intern->free_ptr = 0; + intern->ce = NULL; } /* }}} */ @@ -3056,7 +3247,7 @@ ZEND_METHOD(reflection_extension, getVersion) } /* }}} */ -/* {{{ proto public ReflectionFunction[] Reflection_Extension::getFunctions() +/* {{{ proto public ReflectionFunction[] ReflectionExtension::getFunctions() Returns an array of this extension's fuctions */ ZEND_METHOD(reflection_extension, getFunctions) { @@ -3081,7 +3272,7 @@ ZEND_METHOD(reflection_extension, getFunctions) ALLOC_ZVAL(function); reflection_function_factory(fptr, function TSRMLS_CC); - add_next_index_zval(return_value, function); + add_assoc_zval_ex(return_value, func->fname, strlen(func->fname)+1, function); func++; } } @@ -3162,10 +3353,10 @@ static int add_extension_class(zend_class_entry **pce, int num_args, va_list arg TSRMLS_FETCH(); if (add_reflection_class) { ALLOC_ZVAL(zclass); - reflection_class_factory(*pce, zclass TSRMLS_CC); + zend_reflection_class_factory(*pce, zclass TSRMLS_CC); add_assoc_zval_ex(class_array, (*pce)->name, (*pce)->name_length + 1, zclass); } else { - add_next_index_stringl(class_array, (*pce)->name, (*pce)->name_length + 1, 1); + add_next_index_stringl(class_array, (*pce)->name, (*pce)->name_length, 1); } } return ZEND_HASH_APPLY_KEEP; @@ -3173,7 +3364,7 @@ static int add_extension_class(zend_class_entry **pce, int num_args, va_list arg /* }}} */ /* {{{ proto public ReflectionClass[] ReflectionExtension::getClasses() - Returns an array containing Reflection_Class objects for all classes of this extension */ + Returns an array containing ReflectionClass objects for all classes of this extension */ ZEND_METHOD(reflection_extension, getClasses) { reflection_object *intern; @@ -3235,6 +3426,8 @@ static zend_function_entry reflection_function_functions[] = { ZEND_ME(reflection_function, invoke, NULL, 0) ZEND_ME(reflection_function, returnsReference, NULL, 0) ZEND_ME(reflection_function, getParameters, NULL, 0) + ZEND_ME(reflection_function, getNumberOfParameters, NULL, 0) + ZEND_ME(reflection_function, getNumberOfRequiredParameters, NULL, 0) {NULL, NULL, NULL} }; @@ -3327,6 +3520,9 @@ static zend_function_entry reflection_parameter_functions[] = { ZEND_ME(reflection_parameter, isPassedByReference, NULL, 0) ZEND_ME(reflection_parameter, getClass, NULL, 0) ZEND_ME(reflection_parameter, allowsNull, NULL, 0) + ZEND_ME(reflection_parameter, isOptional, NULL, 0) + ZEND_ME(reflection_parameter, isDefaultValueAvailable, NULL, 0) + ZEND_ME(reflection_parameter, getDefaultValue, NULL, 0) {NULL, NULL, NULL} }; @@ -3346,12 +3542,33 @@ static zend_function_entry reflection_extension_functions[] = { }; /* }}} */ +static zend_object_handlers *zend_std_obj_handlers; + +/* {{{ _reflection_write_property */ +static void _reflection_write_property(zval *object, zval *member, zval *value TSRMLS_DC) +{ + if (Z_TYPE_P(member) == IS_STRING + && zend_hash_exists(&Z_OBJCE_P(object)->default_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1) + && (!strcmp(Z_STRVAL_P(member), "name") || !strcmp(Z_STRVAL_P(member), "class"))) + { + zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, + "Cannot set read-only property %s::$%s", Z_OBJCE_P(object)->name, Z_STRVAL_P(member)); + } + else + { + zend_std_obj_handlers->write_property(object, member, value TSRMLS_CC); + } +} +/* }}} */ + /* {{{ zend_register_reflection_api */ ZEND_API void zend_register_reflection_api(TSRMLS_D) { zend_class_entry _reflection_entry; + zend_std_obj_handlers = zend_get_std_object_handlers(); memcpy(&reflection_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); reflection_object_handlers.clone_obj = NULL; + reflection_object_handlers.write_property = _reflection_write_property; INIT_CLASS_ENTRY(_reflection_entry, "ReflectionException", reflection_exception_functions); reflection_exception_ptr = zend_register_internal_class_ex(&_reflection_entry, zend_exception_get_default(), NULL TSRMLS_CC); @@ -3367,20 +3584,25 @@ ZEND_API void zend_register_reflection_api(TSRMLS_D) { _reflection_entry.create_object = reflection_objects_new; reflection_function_ptr = zend_register_internal_class(&_reflection_entry TSRMLS_CC); reflection_register_implement(reflection_function_ptr, reflector_ptr TSRMLS_CC); + zend_declare_property_string(reflection_function_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC); INIT_CLASS_ENTRY(_reflection_entry, "ReflectionParameter", reflection_parameter_functions); _reflection_entry.create_object = reflection_objects_new; reflection_parameter_ptr = zend_register_internal_class(&_reflection_entry TSRMLS_CC); reflection_register_implement(reflection_parameter_ptr, reflector_ptr TSRMLS_CC); + zend_declare_property_string(reflection_parameter_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC); INIT_CLASS_ENTRY(_reflection_entry, "ReflectionMethod", reflection_method_functions); _reflection_entry.create_object = reflection_objects_new; reflection_method_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_function_ptr, NULL TSRMLS_CC); + zend_declare_property_string(reflection_method_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_string(reflection_method_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC); INIT_CLASS_ENTRY(_reflection_entry, "ReflectionClass", reflection_class_functions); _reflection_entry.create_object = reflection_objects_new; reflection_class_ptr = zend_register_internal_class(&_reflection_entry TSRMLS_CC); reflection_register_implement(reflection_class_ptr, reflector_ptr TSRMLS_CC); + zend_declare_property_string(reflection_class_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC); INIT_CLASS_ENTRY(_reflection_entry, "ReflectionObject", reflection_object_functions); _reflection_entry.create_object = reflection_objects_new; @@ -3390,11 +3612,14 @@ ZEND_API void zend_register_reflection_api(TSRMLS_D) { _reflection_entry.create_object = reflection_objects_new; reflection_property_ptr = zend_register_internal_class(&_reflection_entry TSRMLS_CC); reflection_register_implement(reflection_property_ptr, reflector_ptr TSRMLS_CC); + zend_declare_property_string(reflection_property_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_string(reflection_property_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC); INIT_CLASS_ENTRY(_reflection_entry, "ReflectionExtension", reflection_extension_functions); _reflection_entry.create_object = reflection_objects_new; reflection_extension_ptr = zend_register_internal_class(&_reflection_entry TSRMLS_CC); reflection_register_implement(reflection_extension_ptr, reflector_ptr TSRMLS_CC); + zend_declare_property_string(reflection_extension_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC); /* Property modifiers */ REGISTER_MAIN_LONG_CONSTANT("P_STATIC", ZEND_ACC_STATIC, CONST_PERSISTENT|CONST_CS); diff --git a/Zend/zend_stream.c b/Zend/zend_stream.c index 1e307591d9e4..cd26f61b411d 100644 --- a/Zend/zend_stream.c +++ b/Zend/zend_stream.c @@ -79,11 +79,10 @@ ZEND_API int zend_stream_fixup(zend_file_handle *file_handle TSRMLS_DC) return FAILURE; } - /* promote to stream */ + /* make compatible with stream */ file_handle->handle.stream.handle = file_handle->handle.fp; file_handle->handle.stream.reader = zend_stream_stdio_reader; file_handle->handle.stream.closer = zend_stream_stdio_closer; - file_handle->type = ZEND_HANDLE_STREAM; file_handle->handle.stream.interactive = isatty(fileno((FILE *)file_handle->handle.stream.handle)); } @@ -95,7 +94,16 @@ ZEND_API size_t zend_stream_read(zend_file_handle *file_handle, char *buf, size_ if (file_handle->handle.stream.interactive) { int c = '*', n; +#ifdef NETWARE + /* + c != 4 check is there as fread of a character in NetWare LibC gives 4 upon ^D character. + Ascii value 4 is actually EOT character which is not defined anywhere in the LibC + or else we can use instead of hardcoded 4. + */ + for ( n = 0; n < len && (c = zend_stream_getc( file_handle TSRMLS_CC)) != EOF && c != 4 && c != '\n'; ++n ) +#else for ( n = 0; n < len && (c = zend_stream_getc( file_handle TSRMLS_CC)) != EOF && c != '\n'; ++n ) +#endif buf[n] = (char) c; if ( c == '\n' ) buf[n++] = (char) c; diff --git a/Zend/zend_strtod.c b/Zend/zend_strtod.c new file mode 100644 index 000000000000..87d755006a4e --- /dev/null +++ b/Zend/zend_strtod.c @@ -0,0 +1,1780 @@ +/**************************************************************** + * + * The author of this software is David M. Gay. + * + * Copyright (c) 1991 by AT&T. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + * + ***************************************************************/ + +/* Please send bug reports to + David M. Gay + AT&T Bell Laboratories, Room 2C-463 + 600 Mountain Avenue + Murray Hill, NJ 07974-2070 + U.S.A. + dmg@research.att.com or research!dmg + */ + +/* strtod for IEEE-, VAX-, and IBM-arithmetic machines. + * + * This strtod returns a nearest machine number to the input decimal + * string (or sets errno to ERANGE). With IEEE arithmetic, ties are + * broken by the IEEE round-even rule. Otherwise ties are broken by + * biased rounding (add half and chop). + * + * Inspired loosely by William D. Clinger's paper "How to Read Floating + * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101]. + * + * Modifications: + * + * 1. We only require IEEE, IBM, or VAX double-precision + * arithmetic (not IEEE double-extended). + * 2. We get by with floating-point arithmetic in a case that + * Clinger missed -- when we're computing d * 10^n + * for a small integer d and the integer n is not too + * much larger than 22 (the maximum integer k for which + * we can represent 10^k exactly), we may be able to + * compute (d*10^k) * 10^(e-k) with just one roundoff. + * 3. Rather than a bit-at-a-time adjustment of the binary + * result in the hard case, we use floating-point + * arithmetic to determine the adjustment to within + * one bit; only in really hard cases do we need to + * compute a second residual. + * 4. Because of 3., we don't need a large table of powers of 10 + * for ten-to-e (just some small tables, e.g. of 10^k + * for 0 <= k <= 22). + */ + +/* + * #define IEEE_LITTLE_ENDIAN for IEEE-arithmetic machines where the least + * significant byte has the lowest address. + * #define IEEE_BIG_ENDIAN for IEEE-arithmetic machines where the most + * significant byte has the lowest address. + * #define Long int on machines with 32-bit ints and 64-bit longs. + * #define Sudden_Underflow for IEEE-format machines without gradual + * underflow (i.e., that flush to zero on underflow). + * #define IBM for IBM mainframe-style floating-point arithmetic. + * #define VAX for VAX-style floating-point arithmetic. + * #define Unsigned_Shifts if >> does treats its left operand as unsigned. + * #define No_leftright to omit left-right logic in fast floating-point + * computation of dtoa. + * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3. + * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines + * that use extended-precision instructions to compute rounded + * products and quotients) with IBM. + * #define ROUND_BIASED for IEEE-format with biased rounding. + * #define Inaccurate_Divide for IEEE-format with correctly rounded + * products but inaccurate quotients, e.g., for Intel i860. + * #define Just_16 to store 16 bits per 32-bit Long when doing high-precision + * integer arithmetic. Whether this speeds things up or slows things + * down depends on the machine and the number being converted. + * #define KR_headers for old-style C function headers. + * #define Bad_float_h if your system lacks a float.h or if it does not + * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP, + * FLT_RADIX, FLT_ROUNDS, and DBL_MAX. + * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n) + * if memory is available and otherwise does something you deem + * appropriate. If MALLOC is undefined, malloc will be invoked + * directly -- and assumed always to succeed. + */ + +#include + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#if defined(HAVE_INTTYPES_H) +#include +#elif defined(HAVE_STDINT_H) +#include +#endif + +#ifndef HAVE_INT32_T +# if SIZEOF_INT == 4 +typedef int int32_t; +# elif SIZEOF_LONG == 4 +typedef long int int32_t; +# endif +#endif + +#ifndef HAVE_UINT32_T +# if SIZEOF_INT == 4 +typedef unsigned int uint32_t; +# elif SIZEOF_LONG == 4 +typedef unsigned long int uint32_t; +# endif +#endif + +#ifdef WORDS_BIGENDIAN +#define IEEE_BIG_ENDIAN +#else +#define IEEE_LITTLE_ENDIAN +#endif + +#if defined(__arm__) && !defined(__VFP_FP__) +/* + * Although the CPU is little endian the FP has different + * byte and word endianness. The byte order is still little endian + * but the word order is big endian. + */ +#define IEEE_BIG_ENDIAN +#endif + +#ifdef __vax__ +#define VAX +#endif + +#if defined(_MSC_VER) +#define int32_t __int32 +#define uint32_t unsigned __int32 +#define IEEE_LITTLE_ENDIAN +#endif + +#define Long int32_t +#define ULong uint32_t + +#ifdef __cplusplus +#include "malloc.h" +#include "memory.h" +#else +#ifndef KR_headers +#include "stdlib.h" +#include "string.h" +#include "locale.h" +#else +#include "malloc.h" +#include "memory.h" +#endif +#endif + +#ifdef MALLOC +#ifdef KR_headers +extern char *MALLOC(); +#else +extern void *MALLOC(size_t); +#endif +#else +#define MALLOC malloc +#endif + +#include "ctype.h" +#include "errno.h" + +#ifdef Bad_float_h +#ifdef IEEE_BIG_ENDIAN +#define IEEE_ARITHMETIC +#endif +#ifdef IEEE_LITTLE_ENDIAN +#define IEEE_ARITHMETIC +#endif + +#ifdef IEEE_ARITHMETIC +#define DBL_DIG 15 +#define DBL_MAX_10_EXP 308 +#define DBL_MAX_EXP 1024 +#define FLT_RADIX 2 +#define FLT_ROUNDS 1 +#define DBL_MAX 1.7976931348623157e+308 +#endif + +#ifdef IBM +#define DBL_DIG 16 +#define DBL_MAX_10_EXP 75 +#define DBL_MAX_EXP 63 +#define FLT_RADIX 16 +#define FLT_ROUNDS 0 +#define DBL_MAX 7.2370055773322621e+75 +#endif + +#ifdef VAX +#define DBL_DIG 16 +#define DBL_MAX_10_EXP 38 +#define DBL_MAX_EXP 127 +#define FLT_RADIX 2 +#define FLT_ROUNDS 1 +#define DBL_MAX 1.7014118346046923e+38 +#endif + +#ifndef LONG_MAX +#define LONG_MAX 2147483647 +#endif +#else +#include "float.h" +#endif +#ifndef __MATH_H__ +#include "math.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CONST +#ifdef KR_headers +#define CONST /* blank */ +#else +#define CONST const +#endif +#endif + +#ifdef Unsigned_Shifts +#define Sign_Extend(a,b) if (b < 0) a |= 0xffff0000; +#else +#define Sign_Extend(a,b) /*no-op*/ +#endif + +#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN) + defined(VAX) + \ + defined(IBM) != 1 +Exactly one of IEEE_LITTLE_ENDIAN IEEE_BIG_ENDIAN, VAX, or +IBM should be defined. +#endif + +typedef union { + double d; + ULong ul[2]; +} _double; +#define value(x) ((x).d) +#ifdef IEEE_LITTLE_ENDIAN +#define word0(x) ((x).ul[1]) +#define word1(x) ((x).ul[0]) +#else +#define word0(x) ((x).ul[0]) +#define word1(x) ((x).ul[1]) +#endif + +/* The following definition of Storeinc is appropriate for MIPS processors. + * An alternative that might be better on some machines is + * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff) + */ +#if defined(IEEE_LITTLE_ENDIAN) + defined(VAX) + defined(__arm__) +#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \ +((unsigned short *)a)[0] = (unsigned short)c, a++) +#else +#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \ +((unsigned short *)a)[1] = (unsigned short)c, a++) +#endif + +/* #define P DBL_MANT_DIG */ +/* Ten_pmax = floor(P*log(2)/log(5)) */ +/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */ +/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */ +/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */ + +#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN) +#define Exp_shift 20 +#define Exp_shift1 20 +#define Exp_msk1 0x100000 +#define Exp_msk11 0x100000 +#define Exp_mask 0x7ff00000 +#define P 53 +#define Bias 1023 +#define IEEE_Arith +#define Emin (-1022) +#define Exp_1 0x3ff00000 +#define Exp_11 0x3ff00000 +#define Ebits 11 +#define Frac_mask 0xfffff +#define Frac_mask1 0xfffff +#define Ten_pmax 22 +#define Bletch 0x10 +#define Bndry_mask 0xfffff +#define Bndry_mask1 0xfffff +#define LSB 1 +#define Sign_bit 0x80000000 +#define Log2P 1 +#define Tiny0 0 +#define Tiny1 1 +#define Quick_max 14 +#define Int_max 14 +#define Infinite(x) (word0(x) == 0x7ff00000) /* sufficient test for here */ +#else +#undef Sudden_Underflow +#define Sudden_Underflow +#ifdef IBM +#define Exp_shift 24 +#define Exp_shift1 24 +#define Exp_msk1 0x1000000 +#define Exp_msk11 0x1000000 +#define Exp_mask 0x7f000000 +#define P 14 +#define Bias 65 +#define Exp_1 0x41000000 +#define Exp_11 0x41000000 +#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */ +#define Frac_mask 0xffffff +#define Frac_mask1 0xffffff +#define Bletch 4 +#define Ten_pmax 22 +#define Bndry_mask 0xefffff +#define Bndry_mask1 0xffffff +#define LSB 1 +#define Sign_bit 0x80000000 +#define Log2P 4 +#define Tiny0 0x100000 +#define Tiny1 0 +#define Quick_max 14 +#define Int_max 15 +#else /* VAX */ +#define Exp_shift 23 +#define Exp_shift1 7 +#define Exp_msk1 0x80 +#define Exp_msk11 0x800000 +#define Exp_mask 0x7f80 +#define P 56 +#define Bias 129 +#define Exp_1 0x40800000 +#define Exp_11 0x4080 +#define Ebits 8 +#define Frac_mask 0x7fffff +#define Frac_mask1 0xffff007f +#define Ten_pmax 24 +#define Bletch 2 +#define Bndry_mask 0xffff007f +#define Bndry_mask1 0xffff007f +#define LSB 0x10000 +#define Sign_bit 0x8000 +#define Log2P 1 +#define Tiny0 0x80 +#define Tiny1 0 +#define Quick_max 15 +#define Int_max 15 +#endif +#endif + +#ifndef IEEE_Arith +#define ROUND_BIASED +#endif + +#ifdef RND_PRODQUOT +#define rounded_product(a,b) a = rnd_prod(a, b) +#define rounded_quotient(a,b) a = rnd_quot(a, b) +#ifdef KR_headers +extern double rnd_prod(), rnd_quot(); +#else +extern double rnd_prod(double, double), rnd_quot(double, double); +#endif +#else +#define rounded_product(a,b) a *= b +#define rounded_quotient(a,b) a /= b +#endif + +#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1)) +#define Big1 0xffffffff + +#ifndef Just_16 +/* When Pack_32 is not defined, we store 16 bits per 32-bit Long. + * This makes some inner loops simpler and sometimes saves work + * during multiplications, but it often seems to make things slightly + * slower. Hence the default is now to store 32 bits per Long. + */ +#ifndef Pack_32 +#define Pack_32 +#endif +#endif + +#define Kmax 15 + + struct +Bigint { + struct Bigint *next; + int k, maxwds, sign, wds; + ULong x[1]; + }; + + typedef struct Bigint Bigint; + + static Bigint *freelist[Kmax+1]; + + static Bigint * +Balloc +#ifdef KR_headers + (k) int k; +#else + (int k) +#endif +{ + int x; + Bigint *rv; + + if ((rv = freelist[k])) { + freelist[k] = rv->next; + } + else { + x = 1 << k; + rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(Long)); + rv->k = k; + rv->maxwds = x; + } + rv->sign = rv->wds = 0; + return rv; + } + + static void +Bfree +#ifdef KR_headers + (v) Bigint *v; +#else + (Bigint *v) +#endif +{ + if (v) { + v->next = freelist[v->k]; + freelist[v->k] = v; + } + } + +#define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \ +y->wds*sizeof(Long) + 2*sizeof(int)) + + static Bigint * +multadd +#ifdef KR_headers + (b, m, a) Bigint *b; int m, a; +#else + (Bigint *b, int m, int a) /* multiply by m and add a */ +#endif +{ + int i, wds; + ULong *x, y; +#ifdef Pack_32 + ULong xi, z; +#endif + Bigint *b1; + + wds = b->wds; + x = b->x; + i = 0; + do { +#ifdef Pack_32 + xi = *x; + y = (xi & 0xffff) * m + a; + z = (xi >> 16) * m + (y >> 16); + a = (int)(z >> 16); + *x++ = (z << 16) + (y & 0xffff); +#else + y = *x * m + a; + a = (int)(y >> 16); + *x++ = y & 0xffff; +#endif + } + while(++i < wds); + if (a) { + if (wds >= b->maxwds) { + b1 = Balloc(b->k+1); + Bcopy(b1, b); + Bfree(b); + b = b1; + } + b->x[wds++] = a; + b->wds = wds; + } + return b; + } + + static Bigint * +s2b +#ifdef KR_headers + (s, nd0, nd, y9) CONST char *s; int nd0, nd; ULong y9; +#else + (CONST char *s, int nd0, int nd, ULong y9) +#endif +{ + Bigint *b; + int i, k; + Long x, y; + + x = (nd + 8) / 9; + for(k = 0, y = 1; x > y; y <<= 1, k++) ; +#ifdef Pack_32 + b = Balloc(k); + b->x[0] = y9; + b->wds = 1; +#else + b = Balloc(k+1); + b->x[0] = y9 & 0xffff; + b->wds = (b->x[1] = y9 >> 16) ? 2 : 1; +#endif + + i = 9; + if (9 < nd0) { + s += 9; + do b = multadd(b, 10, *s++ - '0'); + while(++i < nd0); + s++; + } + else + s += 10; + for(; i < nd; i++) + b = multadd(b, 10, *s++ - '0'); + return b; + } + + static int +hi0bits +#ifdef KR_headers + (x) register ULong x; +#else + (register ULong x) +#endif +{ + register int k = 0; + + if (!(x & 0xffff0000)) { + k = 16; + x <<= 16; + } + if (!(x & 0xff000000)) { + k += 8; + x <<= 8; + } + if (!(x & 0xf0000000)) { + k += 4; + x <<= 4; + } + if (!(x & 0xc0000000)) { + k += 2; + x <<= 2; + } + if (!(x & 0x80000000)) { + k++; + if (!(x & 0x40000000)) + return 32; + } + return k; + } + + static int +lo0bits +#ifdef KR_headers + (y) ULong *y; +#else + (ULong *y) +#endif +{ + register int k; + register ULong x = *y; + + if (x & 7) { + if (x & 1) + return 0; + if (x & 2) { + *y = x >> 1; + return 1; + } + *y = x >> 2; + return 2; + } + k = 0; + if (!(x & 0xffff)) { + k = 16; + x >>= 16; + } + if (!(x & 0xff)) { + k += 8; + x >>= 8; + } + if (!(x & 0xf)) { + k += 4; + x >>= 4; + } + if (!(x & 0x3)) { + k += 2; + x >>= 2; + } + if (!(x & 1)) { + k++; + x >>= 1; + if (!x & 1) + return 32; + } + *y = x; + return k; + } + + static Bigint * +i2b +#ifdef KR_headers + (i) int i; +#else + (int i) +#endif +{ + Bigint *b; + + b = Balloc(1); + b->x[0] = i; + b->wds = 1; + return b; + } + + static Bigint * +mult +#ifdef KR_headers + (a, b) Bigint *a, *b; +#else + (Bigint *a, Bigint *b) +#endif +{ + Bigint *c; + int k, wa, wb, wc; + ULong carry, y, z; + ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0; +#ifdef Pack_32 + ULong z2; +#endif + + if (a->wds < b->wds) { + c = a; + a = b; + b = c; + } + k = a->k; + wa = a->wds; + wb = b->wds; + wc = wa + wb; + if (wc > a->maxwds) + k++; + c = Balloc(k); + for(x = c->x, xa = x + wc; x < xa; x++) + *x = 0; + xa = a->x; + xae = xa + wa; + xb = b->x; + xbe = xb + wb; + xc0 = c->x; +#ifdef Pack_32 + for(; xb < xbe; xb++, xc0++) { + if ((y = *xb & 0xffff)) { + x = xa; + xc = xc0; + carry = 0; + do { + z = (*x & 0xffff) * y + (*xc & 0xffff) + carry; + carry = z >> 16; + z2 = (*x++ >> 16) * y + (*xc >> 16) + carry; + carry = z2 >> 16; + Storeinc(xc, z2, z); + } + while(x < xae); + *xc = carry; + } + if ((y = *xb >> 16)) { + x = xa; + xc = xc0; + carry = 0; + z2 = *xc; + do { + z = (*x & 0xffff) * y + (*xc >> 16) + carry; + carry = z >> 16; + Storeinc(xc, z, z2); + z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry; + carry = z2 >> 16; + } + while(x < xae); + *xc = z2; + } + } +#else + for(; xb < xbe; xc0++) { + if (y = *xb++) { + x = xa; + xc = xc0; + carry = 0; + do { + z = *x++ * y + *xc + carry; + carry = z >> 16; + *xc++ = z & 0xffff; + } + while(x < xae); + *xc = carry; + } + } +#endif + for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ; + c->wds = wc; + return c; + } + + static Bigint *p5s; + + static Bigint * +pow5mult +#ifdef KR_headers + (b, k) Bigint *b; int k; +#else + (Bigint *b, int k) +#endif +{ + Bigint *b1, *p5, *p51; + int i; + static int p05[3] = { 5, 25, 125 }; + + if ((i = k & 3)) + b = multadd(b, p05[i-1], 0); + + if (!(k >>= 2)) + return b; + if (!(p5 = p5s)) { + /* first time */ + p5 = p5s = i2b(625); + p5->next = 0; + } + for(;;) { + if (k & 1) { + b1 = mult(b, p5); + Bfree(b); + b = b1; + } + if (!(k >>= 1)) + break; + if (!(p51 = p5->next)) { + p51 = p5->next = mult(p5,p5); + p51->next = 0; + } + p5 = p51; + } + return b; + } + + static Bigint * +lshift +#ifdef KR_headers + (b, k) Bigint *b; int k; +#else + (Bigint *b, int k) +#endif +{ + int i, k1, n, n1; + Bigint *b1; + ULong *x, *x1, *xe, z; + +#ifdef Pack_32 + n = k >> 5; +#else + n = k >> 4; +#endif + k1 = b->k; + n1 = n + b->wds + 1; + for(i = b->maxwds; n1 > i; i <<= 1) + k1++; + b1 = Balloc(k1); + x1 = b1->x; + for(i = 0; i < n; i++) + *x1++ = 0; + x = b->x; + xe = x + b->wds; +#ifdef Pack_32 + if (k &= 0x1f) { + k1 = 32 - k; + z = 0; + do { + *x1++ = *x << k | z; + z = *x++ >> k1; + } + while(x < xe); + if ((*x1 = z)) + ++n1; + } +#else + if (k &= 0xf) { + k1 = 16 - k; + z = 0; + do { + *x1++ = *x << k & 0xffff | z; + z = *x++ >> k1; + } + while(x < xe); + if (*x1 = z) + ++n1; + } +#endif + else do + *x1++ = *x++; + while(x < xe); + b1->wds = n1 - 1; + Bfree(b); + return b1; + } + + static int +cmp +#ifdef KR_headers + (a, b) Bigint *a, *b; +#else + (Bigint *a, Bigint *b) +#endif +{ + ULong *xa, *xa0, *xb, *xb0; + int i, j; + + i = a->wds; + j = b->wds; +#ifdef DEBUG + if (i > 1 && !a->x[i-1]) + Bug("cmp called with a->x[a->wds-1] == 0"); + if (j > 1 && !b->x[j-1]) + Bug("cmp called with b->x[b->wds-1] == 0"); +#endif + if (i -= j) + return i; + xa0 = a->x; + xa = xa0 + j; + xb0 = b->x; + xb = xb0 + j; + for(;;) { + if (*--xa != *--xb) + return *xa < *xb ? -1 : 1; + if (xa <= xa0) + break; + } + return 0; + } + + static Bigint * +diff +#ifdef KR_headers + (a, b) Bigint *a, *b; +#else + (Bigint *a, Bigint *b) +#endif +{ + Bigint *c; + int i, wa, wb; + Long borrow, y; /* We need signed shifts here. */ + ULong *xa, *xae, *xb, *xbe, *xc; +#ifdef Pack_32 + Long z; +#endif + + i = cmp(a,b); + if (!i) { + c = Balloc(0); + c->wds = 1; + c->x[0] = 0; + return c; + } + if (i < 0) { + c = a; + a = b; + b = c; + i = 1; + } + else + i = 0; + c = Balloc(a->k); + c->sign = i; + wa = a->wds; + xa = a->x; + xae = xa + wa; + wb = b->wds; + xb = b->x; + xbe = xb + wb; + xc = c->x; + borrow = 0; +#ifdef Pack_32 + do { + y = (*xa & 0xffff) - (*xb & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + z = (*xa++ >> 16) - (*xb++ >> 16) + borrow; + borrow = z >> 16; + Sign_Extend(borrow, z); + Storeinc(xc, z, y); + } + while(xb < xbe); + while(xa < xae) { + y = (*xa & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + z = (*xa++ >> 16) + borrow; + borrow = z >> 16; + Sign_Extend(borrow, z); + Storeinc(xc, z, y); + } +#else + do { + y = *xa++ - *xb++ + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + *xc++ = y & 0xffff; + } + while(xb < xbe); + while(xa < xae) { + y = *xa++ + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + *xc++ = y & 0xffff; + } +#endif + while(!*--xc) + wa--; + c->wds = wa; + return c; + } + + static double +ulp +#ifdef KR_headers + (_x) double _x; +#else + (double _x) +#endif +{ + _double x; + register Long L; + _double a; + + value(x) = _x; + L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1; +#ifndef Sudden_Underflow + if (L > 0) { +#endif +#ifdef IBM + L |= Exp_msk1 >> 4; +#endif + word0(a) = L; + word1(a) = 0; +#ifndef Sudden_Underflow + } + else { + L = -L >> Exp_shift; + if (L < Exp_shift) { + word0(a) = 0x80000 >> L; + word1(a) = 0; + } + else { + word0(a) = 0; + L -= Exp_shift; + word1(a) = L >= 31 ? 1 : 1 << (31 - L); + } + } +#endif + return value(a); + } + + static double +b2d +#ifdef KR_headers + (a, e) Bigint *a; int *e; +#else + (Bigint *a, int *e) +#endif +{ + ULong *xa, *xa0, w, y, z; + int k; + _double d; +#ifdef VAX + ULong d0, d1; +#else +#define d0 word0(d) +#define d1 word1(d) +#endif + + xa0 = a->x; + xa = xa0 + a->wds; + y = *--xa; +#ifdef DEBUG + if (!y) Bug("zero y in b2d"); +#endif + k = hi0bits(y); + *e = 32 - k; +#ifdef Pack_32 + if (k < Ebits) { + d0 = Exp_1 | y >> (Ebits - k); + w = xa > xa0 ? *--xa : 0; + d1 = y << ((32-Ebits) + k) | w >> (Ebits - k); + goto ret_d; + } + z = xa > xa0 ? *--xa : 0; + if (k -= Ebits) { + d0 = Exp_1 | y << k | z >> (32 - k); + y = xa > xa0 ? *--xa : 0; + d1 = z << k | y >> (32 - k); + } + else { + d0 = Exp_1 | y; + d1 = z; + } +#else + if (k < Ebits + 16) { + z = xa > xa0 ? *--xa : 0; + d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k; + w = xa > xa0 ? *--xa : 0; + y = xa > xa0 ? *--xa : 0; + d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k; + goto ret_d; + } + z = xa > xa0 ? *--xa : 0; + w = xa > xa0 ? *--xa : 0; + k -= Ebits + 16; + d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k; + y = xa > xa0 ? *--xa : 0; + d1 = w << k + 16 | y << k; +#endif + ret_d: +#ifdef VAX + word0(d) = d0 >> 16 | d0 << 16; + word1(d) = d1 >> 16 | d1 << 16; +#else +#undef d0 +#undef d1 +#endif + return value(d); + } + + static Bigint * +d2b +#ifdef KR_headers + (_d, e, bits) double d; int *e, *bits; +#else + (double _d, int *e, int *bits) +#endif +{ + Bigint *b; + int de, i, k; + ULong *x, y, z; + _double d; +#ifdef VAX + ULong d0, d1; +#endif + + value(d) = _d; +#ifdef VAX + d0 = word0(d) >> 16 | word0(d) << 16; + d1 = word1(d) >> 16 | word1(d) << 16; +#else +#define d0 word0(d) +#define d1 word1(d) +#endif + +#ifdef Pack_32 + b = Balloc(1); +#else + b = Balloc(2); +#endif + x = b->x; + + z = d0 & Frac_mask; + d0 &= 0x7fffffff; /* clear sign bit, which we ignore */ +#ifdef Sudden_Underflow + de = (int)(d0 >> Exp_shift); +#ifndef IBM + z |= Exp_msk11; +#endif +#else + if ((de = (int)(d0 >> Exp_shift))) + z |= Exp_msk1; +#endif +#ifdef Pack_32 + if ((y = d1)) { + if ((k = lo0bits(&y))) { + x[0] = y | z << (32 - k); + z >>= k; + } + else + x[0] = y; + i = b->wds = (x[1] = z) ? 2 : 1; + } + else { +#ifdef DEBUG + if (!z) + Bug("Zero passed to d2b"); +#endif + k = lo0bits(&z); + x[0] = z; + i = b->wds = 1; + k += 32; + } +#else + if (y = d1) { + if (k = lo0bits(&y)) + if (k >= 16) { + x[0] = y | z << 32 - k & 0xffff; + x[1] = z >> k - 16 & 0xffff; + x[2] = z >> k; + i = 2; + } + else { + x[0] = y & 0xffff; + x[1] = y >> 16 | z << 16 - k & 0xffff; + x[2] = z >> k & 0xffff; + x[3] = z >> k+16; + i = 3; + } + else { + x[0] = y & 0xffff; + x[1] = y >> 16; + x[2] = z & 0xffff; + x[3] = z >> 16; + i = 3; + } + } + else { +#ifdef DEBUG + if (!z) + Bug("Zero passed to d2b"); +#endif + k = lo0bits(&z); + if (k >= 16) { + x[0] = z; + i = 0; + } + else { + x[0] = z & 0xffff; + x[1] = z >> 16; + i = 1; + } + k += 32; + } + while(!x[i]) + --i; + b->wds = i + 1; +#endif +#ifndef Sudden_Underflow + if (de) { +#endif +#ifdef IBM + *e = (de - Bias - (P-1) << 2) + k; + *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask); +#else + *e = de - Bias - (P-1) + k; + *bits = P - k; +#endif +#ifndef Sudden_Underflow + } + else { + *e = de - Bias - (P-1) + 1 + k; +#ifdef Pack_32 + *bits = 32*i - hi0bits(x[i-1]); +#else + *bits = (i+2)*16 - hi0bits(x[i]); +#endif + } +#endif + return b; + } +#undef d0 +#undef d1 + + static double +ratio +#ifdef KR_headers + (a, b) Bigint *a, *b; +#else + (Bigint *a, Bigint *b) +#endif +{ + _double da, db; + int k, ka, kb; + + value(da) = b2d(a, &ka); + value(db) = b2d(b, &kb); +#ifdef Pack_32 + k = ka - kb + 32*(a->wds - b->wds); +#else + k = ka - kb + 16*(a->wds - b->wds); +#endif +#ifdef IBM + if (k > 0) { + word0(da) += (k >> 2)*Exp_msk1; + if (k &= 3) + da *= 1 << k; + } + else { + k = -k; + word0(db) += (k >> 2)*Exp_msk1; + if (k &= 3) + db *= 1 << k; + } +#else + if (k > 0) + word0(da) += k*Exp_msk1; + else { + k = -k; + word0(db) += k*Exp_msk1; + } +#endif + return value(da) / value(db); + } + +static CONST double +tens[] = { + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, + 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, + 1e20, 1e21, 1e22 +#ifdef VAX + , 1e23, 1e24 +#endif + }; + +#ifdef IEEE_Arith +static CONST double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 }; +static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 }; +#define n_bigtens 5 +#else +#ifdef IBM +static CONST double bigtens[] = { 1e16, 1e32, 1e64 }; +static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 }; +#define n_bigtens 3 +#else +static CONST double bigtens[] = { 1e16, 1e32 }; +static CONST double tinytens[] = { 1e-16, 1e-32 }; +#define n_bigtens 2 +#endif +#endif + +ZEND_API double +zend_strtod +#ifdef KR_headers + (s00, se) CONST char *s00; char **se; +#else + (CONST char *s00, char **se) +#endif +{ + int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, + e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign; + CONST char *s, *s0, *s1; + double aadj, aadj1, adj; + _double rv, rv0; + Long L; + ULong y, z; + Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; + double result; + + CONST char decimal_point = '.'; + + sign = nz0 = nz = 0; + value(rv) = 0.; + + + for(s = s00; isspace((unsigned char) *s); s++) + ; + + if (*s == '-') { + sign = 1; + s++; + } else if (*s == '+') { + s++; + } + + if (*s == '\0') { + s = s00; + goto ret; + } + + if (*s == '0') { + nz0 = 1; + while(*++s == '0') ; + if (!*s) + goto ret; + } + s0 = s; + y = z = 0; + for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) + if (nd < 9) + y = 10*y + c - '0'; + else if (nd < 16) + z = 10*z + c - '0'; + nd0 = nd; + if (c == decimal_point) { + c = *++s; + if (!nd) { + for(; c == '0'; c = *++s) + nz++; + if (c > '0' && c <= '9') { + s0 = s; + nf += nz; + nz = 0; + goto have_dig; + } + goto dig_done; + } + for(; c >= '0' && c <= '9'; c = *++s) { + have_dig: + nz++; + if (c -= '0') { + nf += nz; + for(i = 1; i < nz; i++) + if (nd++ < 9) + y *= 10; + else if (nd <= DBL_DIG + 1) + z *= 10; + if (nd++ < 9) + y = 10*y + c; + else if (nd <= DBL_DIG + 1) + z = 10*z + c; + nz = 0; + } + } + } + dig_done: + e = 0; + if (c == 'e' || c == 'E') { + if (!nd && !nz && !nz0) { + s = s00; + goto ret; + } + s00 = s; + esign = 0; + switch(c = *++s) { + case '-': + esign = 1; + case '+': + c = *++s; + } + if (c >= '0' && c <= '9') { + while(c == '0') + c = *++s; + if (c > '0' && c <= '9') { + L = c - '0'; + s1 = s; + while((c = *++s) >= '0' && c <= '9') + L = 10*L + c - '0'; + if (s - s1 > 8 || L > 19999) + /* Avoid confusion from exponents + * so large that e might overflow. + */ + e = 19999; /* safe for 16 bit ints */ + else + e = (int)L; + if (esign) + e = -e; + } + else + e = 0; + } + else + s = s00; + } + if (!nd) { + if (!nz && !nz0) + s = s00; + goto ret; + } + e1 = e -= nf; + + /* Now we have nd0 digits, starting at s0, followed by a + * decimal point, followed by nd-nd0 digits. The number we're + * after is the integer represented by those digits times + * 10**e */ + + if (!nd0) + nd0 = nd; + k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; + value(rv) = y; + if (k > 9) + value(rv) = tens[k - 9] * value(rv) + z; + bd0 = 0; + if (nd <= DBL_DIG +#ifndef RND_PRODQUOT + && FLT_ROUNDS == 1 +#endif + ) { + if (!e) + goto ret; + if (e > 0) { + if (e <= Ten_pmax) { +#ifdef VAX + goto vax_ovfl_check; +#else + /* value(rv) = */ rounded_product(value(rv), + tens[e]); + goto ret; +#endif + } + i = DBL_DIG - nd; + if (e <= Ten_pmax + i) { + /* A fancier test would sometimes let us do + * this for larger i values. + */ + e -= i; + value(rv) *= tens[i]; +#ifdef VAX + /* VAX exponent range is so narrow we must + * worry about overflow here... + */ + vax_ovfl_check: + word0(rv) -= P*Exp_msk1; + /* value(rv) = */ rounded_product(value(rv), + tens[e]); + if ((word0(rv) & Exp_mask) + > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) + goto ovfl; + word0(rv) += P*Exp_msk1; +#else + /* value(rv) = */ rounded_product(value(rv), + tens[e]); +#endif + goto ret; + } + } +#ifndef Inaccurate_Divide + else if (e >= -Ten_pmax) { + /* value(rv) = */ rounded_quotient(value(rv), + tens[-e]); + goto ret; + } +#endif + } + e1 += nd - k; + + /* Get starting approximation = rv * 10**e1 */ + + if (e1 > 0) { + if ((i = e1 & 15)) + value(rv) *= tens[i]; + if (e1 &= ~15) { + if (e1 > DBL_MAX_10_EXP) { + ovfl: + errno = ERANGE; +#ifndef Bad_float_h + value(rv) = HUGE_VAL; +#else + /* Can't trust HUGE_VAL */ +#ifdef IEEE_Arith + word0(rv) = Exp_mask; + word1(rv) = 0; +#else + word0(rv) = Big0; + word1(rv) = Big1; +#endif +#endif + if (bd0) + goto retfree; + goto ret; + } + if (e1 >>= 4) { + for(j = 0; e1 > 1; j++, e1 >>= 1) + if (e1 & 1) + value(rv) *= bigtens[j]; + /* The last multiplication could overflow. */ + word0(rv) -= P*Exp_msk1; + value(rv) *= bigtens[j]; + if ((z = word0(rv) & Exp_mask) + > Exp_msk1*(DBL_MAX_EXP+Bias-P)) + goto ovfl; + if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) { + /* set to largest number */ + /* (Can't trust DBL_MAX) */ + word0(rv) = Big0; + word1(rv) = Big1; + } + else + word0(rv) += P*Exp_msk1; + } + + } + } + else if (e1 < 0) { + e1 = -e1; + if ((i = e1 & 15)) + value(rv) /= tens[i]; + if (e1 &= ~15) { + e1 >>= 4; + if (e1 >= 1 << n_bigtens) + goto undfl; + for(j = 0; e1 > 1; j++, e1 >>= 1) + if (e1 & 1) + value(rv) *= tinytens[j]; + /* The last multiplication could underflow. */ + value(rv0) = value(rv); + value(rv) *= tinytens[j]; + if (!value(rv)) { + value(rv) = 2.*value(rv0); + value(rv) *= tinytens[j]; + if (!value(rv)) { + undfl: + value(rv) = 0.; + errno = ERANGE; + if (bd0) + goto retfree; + goto ret; + } + word0(rv) = Tiny0; + word1(rv) = Tiny1; + /* The refinement below will clean + * this approximation up. + */ + } + } + } + + /* Now the hard part -- adjusting rv to the correct value.*/ + + /* Put digits into bd: true value = bd * 10^e */ + + bd0 = s2b(s0, nd0, nd, y); + + for(;;) { + bd = Balloc(bd0->k); + Bcopy(bd, bd0); + bb = d2b(value(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */ + bs = i2b(1); + + if (e >= 0) { + bb2 = bb5 = 0; + bd2 = bd5 = e; + } + else { + bb2 = bb5 = -e; + bd2 = bd5 = 0; + } + if (bbe >= 0) + bb2 += bbe; + else + bd2 -= bbe; + bs2 = bb2; +#ifdef Sudden_Underflow +#ifdef IBM + j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3); +#else + j = P + 1 - bbbits; +#endif +#else + i = bbe + bbbits - 1; /* logb(rv) */ + if (i < Emin) /* denormal */ + j = bbe + (P-Emin); + else + j = P + 1 - bbbits; +#endif + bb2 += j; + bd2 += j; + i = bb2 < bd2 ? bb2 : bd2; + if (i > bs2) + i = bs2; + if (i > 0) { + bb2 -= i; + bd2 -= i; + bs2 -= i; + } + if (bb5 > 0) { + bs = pow5mult(bs, bb5); + bb1 = mult(bs, bb); + Bfree(bb); + bb = bb1; + } + if (bb2 > 0) + bb = lshift(bb, bb2); + if (bd5 > 0) + bd = pow5mult(bd, bd5); + if (bd2 > 0) + bd = lshift(bd, bd2); + if (bs2 > 0) + bs = lshift(bs, bs2); + delta = diff(bb, bd); + dsign = delta->sign; + delta->sign = 0; + i = cmp(delta, bs); + if (i < 0) { + /* Error is less than half an ulp -- check for + * special case of mantissa a power of two. + */ + if (dsign || word1(rv) || word0(rv) & Bndry_mask) + break; + delta = lshift(delta,Log2P); + if (cmp(delta, bs) > 0) + goto drop_down; + break; + } + if (i == 0) { + /* exactly half-way between */ + if (dsign) { + if ((word0(rv) & Bndry_mask1) == Bndry_mask1 + && word1(rv) == 0xffffffff) { + /*boundary case -- increment exponent*/ + word0(rv) = (word0(rv) & Exp_mask) + + Exp_msk1 +#ifdef IBM + | Exp_msk1 >> 4 +#endif + ; + word1(rv) = 0; + break; + } + } + else if (!(word0(rv) & Bndry_mask) && !word1(rv)) { + drop_down: + /* boundary case -- decrement exponent */ +#ifdef Sudden_Underflow + L = word0(rv) & Exp_mask; +#ifdef IBM + if (L < Exp_msk1) +#else + if (L <= Exp_msk1) +#endif + goto undfl; + L -= Exp_msk1; +#else + L = (word0(rv) & Exp_mask) - Exp_msk1; +#endif + word0(rv) = L | Bndry_mask1; + word1(rv) = 0xffffffff; +#ifdef IBM + goto cont; +#else + break; +#endif + } +#ifndef ROUND_BIASED + if (!(word1(rv) & LSB)) + break; +#endif + if (dsign) + value(rv) += ulp(value(rv)); +#ifndef ROUND_BIASED + else { + value(rv) -= ulp(value(rv)); +#ifndef Sudden_Underflow + if (!value(rv)) + goto undfl; +#endif + } +#endif + break; + } + if ((aadj = ratio(delta, bs)) <= 2.) { + if (dsign) + aadj = aadj1 = 1.; + else if (word1(rv) || word0(rv) & Bndry_mask) { +#ifndef Sudden_Underflow + if (word1(rv) == Tiny1 && !word0(rv)) + goto undfl; +#endif + aadj = 1.; + aadj1 = -1.; + } + else { + /* special case -- power of FLT_RADIX to be */ + /* rounded down... */ + + if (aadj < 2./FLT_RADIX) + aadj = 1./FLT_RADIX; + else + aadj *= 0.5; + aadj1 = -aadj; + } + } + else { + aadj *= 0.5; + aadj1 = dsign ? aadj : -aadj; +#ifdef Check_FLT_ROUNDS + switch(FLT_ROUNDS) { + case 2: /* towards +infinity */ + aadj1 -= 0.5; + break; + case 0: /* towards 0 */ + case 3: /* towards -infinity */ + aadj1 += 0.5; + } +#else + if (FLT_ROUNDS == 0) + aadj1 += 0.5; +#endif + } + y = word0(rv) & Exp_mask; + + /* Check for overflow */ + + if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { + value(rv0) = value(rv); + word0(rv) -= P*Exp_msk1; + adj = aadj1 * ulp(value(rv)); + value(rv) += adj; + if ((word0(rv) & Exp_mask) >= + Exp_msk1*(DBL_MAX_EXP+Bias-P)) { + if (word0(rv0) == Big0 && word1(rv0) == Big1) + goto ovfl; + word0(rv) = Big0; + word1(rv) = Big1; + goto cont; + } + else + word0(rv) += P*Exp_msk1; + } + else { +#ifdef Sudden_Underflow + if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { + value(rv0) = value(rv); + word0(rv) += P*Exp_msk1; + adj = aadj1 * ulp(value(rv)); + value(rv) += adj; +#ifdef IBM + if ((word0(rv) & Exp_mask) < P*Exp_msk1) +#else + if ((word0(rv) & Exp_mask) <= P*Exp_msk1) +#endif + { + if (word0(rv0) == Tiny0 + && word1(rv0) == Tiny1) + goto undfl; + word0(rv) = Tiny0; + word1(rv) = Tiny1; + goto cont; + } + else + word0(rv) -= P*Exp_msk1; + } + else { + adj = aadj1 * ulp(value(rv)); + value(rv) += adj; + } +#else + /* Compute adj so that the IEEE rounding rules will + * correctly round rv + adj in some half-way cases. + * If rv * ulp(rv) is denormalized (i.e., + * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid + * trouble from bits lost to denormalization; + * example: 1.2e-307 . + */ + if (y <= (P-1)*Exp_msk1 && aadj >= 1.) { + aadj1 = (double)(int)(aadj + 0.5); + if (!dsign) + aadj1 = -aadj1; + } + adj = aadj1 * ulp(value(rv)); + value(rv) += adj; +#endif + } + z = word0(rv) & Exp_mask; + if (y == z) { + /* Can we stop now? */ + L = aadj; + aadj -= L; + /* The tolerances below are conservative. */ + if (dsign || word1(rv) || word0(rv) & Bndry_mask) { + if (aadj < .4999999 || aadj > .5000001) + break; + } + else if (aadj < .4999999/FLT_RADIX) + break; + } + cont: + Bfree(bb); + Bfree(bd); + Bfree(bs); + Bfree(delta); + } + retfree: + Bfree(bb); + Bfree(bd); + Bfree(bs); + Bfree(bd0); + Bfree(delta); + ret: + if (se) + *se = (char *)s; + result = sign ? -value(rv) : value(rv); + return result; + } diff --git a/Zend/zend_strtod.h b/Zend/zend_strtod.h new file mode 100644 index 000000000000..2fbaceaedde7 --- /dev/null +++ b/Zend/zend_strtod.h @@ -0,0 +1,31 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2004 Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@zend.com so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Derick Rethans | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +/* This is a header file for the strtod implementation by David M. Gay which + * can be found in zend_strtod.c */ +#ifndef ZEND_STRTOD_H +#define ZEND_STRTOD_H +#include + +BEGIN_EXTERN_C() +ZEND_API double zend_strtod(const char *s00, char **se); +END_EXTERN_C() + +#endif diff --git a/acinclude.m4 b/acinclude.m4 index 084f70cc56db..294d1deee95d 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -1,4 +1,4 @@ -dnl $Id$ +dnl $Id$ -*- autoconf -*- dnl dnl This file contains local autoconf functions. @@ -16,22 +16,36 @@ AC_DEFUN([PHP_ADD_MAKEFILE_FRAGMENT],[ sed -e "s#\$(srcdir)#$ac_srcdir#g" -e "s#\$(builddir)#$ac_builddir#g" $src >> Makefile.fragments ]) -AC_DEFUN(PHP_PROG_RE2C,[ +AC_DEFUN([PHP_PROG_RE2C],[ AC_CHECK_PROG(RE2C, re2c, re2c, [exit 0;]) ]) -dnl PHP_DEFINE(WHAT[, value]) +dnl PHP_DEFINE(WHAT[, value[, directory]]) dnl dnl Creates builddir/include/what.h and in there #define WHAT value dnl AC_DEFUN([PHP_DEFINE],[ - [echo "#define ]$1[]ifelse([$2],,[ 1],[ $2])[" > include/php_]translit($1,A-Z,a-z)[.h] + [echo "#define ]$1[]ifelse([$2],,[ 1],[ $2])[" > ]ifelse([$3],,[include],[$3])[/php_]translit($1,A-Z,a-z)[.h] +]) + +dnl PHP_CANONICAL_HOST +dnl +AC_DEFUN([PHP_CANONICAL_HOST],[ + AC_REQUIRE([AC_CANONICAL_HOST])dnl + dnl Make sure we do not continue if host_alias is empty. + if test -z "$host_alias" && test -n "$host"; then + host_alias=$host + fi + if test -z "$host_alias"; then + AC_MSG_ERROR([host_alias is not set!]) + fi ]) dnl PHP_INIT_BUILD_SYSTEM dnl AC_DEFUN([PHP_INIT_BUILD_SYSTEM],[ +AC_REQUIRE([PHP_CANONICAL_HOST])dnl test -d include || mkdir include > Makefile.objects > Makefile.fragments @@ -132,7 +146,7 @@ dnl choose the right compiler/flags/etc. for the source-file *.c[)] ac_comp="$b_c_pre $3 $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $6$b_c_post" ;; *.s[)] ac_comp="$b_c_pre $3 $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $6$b_c_post" ;; *.S[)] ac_comp="$b_c_pre $3 $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $6$b_c_post" ;; - *.cpp[)] ac_comp="$b_cxx_pre $3 $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $6$b_cxx_post" ;; + *.cpp|*.cc[)] ac_comp="$b_cxx_pre $3 $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $6$b_cxx_post" ;; esac dnl create a rule for the object/source combo @@ -273,6 +287,7 @@ int readdir_r(DIR *, struct dirent *); ]) AC_DEFUN([PHP_SHLIB_SUFFIX_NAME],[ + AC_REQUIRE([PHP_CANONICAL_HOST])dnl PHP_SUBST(SHLIB_SUFFIX_NAME) SHLIB_SUFFIX_NAME=so case $host_alias in @@ -771,12 +786,17 @@ AC_DEFUN([PHP_BUILD_PROGRAM],[ php_cxx_meta='$(COMMON_FLAGS) $(CXXFLAGS_CLEAN) $(EXTRA_CXXFLAGS)' php_cxx_post=' && echo > $[@]' php_lo=o - + + case $with_pic in + yes) pic_setting='-prefer-pic';; + no) pic_setting='-prefer-non-pic';; + esac + shared_c_pre='$(LIBTOOL) --mode=compile $(CC)' - shared_c_meta='$(COMMON_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) -prefer-pic' + shared_c_meta='$(COMMON_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) '$pic_setting shared_c_post= shared_cxx_pre='$(LIBTOOL) --mode=compile $(CXX)' - shared_cxx_meta='$(COMMON_FLAGS) $(CXXFLAGS_CLEAN) $(EXTRA_CXXFLAGS) -prefer-pic' + shared_cxx_meta='$(COMMON_FLAGS) $(CXXFLAGS_CLEAN) $(EXTRA_CXXFLAGS) '$pic_setting shared_cxx_post= shared_lo=lo @@ -1066,20 +1086,33 @@ AC_DEFUN([PHP_CHECK_CC_OPTION],[ rm -rf conftest* ]) -AC_DEFUN([PHP_REGEX],[ -if test "$REGEX_TYPE" = "php"; then - AC_DEFINE(HSREGEX,1,[ ]) - AC_DEFINE(REGEX,1,[ ]) - PHP_ADD_SOURCES(regex, regcomp.c regexec.c regerror.c regfree.c) -elif test "$REGEX_TYPE" = "system"; then - AC_DEFINE(REGEX,0,[ ]) -fi - -AC_MSG_CHECKING([which regex library to use]) -AC_MSG_RESULT([$REGEX_TYPE]) +dnl +dnl PHP_REGEX +dnl +AC_DEFUN([PHP_REGEX],[ + if test "$REGEX_TYPE" = "php"; then + AC_DEFINE(HAVE_REGEX_T_RE_MAGIC, 1, [ ]) + AC_DEFINE(HSREGEX,1,[ ]) + AC_DEFINE(REGEX,1,[ ]) + PHP_ADD_SOURCES(regex, regcomp.c regexec.c regerror.c regfree.c) + elif test "$REGEX_TYPE" = "system"; then + AC_DEFINE(REGEX,0,[ ]) + dnl Check if field re_magic exists in struct regex_t + AC_CACHE_CHECK([whether field re_magic exists in struct regex_t], ac_cv_regex_t_re_magic, [ + AC_TRY_COMPILE([#include +#include ], [regex_t rt; rt.re_magic;], + [ac_cv_regex_t_re_magic=yes], [ac_cv_regex_t_re_magic=no]) + ]) + if test "$ac_cv_regex_t_re_magic" = "yes"; then + AC_DEFINE([HAVE_REGEX_T_RE_MAGIC], [ ], 1) + fi + fi + AC_MSG_CHECKING([which regex library to use]) + AC_MSG_RESULT([$REGEX_TYPE]) ]) + dnl dnl See if we have broken header files like SunOS has. dnl @@ -1156,14 +1189,30 @@ dnl from object_var in build-dir. dnl AC_DEFUN([PHP_SHARED_MODULE],[ install_modules="install-modules" - PHP_MODULES="$PHP_MODULES \$(phplibdir)/$1.la" + + case $host_alias in + *darwin*[)] + suffix=so + link_cmd='ifelse($4,,[$(CC)],[$(CXX)]) -dynamic -flat_namespace -bundle -undefined suppress $(COMMON_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) $(LDFLAGS) -o [$]@ $(EXTRA_LDFLAGS) $($2) $(translit($1,a-z_-,A-Z__)_SHARED_LIBADD)' + ;; + *netware*[)] + suffix=nlm + link_cmd='$(LIBTOOL) --mode=link ifelse($4,,[$(CC)],[$(CXX)]) $(COMMON_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) $(LDFLAGS) -o [$]@ -shared -export-dynamic -avoid-version -prefer-pic -module -rpath $(phplibdir) $(EXTRA_LDFLAGS) $($2) $(translit($1,a-z_-,A-Z__)_SHARED_LIBADD)' + ;; + *[)] + suffix=la + link_cmd='$(LIBTOOL) --mode=link ifelse($4,,[$(CC)],[$(CXX)]) $(COMMON_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) $(LDFLAGS) -o [$]@ -export-dynamic -avoid-version -prefer-pic -module -rpath $(phplibdir) $(EXTRA_LDFLAGS) $($2) $(translit($1,a-z_-,A-Z__)_SHARED_LIBADD)' + ;; + esac + + PHP_MODULES="$PHP_MODULES \$(phplibdir)/$1.$suffix" PHP_SUBST($2) cat >>Makefile.objects< ext/iconv/php_have_bsd_iconv.h + echo > ext/iconv/php_have_glibc_iconv.h + echo > ext/iconv/php_have_libiconv.h + echo > ext/iconv/php_have_iconv.h + echo > ext/iconv/php_php_iconv_impl.h + echo > ext/iconv/php_php_iconv_h_path.h + echo > ext/iconv/php_iconv_supports_errno.h + dnl dnl Check libc first if no path is provided in --with-iconv dnl if test "$PHP_ICONV" = "yes"; then AC_CHECK_FUNC(iconv, [ - PHP_DEFINE(HAVE_ICONV) + PHP_DEFINE(HAVE_ICONV,1,[ext/iconv]) found_iconv=yes ],[ AC_CHECK_FUNC(libiconv,[ - PHP_DEFINE(HAVE_LIBICONV) + PHP_DEFINE(HAVE_LIBICONV,1,[ext/iconv]) found_iconv=yes ]) ]) @@ -1737,11 +1873,11 @@ AC_DEFUN([PHP_SETUP_ICONV], [ then PHP_CHECK_LIBRARY($iconv_lib_name, libiconv, [ found_iconv=yes - PHP_DEFINE(HAVE_LIBICONV) + PHP_DEFINE(HAVE_LIBICONV,1,[ext/iconv]) ], [ PHP_CHECK_LIBRARY($iconv_lib_name, iconv, [ found_iconv=yes - PHP_DEFINE(HAVE_ICONV) + PHP_DEFINE(HAVE_ICONV,1,[ext/iconv]) ], [], [ -L$ICONV_DIR/lib ]) @@ -1900,7 +2036,7 @@ dnl dnl PHP_TEST_BUILD(function, action-if-ok, action-if-not-ok [, extra-libs [, extra-source]]) dnl This macro checks whether build works and given function exists. dnl -AC_DEFUN(PHP_TEST_BUILD, [ +AC_DEFUN([PHP_TEST_BUILD], [ old_LIBS=$LIBS LIBS="$4 $LIBS" AC_TRY_RUN([ @@ -1920,3 +2056,62 @@ AC_DEFUN(PHP_TEST_BUILD, [ LIBS=$old_LIBS ]) ]) + +dnl This macro is currently a placeholder in the config.m4 file +dnl it is scanned by genif.sh when it builds the internal functions +dnl list, so that modules can be init'd in the correct order +dnl $1 = name of extension, $2 = extension upon which it depends +dnl $3 = optional: if true, it's ok for $2 to have not been configured +dnl default is false and should halt the build. +dnl See ADD_EXTENSION_DEP in win32 build +AC_DEFUN([PHP_ADD_EXTENSION_DEP], []) + + +dnl +dnl PHP_C_BIGENDIAN +dnl Replacement macro for AC_C_BIGENDIAN +dnl +AC_DEFUN([PHP_C_BIGENDIAN], +[AC_CACHE_CHECK([whether byte ordering is bigendian], ac_cv_c_bigendian_php, + [ + ac_cv_c_bigendian_php=unknown + AC_TRY_RUN( + [ +int main(void) +{ + short one = 1; + char *cp = (char *)&one; + + if (*cp == 0) { + return(0); + } else { + return(1); + } +} + ], [ac_cv_c_bigendian_php=yes], [ac_cv_c_bigendian_php=no], [ac_cv_c_bigendian_php=unknown]) + ]) + if test $ac_cv_c_bigendian_php = yes; then + AC_DEFINE(WORDS_BIGENDIAN, [], [Define if processor uses big-endian word]) + fi +]) + +dnl +dnl PHP_CHECK_PDO_INCLUDES([found [, not-found]]) +dnl +AC_DEFUN([PHP_CHECK_PDO_INCLUDES],[ + AC_CACHE_CHECK([for PDO includes], pdo_inc_path, [ + AC_MSG_CHECKING([for PDO includes]) + if test -f $abs_srcdir/include/php/ext/pdo/php_pdo_driver.h; then + pdo_inc_path=$abs_srcdir/ext + elif test -f $abs_srcdir/ext/pdo/php_pdo_driver.h; then + pdo_inc_path=$abs_srcdir/ext + elif test -f $prefix/include/php/ext/pdo/php_pdo_driver.h; then + pdo_inc_path=$prefix/include/php/ext + fi + ]) + if test -n "$pdo_inc_path"; then +ifelse([$1],[],:,[$1]) + else +ifelse([$2],[],[AC_MSG_ERROR([Cannot find php_pdo_driver.h.])],[$2]) + fi +]) diff --git a/build/build2.mk b/build/build2.mk index 9b3d538d196a..6de26fcad813 100644 --- a/build/build2.mk +++ b/build/build2.mk @@ -32,6 +32,10 @@ acconfig_h_SOURCES = acconfig.h.in $(config_h_files) targets = $(TOUCH_FILES) configure $(config_h_in) +PHP_AUTOCONF ?= 'autoconf' +PHP_AUTOHEADER ?= 'autoheader' + +SUPPRESS_WARNINGS ?= 2>&1 | (egrep -v '(AC_TRY_RUN called without default to allow cross compiling|AC_PROG_CXXCPP was called before AC_PROG_CXX|defined in acinclude.m4 but never used|AC_PROG_LEX invoked multiple times|AC_DECL_YYTEXT is expanded from...|the top level)'||true) all: $(targets) @@ -39,26 +43,21 @@ acconfig.h: $(acconfig_h_SOURCES) @echo rebuilding $@ cat $(acconfig_h_SOURCES) > $@ -SUPPRESS_WARNINGS = (egrep -v '(AC_TRY_RUN called without default to allow cross compiling|AC_PROG_CXXCPP was called before AC_PROG_CXX|defined in acinclude.m4 but never used|AC_PROG_LEX invoked multiple times)'||true) - $(config_h_in): configure acconfig.h # explicitly remove target since autoheader does not seem to work # correctly otherwise (timestamps are not updated) @echo rebuilding $@ @rm -f $@ - @autoheader 2>&1 | $(SUPPRESS_WARNINGS) + $(PHP_AUTOHEADER) $(SUPPRESS_WARNINGS) $(TOUCH_FILES): touch $(TOUCH_FILES) aclocal.m4: configure.in acinclude.m4 @echo rebuilding $@ - @libtoolize=`./build/shtool path glibtoolize libtoolize`; \ - $$libtoolize --copy --automake; \ - ltpath=`dirname $$libtoolize`; \ - ltfile=`cd $$ltpath/../share/aclocal; pwd`/libtool.m4; \ - cat acinclude.m4 $$ltfile > $@ + cat acinclude.m4 ./build/libtool.m4 > $@ configure: aclocal.m4 configure.in $(config_m4_files) @echo rebuilding $@ - @autoconf 2>&1 | $(SUPPRESS_WARNINGS) + $(PHP_AUTOCONF) $(SUPPRESS_WARNINGS) + diff --git a/build/buildcheck.sh b/build/buildcheck.sh index aed6126b5e30..1e24ce879280 100755 --- a/build/buildcheck.sh +++ b/build/buildcheck.sh @@ -16,15 +16,20 @@ # | Sascha Schumann | # +----------------------------------------------------------------------+ # -# $Id: buildcheck.sh,v 1.30 2004-01-08 17:31:49 sniper Exp $ +# $Id: buildcheck.sh,v 1.30.2.6 2005-04-07 23:33:37 jon Exp $ # echo "buildconf: checking installation..." stamp=$1 +# Allow the autoconf executable to be overridden by $PHP_AUTOCONF. +if test -z "$PHP_AUTOCONF"; then + PHP_AUTOCONF='autoconf' +fi + # autoconf 2.13 or newer -ac_version=`autoconf --version 2>/dev/null|head -n 1|sed -e 's/^[^0-9]*//' -e 's/[a-z]* *$//'` +ac_version=`$PHP_AUTOCONF --version 2>/dev/null|head -n 1|sed -e 's/^[^0-9]*//' -e 's/[a-z]* *$//'` if test -z "$ac_version"; then echo "buildconf: autoconf not found." echo " You need autoconf version 2.13 or newer installed" @@ -41,7 +46,6 @@ else echo "buildconf: autoconf version $ac_version (ok)" fi - if test "$1" = "2" && test "$2" -ge "50"; then echo "buildconf: Your version of autoconf likely contains buggy cache code." echo " Running cvsclean for you." @@ -50,44 +54,6 @@ if test "$1" = "2" && test "$2" -ge "50"; then stamp= fi -# libtoolize 1.4.3 or newer -# Prefer glibtoolize over libtoolize for Mac OS X compatibility -libtoolize=`./build/shtool path glibtoolize libtoolize 2> /dev/null` -lt_pversion=`$libtoolize --version 2>/dev/null|head -n 1|sed -e 's/^[^0-9]*//'` -if test "$lt_pversion" = ""; then -echo "buildconf: libtool not found." -echo " You need libtool version 1.4.3 or newer installed" -echo " to build PHP from CVS." -exit 1 -fi -IFS=.; set $lt_pversion; IFS=' ' - -if test "$3" = ""; then - third=0 -else - third=$3 -fi - -if test "$1" -gt "1" || test "$2" -ge "5" || (test "$2" -ge "4" && test "$third" -ge "3") -then -echo "buildconf: libtool version $lt_pversion (ok)" -else -echo "buildconf: libtool version $lt_pversion found." -echo " You need libtool version 1.4.3 or newer installed" -echo " to build PHP from CVS." -exit 1 -fi - -ltpath=`echo $libtoolize | sed -e 's#/[^/]*/[^/]*$##'` -ltfile="$ltpath/share/aclocal/libtool.m4" -if test -r "$ltfile"; then - : -else - echo "buildconf: $ltfile does not exist." - echo " Please reinstall libtool." - exit 1 -fi - test -n "$stamp" && touch $stamp exit 0 diff --git a/build/libtool.m4 b/build/libtool.m4 new file mode 100644 index 000000000000..41adb2b9e740 --- /dev/null +++ b/build/libtool.m4 @@ -0,0 +1,3713 @@ +# libtool.m4 - Configure libtool for the host system. -*-Shell-script-*- +## Copyright 1996, 1997, 1998, 1999, 2000, 2001 +## Free Software Foundation, Inc. +## Originally by Gordon Matzigkeit , 1996 +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +## +## As a special exception to the GNU General Public License, if you +## distribute this file as part of a program that contains a +## configuration script generated by Autoconf, you may include it under +## the same distribution terms that you use for the rest of that program. + +# serial 46 AC_PROG_LIBTOOL + +AC_DEFUN([AC_PROG_LIBTOOL], +[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +# Prevent multiple expansion +define([AC_PROG_LIBTOOL], []) +]) + +AC_DEFUN([AC_LIBTOOL_SETUP], +[AC_PREREQ(2.13)dnl +AC_REQUIRE([AC_ENABLE_SHARED])dnl +AC_REQUIRE([AC_ENABLE_STATIC])dnl +AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_LD])dnl +AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl +AC_REQUIRE([AC_PROG_NM])dnl +AC_REQUIRE([LT_AC_PROG_SED])dnl + +AC_REQUIRE([AC_PROG_LN_S])dnl +AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl +AC_REQUIRE([AC_OBJEXT])dnl +AC_REQUIRE([AC_EXEEXT])dnl +dnl + +_LT_AC_PROG_ECHO_BACKSLASH +# Only perform the check for file, if the check method requires it +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + AC_PATH_MAGIC + fi + ;; +esac + +AC_CHECK_TOOL(RANLIB, ranlib, :) +AC_CHECK_TOOL(STRIP, strip, :) + +ifdef([AC_PROVIDE_AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) +ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL], +enable_win32_dll=yes, enable_win32_dll=no) + +AC_ARG_ENABLE(libtool-lock, + [ --disable-libtool-lock avoid locking (might break parallel builds)]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_SAVE + AC_LANG_C + AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_RESTORE]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; + +ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL], +[*-*-cygwin* | *-*-mingw* | *-*-pw32*) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + + # recent cygwin and mingw systems supply a stub DllMain which the user + # can override, but on older systems we have to supply one + AC_CACHE_CHECK([if libtool should supply DllMain function], lt_cv_need_dllmain, + [AC_TRY_LINK([], + [extern int __attribute__((__stdcall__)) DllMain(void*, int, void*); + DllMain (0, 0, 0);], + [lt_cv_need_dllmain=no],[lt_cv_need_dllmain=yes])]) + + case $host/$CC in + *-*-cygwin*/gcc*-mno-cygwin*|*-*-mingw*) + # old mingw systems require "-dll" to link a DLL, while more recent ones + # require "-mdll" + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -mdll" + AC_CACHE_CHECK([how to link DLLs], lt_cv_cc_dll_switch, + [AC_TRY_LINK([], [], [lt_cv_cc_dll_switch=-mdll],[lt_cv_cc_dll_switch=-dll])]) + CFLAGS="$SAVE_CFLAGS" ;; + *-*-cygwin* | *-*-pw32*) + # cygwin systems need to pass --dll to the linker, and not link + # crt.o which will require a WinMain@16 definition. + lt_cv_cc_dll_switch="-Wl,--dll -nostartfiles" ;; + esac + ;; + ]) +esac + +_LT_AC_LTCONFIG_HACK + +]) + +# AC_LIBTOOL_HEADER_ASSERT +# ------------------------ +AC_DEFUN([AC_LIBTOOL_HEADER_ASSERT], +[AC_CACHE_CHECK([whether $CC supports assert without backlinking], + [lt_cv_func_assert_works], + [case $host in + *-*-solaris*) + if test "$GCC" = yes && test "$with_gnu_ld" != yes; then + case `$CC --version 2>/dev/null` in + [[12]].*) lt_cv_func_assert_works=no ;; + *) lt_cv_func_assert_works=yes ;; + esac + fi + ;; + esac]) + +if test "x$lt_cv_func_assert_works" = xyes; then + AC_CHECK_HEADERS(assert.h) +fi +])# AC_LIBTOOL_HEADER_ASSERT + +# _LT_AC_CHECK_DLFCN +# -------------------- +AC_DEFUN([_LT_AC_CHECK_DLFCN], +[AC_CHECK_HEADERS(dlfcn.h) +])# _LT_AC_CHECK_DLFCN + +# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +# --------------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], +[AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_NM]) +AC_REQUIRE([AC_OBJEXT]) +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [dnl + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Transform the above into a raw symbol and a C symbol. +symxfrm='\1 \2\3 \3' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) # Its linker distinguishes data from code symbols + lt_cv_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris* | sysv5*) + symcode='[[BDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $host_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then + symcode='[[ABCDGISTW]]' +fi + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Write the raw and C identifiers. +lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + rm -f conftest* + cat > conftest.$ac_ext < $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if egrep ' nm_test_var$' "$nlist" >/dev/null; then + if egrep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_global_symbol_to_cdecl"' < "$nlist" >> conftest.$ac_ext' + + cat <> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr void * +#else +# define lt_ptr char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr address; +} +lt_preloaded_symbols[[]] = +{ +EOF + sed "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr) \&\2},/" < "$nlist" >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$no_builtin_flag" + if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&AC_FD_CC + fi + else + echo "cannot find nm_test_var in $nlist" >&AC_FD_CC + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AC_FD_CC + fi + else + echo "$progname: failed program was:" >&AC_FD_CC + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +global_symbol_pipe="$lt_cv_sys_global_symbol_pipe" +if test -z "$lt_cv_sys_global_symbol_pipe"; then + global_symbol_to_cdecl= + global_symbol_to_c_name_address= +else + global_symbol_to_cdecl="$lt_cv_global_symbol_to_cdecl" + global_symbol_to_c_name_address="$lt_cv_global_symbol_to_c_name_address" +fi +if test -z "$global_symbol_pipe$global_symbol_to_cdec$global_symbol_to_c_name_address"; +then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi +]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE + +# _LT_AC_LIBTOOL_SYS_PATH_SEPARATOR +# --------------------------------- +AC_DEFUN([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR], +[# Find the correct PATH separator. Usually this is `:', but +# DJGPP uses `;' like DOS. +if test "X${PATH_SEPARATOR+set}" != Xset; then + UNAME=${UNAME-`uname 2>/dev/null`} + case X$UNAME in + *-DOS) lt_cv_sys_path_separator=';' ;; + *) lt_cv_sys_path_separator=':' ;; + esac + PATH_SEPARATOR=$lt_cv_sys_path_separator +fi +])# _LT_AC_LIBTOOL_SYS_PATH_SEPARATOR + +# _LT_AC_PROG_ECHO_BACKSLASH +# -------------------------- +# Add some code to the start of the generated configure script which +# will find an echo command which doesn't interpret backslashes. +AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], +[ifdef([AC_DIVERSION_NOTICE], [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], + [AC_DIVERT_PUSH(NOTICE)]) +_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR + +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` + ;; +esac + +echo=${ECHO-echo} +if test "X[$]1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X[$]1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} +fi + +if test "X[$]1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null && + echo_test_string="`eval $cmd`" && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null + then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : +else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + IFS="${IFS= }"; save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} + else + # Try using printf. + echo='printf %s\n' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL [$]0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$CONFIG_SHELL [$]0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "[$]0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +ECHO=$echo +if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then + ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" +fi + +AC_SUBST(ECHO) +AC_DIVERT_POP +])# _LT_AC_PROG_ECHO_BACKSLASH + +# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ------------------------------------------------------------------ +AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], +[if test "$cross_compiling" = yes; then : + [$4] +else + AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + + exit (status); +}] +EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_unknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_AC_TRY_DLOPEN_SELF + +# AC_LIBTOOL_DLOPEN_SELF +# ------------------- +AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], +[if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + cygwin* | mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + LDFLAGS="$LDFLAGS $link_static_flag" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +])# AC_LIBTOOL_DLOPEN_SELF + +AC_DEFUN([_LT_AC_LTCONFIG_HACK], +[AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])dnl +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e s/^X//' +sed_quote_subst='s/\([[\\"\\`$\\\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([[\\"\\`\\\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Constants: +rm="rm -f" + +# Global variables: +default_ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except M$VC, +# which needs '.lib'). +libext=a +ltmain="$ac_aux_dir/ltmain.sh" +ofile="$default_ofile" +with_gnu_ld="$lt_cv_prog_gnu_ld" +need_locks="$enable_libtool_lock" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +test -z "$AS" && AS=as +test -z "$CC" && CC=cc +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$LD" && LD=ld +test -z "$LN_S" && LN_S="ln -s" +test -z "$MAGIC_CMD" && MAGIC_CMD=file +test -z "$NM" && NM=nm +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$RANLIB" && RANLIB=: +test -z "$STRIP" && STRIP=: +test -z "$ac_objext" && ac_objext=o + +if test x"$host" != x"$build"; then + ac_tool_prefix=${host_alias}- +else + ac_tool_prefix= +fi + +# Transform linux* to *-*-linux-gnu*, to support old configure scripts. +case $host_os in +linux-gnu*) ;; +linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'` +esac + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds" + ;; + *) + old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +# Allow CC to be a program name with arguments. +set dummy $CC +compiler="[$]2" + +## FIXME: this should be a separate macro +## +AC_MSG_CHECKING([for objdir]) +rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + objdir=_libs +fi +rmdir .libs 2>/dev/null +AC_MSG_RESULT($objdir) +## +## END FIXME + + +## FIXME: this should be a separate macro +## +AC_ARG_WITH(pic, +[ --with-pic try to use only PIC/non-PIC objects [default=use both]], +pic_mode="$withval", pic_mode=default) +test -z "$pic_mode" && pic_mode=default + +# We assume here that the value for lt_cv_prog_cc_pic will not be cached +# in isolation, and that seeing it set (from the cache) indicates that +# the associated values are set (in the cache) correctly too. +AC_MSG_CHECKING([for $compiler option to produce PIC]) +AC_CACHE_VAL(lt_cv_prog_cc_pic, +[ lt_cv_prog_cc_pic= + lt_cv_prog_cc_shlib= + lt_cv_prog_cc_wl= + lt_cv_prog_cc_static= + lt_cv_prog_cc_no_builtin= + lt_cv_prog_cc_can_build_shared=$can_build_shared + + if test "$GCC" = yes; then + lt_cv_prog_cc_wl='-Wl,' + lt_cv_prog_cc_static='-static' + + case $host_os in + aix*) + # Below there is a dirty hack to force normal static linking with -ldl + # The problem is because libdl dynamically linked with both libc and + # libC (AIX C++ library), which obviously doesn't included in libraries + # list by gcc. This cause undefined symbols with -static flags. + # This hack allows C programs to be linked with "-static -ldl", but + # not sure about C++ programs. + lt_cv_prog_cc_static="$lt_cv_prog_cc_static ${lt_cv_prog_cc_wl}-lC" + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_cv_prog_cc_pic='-m68020 -resident32 -malways-restore-a4' + ;; + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_cv_prog_cc_pic='-fno-common' + ;; + cygwin* | mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_cv_prog_cc_pic='-DDLL_EXPORT' + ;; + sysv4*MP*) + if test -d /usr/nec; then + lt_cv_prog_cc_pic=-Kconform_pic + fi + ;; + *) + lt_cv_prog_cc_pic='-fPIC' + ;; + esac + else + # PORTME Check for PIC flags for the system compiler. + case $host_os in + aix3* | aix4* | aix5*) + lt_cv_prog_cc_wl='-Wl,' + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_cv_prog_cc_static='-Bstatic' + else + lt_cv_prog_cc_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + hpux9* | hpux10* | hpux11*) + # Is there a better lt_cv_prog_cc_static that works with the bundled CC? + lt_cv_prog_cc_wl='-Wl,' + lt_cv_prog_cc_static="${lt_cv_prog_cc_wl}-a ${lt_cv_prog_cc_wl}archive" + lt_cv_prog_cc_pic='+Z' + ;; + + irix5* | irix6* | nonstopux*) + lt_cv_prog_cc_wl='-Wl,' + lt_cv_prog_cc_static='-non_shared' + # PIC (with -KPIC) is the default. + ;; + + cygwin* | mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_cv_prog_cc_pic='-DDLL_EXPORT' + ;; + + newsos6) + lt_cv_prog_cc_pic='-KPIC' + lt_cv_prog_cc_static='-Bstatic' + ;; + + osf3* | osf4* | osf5*) + # All OSF/1 code is PIC. + lt_cv_prog_cc_wl='-Wl,' + lt_cv_prog_cc_static='-non_shared' + ;; + + sco3.2v5*) + lt_cv_prog_cc_pic='-Kpic' + lt_cv_prog_cc_static='-dn' + lt_cv_prog_cc_shlib='-belf' + ;; + + solaris*) + lt_cv_prog_cc_pic='-KPIC' + lt_cv_prog_cc_static='-Bstatic' + lt_cv_prog_cc_wl='-Wl,' + ;; + + sunos4*) + lt_cv_prog_cc_pic='-PIC' + lt_cv_prog_cc_static='-Bstatic' + lt_cv_prog_cc_wl='-Qoption ld ' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + lt_cv_prog_cc_pic='-KPIC' + lt_cv_prog_cc_static='-Bstatic' + lt_cv_prog_cc_wl='-Wl,' + ;; + + uts4*) + lt_cv_prog_cc_pic='-pic' + lt_cv_prog_cc_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_cv_prog_cc_pic='-Kconform_pic' + lt_cv_prog_cc_static='-Bstatic' + fi + ;; + + *) + lt_cv_prog_cc_can_build_shared=no + ;; + esac + fi +]) +if test -z "$lt_cv_prog_cc_pic"; then + AC_MSG_RESULT([none]) +else + AC_MSG_RESULT([$lt_cv_prog_cc_pic]) + + # Check to make sure the pic_flag actually works. + AC_MSG_CHECKING([if $compiler PIC flag $lt_cv_prog_cc_pic works]) + AC_CACHE_VAL(lt_cv_prog_cc_pic_works, [dnl + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $lt_cv_prog_cc_pic -DPIC" + AC_TRY_COMPILE([], [], [dnl + case $host_os in + hpux9* | hpux10* | hpux11*) + # On HP-UX, both CC and GCC only warn that PIC is supported... then + # they create non-PIC objects. So, if there were any warnings, we + # assume that PIC is not supported. + if test -s conftest.err; then + lt_cv_prog_cc_pic_works=no + else + lt_cv_prog_cc_pic_works=yes + fi + ;; + *) + lt_cv_prog_cc_pic_works=yes + ;; + esac + ], [dnl + lt_cv_prog_cc_pic_works=no + ]) + CFLAGS="$save_CFLAGS" + ]) + + if test "X$lt_cv_prog_cc_pic_works" = Xno; then + lt_cv_prog_cc_pic= + lt_cv_prog_cc_can_build_shared=no + else + lt_cv_prog_cc_pic=" $lt_cv_prog_cc_pic" + fi + + AC_MSG_RESULT([$lt_cv_prog_cc_pic_works]) +fi +## +## END FIXME + +# Check for any special shared library compilation flags. +if test -n "$lt_cv_prog_cc_shlib"; then + AC_MSG_WARN([\`$CC' requires \`$lt_cv_prog_cc_shlib' to build shared libraries]) + if echo "$old_CC $old_CFLAGS " | egrep -e "[[ ]]$lt_cv_prog_cc_shlib[[ ]]" >/dev/null; then : + else + AC_MSG_WARN([add \`$lt_cv_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure]) + lt_cv_prog_cc_can_build_shared=no + fi +fi + +## FIXME: this should be a separate macro +## +AC_MSG_CHECKING([if $compiler static flag $lt_cv_prog_cc_static works]) +AC_CACHE_VAL([lt_cv_prog_cc_static_works], [dnl + lt_cv_prog_cc_static_works=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_cv_prog_cc_static" + AC_TRY_LINK([], [], [lt_cv_prog_cc_static_works=yes]) + LDFLAGS="$save_LDFLAGS" +]) + +# Belt *and* braces to stop my trousers falling down: +test "X$lt_cv_prog_cc_static_works" = Xno && lt_cv_prog_cc_static= +AC_MSG_RESULT([$lt_cv_prog_cc_static_works]) + +pic_flag="$lt_cv_prog_cc_pic" +special_shlib_compile_flags="$lt_cv_prog_cc_shlib" +wl="$lt_cv_prog_cc_wl" +link_static_flag="$lt_cv_prog_cc_static" +no_builtin_flag="$lt_cv_prog_cc_no_builtin" +can_build_shared="$lt_cv_prog_cc_can_build_shared" +## +## END FIXME + + +## FIXME: this should be a separate macro +## +# Check to see if options -o and -c are simultaneously supported by compiler +AC_MSG_CHECKING([if $compiler supports -c -o file.$ac_objext]) +AC_CACHE_VAL([lt_cv_compiler_c_o], [ +$rm -r conftest 2>/dev/null +mkdir conftest +cd conftest +echo "int some_variable = 0;" > conftest.$ac_ext +mkdir out +# According to Tom Tromey, Ian Lance Taylor reported there are C compilers +# that will create temporary files in the current directory regardless of +# the output directory. Thus, making CWD read-only will cause this test +# to fail, enabling locking or at least warning the user not to do parallel +# builds. +chmod -w . +save_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -o out/conftest2.$ac_objext" +compiler_c_o=no +if { (eval echo configure:__oline__: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s out/conftest.err; then + lt_cv_compiler_c_o=no + else + lt_cv_compiler_c_o=yes + fi +else + # Append any errors to the config.log. + cat out/conftest.err 1>&AC_FD_CC + lt_cv_compiler_c_o=no +fi +CFLAGS="$save_CFLAGS" +chmod u+w . +$rm conftest* out/* +rmdir out +cd .. +rmdir conftest +$rm -r conftest 2>/dev/null +]) +compiler_c_o=$lt_cv_compiler_c_o +AC_MSG_RESULT([$compiler_c_o]) + +if test x"$compiler_c_o" = x"yes"; then + # Check to see if we can write to a .lo + AC_MSG_CHECKING([if $compiler supports -c -o file.lo]) + AC_CACHE_VAL([lt_cv_compiler_o_lo], [ + lt_cv_compiler_o_lo=no + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -c -o conftest.lo" + save_objext="$ac_objext" + ac_objext=lo + AC_TRY_COMPILE([], [int some_variable = 0;], [dnl + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + lt_cv_compiler_o_lo=no + else + lt_cv_compiler_o_lo=yes + fi + ]) + ac_objext="$save_objext" + CFLAGS="$save_CFLAGS" + ]) + compiler_o_lo=$lt_cv_compiler_o_lo + AC_MSG_RESULT([$compiler_o_lo]) +else + compiler_o_lo=no +fi +## +## END FIXME + +## FIXME: this should be a separate macro +## +# Check to see if we can do hard links to lock some files if needed +hard_links="nottested" +if test "$compiler_c_o" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([\`$CC' does not support \`-c -o', so \`make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +## +## END FIXME + +## FIXME: this should be a separate macro +## +if test "$GCC" = yes; then + # Check to see if options -fno-rtti -fno-exceptions are supported by compiler + AC_MSG_CHECKING([if $compiler supports -fno-rtti -fno-exceptions]) + echo "int some_variable = 0;" > conftest.$ac_ext + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.$ac_ext" + compiler_rtti_exceptions=no + AC_TRY_COMPILE([], [int some_variable = 0;], [dnl + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + compiler_rtti_exceptions=no + else + compiler_rtti_exceptions=yes + fi + ]) + CFLAGS="$save_CFLAGS" + AC_MSG_RESULT([$compiler_rtti_exceptions]) + + if test "$compiler_rtti_exceptions" = "yes"; then + no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions' + else + no_builtin_flag=' -fno-builtin' + fi +fi +## +## END FIXME + +## FIXME: this should be a separate macro +## +# See if the linker supports building shared libraries. +AC_MSG_CHECKING([whether the linker ($LD) supports shared libraries]) + +allow_undefined_flag= +no_undefined_flag= +need_lib_prefix=unknown +need_version=unknown +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +archive_cmds= +archive_expsym_cmds= +old_archive_from_new_cmds= +old_archive_from_expsyms_cmds= +export_dynamic_flag_spec= +whole_archive_flag_spec= +thread_safe_flag_spec= +hardcode_into_libs=no +hardcode_libdir_flag_spec= +hardcode_libdir_separator= +hardcode_direct=no +hardcode_minus_L=no +hardcode_shlibpath_var=unsupported +runpath_var= +link_all_deplibs=unknown +always_export_symbols=no +export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols' +# include_expsyms should be a list of space-separated symbols to be *always* +# included in the symbol list +include_expsyms= +# exclude_expsyms can be an egrep regular expression of symbols to exclude +# it will be wrapped by ` (' and `)$', so one must not match beginning or +# end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', +# as well as any symbol that contains `d'. +exclude_expsyms="_GLOBAL_OFFSET_TABLE_" +# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out +# platforms (ab)use it in PIC code, but their linkers get confused if +# the symbol is explicitly referenced. Since portable code cannot +# rely on this symbol name, it's probably fine to never include it in +# preloaded symbol tables. +extract_expsyms_cmds= + +case $host_os in +cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; +openbsd*) + with_gnu_ld=no + ;; +esac + +ld_shlibs=yes +if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX, the GNU linker is very broken + # Note:Check GNU linker on AIX 5-IA64 when/if it becomes available. + ld_shlibs=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + ;; + + amigaos*) + archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can use + # them. + ld_shlibs=no + ;; + + beos*) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32*) + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + allow_undefined_flag=unsupported + always_export_symbols=yes + + extract_expsyms_cmds='test -f $output_objdir/impgen.c || \ + sed -e "/^# \/\* impgen\.c starts here \*\//,/^# \/\* impgen.c ends here \*\// { s/^# //;s/^# *$//; p; }" -e d < $''0 > $output_objdir/impgen.c~ + test -f $output_objdir/impgen.exe || (cd $output_objdir && \ + if test "x$HOST_CC" != "x" ; then $HOST_CC -o impgen impgen.c ; \ + else $CC -o impgen impgen.c ; fi)~ + $output_objdir/impgen $dir/$soroot > $output_objdir/$soname-def' + + old_archive_from_expsyms_cmds='$DLLTOOL --as=$AS --dllname $soname --def $output_objdir/$soname-def --output-lib $output_objdir/$newlib' + + # cygwin and mingw dlls have different entry points and sets of symbols + # to exclude. + # FIXME: what about values for MSVC? + dll_entry=__cygwin_dll_entry@12 + dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12~ + case $host_os in + mingw*) + # mingw values + dll_entry=_DllMainCRTStartup@12 + dll_exclude_symbols=DllMain@12,DllMainCRTStartup@12,DllEntryPoint@12~ + ;; + esac + + # mingw and cygwin differ, and it's simplest to just exclude the union + # of the two symbol sets. + dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 + + # recent cygwin and mingw systems supply a stub DllMain which the user + # can override, but on older systems we have to supply one (in ltdll.c) + if test "x$lt_cv_need_dllmain" = "xyes"; then + ltdll_obj='$output_objdir/$soname-ltdll.'"$ac_objext " + ltdll_cmds='test -f $output_objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $''0 > $output_objdir/$soname-ltdll.c~ + test -f $output_objdir/$soname-ltdll.$ac_objext || (cd $output_objdir && $CC -c $soname-ltdll.c)~' + else + ltdll_obj= + ltdll_cmds= + fi + + # Extract the symbol export list from an `--export-all' def file, + # then regenerate the def file from the symbol export list, so that + # the compiled dll only exports the symbol export list. + # Be careful not to strip the DATA tag left be newer dlltools. + export_symbols_cmds="$ltdll_cmds"' + $DLLTOOL --export-all --exclude-symbols '$dll_exclude_symbols' --output-def $output_objdir/$soname-def '$ltdll_obj'$libobjs $convenience~ + sed -e "1,/EXPORTS/d" -e "s/ @ [[0-9]]*//" -e "s/ *;.*$//" < $output_objdir/$soname-def > $export_symbols' + + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is. + # If DATA tags from a recent dlltool are present, honour them! + archive_expsym_cmds='if test "x`sed 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname-def; + else + echo EXPORTS > $output_objdir/$soname-def; + _lt_hint=1; + cat $export_symbols | while read symbol; do + set dummy \$symbol; + case \[$]# in + 2) echo " \[$]2 @ \$_lt_hint ; " >> $output_objdir/$soname-def;; + 4) echo " \[$]2 \[$]3 \[$]4 ; " >> $output_objdir/$soname-def; _lt_hint=`expr \$_lt_hint - 1`;; + *) echo " \[$]2 @ \$_lt_hint \[$]3 ; " >> $output_objdir/$soname-def;; + esac; + _lt_hint=`expr 1 + \$_lt_hint`; + done; + fi~ + '"$ltdll_cmds"' + $CC -Wl,--base-file,$output_objdir/$soname-base '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~ + $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp~ + $CC -Wl,--base-file,$output_objdir/$soname-base $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~ + $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp --output-lib $output_objdir/$libname.dll.a~ + $CC $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags' + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test "$ld_shlibs" = yes; then + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + case $host_os in + cygwin* | mingw* | pw32*) + # dlltool doesn't understand --whole-archive et. al. + whole_archive_flag_spec= + ;; + *) + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec= + fi + ;; + esac + fi +else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes && test -z "$link_static_flag"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + hardcode_direct=yes + archive_cmds='' + hardcode_libdir_separator=':' + if test "$GCC" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct=yes + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + esac + + shared_flag='-shared' + else + # not using gcc + if test "$host_cpu" = ia64; then + shared_flag='${wl}-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall can do strange things, so it is better to + # generate a list of symbols to export. + always_export_symbols=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:/usr/lib:/lib' + archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname ${wl}-h$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" + else + hardcode_libdir_flag_spec='${wl}-bnolibpath ${wl}-blibpath:$libdir:/usr/lib:/lib' + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='${wl}-berok' + # This is a bit strange, but is similar to how AIX traditionally builds + # it's shared libraries. + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"' ~$AR -crlo $objdir/$libname$release.a $objdir/$soname' + fi + fi + ;; + + amigaos*) + archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + # see comment about different semantics on the GNU ld section + ld_shlibs=no + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path='`cygpath -w "$srcfile"`' + ;; + + darwin* | rhapsody*) + case "$host_os" in + rhapsody* | darwin1.[[012]]) + allow_undefined_flag='-undefined suppress' + ;; + *) # Darwin 1.3 on + allow_undefined_flag='-flat_namespace -undefined suppress' + ;; + esac + # FIXME: Relying on posixy $() will cause problems for + # cross-compilation, but unfortunately the echo tests do not + # yet detect zsh echo's removal of \ escapes. Also zsh mangles + # `"' quotes if we put them in here... so don't! + archive_cmds='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs && $CC $(test .$module = .yes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib ${lib}-master.o $deplibs$linker_flags $(test .$module != .yes && echo -install_name $rpath/$soname $verstring)' + # We need to add '_' to the symbols in $export_symbols first + #archive_expsym_cmds="$archive_cmds"' && strip -s $export_symbols' + hardcode_direct=yes + hardcode_shlibpath_var=no + whole_archive_flag_spec='-all_load $convenience' + ;; + + freebsd1*) + ld_shlibs=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd*) + archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9* | hpux10* | hpux11*) + case $host_os in + hpux9*) archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' ;; + *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' ;; + esac + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_minus_L=yes # Not in the search PATH, but as the default + # location of the library. + export_dynamic_flag_spec='${wl}-E' + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec='-rpath $libdir' + fi + hardcode_libdir_separator=: + link_all_deplibs=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + openbsd*) + hardcode_direct=yes + hardcode_shlibpath_var=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + else + case "$host_os" in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "-exported_symbol " >> $lib.exp; echo "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' + + #Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + hardcode_libdir_separator=: + ;; + + sco3.2v5*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + export_dynamic_flag_spec='${wl}-Bexport' + ;; + + solaris*) + # gcc --version < 3.0 without binutils cannot create self contained + # shared libraries reliably, requiring libgcc.a to resolve some of + # the object symbols generated in some cases. Libraries that use + # assert need libgcc.a to resolve __eprintf, for example. Linking + # a copy of libgcc.a into every shared library to guarantee resolving + # such symbols causes other problems: According to Tim Van Holder + # , C++ libraries end up with a separate + # (to the application) exception stack for one thing. + no_undefined_flag=' -z defs' + if test "$GCC" = yes; then + case `$CC --version 2>/dev/null` in + [[12]].*) + cat <&2 + +*** Warning: Releases of GCC earlier than version 3.0 cannot reliably +*** create self contained shared libraries on Solaris systems, without +*** introducing a dependency on libgcc.a. Therefore, libtool is disabling +*** -no-undefined support, which will at least allow you to build shared +*** libraries. However, you may find that when you link such libraries +*** into an application without using GCC, you have to manually add +*** \`gcc --print-libgcc-file-name\` to the link command. We urge you to +*** upgrade to a newer version of GCC. Another option is to rebuild your +*** current GCC to use the GNU linker from GNU binutils 2.9.1 or newer. + +EOF + no_undefined_flag= + ;; + esac + fi + # $CC -shared without GNU ld will not create a library from C++ + # object files and a static libstdc++, better avoid it by now + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) # Supported since Solaris 2.6 (maybe 2.5.1?) + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4.2uw2*) + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=no + hardcode_shlibpath_var=no + hardcode_runpath_var=yes + runpath_var=LD_RUN_PATH + ;; + + sysv5* | unixware7*) + no_undefined_flag='${wl}-z ${wl}text' + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac +fi +AC_MSG_RESULT([$ld_shlibs]) +test "$ld_shlibs" = no && can_build_shared=no +## +## END FIXME + +## FIXME: this should be a separate macro +## +# Check hardcoding attributes. +AC_MSG_CHECKING([how to hardcode library paths into programs]) +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || \ + test -n "$runpath_var"; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$hardcode_shlibpath_var" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +AC_MSG_RESULT([$hardcode_action]) +## +## END FIXME + +## FIXME: this should be a separate macro +## +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi +## +## END FIXME + +reload_cmds='$LD$reload_flag -o $output$reload_objs' +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +## FIXME: this should be a separate macro +## +# PORTME Fill in your ld.so characteristics +AC_MSG_CHECKING([dynamic linker characteristics]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}.so$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}.so$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}.so$major ${libname}${release}.so$versuffix $libname.so' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can + # not hardcode correct soname into executable. Probably we can + # add versioning support to collect2, so additional links can + # be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}.so$major' + fi + shlibpath_var=LIBPATH + fi + hardcode_into_libs=yes + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}.so' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi4*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + export_dynamic_flag_spec=-rdynamic + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + need_version=no + need_lib_prefix=no + case $GCC,$host_os in + yes,cygwin*) + library_names_spec='$libname.dll.a' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll' + postinstall_cmds='dlpath=`bash 2>&1 -c '\''. $dir/${file}i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog .libs/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`bash 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + ;; + yes,mingw*) + library_names_spec='${libname}`echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | sed -e "s/^libraries://" -e "s/;/ /g" -e "s,=/,/,g"` + ;; + yes,pw32*) + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll' + ;; + *) + library_names_spec='${libname}`echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + # FIXME: Relying on posixy $() will cause problems for + # cross-compilation, but unfortunately the echo tests do not + # yet detect zsh echo's removal of \ escapes. + library_names_spec='${libname}${release}${versuffix}.$(test .$module = .yes && echo so || echo dylib) ${libname}${release}${major}.$(test .$module = .yes && echo so || echo dylib) ${libname}.$(test .$module = .yes && echo so || echo dylib)' + soname_spec='${libname}${release}${major}.$(test .$module = .yes && echo so || echo dylib)' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd*) + objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + *) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + dynamic_linker="$host_os dld.sl" + version_type=sunos + need_lib_prefix=no + need_version=no + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl' + soname_spec='${libname}${release}.sl$major' + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) version_type=irix ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}.so$major' + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so $libname.so' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux-gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + + # Find out which ABI we are using (multilib Linux x86_64 hack). + libsuff= + case "$host_cpu" in + x86_64*|s390x*) + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *64-bit*) + libsuff=64 + ;; + esac + fi + rm -rf conftest* + ;; + *) + ;; + esac + sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff}" + sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}" + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so' + soname_spec='${libname}${release}.so$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case "$host_os" in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + ;; + +os2*) + libname_spec='$name' + need_lib_prefix=no + library_names_spec='$libname.dll $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_version=no + soname_spec='${libname}${release}.so$major' + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + hardcode_into_libs=yes + ;; + +sco3.2v5*) + version_type=osf + soname_spec='${libname}${release}.so$major' + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + shlibpath_var=LD_LIBRARY_PATH + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + version_type=linux + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so' + soname_spec='$libname.so.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no +## +## END FIXME + +## FIXME: this should be a separate macro +## +# Report the final consequences. +AC_MSG_CHECKING([if libtool supports shared libraries]) +AC_MSG_RESULT([$can_build_shared]) +## +## END FIXME + +## FIXME: this should be a separate macro +## +AC_MSG_CHECKING([whether to build shared libraries]) +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case "$host_os" in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +AC_MSG_RESULT([$enable_shared]) +## +## END FIXME + +## FIXME: this should be a separate macro +## +AC_MSG_CHECKING([whether to build static libraries]) +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +AC_MSG_RESULT([$enable_static]) +## +## END FIXME + +if test "$hardcode_action" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +AC_LIBTOOL_DLOPEN_SELF + +## FIXME: this should be a separate macro +## +if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_MSG_CHECKING([whether -lc should be explicitly linked in]) + AC_CACHE_VAL([lt_cv_archive_cmds_need_lc], + [$rm conftest* + echo 'static int dummy;' > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile); then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_cv_prog_cc_wl + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if AC_TRY_EVAL(archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi]) + AC_MSG_RESULT([$lt_cv_archive_cmds_need_lc]) + ;; + esac +fi +need_lc=${lt_cv_archive_cmds_need_lc-yes} +## +## END FIXME + +## FIXME: this should be a separate macro +## +# The second clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + : +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + test -f Makefile && make "$ltmain" +fi + +if test -f "$ltmain"; then + trap "$rm \"${ofile}T\"; exit 1" 1 2 15 + $rm -f "${ofile}T" + + echo creating $ofile + + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS SED \ + AR AR_FLAGS CC LD LN_S NM SHELL \ + reload_flag reload_cmds wl \ + pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \ + thread_safe_flag_spec whole_archive_flag_spec libname_spec \ + library_names_spec soname_spec \ + RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \ + old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds \ + postuninstall_cmds extract_expsyms_cmds old_archive_from_expsyms_cmds \ + old_striplib striplib file_magic_cmd export_symbols_cmds \ + deplibs_check_method allow_undefined_flag no_undefined_flag \ + finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \ + global_symbol_to_c_name_address \ + hardcode_libdir_flag_spec hardcode_libdir_separator \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do + + case $var in + reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + export_symbols_cmds | archive_cmds | archive_expsym_cmds | \ + extract_expsyms_cmds | old_archive_from_expsyms_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + cat <<__EOF__ > "${ofile}T" +#! $SHELL + +# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996-2000 Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A sed that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="${SED} -e s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi + +# ### BEGIN LIBTOOL CONFIG + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$need_lc + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# The default C compiler. +CC=$lt_CC + +# Is the compiler the GNU C compiler? +with_gcc=$GCC + +# The linker used to build libraries. +LD=$lt_LD + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_wl + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_pic_flag +pic_mode=$pic_mode + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_compiler_c_o + +# Can we write directly to a .lo ? +compiler_o_lo=$lt_compiler_o_lo + +# Must we lock files when doing compilation ? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_link_static_flag + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_no_builtin_flag + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# ### END LIBTOOL CONFIG + +__EOF__ + + case $host_os in + aix3*) + cat <<\EOF >> "${ofile}T" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + case $host_os in + cygwin* | mingw* | pw32* | os2*) + cat <<'EOF' >> "${ofile}T" + # This is a source program that is used to create dlls on Windows + # Don't remove nor modify the starting and closing comments +# /* ltdll.c starts here */ +# #define WIN32_LEAN_AND_MEAN +# #include +# #undef WIN32_LEAN_AND_MEAN +# #include +# +# #ifndef __CYGWIN__ +# # ifdef __CYGWIN32__ +# # define __CYGWIN__ __CYGWIN32__ +# # endif +# #endif +# +# #ifdef __cplusplus +# extern "C" { +# #endif +# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); +# #ifdef __cplusplus +# } +# #endif +# +# #ifdef __CYGWIN__ +# #include +# DECLARE_CYGWIN_DLL( DllMain ); +# #endif +# HINSTANCE __hDllInstance_base; +# +# BOOL APIENTRY +# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) +# { +# __hDllInstance_base = hInst; +# return TRUE; +# } +# /* ltdll.c ends here */ + # This is a source program that is used to create import libraries + # on Windows for dlls which lack them. Don't remove nor modify the + # starting and closing comments +# /* impgen.c starts here */ +# /* Copyright (C) 1999-2000 Free Software Foundation, Inc. +# +# This file is part of GNU libtool. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# */ +# +# #include /* for printf() */ +# #include /* for open(), lseek(), read() */ +# #include /* for O_RDONLY, O_BINARY */ +# #include /* for strdup() */ +# +# /* O_BINARY isn't required (or even defined sometimes) under Unix */ +# #ifndef O_BINARY +# #define O_BINARY 0 +# #endif +# +# static unsigned int +# pe_get16 (fd, offset) +# int fd; +# int offset; +# { +# unsigned char b[2]; +# lseek (fd, offset, SEEK_SET); +# read (fd, b, 2); +# return b[0] + (b[1]<<8); +# } +# +# static unsigned int +# pe_get32 (fd, offset) +# int fd; +# int offset; +# { +# unsigned char b[4]; +# lseek (fd, offset, SEEK_SET); +# read (fd, b, 4); +# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); +# } +# +# static unsigned int +# pe_as32 (ptr) +# void *ptr; +# { +# unsigned char *b = ptr; +# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); +# } +# +# int +# main (argc, argv) +# int argc; +# char *argv[]; +# { +# int dll; +# unsigned long pe_header_offset, opthdr_ofs, num_entries, i; +# unsigned long export_rva, export_size, nsections, secptr, expptr; +# unsigned long name_rvas, nexp; +# unsigned char *expdata, *erva; +# char *filename, *dll_name; +# +# filename = argv[1]; +# +# dll = open(filename, O_RDONLY|O_BINARY); +# if (dll < 1) +# return 1; +# +# dll_name = filename; +# +# for (i=0; filename[i]; i++) +# if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':') +# dll_name = filename + i +1; +# +# pe_header_offset = pe_get32 (dll, 0x3c); +# opthdr_ofs = pe_header_offset + 4 + 20; +# num_entries = pe_get32 (dll, opthdr_ofs + 92); +# +# if (num_entries < 1) /* no exports */ +# return 1; +# +# export_rva = pe_get32 (dll, opthdr_ofs + 96); +# export_size = pe_get32 (dll, opthdr_ofs + 100); +# nsections = pe_get16 (dll, pe_header_offset + 4 +2); +# secptr = (pe_header_offset + 4 + 20 + +# pe_get16 (dll, pe_header_offset + 4 + 16)); +# +# expptr = 0; +# for (i = 0; i < nsections; i++) +# { +# char sname[8]; +# unsigned long secptr1 = secptr + 40 * i; +# unsigned long vaddr = pe_get32 (dll, secptr1 + 12); +# unsigned long vsize = pe_get32 (dll, secptr1 + 16); +# unsigned long fptr = pe_get32 (dll, secptr1 + 20); +# lseek(dll, secptr1, SEEK_SET); +# read(dll, sname, 8); +# if (vaddr <= export_rva && vaddr+vsize > export_rva) +# { +# expptr = fptr + (export_rva - vaddr); +# if (export_rva + export_size > vaddr + vsize) +# export_size = vsize - (export_rva - vaddr); +# break; +# } +# } +# +# expdata = (unsigned char*)malloc(export_size); +# lseek (dll, expptr, SEEK_SET); +# read (dll, expdata, export_size); +# erva = expdata - export_rva; +# +# nexp = pe_as32 (expdata+24); +# name_rvas = pe_as32 (expdata+32); +# +# printf ("EXPORTS\n"); +# for (i = 0; i> "${ofile}T" || (rm -f "${ofile}T"; exit 1) + + mv -f "${ofile}T" "$ofile" || \ + (rm -f "$ofile" && cp "${ofile}T" "$ofile" && rm -f "${ofile}T") + chmod +x "$ofile" +fi +## +## END FIXME + +])# _LT_AC_LTCONFIG_HACK + +# AC_LIBTOOL_DLOPEN - enable checks for dlopen support +AC_DEFUN([AC_LIBTOOL_DLOPEN], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])]) + +# AC_LIBTOOL_WIN32_DLL - declare package support for building win32 dll's +AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_BEFORE([$0], [AC_LIBTOOL_SETUP])]) + +# AC_ENABLE_SHARED - implement the --enable-shared flag +# Usage: AC_ENABLE_SHARED[(DEFAULT)] +# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to +# `yes'. +AC_DEFUN([AC_ENABLE_SHARED], +[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE(shared, +changequote(<<, >>)dnl +<< --enable-shared[=PKGS] build shared libraries [default=>>AC_ENABLE_SHARED_DEFAULT], +changequote([, ])dnl +[p=${PACKAGE-default} +case $enableval in +yes) enable_shared=yes ;; +no) enable_shared=no ;; +*) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac], +enable_shared=AC_ENABLE_SHARED_DEFAULT)dnl +]) + +# AC_DISABLE_SHARED - set the default shared flag to --disable-shared +AC_DEFUN([AC_DISABLE_SHARED], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_SHARED(no)]) + +# AC_ENABLE_STATIC - implement the --enable-static flag +# Usage: AC_ENABLE_STATIC[(DEFAULT)] +# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to +# `yes'. +AC_DEFUN([AC_ENABLE_STATIC], +[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE(static, +changequote(<<, >>)dnl +<< --enable-static[=PKGS] build static libraries [default=>>AC_ENABLE_STATIC_DEFAULT], +changequote([, ])dnl +[p=${PACKAGE-default} +case $enableval in +yes) enable_static=yes ;; +no) enable_static=no ;; +*) + enable_static=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac], +enable_static=AC_ENABLE_STATIC_DEFAULT)dnl +]) + +# AC_DISABLE_STATIC - set the default static flag to --disable-static +AC_DEFUN([AC_DISABLE_STATIC], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_STATIC(no)]) + + +# AC_ENABLE_FAST_INSTALL - implement the --enable-fast-install flag +# Usage: AC_ENABLE_FAST_INSTALL[(DEFAULT)] +# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to +# `yes'. +AC_DEFUN([AC_ENABLE_FAST_INSTALL], +[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE(fast-install, +changequote(<<, >>)dnl +<< --enable-fast-install[=PKGS] optimize for fast installation [default=>>AC_ENABLE_FAST_INSTALL_DEFAULT], +changequote([, ])dnl +[p=${PACKAGE-default} +case $enableval in +yes) enable_fast_install=yes ;; +no) enable_fast_install=no ;; +*) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac], +enable_fast_install=AC_ENABLE_FAST_INSTALL_DEFAULT)dnl +]) + +# AC_DISABLE_FAST_INSTALL - set the default to --disable-fast-install +AC_DEFUN([AC_DISABLE_FAST_INSTALL], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_FAST_INSTALL(no)]) + +# AC_LIBTOOL_PICMODE - implement the --with-pic flag +# Usage: AC_LIBTOOL_PICMODE[(MODE)] +# Where MODE is either `yes' or `no'. If omitted, it defaults to +# `both'. +AC_DEFUN([AC_LIBTOOL_PICMODE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +pic_mode=ifelse($#,1,$1,default)]) + + +# AC_PATH_TOOL_PREFIX - find a file program which can recognise shared library +AC_DEFUN([AC_PATH_TOOL_PREFIX], +[AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in + /*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; + ?:/*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a dos path. + ;; + *) + ac_save_MAGIC_CMD="$MAGIC_CMD" + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="ifelse([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + egrep "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$ac_save_ifs" + MAGIC_CMD="$ac_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +]) + + +# AC_PATH_MAGIC - find a file program which can recognise a shared library +AC_DEFUN([AC_PATH_MAGIC], +[AC_REQUIRE([AC_CHECK_TOOL_PREFIX])dnl +AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin:$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + AC_PATH_TOOL_PREFIX(file, /usr/bin:$PATH) + else + MAGIC_CMD=: + fi +fi +]) + + +# AC_PROG_LD - find the path to the GNU or non-GNU linker +AC_DEFUN([AC_PROG_LD], +[AC_ARG_WITH(gnu-ld, +[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]], +test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no) +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR])dnl +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by GCC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | [[A-Za-z]]:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$lt_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" +else + lt_cv_path_LD="$LD" # Let the user override the test with a path. +fi]) +LD="$lt_cv_path_LD" +if test -n "$LD"; then + AC_MSG_RESULT($LD) +else + AC_MSG_RESULT(no) +fi +test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) +AC_PROG_LD_GNU +]) + +# AC_PROG_LD_GNU - +AC_DEFUN([AC_PROG_LD_GNU], +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld, +[# I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 &5; then + lt_cv_prog_gnu_ld=yes +else + lt_cv_prog_gnu_ld=no +fi]) +with_gnu_ld=$lt_cv_prog_gnu_ld +]) + +# AC_PROG_LD_RELOAD_FLAG - find reload flag for linker +# -- PORTME Some linkers may need a different reload flag. +AC_DEFUN([AC_PROG_LD_RELOAD_FLAG], +[AC_CACHE_CHECK([for $LD option to reload object files], lt_cv_ld_reload_flag, +[lt_cv_ld_reload_flag='-r']) +reload_flag=$lt_cv_ld_reload_flag +test -n "$reload_flag" && reload_flag=" $reload_flag" +]) + +# AC_DEPLIBS_CHECK_METHOD - how to check for library dependencies +# -- PORTME fill in with the dynamic library characteristics +AC_DEFUN([AC_DEPLIBS_CHECK_METHOD], +[AC_CACHE_CHECK([how to recognise dependent libraries], +lt_cv_deplibs_check_method, +[lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given egrep regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. + +case $host_os in +aix4* | aix5*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi4*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin* | mingw* | pw32*) + lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method='file_magic Mach-O dynamically linked shared library' + lt_cv_file_magic_cmd='/usr/bin/file -L' + case "$host_os" in + rhapsody* | darwin1.[[012]]) + lt_cv_file_magic_test_file=`echo /System/Library/Frameworks/System.framework/Versions/*/System | head -1` + ;; + *) # Darwin 1.3 on + lt_cv_file_magic_test_file='/usr/lib/libSystem.dylib' + ;; + esac + ;; + +freebsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20*|hpux11*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + irix5* | nonstopux*) + # this will be overridden with pass_all, but let us keep it just in case + lt_cv_deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1" + ;; + *) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + # this will be overridden with pass_all, but let us keep it just in case + lt_cv_deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[[1234]] dynamic lib MIPS - version 1" + ;; + esac + lt_cv_file_magic_test_file=`echo /lib${libsuff}/libc.so*` + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux-gnu*) + case $host_cpu in + alpha* | hppa* | i*86 | mips | mipsel | powerpc* | sparc* | ia64* | s390* | x86_64*) + lt_cv_deplibs_check_method=pass_all ;; + *) + # glibc up to 2.1.1 does not perform some relocations on ARM + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; + esac + lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so` + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/\.]]+\.so\.[[0-9]]+\.[[0-9]]+$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/\.]]+\.so$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +openbsd*) + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB shared object' + else + lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library' + fi + ;; + +osf3* | osf4* | osf5*) + # this will be overridden with pass_all, but let us keep it just in case + lt_cv_deplibs_check_method='file_magic COFF format alpha shared library' + lt_cv_file_magic_test_file=/shlib/libc.so + lt_cv_deplibs_check_method=pass_all + ;; + +sco3.2v5*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + lt_cv_file_magic_test_file=/lib/libc.so + ;; + +sysv5* | sysv4*uw2*) + lt_cv_archive_cmds_need_lc=no + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; +esac +]) +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +]) + + +# AC_PROG_NM - find the path to a BSD-compatible name lister +AC_DEFUN([AC_PROG_NM], +[AC_REQUIRE([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR])dnl +AC_MSG_CHECKING([for BSD-compatible nm]) +AC_CACHE_VAL(lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/${ac_tool_prefix}nm + if test -f $tmp_nm || test -f $tmp_nm$ac_exeext ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + if ($tmp_nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep '(/dev/null|Invalid file or object type)' >/dev/null; then + lt_cv_path_NM="$tmp_nm -B" + break + elif ($tmp_nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + lt_cv_path_NM="$tmp_nm -p" + break + else + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + fi + fi + done + IFS="$ac_save_ifs" + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi]) +NM="$lt_cv_path_NM" +AC_MSG_RESULT([$NM]) +]) + +# AC_CHECK_LIBM - check for math library +AC_DEFUN([AC_CHECK_LIBM], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cygwin* | *-*-pw32*) + # These system don't have libm + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, main, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, main, LIBM="-lm") + ;; +esac +]) + +# AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for +# the libltdl convenience library and LTDLINCL to the include flags for +# the libltdl header and adds --enable-ltdl-convenience to the +# configure arguments. Note that LIBLTDL and LTDLINCL are not +# AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If DIR is not +# provided, it is assumed to be `libltdl'. LIBLTDL will be prefixed +# with '${top_builddir}/' and LTDLINCL will be prefixed with +# '${top_srcdir}/' (note the single quotes!). If your package is not +# flat and you're not using automake, define top_builddir and +# top_srcdir appropriately in the Makefiles. +AC_DEFUN([AC_LIBLTDL_CONVENIENCE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + case $enable_ltdl_convenience in + no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; + "") enable_ltdl_convenience=yes + ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; + esac + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +]) + +# AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for +# the libltdl installable library and LTDLINCL to the include flags for +# the libltdl header and adds --enable-ltdl-install to the configure +# arguments. Note that LIBLTDL and LTDLINCL are not AC_SUBSTed, nor is +# AC_CONFIG_SUBDIRS called. If DIR is not provided and an installed +# libltdl is not found, it is assumed to be `libltdl'. LIBLTDL will +# be prefixed with '${top_builddir}/' and LTDLINCL will be prefixed +# with '${top_srcdir}/' (note the single quotes!). If your package is +# not flat and you're not using automake, define top_builddir and +# top_srcdir appropriately in the Makefiles. +# In the future, this macro may have to be called after AC_PROG_LIBTOOL. +AC_DEFUN([AC_LIBLTDL_INSTALLABLE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + AC_CHECK_LIB(ltdl, main, + [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], + [if test x"$enable_ltdl_install" = xno; then + AC_MSG_WARN([libltdl not installed, but installation disabled]) + else + enable_ltdl_install=yes + fi + ]) + if test x"$enable_ltdl_install" = x"yes"; then + ac_configure_args="$ac_configure_args --enable-ltdl-install" + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + else + ac_configure_args="$ac_configure_args --enable-ltdl-install=no" + LIBLTDL="-lltdl" + LTDLINCL= + fi + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +]) + +# old names +AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) +AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) +AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) +AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) +AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) + +# This is just to silence aclocal about the macro not being used +ifelse([AC_DISABLE_FAST_INSTALL]) + +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +# LT_AC_PROG_SED +# -------------- +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +AC_DEFUN([LT_AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_executable_p="test -f" +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + _sed_list="$_sed_list $as_dir/$ac_prog$ac_exec_ext" + fi + done + done +done + + # Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. +: ${TMPDIR=/tmp} +{ + tmp=`(umask 077 && mktemp -d -q "$TMPDIR/sedXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=$TMPDIR/sed$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in $TMPDIR" >&2 + { (exit 1); exit 1; } +} + _max=0 + _count=0 + # Add /usr/xpg4/bin/sed as it is typically found on Solaris + # along with /bin/sed that truncates output. + for _sed in $_sed_list /usr/xpg4/bin/sed; do + test ! -f ${_sed} && break + cat /dev/null > "$tmp/sed.in" + _count=0 + echo ${ECHO_N-$ac_n} "0123456789${ECHO_C-$ac_c}" >"$tmp/sed.in" + # Check for GNU sed and select it if it is found. + if "${_sed}" --version 2>&1 < /dev/null | egrep '(GNU)' > /dev/null; then + lt_cv_path_SED=${_sed} + break + fi + while true; do + cat "$tmp/sed.in" "$tmp/sed.in" >"$tmp/sed.tmp" + mv "$tmp/sed.tmp" "$tmp/sed.in" + cp "$tmp/sed.in" "$tmp/sed.nl" + echo >>"$tmp/sed.nl" + ${_sed} -e 's/a$//' < "$tmp/sed.nl" >"$tmp/sed.out" || break + cmp -s "$tmp/sed.out" "$tmp/sed.nl" || break + # 40000 chars as input seems more than enough + test $_count -gt 10 && break + _count=`expr $_count + 1` + if test $_count -gt $_max; then + _max=$_count + lt_cv_path_SED=$_sed + fi + done + done + rm -rf "$tmp" +]) +if test "X$SED" != "X"; then + lt_cv_path_SED=$SED +else + SED=$lt_cv_path_SED +fi +AC_MSG_RESULT([$SED]) +]) diff --git a/build/shtool b/build/shtool index f3250796ec4b..cd5352d22925 100755 --- a/build/shtool +++ b/build/shtool @@ -1,12 +1,12 @@ #!/bin/sh ## ## GNU shtool -- The GNU Portable Shell Tool -## Copyright (c) 1994-2002 Ralf S. Engelschall +## Copyright (c) 1994-2005 Ralf S. Engelschall ## ## See http://www.gnu.org/software/shtool/ for more information. ## See ftp://ftp.gnu.org/gnu/shtool/ for latest version. ## -## Version: 1.6.2 (02-Nov-2002) +## Version: 2.0.2 (15-Jun-2005) ## Contents: 4/19 available modules ## @@ -54,7 +54,7 @@ ## rotate Logfile rotation ## tarball Roll distribution tarballs ## subst Apply sed(1) substitution operations -## guessos Simple operating system guesser +## platform Platform Identification Utility ## arx Extended archive command ## slo Separate linker options by library class ## scpp Sharing C Pre-Processor @@ -66,9 +66,9 @@ if [ $# -eq 0 ]; then echo "$0:Hint: run \`$0 -h' for usage" 1>&2 exit 1 fi -if [ ".$1" = ".-h" -o ".$1" = ".--help" ]; then - echo "This is GNU shtool, version 1.6.2 (02-Nov-2002)" - echo "Copyright (c) 1994-2002 Ralf S. Engelschall " +if [ ".$1" = ".-h" ] || [ ".$1" = ".--help" ]; then + echo "This is GNU shtool, version 2.0.2 (15-Jun-2005)" + echo "Copyright (c) 1994-2005 Ralf S. Engelschall " echo "Report bugs to " echo '' echo "Usage: shtool [] [ [] []]" @@ -80,7 +80,7 @@ if [ ".$1" = ".-h" -o ".$1" = ".--help" ]; then echo ' -r, --recreate recreate this shtool script via shtoolize' echo '' echo 'Available [] []:' - echo ' echo [-n|--newline] [-e|--expand] [ ...]' + echo ' echo [-n|--newline] [-e|--expand] [ ...]' echo ' install [-v|--verbose] [-t|--trace] [-d|--mkdir] [-c|--copy]' echo ' [-C|--compare-copy] [-s|--strip] [-m|--mode ]' echo ' [-o|--owner ] [-g|--group ] [-e|--exec' @@ -106,17 +106,21 @@ if [ ".$1" = ".-h" -o ".$1" = ".--help" ]; then echo ' rotate [-v|--verbose] [-t|--trace] [-f|--force] [-n|--num-files' echo ' ] [-s|--size ] [-c|--copy] [-r|--remove]' echo ' [-a|--archive-dir ] [-z|--compress [:]]' - echo ' [-b|--background] [-d|--delay] [-p|--pad ] [-o|--owner' - echo ' ] [-g|--group ] [-m|--mode ] [-M|--migrate' + echo ' [-b|--background] [-d|--delay] [-p|--pad ] [-m|--mode' + echo ' ] [-o|--owner ] [-g|--group ] [-M|--migrate' echo ' ] [-P|--prolog ] [-E|--epilog ] [...]' echo ' tarball [-t|--trace] [-v|--verbose] [-o|--output ]' echo ' [-c|--compress ] [-d|--directory ] [-u|--user' echo ' ] [-g|--group ] [-e|--exclude ]' echo ' [ ...]' - echo ' subst [-v|--verbose] [-t|--trace] [-n|--nop] [-s|--stealth]' - echo ' [-i|--interactive] [-b|--backup ] [-e|--exec ]' - echo ' [-f|--file ] [] [...]' - echo ' guessos ' + echo ' subst [-v|--verbose] [-t|--trace] [-n|--nop] [-w|--warning]' + echo ' [-q|--quiet] [-s|--stealth] [-i|--interactive] [-b|--backup' + echo ' ] [-e|--exec ] [-f|--file ] []' + echo ' [...]' + echo ' platform [-F|--format ] [-S|--sep ] [-C|--conc' + echo ' ] [-L|--lower] [-U|--upper] [-v|--verbose]' + echo ' [-c|--concise] [-n|--no-newline] [-t|--type ]' + echo ' [-V|--version] [-h|--help]' echo ' arx [-t|--trace] [-C|--command ] [' echo ' ...]' echo ' slo [-p|--prefix ] -- -L -l [-L -l' @@ -131,15 +135,15 @@ if [ ".$1" = ".-h" -o ".$1" = ".--help" ]; then echo '' exit 0 fi -if [ ".$1" = ".-v" -o ".$1" = ."--version" ]; then - echo "GNU shtool 1.6.2 (02-Nov-2002)" +if [ ".$1" = ".-v" ] || [ ".$1" = ".--version" ]; then + echo "GNU shtool 2.0.2 (15-Jun-2005)" exit 0 fi -if [ ".$1" = ".-r" -o ".$1" = ."--recreate" ]; then +if [ ".$1" = ".-r" ] || [ ".$1" = ".--recreate" ]; then shtoolize -oshtool echo install mkdir path exit 0 fi -if [ ".$1" = ".-d" -o ".$1" = ."--debug" ]; then +if [ ".$1" = ".-d" ] || [ ".$1" = ".--debug" ]; then shift set -x fi @@ -166,7 +170,7 @@ gen_tmpfile=no case $tool in echo ) str_tool="echo" - str_usage="[-n|--newline] [-e|--expand] [ ...]" + str_usage="[-n|--newline] [-e|--expand] [ ...]" arg_spec="0+" opt_spec="n.e." opt_alias="n:newline,e:expand" @@ -261,7 +265,7 @@ eval `echo h.$opt_spec |\ # parse option alias string eval `echo h:help,$opt_alias |\ - tr 'x-' 'x_' | sed -e 's/\([a-zA-Z0-9]\):\([^,]*\),*/opt_ALIAS_\2=\1;/g'` + sed -e 's/-/_/g' -e 's/\([a-zA-Z0-9]\):\([^,]*\),*/opt_ALIAS_\2=\1;/g'` # interate over argument line opt_PREV='' @@ -286,12 +290,12 @@ while [ $# -gt 0 ]; do --[a-zA-Z0-9]*=*) eval `echo "x$1" |\ sed -e 's/^x--\([a-zA-Z0-9-]*\)=\(.*\)$/opt_OPT="\1";opt_ARG="\2"/'` - opt_STR=`echo $opt_OPT | tr 'x-' 'x_'` + opt_STR=`echo $opt_OPT | sed -e 's/-/_/g'` eval "opt_OPT=\${opt_ALIAS_${opt_STR}-${opt_OPT}}" ;; --[a-zA-Z0-9]*) opt_OPT=`echo "x$1" | cut -c4-` - opt_STR=`echo $opt_OPT | tr 'x-' 'x_'` + opt_STR=`echo $opt_OPT | sed -e 's/-/_/g'` eval "opt_OPT=\${opt_ALIAS_${opt_STR}-${opt_OPT}}" opt_ARG='' ;; @@ -315,8 +319,8 @@ while [ $# -gt 0 ]; do # determine whether option needs an argument eval "opt_MODE=\$opt_MODE_${opt_OPT}" - if [ ".$opt_ARG" = . -a ".$opt_ARG_OK" != .yes ]; then - if [ ".$opt_MODE" = ".:" -o ".$opt_MODE" = ".+" ]; then + if [ ".$opt_ARG" = . ] && [ ".$opt_ARG_OK" != .yes ]; then + if [ ".$opt_MODE" = ".:" ] || [ ".$opt_MODE" = ".+" ]; then opt_PREV="$opt_OPT" continue fi @@ -375,6 +379,7 @@ esac # establish a temporary file on request if [ ".$gen_tmpfile" = .yes ]; then + # create (explicitly) secure temporary directory if [ ".$TMPDIR" != . ]; then tmpdir="$TMPDIR" elif [ ".$TEMPDIR" != . ]; then @@ -382,12 +387,40 @@ if [ ".$gen_tmpfile" = .yes ]; then else tmpdir="/tmp" fi - tmpfile="$tmpdir/.shtool.$$" - rm -f $tmpfile >/dev/null 2>&1 - touch $tmpfile - chmod 600 $tmpfile + tmpdir="$tmpdir/.shtool.$$" + ( umask 077 + rm -rf "$tmpdir" >/dev/null 2>&1 || true + mkdir "$tmpdir" >/dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "$msgprefix:Error: failed to create temporary directory \`$tmpdir'" 1>&2 + exit 1 + fi + ) + + # create (implicitly) secure temporary file + tmpfile="$tmpdir/shtool.tmp" + touch "$tmpfile" fi +# utility function: map string to lower case +util_lower () { + echo "$1" | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' +} + +# utility function: map string to upper case +util_upper () { + echo "$1" | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +} + +# cleanup procedure +shtool_exit () { + rc="$1" + if [ ".$gen_tmpfile" = .yes ]; then + rm -rf "$tmpdir" >/dev/null 2>&1 || true + fi + exit $rc +} + ## ## DISPATCH INTO SCRIPT BODY ## @@ -397,12 +430,11 @@ case $tool in echo ) ## ## echo -- Print string with optional construct expansion - ## Copyright (c) 1998-2002 Ralf S. Engelschall - ## Originally written for WML as buildinfo + ## Copyright (c) 1998-2005 Ralf S. Engelschall ## - + text="$*" - + # check for broken escape sequence expansion seo='' bytes=`echo '\1' | wc -c | awk '{ printf("%s", $1); }'` @@ -412,18 +444,18 @@ echo ) seo='-E' fi fi - + # check for existing -n option (to suppress newline) minusn='' bytes=`echo -n 123 2>/dev/null | wc -c | awk '{ printf("%s", $1); }'` if [ ".$bytes" = .3 ]; then minusn='-n' fi - + # determine terminal bold sequence term_bold='' term_norm='' - if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%[Bb]'`" != . ]; then + if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%[Bb]'`" != . ]; then case $TERM in # for the most important terminal types we directly know the sequences xterm|xterm*|vt220|vt220*) @@ -459,96 +491,139 @@ echo ) break fi done - if [ ".$term_bold" != . -a ".$term_norm" != . ]; then + if [ ".$term_bold" != . ] && [ ".$term_norm" != . ]; then break; fi done ;; esac - if [ ".$term_bold" = . -o ".$term_norm" = . ]; then + if [ ".$term_bold" = . ] || [ ".$term_norm" = . ]; then echo "$msgprefix:Warning: unable to determine terminal sequence for bold mode" 1>&2 term_bold='' term_norm='' fi fi - + # determine user name username='' - if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%[uUgG]'`" != . ]; then - username="$LOGNAME" + if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%[uUgG]'`" != . ]; then + username="`(id -un) 2>/dev/null`" if [ ".$username" = . ]; then - username="$USER" + str="`(id) 2>/dev/null`" + if [ ".`echo $str | grep '^uid[ ]*=[ ]*[0-9]*('`" != . ]; then + username=`echo $str | sed -e 's/^uid[ ]*=[ ]*[0-9]*(//' -e 's/).*$//'` + fi if [ ".$username" = . ]; then - username="`(whoami) 2>/dev/null |\ - awk '{ printf("%s", $1); }'`" + username="$LOGNAME" if [ ".$username" = . ]; then - username="`(who am i) 2>/dev/null |\ - awk '{ printf("%s", $1); }'`" + username="$USER" if [ ".$username" = . ]; then - username='unknown' + username="`(whoami) 2>/dev/null |\ + awk '{ printf("%s", $1); }'`" + if [ ".$username" = . ]; then + username="`(who am i) 2>/dev/null |\ + awk '{ printf("%s", $1); }'`" + if [ ".$username" = . ]; then + username='unknown' + fi + fi fi fi fi fi fi - + # determine user id userid='' - if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%U'`" != . ]; then + if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%U'`" != . ]; then userid="`(id -u) 2>/dev/null`" if [ ".$userid" = . ]; then - str="`(id) 2>/dev/null`" - if [ ".`echo $str | grep '^uid[ ]*=[ ]*[0-9]*('`" != . ]; then - userid=`echo $str | sed -e 's/^uid[ ]*=[ ]*//' -e 's/(.*//'` - fi + userid="`(id -u ${username}) 2>/dev/null`" if [ ".$userid" = . ]; then - userid=`egrep "^${username}:" /etc/passwd 2>/dev/null | \ - sed -e 's/[^:]*:[^:]*://' -e 's/:.*$//'` + str="`(id) 2>/dev/null`" + if [ ".`echo $str | grep '^uid[ ]*=[ ]*[0-9]*('`" != . ]; then + userid=`echo $str | sed -e 's/^uid[ ]*=[ ]*//' -e 's/(.*$//'` + fi if [ ".$userid" = . ]; then - userid=`(ypcat passwd) 2>/dev/null | - egrep "^${username}:" | \ + userid=`(getent passwd ${username}) 2>/dev/null | \ sed -e 's/[^:]*:[^:]*://' -e 's/:.*$//'` if [ ".$userid" = . ]; then - userid='?' + userid=`grep "^${username}:" /etc/passwd 2>/dev/null | \ + sed -e 's/[^:]*:[^:]*://' -e 's/:.*$//'` + if [ ".$userid" = . ]; then + userid=`(ypcat passwd) 2>/dev/null | + grep "^${username}:" | \ + sed -e 's/[^:]*:[^:]*://' -e 's/:.*$//'` + if [ ".$userid" = . ]; then + userid='?' + fi + fi fi fi fi fi fi - + # determine (primary) group id groupid='' - if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%[gG]'`" != . ]; then - groupid=`egrep "^${username}:" /etc/passwd 2>/dev/null | \ - sed -e 's/[^:]*:[^:]*:[^:]*://' -e 's/:.*$//'` + if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%[gG]'`" != . ]; then + groupid="`(id -g ${username}) 2>/dev/null`" if [ ".$groupid" = . ]; then - groupid=`(ypcat passwd) 2>/dev/null | egrep "^${username}:" | \ - sed -e 's/[^:]*:[^:]*:[^:]*://' -e 's/:.*$//'` + str="`(id) 2>/dev/null`" + if [ ".`echo $str | grep 'gid[ ]*=[ ]*[0-9]*('`" != . ]; then + groupid=`echo $str | sed -e 's/^.*gid[ ]*=[ ]*//' -e 's/(.*$//'` + fi if [ ".$groupid" = . ]; then - groupid='?' + groupid=`(getent passwd ${username}) 2>/dev/null | \ + sed -e 's/[^:]*:[^:]*:[^:]*://' -e 's/:.*$//'` + if [ ".$groupid" = . ]; then + groupid=`grep "^${username}:" /etc/passwd 2>/dev/null | \ + sed -e 's/[^:]*:[^:]*:[^:]*://' -e 's/:.*$//'` + if [ ".$groupid" = . ]; then + groupid=`(ypcat passwd) 2>/dev/null | grep "^${username}:" | \ + sed -e 's/[^:]*:[^:]*:[^:]*://' -e 's/:.*$//'` + if [ ".$groupid" = . ]; then + groupid='?' + fi + fi + fi fi fi fi - + # determine (primary) group name groupname='' - if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%g'`" != . ]; then - groupname=`egrep "^[^:]*:[^:]*:${groupid}:" /etc/group 2>/dev/null | \ - sed -e 's/:.*$//'` + if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%g'`" != . ]; then + groupname="`(id -gn ${username}) 2>/dev/null`" if [ ".$groupname" = . ]; then - groupname=`(ypcat group) 2>/dev/null | \ - egrep "^[^:]*:[^:]*:${groupid}:" | \ - sed -e 's/:.*$//'` + str="`(id) 2>/dev/null`" + if [ ".`echo $str | grep 'gid[ ]*=[ ]*[0-9]*('`" != . ]; then + groupname=`echo $str | sed -e 's/^.*gid[ ]*=[ ]*[0-9]*(//' -e 's/).*$//'` + fi if [ ".$groupname" = . ]; then - groupname='?' + groupname=`(getent group) 2>/dev/null | \ + grep "^[^:]*:[^:]*:${groupid}:" | \ + sed -e 's/:.*$//'` + if [ ".$groupname" = . ]; then + groupname=`grep "^[^:]*:[^:]*:${groupid}:" /etc/group 2>/dev/null | \ + sed -e 's/:.*$//'` + if [ ".$groupname" = . ]; then + groupname=`(ypcat group) 2>/dev/null | \ + grep "^[^:]*:[^:]*:${groupid}:" | \ + sed -e 's/:.*$//'` + if [ ".$groupname" = . ]; then + groupname='?' + fi + fi + fi fi fi fi - + # determine host and domain name hostname='' domainname='' - if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%h'`" != . ]; then + if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%h'`" != . ]; then hostname="`(uname -n) 2>/dev/null |\ awk '{ printf("%s", $1); }'`" if [ ".$hostname" = . ]; then @@ -565,16 +640,16 @@ echo ) ;; esac fi - if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%d'`" != . ]; then + if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%d'`" != . ]; then if [ ".$domainname" = . ]; then if [ -f /etc/resolv.conf ]; then - domainname="`egrep '^[ ]*domain' /etc/resolv.conf | sed -e 'q' |\ + domainname="`grep '^[ ]*domain' /etc/resolv.conf | sed -e 'q' |\ sed -e 's/.*domain//' \ -e 's/^[ ]*//' -e 's/^ *//' -e 's/^ *//' \ -e 's/^\.//' -e 's/^/./' |\ awk '{ printf("%s", $1); }'`" if [ ".$domainname" = . ]; then - domainname="`egrep '^[ ]*search' /etc/resolv.conf | sed -e 'q' |\ + domainname="`grep '^[ ]*search' /etc/resolv.conf | sed -e 'q' |\ sed -e 's/.*search//' \ -e 's/^[ ]*//' -e 's/^ *//' -e 's/^ *//' \ -e 's/ .*//' -e 's/ .*//' \ @@ -584,13 +659,13 @@ echo ) fi fi fi - + # determine current time time_day='' time_month='' time_year='' time_monthname='' - if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%[DMYm]'`" != . ]; then + if [ ".$opt_e" = .yes ] && [ ".`echo $text | grep '%[DMYm]'`" != . ]; then time_day=`date '+%d'` time_month=`date '+%m'` time_year=`date '+%Y' 2>/dev/null` @@ -616,7 +691,7 @@ echo ) 12) time_monthname='Dec' ;; esac fi - + # expand special ``%x'' constructs if [ ".$opt_e" = .yes ]; then text=`echo $seo "$text" |\ @@ -633,7 +708,7 @@ echo ) -e "s/%Y/${time_year}/g" \ -e "s/%m/${time_monthname}/g" 2>/dev/null` fi - + # create output if [ .$opt_n = .no ]; then echo $seo "$text" @@ -646,15 +721,16 @@ echo ) echo dummy | awk '{ printf("%s", TEXT); }' TEXT="$text" fi fi + + shtool_exit 0 ;; install ) ## ## install -- Install a program, script or datafile - ## Copyright (c) 1997-2002 Ralf S. Engelschall - ## Originally written for shtool + ## Copyright (c) 1997-2005 Ralf S. Engelschall ## - + # special case: "shtool install -d [...]" internally # maps to "shtool mkdir -f -p -m 755 [...]" if [ "$opt_d" = yes ]; then @@ -672,11 +748,11 @@ install ) cmd="$cmd -t" fi for dir in "$@"; do - eval "$cmd $dir" || exit $? + eval "$cmd $dir" || shtool_exit $? done - exit 0 + shtool_exit 0 fi - + # determine source(s) and destination argc=$# srcs="" @@ -685,30 +761,30 @@ install ) shift done dstpath="$1" - + # type check for destination dstisdir=0 if [ -d $dstpath ]; then dstpath=`echo "$dstpath" | sed -e 's:/$::'` dstisdir=1 fi - + # consistency check for destination - if [ $argc -gt 2 -a $dstisdir = 0 ]; then + if [ $argc -gt 2 ] && [ $dstisdir = 0 ]; then echo "$msgprefix:Error: multiple sources require destination to be directory" 1>&2 - exit 1 + shtool_exit 1 fi - + # iterate over all source(s) for src in $srcs; do dst=$dstpath - + # if destination is a directory, append the input filename if [ $dstisdir = 1 ]; then dstfile=`echo "$src" | sed -e 's;.*/\([^/]*\)$;\1;'` dst="$dst/$dstfile" fi - + # check for correct arguments if [ ".$src" = ".$dst" ]; then echo "$msgprefix:Warning: source and destination are the same - skipped" 1>&2 @@ -718,17 +794,17 @@ install ) echo "$msgprefix:Warning: source \`$src' is a directory - skipped" 1>&2 continue fi - + # make a temp file name in the destination directory dsttmp=`echo $dst |\ sed -e 's;[^/]*$;;' -e 's;\(.\)/$;\1;' -e 's;^$;.;' \ -e "s;\$;/#INST@$$#;"` - + # verbosity if [ ".$opt_v" = .yes ]; then echo "$src -> $dst" 1>&2 fi - + # copy or move the file name to the temp name # (because we might be not allowed to change the source) if [ ".$opt_C" = .yes ]; then @@ -738,14 +814,14 @@ install ) if [ ".$opt_t" = .yes ]; then echo "cp $src $dsttmp" 1>&2 fi - cp $src $dsttmp || exit $? + cp $src $dsttmp || shtool_exit $? else if [ ".$opt_t" = .yes ]; then echo "mv $src $dsttmp" 1>&2 fi - mv $src $dsttmp || exit $? + mv $src $dsttmp || shtool_exit $? fi - + # adjust the target file if [ ".$opt_e" != . ]; then sed='sed' @@ -755,34 +831,35 @@ install ) sed="$sed -e '$e'" done cp $dsttmp $dsttmp.old - eval "$sed <$dsttmp.old >$dsttmp" || exit $? + chmod u+w $dsttmp + eval "$sed <$dsttmp.old >$dsttmp" || shtool_exit $? rm -f $dsttmp.old fi if [ ".$opt_s" = .yes ]; then if [ ".$opt_t" = .yes ]; then echo "strip $dsttmp" 1>&2 fi - strip $dsttmp || exit $? + strip $dsttmp || shtool_exit $? fi if [ ".$opt_o" != . ]; then if [ ".$opt_t" = .yes ]; then echo "chown $opt_o $dsttmp" 1>&2 fi - chown $opt_o $dsttmp || exit $? + chown $opt_o $dsttmp || shtool_exit $? fi if [ ".$opt_g" != . ]; then if [ ".$opt_t" = .yes ]; then echo "chgrp $opt_g $dsttmp" 1>&2 fi - chgrp $opt_g $dsttmp || exit $? + chgrp $opt_g $dsttmp || shtool_exit $? fi if [ ".$opt_m" != ".-" ]; then if [ ".$opt_t" = .yes ]; then echo "chmod $opt_m $dsttmp" 1>&2 fi - chmod $opt_m $dsttmp || exit $? + chmod $opt_m $dsttmp || shtool_exit $? fi - + # determine whether to do a quick install # (has to be done _after_ the strip was already done) quick=no @@ -793,7 +870,7 @@ install ) fi fi fi - + # finally, install the file to the real destination if [ $quick = yes ]; then if [ ".$opt_t" = .yes ]; then @@ -807,21 +884,21 @@ install ) rm -f $dst && mv $dsttmp $dst fi done + + shtool_exit 0 ;; mkdir ) ## ## mkdir -- Make one or more directories - ## Copyright (c) 1996-2002 Ralf S. Engelschall - ## Originally written for public domain by Noah Friedman - ## Cleaned up and enhanced for shtool + ## Copyright (c) 1996-2005 Ralf S. Engelschall ## - + errstatus=0 for p in ${1+"$@"}; do # if the directory already exists... if [ -d "$p" ]; then - if [ ".$opt_f" = .no -a ".$opt_p" = .no ]; then + if [ ".$opt_f" = .no ] && [ ".$opt_p" = .no ]; then echo "$msgprefix:Error: directory already exists: $p" 1>&2 errstatus=1 break @@ -895,32 +972,32 @@ mkdir ) done fi done - exit $errstatus + + shtool_exit $errstatus ;; path ) ## ## path -- Deal with program paths - ## Copyright (c) 1998-2002 Ralf S. Engelschall - ## Originally written for Apache + ## Copyright (c) 1998-2005 Ralf S. Engelschall ## - + namelist="$*" - + # check whether the test command supports the -x option if [ -x /bin/sh ] 2>/dev/null; then minusx="-x" else minusx="-r" fi - + # split path string paths="`echo $opt_p |\ sed -e 's/^:/.:/' \ -e 's/::/:.:/g' \ -e 's/:$/:./' \ -e 's/:/ /g'`" - + # SPECIAL REQUEST # translate forward to reverse path if [ ".$opt_r" = .yes ]; then @@ -933,25 +1010,25 @@ path ) done fi echo $rp | sed -e 's:/$::' - exit 0 + shtool_exit 0 fi - + # SPECIAL REQUEST # strip out directory or base name if [ ".$opt_d" = .yes ]; then echo "$namelist" |\ sed -e 's;[^/]*$;;' -e 's;\(.\)/$;\1;' - exit 0 + shtool_exit 0 fi if [ ".$opt_b" = .yes ]; then echo "$namelist" |\ sed -e 's;.*/\([^/]*\)$;\1;' - exit 0 + shtool_exit 0 fi - + # MAGIC SITUATION # Perl Interpreter (perl) - if [ ".$opt_m" = .yes -a ".$namelist" = .perl ]; then + if [ ".$opt_m" = .yes ] && [ ".$namelist" = .perl ]; then rm -f $tmpfile >/dev/null 2>&1 touch $tmpfile found=0 @@ -960,7 +1037,7 @@ path ) dir=`echo $dir | sed -e 's;/*$;;'` nc=99 for name in perl perl5 miniperl; do - if [ $minusx "$dir/$name" -a ! -d "$dir/$name" ]; then + if [ $minusx "$dir/$name" ] && [ ! -d "$dir/$name" ]; then perl="$dir/$name" pv=`$perl -e 'printf("%.3f", $]);'` echo "$pv:$pc:$nc:$perl" >>$tmpfile @@ -974,15 +1051,15 @@ path ) perl="`cat $tmpfile | sort -r -u | sed -e 'q' | cut -d: -f4`" rm -f $tmpfile >/dev/null 2>&1 echo "$perl" - exit 0 + shtool_exit 0 fi rm -f $tmpfile >/dev/null 2>&1 - exit 1 + shtool_exit 1 fi - + # MAGIC SITUATION # C pre-processor (cpp) - if [ ".$opt_m" = .yes -a ".$namelist" = .cpp ]; then + if [ ".$opt_m" = .yes ] && [ ".$namelist" = .cpp ]; then echo >$tmpfile.c "#include " echo >>$tmpfile.c "Syntax Error" # 1. try the standard cc -E approach @@ -998,7 +1075,7 @@ path ) # 3. try a standalone cpp command in path and lib dirs for path in $paths /lib /usr/lib /usr/local/lib; do path=`echo $path | sed -e 's;/*$;;'` - if [ $minusx "$path/cpp" -a ! -d "$path/cpp" ]; then + if [ $minusx "$path/cpp" ] && [ ! -d "$path/cpp" ]; then cpp="$path/cpp" break fi @@ -1017,30 +1094,30 @@ path ) rm -f $tmpfile.c $tmpfile.out >/dev/null 2>&1 if [ ".$cpp" != . ]; then echo "$cpp" - exit 0 + shtool_exit 0 fi - exit 1 + shtool_exit 1 fi - + # STANDARD SITUATION # iterate over names for name in $namelist; do # iterate over paths for path in $paths; do path=`echo $path | sed -e 's;/*$;;'` - if [ $minusx "$path/$name" -a ! -d "$path/$name" ]; then + if [ $minusx "$path/$name" ] && [ ! -d "$path/$name" ]; then if [ ".$opt_s" != .yes ]; then echo "$path/$name" fi - exit 0 + shtool_exit 0 fi done done - exit 1 + + shtool_exit 1 ;; esac -exit 0 +shtool_exit 0 -##EOF## diff --git a/buildconf b/buildconf index 95aa69c1bae5..8b91c3b14795 100755 --- a/buildconf +++ b/buildconf @@ -12,6 +12,7 @@ case "$EXTRA_VERSION" in esac devok=0 +debug=no while test $# -gt 0; do if test "$1" = "--copy"; then @@ -23,6 +24,10 @@ while test $# -gt 0; do echo "Forcing buildconf" fi + if test "$1" = "--debug"; then + debug=yes + fi + shift done @@ -48,17 +53,21 @@ if test -z "$ZENDDIR"; then fi else if test -r "Zend/zend_execute_globals.h"; then - : + : else mv Zend ZendEngine2 2>/dev/null mv ZendEngine1 Zend fi fi - + ZENDDIR=Zend echo "using default Zend directory" fi rm -f generated_lists -${MAKE:-make} -s -f build/build.mk AMFLAGS="$automake_flags" ZENDDIR="$ZENDDIR" +if test "$debug" = "yes"; then + ${MAKE:-make} -s -f build/build.mk AMFLAGS="$automake_flags" ZENDDIR="$ZENDDIR" SUPPRESS_WARNINGS="" +else + ${MAKE:-make} -s -f build/build.mk AMFLAGS="$automake_flags" ZENDDIR="$ZENDDIR" +fi diff --git a/config.guess b/config.guess index 5145e3571799..78f6b92cd307 100644 --- a/config.guess +++ b/config.guess @@ -1,9 +1,9 @@ #! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002 Free Software Foundation, Inc. +# 2000, 2001, 2002, 2003 Free Software Foundation, Inc. -timestamp='2002-10-21' +timestamp='2003-01-10' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -98,14 +98,17 @@ trap 'exit 1' 1 2 15 # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. -# This shell variable is my proudest work .. or something. --bje +# Portable tmp directory creation inspired by the Autoconf team. -set_cc_for_build='tmpdir=${TMPDIR-/tmp}/config-guess-$$ ; -(old=`umask` && umask 077 && mkdir $tmpdir && umask $old && unset old) - || (echo "$me: cannot create $tmpdir" >&2 && exit 1) ; -dummy=$tmpdir/dummy ; -files="$dummy.c $dummy.o $dummy.rel $dummy" ; -trap '"'"'rm -f $files; rmdir $tmpdir; exit 1'"'"' 1 2 15 ; +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do @@ -113,15 +116,13 @@ case $CC_FOR_BUILD,$HOST_CC,$CC in CC_FOR_BUILD="$c"; break ; fi ; done ; - rm -f $files ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; -unset files' +esac ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) @@ -178,7 +179,18 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in ;; esac # The OS release - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. @@ -223,6 +235,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:OpenBSD:*:*) echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} exit 0 ;; + *:MicroBSD:*:*) + echo ${UNAME_MACHINE}-unknown-microbsd${UNAME_RELEASE} + exit 0 ;; alpha:OSF1:*:*) if test $UNAME_RELEASE = "V4.0"; then UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` @@ -286,7 +301,6 @@ EOF ;; esac fi - rm -f $dummy.s $dummy && rmdir $tmpdir echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit 0 ;; Alpha\ *:Windows_NT*:*) @@ -439,8 +453,7 @@ EOF EOF $CC_FOR_BUILD -o $dummy $dummy.c \ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ - && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 - rm -f $dummy.c $dummy && rmdir $tmpdir + && exit 0 echo mips-mips-riscos${UNAME_RELEASE} exit 0 ;; Motorola:PowerMAX_OS:*:*) @@ -449,7 +462,7 @@ EOF Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit 0 ;; - Night_Hawk:*:*:PowerMAX_OS) + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit 0 ;; Night_Hawk:Power_UNIX:*:*) @@ -524,8 +537,7 @@ EOF exit(0); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 - rm -f $dummy.c $dummy && rmdir $tmpdir + $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 echo rs6000-ibm-aix3.2.5 elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 @@ -624,10 +636,20 @@ EOF } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` - if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi - rm -f $dummy.c $dummy && rmdir $tmpdir + test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + # avoid double evaluation of $set_cc_for_build + test -n "$CC_FOR_BUILD" || eval $set_cc_for_build + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit 0 ;; ia64:HP-UX:*:*) @@ -661,8 +683,7 @@ EOF exit (0); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 - rm -f $dummy.c $dummy && rmdir $tmpdir + $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 echo unknown-hitachi-hiuxwe2 exit 0 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) @@ -720,15 +741,15 @@ EOF CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; - CRAY*T3D:*:*:*) - echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; + *:UNICOS/mp:*:*) + echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` @@ -756,7 +777,6 @@ EOF #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` - rm -f $dummy.c && rmdir $tmpdir echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC} exit 0 ;; i*:CYGWIN*:*) @@ -769,13 +789,16 @@ EOF echo ${UNAME_MACHINE}-pc-pw32 exit 0 ;; x86:Interix*:3*) - echo i386-pc-interix3 + echo i586-pc-interix3 + exit 0 ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks exit 0 ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? - echo i386-pc-interix + echo i586-pc-interix exit 0 ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin @@ -818,8 +841,26 @@ EOF #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` - rm -f $dummy.c && rmdir $tmpdir - test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0 + test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu @@ -914,7 +955,6 @@ EOF #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` - rm -f $dummy.c && rmdir $tmpdir test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 ;; @@ -932,6 +972,23 @@ EOF # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit 0 ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit 0 ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit 0 ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit 0 ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then @@ -966,9 +1023,6 @@ EOF echo ${UNAME_MACHINE}-pc-sysv32 fi exit 0 ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit 0 ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about @@ -995,9 +1049,12 @@ EOF mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit 0 ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit 0 ;; M68*:*:R3V[567]*:*) test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; - 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0) + 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` @@ -1014,9 +1071,6 @@ EOF mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit 0 ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; @@ -1098,7 +1152,11 @@ EOF echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Darwin:*:*) - echo `uname -p`-apple-darwin${UNAME_RELEASE} + case `uname -p` in + *86) UNAME_PROCESSOR=i686 ;; + powerpc) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit 0 ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` @@ -1134,11 +1192,6 @@ EOF fi echo ${UNAME_MACHINE}-unknown-plan9 exit 0 ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit 0 ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit 0 ;; @@ -1157,12 +1210,6 @@ EOF *:ITS:*:*) echo pdp10-unknown-its exit 0 ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop - exit 0 ;; - i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos - exit 0 ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 @@ -1283,8 +1330,7 @@ main () } EOF -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 -rm -f $dummy.c $dummy && rmdir $tmpdir +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0 # Apollos put the system type in the environment. diff --git a/config.sub b/config.sub index 1dea9b79d550..d6d67c3fd9d5 100644 --- a/config.sub +++ b/config.sub @@ -1,9 +1,9 @@ #! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002 Free Software Foundation, Inc. +# 2000, 2001, 2002, 2003 Free Software Foundation, Inc. -timestamp='2002-09-05' +timestamp='2003-01-03' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -118,7 +118,7 @@ esac # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in - nto-qnx* | linux-gnu* | freebsd*-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*) + nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; @@ -245,16 +245,19 @@ case $basic_machine in | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ + | msp430 \ | ns16k | ns32k \ | openrisc | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ + | s390 | s390x \ | sh | sh[1234] | sh3e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ @@ -315,16 +318,19 @@ case $basic_machine in | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipstx39 | mipstx39el \ - | none-* | np1-* | ns16k-* | ns32k-* \ + | mipstx39-* | mipstx39el-* \ + | msp430-* \ + | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ + | s390-* | s390x-* \ | sh-* | sh[1234]-* | sh3e-* | sh[34]eb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ @@ -716,6 +722,10 @@ case $basic_machine in np1) basic_machine=np1-gould ;; + nv1) + basic_machine=nv1-cray + os=-unicosmp + ;; nsr-tandem) basic_machine=nsr-tandem ;; @@ -812,12 +822,6 @@ case $basic_machine in rtpc | rtpc-*) basic_machine=romp-ibm ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; sa29200) basic_machine=a29k-amd os=-udi @@ -901,10 +905,6 @@ case $basic_machine in basic_machine=i386-sequent os=-dynix ;; - t3d) - basic_machine=alpha-cray - os=-unicos - ;; t3e) basic_machine=alphaev5-cray os=-unicos @@ -977,10 +977,6 @@ case $basic_machine in basic_machine=hppa1.1-winbond os=-proelf ;; - windows32) - basic_machine=i386-pc - os=-windows32-msvcrt - ;; xps | xps100) basic_machine=xps100-honeywell ;; @@ -1113,11 +1109,12 @@ case $os in | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* | -powermax*) + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -microbsd*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1129,8 +1126,10 @@ case $os in ;; esac ;; + -nto-qnx*) + ;; -nto*) - os=-nto-qnx + os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ diff --git a/configure.in b/configure.in index 3a417526635e..8e3405f934b3 100644 --- a/configure.in +++ b/configure.in @@ -35,20 +35,20 @@ for arg in $0 "$@"; do CONFIGURE_COMMAND="$CONFIGURE_COMMAND '$arg'" done -AC_CANONICAL_HOST +PHP_CANONICAL_HOST AC_CONFIG_HEADER(main/php_config.h) MAJOR_VERSION=5 MINOR_VERSION=0 -RELEASE_VERSION=1 -EXTRA_VERSION="-dev" +RELEASE_VERSION=5 +EXTRA_VERSION="-p1" VERSION="$MAJOR_VERSION.$MINOR_VERSION.$RELEASE_VERSION$EXTRA_VERSION" dnl Define where extension directories are located in the configure context -AC_DEFUN(PHP_EXT_BUILDDIR,[ext/$1])dnl -AC_DEFUN(PHP_EXT_DIR,[ext/$1])dnl -AC_DEFUN(PHP_EXT_SRCDIR,[$abs_srcdir/ext/$1])dnl -AC_DEFUN(PHP_ALWAYS_SHARED,[])dnl +AC_DEFUN([PHP_EXT_BUILDDIR],[ext/$1])dnl +AC_DEFUN([PHP_EXT_DIR],[ext/$1])dnl +AC_DEFUN([PHP_EXT_SRCDIR],[$abs_srcdir/ext/$1])dnl +AC_DEFUN([PHP_ALWAYS_SHARED],[])dnl dnl Setting up the PHP version based on the information above. dnl ------------------------------------------------------------------------- @@ -81,7 +81,11 @@ if test -n "$with_apache" && test -n "$with_apxs"; then AC_MSG_ERROR([--with-apache and --with-apxs cannot be used together]) fi +if test -n "$with_apxs2filter" && test -n "$with_apxs2"; then + AC_MSG_ERROR([--with-apxs2filter and --with-apxs2 cannot be used together]) +fi + dnl Settings we want to make before the checks. dnl ------------------------------------------------------------------------- @@ -128,7 +132,6 @@ dnl check for -R, etc. switch PHP_RUNPATH_SWITCH PHP_PROG_RE2C -AC_PROG_RANLIB AC_PROG_LN_S AC_PROG_AWK AC_PROG_YACC @@ -170,13 +173,23 @@ else AC_MSG_WARN(You will need flex 2.5.4 or later if you want to regenerate Zend/PHP lexical parsers.) fi +dnl Check whether byte ordering is bigendian +PHP_C_BIGENDIAN + + dnl Platform-specific compile settings. dnl ------------------------------------------------------------------------- -dnl if host_alias is empty, ac_cv_host_alias may still have the info -if test -z "$host_alias"; then - host_alias=$ac_cv_host_alias -fi +dnl See bug #28605 +case $host_cpu in +alpha*) + if test "$GCC" = "yes"; then + CFLAGS="$CFLAGS -mieee" + else + CFLAGS="$CFLAGS -ieee" + fi + ;; +esac case $host_alias in *solaris*) @@ -196,6 +209,35 @@ case $host_alias in LIBS="$LIBS -lbe -lroot";; *mips*) CPPFLAGS="$CPPFLAGS -D_XPG_IV";; +*hpux*) + if test "$GCC" = "yes"; then + CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE_EXTENDED" + fi + ;; +*netware*) + PHP_BUILD_PROGRAM + PHP_ADD_SOURCES(/main, internal_functions.c,,PHP_GLOBAL_OBJS) + PHP_ADD_SOURCES(win32, sendmail.c, -I$CFLAGS, PHP_GLOBAL_OBJS) + PHP5LIB_SHARED_LIBADD=\$\(EXTRA_LIBS\) + EXTENSION_DIR=sys:/php$MAJOR_VERSION/ext + PHP_SUBST(PHP5LIB_SHARED_LIBADD) + PHP_SHARED_MODULE(php5lib, PHP_GLOBAL_OBJS, netware) + ;; +esac + +# Disable PIC mode by default where it is known to be safe to do so, +# to avoid the performance hit from the lost register +AC_MSG_CHECKING([whether to force non-PIC code in shared modules]) +case $host_alias in +i?86-*-linux*|i?86-*-freebsd*) + if test "${with_pic+set}" != "set" || test "$with_pic" = "no"; then + with_pic=no + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi + ;; +*) AC_MSG_RESULT(no) ;; esac @@ -278,7 +320,6 @@ if test -d /usr/pkg/include -a -d /usr/pkg/lib ; then CPPFLAGS="$CPPFLAGS -I/usr/pkg/include" LDFLAGS="$LDFLAGS -L/usr/pkg/lib" fi -INCLUDES="$INCLUDES -I\$(top_builddir)/Zend" test -d /usr/ucblib && PHP_ADD_LIBPATH(/usr/ucblib) @@ -323,6 +364,8 @@ AC_HEADER_DIRENT PHP_MISSING_FCLOSE_DECL dnl QNX requires unix.h to allow functions in libunix to work properly AC_CHECK_HEADERS([ \ +inttypes.h \ +stdint.h \ dirent.h \ ApplicationServices/ApplicationServices.h \ sys/param.h \ @@ -371,8 +414,7 @@ unix.h \ utime.h \ sys/utsname.h \ sys/ipc.h \ -dlfcn.h \ -inttypes.h +dlfcn.h ],[],[],[ #ifdef HAVE_SYS_PARAM_H #include @@ -545,17 +587,20 @@ AC_CACHE_CHECK([for getaddrinfo], ac_cv_func_getaddrinfo, AC_TRY_RUN([ #include #include +#ifndef AF_INET +# include +#endif int main(void) { struct addrinfo *ai, *pai, hints; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_NUMERICHOST; - if (getaddrinfo("127.0.0.1", NULL, &hints, &ai) < 0) { + if (getaddrinfo("127.0.0.1", 0, &hints, &ai) < 0) { exit(1); } - if (ai == NULL) { + if (ai == 0) { exit(1); } @@ -584,8 +629,8 @@ fi AC_REPLACE_FUNCS(strlcat strlcpy getopt) AC_FUNC_UTIME_NULL AC_FUNC_ALLOCA -PHP_AC_BROKEN_SPRINTF -PHP_AC_BROKEN_SNPRINTF +dnl PHP_AC_BROKEN_SPRINTF +dnl PHP_AC_BROKEN_SNPRINTF PHP_DECLARED_TIMEZONE PHP_TIME_R_TYPE PHP_READDIR_R_TYPE @@ -765,6 +810,19 @@ if test "$PHP_IPV6" != "no" && test "$ac_cv_ipv6_support" = yes; then AC_DEFINE(HAVE_IPV6,1,[Whether to enable IPv6 support]) fi +AC_MSG_CHECKING([how big to make fd sets]) +AC_ARG_ENABLE(fd-setsize, +[ --enable-fd-setsize Set size of descriptor sets],[ + if test "x$enableval" != "xyes"; then + CPPFLAGS="$CPPFLAGS -DFD_SETSIZE=$enableval" + AC_MSG_RESULT(using $enableval) + else + AC_MSG_RESULT(using system default) + fi +],[ + AC_MSG_RESULT(using system default) +]) + AC_MSG_CHECKING([whether to enable versioning]) AC_ARG_ENABLE(versioning, [ --enable-versioning Export only required symbols. @@ -826,7 +884,6 @@ fi enable_shared=yes enable_static=yes -unset with_pic case $php_build_target in program|static) @@ -837,7 +894,10 @@ program|static) ;; shared) enable_static=no - standard_libtool_flag=-prefer-pic + case $with_pic in + yes) standard_libtool_flag='-prefer-pic';; + no) standard_libtool_flag='-prefer-non-pic';; + esac EXTRA_LDFLAGS="$EXTRA_LDFLAGS -avoid-version -module" ;; esac @@ -863,6 +923,11 @@ if test -z "$with_pear" && test "$enable_pear" = "no"; then with_pear=no fi +# If CLI is disabled -> disable PEAR +if test "$PHP_SAPI_CLI" = "no"; then + with_pear=no +fi + PHP_ARG_WITH(pear, [whether to install PEAR], [ --with-pear=DIR Install PEAR in DIR (default PREFIX/lib/php) --without-pear Do not install PEAR], DEFAULT, yes) @@ -872,17 +937,13 @@ if test "$PHP_PEAR" != "no"; then dnl dnl PEAR dependancies dnl - if test "$PHP_SAPI_CLI" = "no"; then - pear_error_msg="$pear_error_msg - PEAR requires CLI to be enabled. Add --enable-cli to the configure line. (or --disable-pear)" - fi if test "$PHP_PCRE_REGEX" = "no"; then pear_error_msg="$pear_error_msg - PEAR requires PCRE to be enabled. Add --with-pcre-regex to the configure line. (or --disable-pear)" + PEAR requires PCRE to be enabled. Add --with-pcre-regex to the configure line. (or --without-pear)" fi if test "$PHP_XML" = "no"; then pear_error_msg="$pear_error_msg - PEAR requires XML to be enabled. Add --enable-xml to the configure line. (or --disable-pear)" + PEAR requires XML to be enabled. Add --enable-xml to the configure line. (or --without-pear)" fi dnl @@ -890,7 +951,7 @@ dnl ext/xmlrpc is not really there yet to be a requirement.. dnl dnl if test "$PHP_XMLRPC" = "no"; then dnl pear_error_msg="$pear_error_msg -dnl PEAR requires XML-RPC to be enabled. Add --with-xmlrpc to the configure line. (or --disable-pear)" +dnl PEAR requires XML-RPC to be enabled. Add --with-xmlrpc to the configure line. (or --without-pear)" dnl fi dnl @@ -907,6 +968,8 @@ dnl *) PEAR_INSTALLDIR=$libdir/php;; esac fi + + PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/pear/Makefile.frag,$abs_srcdir/pear,pear) fi @@ -920,10 +983,6 @@ LIBZEND_BASIC_CHECKS LIBZEND_DLSYM_CHECK LIBZEND_OTHER_CHECKS -TSRM_LIB='TSRM/libtsrm.la' -TSRM_DIR=TSRM -CPPFLAGS="$CPPFLAGS -I\$(top_builddir)/TSRM" - if test "$ZEND_MAINTAINER_ZTS" = "yes"; then AC_DEFINE(ZTS,1,[ ]) PHP_THREAD_SAFETY=yes @@ -931,9 +990,12 @@ else PHP_THREAD_SAFETY=no fi +INCLUDES="$INCLUDES -I\$(top_builddir)/TSRM" +INCLUDES="$INCLUDES -I\$(top_builddir)/Zend" + if test "$abs_srcdir" != "$abs_builddir"; then INCLUDES="$INCLUDES -I\$(top_srcdir)/main -I\$(top_srcdir)/Zend" - INCLUDES="$INCLUDES -I\$(top_srcdir)/TSRM" + INCLUDES="$INCLUDES -I\$(top_srcdir)/TSRM -I\$(top_builddir)/" fi ZEND_EXTRA_LIBS="$LIBS" @@ -1052,10 +1114,20 @@ EXTRA_LDFLAGS_PROGRAM="$EXTRA_LDFLAGS_PROGRAM $PHP_LDFLAGS" PHP_BUILD_DATE=`date '+%Y-%m-%d'` AC_DEFINE_UNQUOTED(PHP_BUILD_DATE,"$PHP_BUILD_DATE",[PHP build date]) -PHP_UNAME=`uname -a | xargs` -AC_DEFINE_UNQUOTED(PHP_UNAME,"$PHP_UNAME",[uname -a output]) -PHP_OS=`uname | xargs` -AC_DEFINE_UNQUOTED(PHP_OS,"$PHP_OS",[uname output]) +case $host_alias in +*netware*) + PHP_OS="NetWare" + PHP_UNAME="NetWare" + AC_DEFINE_UNQUOTED(PHP_OS,"$PHP_OS",[hardcode for each of the cross compiler host]) + AC_DEFINE_UNQUOTED(PHP_UNAME,"$PHP_UNAME",[hardcode for each of the cross compiler host]) + ;; +*) + PHP_UNAME=`uname -a | xargs` + AC_DEFINE_UNQUOTED(PHP_UNAME,"$PHP_UNAME",[uname -a output]) + PHP_OS=`uname | xargs` + AC_DEFINE_UNQUOTED(PHP_OS,"$PHP_OS",[uname output]) + ;; +esac if test "$PHP_SAPI_CLI" != "no"; then PHP_CLI_TARGET="\$(SAPI_CLI_PATH)" @@ -1092,6 +1164,7 @@ PHP_SUBST(datadir) PHP_SUBST(sysconfdir) PHP_SUBST(AWK) +PHP_SUBST(EXEEXT) PHP_SUBST(CC) PHP_SUBST(CFLAGS) PHP_SUBST(CFLAGS_CLEAN) @@ -1103,7 +1176,6 @@ PHP_SUBST(CXXFLAGS) PHP_SUBST(CXXFLAGS_CLEAN) PHP_SUBST(CXX_PHP_COMPILE) PHP_SUBST_OLD(DEBUG_CFLAGS) -PHP_SUBST(DEFS) PHP_SUBST_OLD(EXTENSION_DIR) PHP_SUBST_OLD(EXTRA_LDFLAGS) PHP_SUBST_OLD(EXTRA_LDFLAGS_PROGRAM) @@ -1132,8 +1204,6 @@ PHP_SUBST(PROG_SENDMAIL) PHP_SUBST(RE2C) PHP_SUBST(SHELL) PHP_SUBST(SHARED_LIBTOOL) -PHP_SUBST(TSRM_DIR) -PHP_SUBST(TSRM_LIB) PHP_SUBST(WARNING_LEVEL) PHP_SUBST(PHP_FRAMEWORKS) PHP_SUBST(PHP_FRAMEWORKPATH) @@ -1220,7 +1290,16 @@ PHP_ADD_SOURCES(main/streams, streams.c cast.c memory.c filter.c \ plain_wrapper.c userspace.c transports.c xp_socket.c mmap.c) PHP_ADD_SOURCES(/main, internal_functions.c,, sapi) -PHP_ADD_SOURCES(/main, internal_functions_cli.c,, cli) + +case $host_alias in +*netware*) + PHP_ADD_BUILD_DIR(win32) + PHP_ADD_BUILD_DIR(netware) + ;; +*) + PHP_ADD_SOURCES(/main, internal_functions_cli.c,, cli) + ;; +esac PHP_ADD_SOURCES(/Zend, zend_language_parser.c zend_language_scanner.c \ zend_ini_parser.c zend_ini_scanner.c) @@ -1232,7 +1311,7 @@ PHP_ADD_SOURCES(Zend, \ zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \ zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \ zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c zend_stream.c \ - zend_iterators.c zend_interfaces.c zend_exceptions.c) + zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c) if test -r "$abs_srcdir/Zend/zend_objects.c"; then PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c zend_mm.c \ @@ -1256,7 +1335,6 @@ PHP_ADD_BUILD_DIR(TSRM) PHP_ADD_BUILD_DIR(Zend) PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/scripts/Makefile.frag,$abs_srcdir/scripts,scripts) -PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/pear/Makefile.frag,$abs_srcdir/pear,pear) PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/Makefile.frag,$abs_srcdir/Zend,Zend) PHP_GEN_BUILD_DIRS @@ -1266,9 +1344,11 @@ AC_DEFINE([HAVE_BUILD_DEFS_H], 1, [ ]) $php_shtool mkdir -p pear/scripts $php_shtool mkdir -p scripts +$php_shtool mkdir -p scripts/man1 ALL_OUTPUT_FILES="php5.spec main/build-defs.h \ -scripts/phpize scripts/php-config \ +scripts/phpize scripts/man1/phpize.1 \ +scripts/php-config scripts/man1/php-config.1 \ $PHP_OUTPUT_FILES" AC_OUTPUT($ALL_OUTPUT_FILES, [], [ @@ -1282,12 +1362,12 @@ fi # test -d TSRM || $php_shtool mkdir TSRM -echo '#include "../main/php_config.h"' > TSRM/tsrm_config.h +echo '#include <../main/php_config.h>' > TSRM/tsrm_config.h test -d Zend || $php_shtool mkdir Zend cat >Zend/zend_config.h < #if defined(APACHE) && defined(PHP_API_VERSION) #undef HAVE_DLFCN_H #endif diff --git a/ext/bcmath/libbcmath/aclocal.m4 b/ext/bcmath/libbcmath/aclocal.m4 index f23ba2904e17..e60c9eb55c78 100644 --- a/ext/bcmath/libbcmath/aclocal.m4 +++ b/ext/bcmath/libbcmath/aclocal.m4 @@ -19,7 +19,7 @@ dnl PARTICULAR PURPOSE. dnl Usage: dnl AM_INIT_AUTOMAKE(package,version, [no-define]) -AC_DEFUN(AM_INIT_AUTOMAKE, +AC_DEFUN([AM_INIT_AUTOMAKE], [AC_REQUIRE([AC_PROG_INSTALL]) PACKAGE=[$1] AC_SUBST(PACKAGE) @@ -47,7 +47,7 @@ AC_REQUIRE([AC_PROG_MAKE_SET])]) # Check to make sure that the build environment is sane. # -AC_DEFUN(AM_SANITY_CHECK, +AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Just in case sleep 1 @@ -88,7 +88,7 @@ AC_MSG_RESULT(yes)]) dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY) dnl The program must properly implement --version. -AC_DEFUN(AM_MISSING_PROG, +AC_DEFUN([AM_MISSING_PROG], [AC_MSG_CHECKING(for working $2) # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. @@ -104,7 +104,7 @@ AC_SUBST($1)]) # Like AC_CONFIG_HEADER, but automatically create stamp file. -AC_DEFUN(AM_CONFIG_HEADER, +AC_DEFUN([AM_CONFIG_HEADER], [AC_PREREQ([2.12]) AC_CONFIG_HEADER([$1]) dnl When config.status generates a header, we must update the stamp-h file. diff --git a/ext/bcmath/libbcmath/src/config.h b/ext/bcmath/libbcmath/src/config.h index 89e3e43b698c..cc29a15f9594 100644 --- a/ext/bcmath/libbcmath/src/config.h +++ b/ext/bcmath/libbcmath/src/config.h @@ -1,9 +1,7 @@ #if PHP_WIN32 #include "../../../../main/config.w32.h" -#elif defined(NETWARE) -#include "config.nw.h" #else -#include "php_config.h" +#include #endif #include "php.h" diff --git a/ext/bcmath/libbcmath/src/raisemod.c b/ext/bcmath/libbcmath/src/raisemod.c index 3f6edcc2ac16..58964bec58df 100644 --- a/ext/bcmath/libbcmath/src/raisemod.c +++ b/ext/bcmath/libbcmath/src/raisemod.c @@ -92,6 +92,7 @@ bc_raisemod (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale TSR bc_free_num (&power); bc_free_num (&exponent); bc_free_num (result); + bc_free_num (&parity); *result = temp; return 0; /* Everything is OK. */ } diff --git a/ext/bz2/bz2.c b/ext/bz2/bz2.c index 515197f9d34c..5d744d3033cd 100644 --- a/ext/bz2/bz2.c +++ b/ext/bz2/bz2.c @@ -40,9 +40,6 @@ #define PHP_BZ_ERRSTR 1 #define PHP_BZ_ERRBOTH 2 -/* Blocksize of the decompression buffer */ -#define PHP_BZ_DECOMPRESS_SIZE 4096 - function_entry bz2_functions[] = { PHP_FE(bzopen, NULL) PHP_FE(bzread, NULL) @@ -185,7 +182,7 @@ PHP_BZ2_API php_stream *_php_stream_bz2open(php_stream_wrapper *wrapper, if (bz_file == NULL) { /* that didn't work, so try and get something from the network/wrapper */ - stream = php_stream_open_wrapper(path, mode, options, opened_path); + stream = php_stream_open_wrapper(path, mode, options | STREAM_WILL_CAST, opened_path); if (stream) { int fd; @@ -196,7 +193,7 @@ PHP_BZ2_API php_stream *_php_stream_bz2open(php_stream_wrapper *wrapper, /* remove the file created by php_stream_open_wrapper(), it is not needed since BZ2 functions * failed. */ - if (!bz_file && mode[0] == 'w') { + if (opened_path && !bz_file && mode[0] == 'w') { VCWD_UNLINK(*opened_path); } } @@ -438,56 +435,49 @@ PHP_FUNCTION(bzcompress) Decompresses BZip2 compressed data */ PHP_FUNCTION(bzdecompress) { - zval **source, /* Source data to decompress */ - **zsmall; /* (Optional) user specified small */ - char *dest; /* Destination buffer, initially allocated */ - int error, /* Error container */ - iter = 1, /* Iteration count for the compression loop */ - size, /* Current size to realloc the dest buffer to */ - dest_len = PHP_BZ_DECOMPRESS_SIZE, /* Size of the destination length */ - small = 0, /* The actual small */ - argc = ZEND_NUM_ARGS(); /* Argument count */ - - if (argc < 1 || argc > 2 || zend_get_parameters_ex(argc, &source, &zsmall) == FAILURE) { - WRONG_PARAM_COUNT; + char *source, *dest; + int source_len, error; + long small = 0; + unsigned long long size = 0; + bz_stream bzs; + + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &source, &source_len, &small)) { + RETURN_FALSE; } - convert_to_string_ex(source); - - /* optional small argument handling */ - if (argc > 1) { - convert_to_long_ex(zsmall); - small = Z_LVAL_PP(zsmall); + bzs.bzalloc = NULL; + bzs.bzfree = NULL; + + if (BZ2_bzDecompressInit(&bzs, 0, small) != BZ_OK) { + RETURN_FALSE; } - /* Depending on the size of the source buffer, either allocate - the length of the source buffer or the a default decompression - size */ - dest = emalloc(PHP_BZ_DECOMPRESS_SIZE > Z_STRLEN_PP(source) ? PHP_BZ_DECOMPRESS_SIZE : Z_STRLEN_PP(source)); - - /* (de)Compression Loop */ - do { - /* Handle the (re)allocation of the buffer */ - size = dest_len * iter; - if (iter > 1) { - dest = erealloc(dest, size); - } - ++iter; + bzs.next_in = source; + bzs.avail_in = source_len; - /* Perform the decompression */ - error = BZ2_bzBuffToBuffDecompress(dest, &size, Z_STRVAL_PP(source), Z_STRLEN_PP(source), small, 0); - } while (error == BZ_OUTBUFF_FULL); + /* in most cases bz2 offers at least 2:1 compression, so we use that as our base */ + bzs.avail_out = source_len * 2; + bzs.next_out = dest = emalloc(bzs.avail_out + 1); - if (error != BZ_OK) { - efree(dest); - RETURN_LONG(error); - } else { - /* we might have allocated a little to much, so erealloc the buffer - down to size, before returning it */ + while ((error = BZ2_bzDecompress(&bzs)) == BZ_OK && bzs.avail_in > 0) { + /* compression is better then 2:1, need to allocate more memory */ + bzs.avail_out = source_len; + size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32; + dest = erealloc(dest, size + bzs.avail_out + 1); + bzs.next_out = dest + size; + } + + if (error == BZ_STREAM_END || error == BZ_OK) { + size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32; dest = erealloc(dest, size + 1); - dest[size] = 0; - RETURN_STRINGL(dest, size, 0); + dest[size] = '\0'; + RETVAL_STRINGL(dest, size, 0); + } else { /* real error */ + efree(dest); + RETVAL_LONG(error); } + + BZ2_bzDecompressEnd(&bzs); } /* }}} */ diff --git a/ext/calendar/calendar.c b/ext/calendar/calendar.c index 16fef3dbd47d..6004b8d4ad32 100644 --- a/ext/calendar/calendar.c +++ b/ext/calendar/calendar.c @@ -163,26 +163,14 @@ PHP_MINFO_FUNCTION(calendar) php_info_print_table_end(); } -/* {{{ proto array cal_info(int calendar) - Returns information about a particular calendar */ -PHP_FUNCTION(cal_info) +static void _php_cal_info(int cal, zval **ret) { - long cal; zval *months, *smonths; int i; struct cal_entry_t *calendar; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &cal) == FAILURE) { - RETURN_FALSE; - } - - if (cal < 0 || cal >= CAL_NUM_CALS) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid calendar ID %ld.", cal); - RETURN_FALSE; - } - calendar = &cal_conversion_table[cal]; - array_init(return_value); + array_init(*ret); MAKE_STD_ZVAL(months); MAKE_STD_ZVAL(smonths); @@ -193,11 +181,46 @@ PHP_FUNCTION(cal_info) add_index_string(months, i, calendar->month_name_long[i], 1); add_index_string(smonths, i, calendar->month_name_short[i], 1); } - add_assoc_zval(return_value, "months", months); - add_assoc_zval(return_value, "abbrevmonths", smonths); - add_assoc_long(return_value, "maxdaysinmonth", calendar->max_days_in_month); - add_assoc_string(return_value, "calname", calendar->name, 1); - add_assoc_string(return_value, "calsymbol", calendar->symbol, 1); + add_assoc_zval(*ret, "months", months); + add_assoc_zval(*ret, "abbrevmonths", smonths); + add_assoc_long(*ret, "maxdaysinmonth", calendar->max_days_in_month); + add_assoc_string(*ret, "calname", calendar->name, 1); + add_assoc_string(*ret, "calsymbol", calendar->symbol, 1); + +} + +/* {{{ proto array cal_info(int calendar) + Returns information about a particular calendar */ +PHP_FUNCTION(cal_info) +{ + long cal = -1; + + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &cal) == FAILURE) { + RETURN_FALSE; + } + + if (cal == -1) { + int i; + zval *val; + + array_init(return_value); + + for (i = 0; i < CAL_NUM_CALS; i++) { + MAKE_STD_ZVAL(val); + _php_cal_info(i, &val); + add_index_zval(return_value, i, val); + } + return; + } + + + if (cal != -1 && (cal < 0 || cal >= CAL_NUM_CALS)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid calendar ID %ld.", cal); + RETURN_FALSE; + } + + _php_cal_info(cal, &return_value); } /* }}} */ @@ -223,6 +246,11 @@ PHP_FUNCTION(cal_days_in_month) sdn_start = calendar->to_jd(year, month, 1); + if (sdn_start == 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid date."); + RETURN_FALSE; + } + sdn_next = calendar->to_jd(year, 1 + month, 1); if (sdn_next == 0) { @@ -238,7 +266,7 @@ PHP_FUNCTION(cal_days_in_month) Converts from a supported calendar to Julian Day Count */ PHP_FUNCTION(cal_to_jd) { - long cal, month, day, year, jdate; + long cal, month, day, year; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llll", &cal, &month, &day, &year) != SUCCESS) { RETURN_FALSE; @@ -249,8 +277,7 @@ PHP_FUNCTION(cal_to_jd) RETURN_FALSE; } - jdate = cal_conversion_table[cal].to_jd(year, month, day); - RETURN_LONG(jdate); + RETURN_LONG(cal_conversion_table[cal].to_jd(year, month, day)); } /* }}} */ @@ -319,15 +346,12 @@ PHP_FUNCTION(jdtogregorian) PHP_FUNCTION(gregoriantojd) { long year, month, day; - int jdate; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &month, &day, &year) == FAILURE) { RETURN_FALSE; } - jdate = GregorianToSdn(year, month, day); - - RETURN_LONG(jdate); + RETURN_LONG(GregorianToSdn(year, month, day)); } /* }}} */ @@ -355,15 +379,12 @@ PHP_FUNCTION(jdtojulian) PHP_FUNCTION(juliantojd) { long year, month, day; - int jdate; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &month, &day, &year) == FAILURE) { RETURN_FALSE; } - jdate = JulianToSdn(year, month, day); - - RETURN_LONG(jdate); + RETURN_LONG(JulianToSdn(year, month, day)); } /* }}} */ @@ -506,15 +527,12 @@ PHP_FUNCTION(jdtojewish) PHP_FUNCTION(jewishtojd) { long year, month, day; - int jdate; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &month, &day, &year) == FAILURE) { RETURN_FALSE; } - jdate = JewishToSdn(year, month, day); - - RETURN_LONG(jdate); + RETURN_LONG(JewishToSdn(year, month, day)); } /* }}} */ @@ -542,15 +560,12 @@ PHP_FUNCTION(jdtofrench) PHP_FUNCTION(frenchtojd) { long year, month, day; - int jdate; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &month, &day, &year) == FAILURE) { RETURN_FALSE; } - jdate = FrenchToSdn(year, month, day); - - RETURN_LONG(jdate); + RETURN_LONG(FrenchToSdn(year, month, day)); } /* }}} */ diff --git a/ext/com_dotnet/com_com.c b/ext/com_dotnet/com_com.c index 39c90eae1f81..25a5c73e5161 100644 --- a/ext/com_dotnet/com_com.c +++ b/ext/com_dotnet/com_com.c @@ -398,7 +398,7 @@ HRESULT php_com_invoke_helper(php_com_dotnet_object *obj, DISPID id_member, default: desc = php_win_err(hr); - spprintf(&msg, 0, "Error %s", desc); + spprintf(&msg, 0, "Error [0x%08x] %s", hr, desc); LocalFree(desc); break; } @@ -620,7 +620,7 @@ int php_com_do_invoke_by_id(php_com_dotnet_object *obj, DISPID dispid, efree(vargs); } - /* a bit strange this, but... */ + /* a bit of a hack this, but it's needed for COM array access. */ if (hr == DISP_E_BADPARAMCOUNT) return hr; diff --git a/ext/com_dotnet/com_dotnet.c b/ext/com_dotnet/com_dotnet.c index 7199b91aa728..18bb22e979ed 100644 --- a/ext/com_dotnet/com_dotnet.c +++ b/ext/com_dotnet/com_dotnet.c @@ -32,53 +32,139 @@ # include "Zend/zend_exceptions.h" # include +/* Since there is no official public mscorlib.h header file, and since + * generating your own version from the elusive binary .tlb file takes a lot of + * hacking and results in a 3MB header file (!), we opt for this slightly + * voodoo approach. The following is just enough definition to be able to + * reach the _AppDomain::CreateInstance method that we need to use to be able + * to fire up .Net objects. We used to use IDispatch for this, but it would + * not always work. + * + * The following info was obtained using OleView to export the IDL from + * mscorlib.tlb. Note that OleView is unable to generate C headers for this + * particular tlb... hence this mess. + */ + +const GUID IID_mscorlib_System_AppDomain = { +0x05F696DC, 0x2B29, 0x3663, {0xAD, 0x8B, 0xC4, 0x38, 0x9C, 0xF2, 0xA7, 0x13 }}; + +typedef struct _Imscorlib_System_AppDomain IAppDomain; + +struct _Imscorlib_System_AppDomainVtbl { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IAppDomain * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IAppDomain * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IAppDomain * This); + + /* this is padding to get CreateInstance into the correct position */ +#define DUMMY_METHOD(x) HRESULT ( STDMETHODCALLTYPE *dummy_##x )(IAppDomain *This) + + DUMMY_METHOD(GetTypeInfoCount); + DUMMY_METHOD(GetTypeInfo); + DUMMY_METHOD(GetIDsOfNames); + DUMMY_METHOD(Invoke); + DUMMY_METHOD(ToString); + DUMMY_METHOD(Equals); + DUMMY_METHOD(GetHashCode); + DUMMY_METHOD(GetType); + DUMMY_METHOD(InitializeLifetimeService); + DUMMY_METHOD(GetLifetimeService); + DUMMY_METHOD(Evidence); + DUMMY_METHOD(add_DomainUnload); + DUMMY_METHOD(remove_DomainUnload); + DUMMY_METHOD(add_AssemblyLoad); + DUMMY_METHOD(remove_AssemblyLoad); + DUMMY_METHOD(add_ProcessExit); + DUMMY_METHOD(remove_ProcessExit); + DUMMY_METHOD(add_TypeResolve); + DUMMY_METHOD(remove_TypeResolve); + DUMMY_METHOD(add_ResourceResolve); + DUMMY_METHOD(remove_ResourceResolve); + DUMMY_METHOD(add_AssemblyResolve); + DUMMY_METHOD(remove_AssemblyResolve); + DUMMY_METHOD(add_UnhandledException); + DUMMY_METHOD(remove_UnhandledException); + DUMMY_METHOD(DefineDynamicAssembly); + DUMMY_METHOD(DefineDynamicAssembly_2); + DUMMY_METHOD(DefineDynamicAssembly_3); + DUMMY_METHOD(DefineDynamicAssembly_4); + DUMMY_METHOD(DefineDynamicAssembly_5); + DUMMY_METHOD(DefineDynamicAssembly_6); + DUMMY_METHOD(DefineDynamicAssembly_7); + DUMMY_METHOD(DefineDynamicAssembly_8); + DUMMY_METHOD(DefineDynamicAssembly_9); + + HRESULT ( STDMETHODCALLTYPE *CreateInstance )(IAppDomain * This, BSTR AssemblyName, BSTR typeName, IUnknown **pRetVal); + HRESULT ( STDMETHODCALLTYPE *CreateInstanceFrom )(IAppDomain * This, BSTR AssemblyFile, BSTR typeName, IUnknown **pRetVal); + + /* more methods live here */ + + END_INTERFACE +}; + +struct _Imscorlib_System_AppDomain { + struct _Imscorlib_System_AppDomainVtbl *lpVtbl; +}; + + struct dotnet_runtime_stuff { ICorRuntimeHost *dotnet_host; - IDispatch *dotnet_domain; + IAppDomain *dotnet_domain; DISPID create_instance; }; -/* Since there is no official public mscorlib.h header file, and since - * generating your own version from the binary .tlb file results in a 3MB - * header file (!), we opt for the Dispatch-able approach. This is slightly - * slower for creating new objects, but not too bad */ -static int dotnet_init(TSRMLS_D) +static HRESULT dotnet_init(char **p_where TSRMLS_DC) { HRESULT hr; struct dotnet_runtime_stuff *stuff; IUnknown *unk = NULL; - OLECHAR *olename; + OLECHAR *olename, *oletmp; + char *where = ""; stuff = malloc(sizeof(*stuff)); memset(stuff, 0, sizeof(*stuff)); - if (SUCCEEDED(CoCreateInstance(&CLSID_CorRuntimeHost, NULL, CLSCTX_ALL, - &IID_ICorRuntimeHost, (LPVOID*)&stuff->dotnet_host))) { - - /* fire up the host and get the domain object */ - if (SUCCEEDED(ICorRuntimeHost_Start(stuff->dotnet_host)) && - SUCCEEDED(ICorRuntimeHost_GetDefaultDomain(stuff->dotnet_host, &unk)) && - SUCCEEDED(IUnknown_QueryInterface(unk, &IID_IDispatch, (LPVOID*)&stuff->dotnet_domain))) { + where = "CoCreateInstance"; + hr = CoCreateInstance(&CLSID_CorRuntimeHost, NULL, CLSCTX_ALL, + &IID_ICorRuntimeHost, (LPVOID*)&stuff->dotnet_host); - /* locate the create-instance member */ - olename = php_com_string_to_olestring("CreateInstance", sizeof("CreateInstance")-1, CP_ACP TSRMLS_CC); - hr = IDispatch_GetIDsOfNames(stuff->dotnet_domain, &IID_NULL, &olename, 1, LOCALE_SYSTEM_DEFAULT, &stuff->create_instance); - efree(olename); + if (FAILED(hr)) + goto out; - if (SUCCEEDED(hr)) { - COMG(dotnet_runtime_stuff) = stuff; - } - } - - if (unk) { - IUnknown_Release(unk); - } + /* fire up the host and get the domain object */ + where = "ICorRuntimeHost_Start\n"; + hr = ICorRuntimeHost_Start(stuff->dotnet_host); + if (FAILED(hr)) + goto out; + + where = "ICorRuntimeHost_GetDefaultDomain"; + hr = ICorRuntimeHost_GetDefaultDomain(stuff->dotnet_host, &unk); + if (FAILED(hr)) + goto out; + + where = "QI: System._AppDomain"; + hr = IUnknown_QueryInterface(unk, &IID_mscorlib_System_AppDomain, (LPVOID*)&stuff->dotnet_domain); + if (FAILED(hr)) + goto out; + + COMG(dotnet_runtime_stuff) = stuff; + +out: + if (unk) { + IUnknown_Release(unk); } - if (COMG(dotnet_runtime_stuff) == NULL) { /* clean up */ if (stuff->dotnet_domain) { - IDispatch_Release(stuff->dotnet_domain); + IUnknown_Release(stuff->dotnet_domain); } if (stuff->dotnet_host) { ICorRuntimeHost_Stop(stuff->dotnet_host); @@ -86,10 +172,12 @@ static int dotnet_init(TSRMLS_D) } free(stuff); - return FAILURE; + *p_where = where; + + return hr; } - return SUCCESS; + return S_OK; } /* {{{ com_dotnet_create_instance - ctor for DOTNET class */ @@ -100,16 +188,21 @@ PHP_FUNCTION(com_dotnet_create_instance) char *assembly_name, *datatype_name; int assembly_name_len, datatype_name_len; struct dotnet_runtime_stuff *stuff; - IObjectHandle *handle; - DISPPARAMS params; - VARIANT vargs[2]; - VARIANT retval; + OLECHAR *olestring, *oleassembly, *oletype; HRESULT hr; int ret = FAILURE; + char *where = ""; + IUnknown *unk = NULL; if (COMG(dotnet_runtime_stuff) == NULL) { - if (FAILURE == dotnet_init(TSRMLS_C)) { - php_com_throw_exception(E_ERROR, "Failed to initialize .Net runtime" TSRMLS_CC); + hr = dotnet_init(&where TSRMLS_CC); + if (FAILED(hr)) { + char buf[1024]; + char *err = php_win_err(hr); + snprintf(buf, sizeof(buf), "Failed to init .Net runtime [%s] %s", where, err); + if (err) + LocalFree(err); + php_com_throw_exception(hr, buf TSRMLS_CC); ZVAL_NULL(object); return; } @@ -128,50 +221,63 @@ PHP_FUNCTION(com_dotnet_create_instance) return; } - params.cArgs = 2; - params.cNamedArgs = 0; - params.rgdispidNamedArgs = NULL; - params.rgvarg = vargs; - - VariantInit(&vargs[0]); - VariantInit(&vargs[1]); - VariantInit(&retval); - - V_VT(&vargs[0]) = VT_BSTR; - V_BSTR(&vargs[0]) = php_com_string_to_olestring(datatype_name, datatype_name_len, obj->code_page TSRMLS_CC); - - V_VT(&vargs[1]) = VT_BSTR; - V_BSTR(&vargs[1]) = php_com_string_to_olestring(assembly_name, assembly_name_len, obj->code_page TSRMLS_CC); - - hr = IDispatch_Invoke(stuff->dotnet_domain, stuff->create_instance, &IID_NULL, LOCALE_SYSTEM_DEFAULT, - DISPATCH_METHOD, ¶ms, &retval, NULL, NULL); + oletype = php_com_string_to_olestring(datatype_name, datatype_name_len, obj->code_page TSRMLS_CC); + oleassembly = php_com_string_to_olestring(assembly_name, assembly_name_len, obj->code_page TSRMLS_CC); + where = "CreateInstance"; + hr = stuff->dotnet_domain->lpVtbl->CreateInstance(stuff->dotnet_domain, oleassembly, oletype, &unk); + efree(oletype); + efree(oleassembly); if (SUCCEEDED(hr)) { - /* retval should now be an IUnknown/IDispatch representation of an IObjectHandle interface */ - if ((V_VT(&retval) == VT_UNKNOWN || V_VT(&retval) == VT_DISPATCH) && - SUCCEEDED(IUnknown_QueryInterface(V_UNKNOWN(&retval), &IID_IObjectHandle, &handle))) { - VARIANT unwrapped; + VARIANT unwrapped; + IObjectHandle *handle = NULL; - if (SUCCEEDED(IObjectHandle_Unwrap(handle, &unwrapped))) { - /* unwrapped is now the dispatch pointer we want */ - V_DISPATCH(&obj->v) = V_DISPATCH(&unwrapped); - V_VT(&obj->v) = VT_DISPATCH; + where = "QI: IObjectHandle"; + hr = IUnknown_QueryInterface(unk, &IID_IObjectHandle, &handle); - /* get its type-info */ - IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &obj->typeinfo); + if (SUCCEEDED(hr)) { + where = "IObjectHandle_Unwrap"; + hr = IObjectHandle_Unwrap(handle, &unwrapped); + if (SUCCEEDED(hr)) { - ret = SUCCESS; + if (V_VT(&unwrapped) == VT_UNKNOWN) { + where = "Unwrapped, QI for IDispatch"; + hr = IUnknown_QueryInterface(V_UNKNOWN(&unwrapped), &IID_IDispatch, &V_DISPATCH(&obj->v)); + + if (SUCCEEDED(hr)) { + V_VT(&obj->v) = VT_DISPATCH; + + /* get its type-info */ + IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &obj->typeinfo); + ret = SUCCESS; + } + } else if (V_VT(&unwrapped) == VT_DISPATCH) { + /* unwrapped is now the dispatch pointer we want */ + V_DISPATCH(&obj->v) = V_DISPATCH(&unwrapped); + V_VT(&obj->v) = VT_DISPATCH; + + /* get its type-info */ + IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &obj->typeinfo); + + ret = SUCCESS; + } else { + /* shouldn't happen, but let's be ready for it */ + VariantClear(&unwrapped); + hr = E_INVALIDARG; + } } IObjectHandle_Release(handle); } - VariantClear(&retval); + IUnknown_Release(unk); } - VariantClear(&vargs[0]); - VariantClear(&vargs[1]); - if (ret == FAILURE) { - php_com_throw_exception(hr, "Failed to instantiate .Net object" TSRMLS_CC); + char buf[1024]; + char *err = php_win_err(hr); + snprintf(buf, sizeof(buf), "Failed to instantiate .Net object [%s] [0x%08x] %s", where, hr, err); + if (err) + LocalFree(err); + php_com_throw_exception(hr, buf TSRMLS_CC); ZVAL_NULL(object); return; } diff --git a/ext/com_dotnet/com_extension.c b/ext/com_dotnet/com_extension.c index 51484514605c..bcd2e609fabb 100644 --- a/ext/com_dotnet/com_extension.c +++ b/ext/com_dotnet/com_extension.c @@ -194,12 +194,12 @@ PHP_MINIT_FUNCTION(com_dotnet) INIT_CLASS_ENTRY(ce, "com_exception", NULL); php_com_exception_class_entry = zend_register_internal_class_ex(&ce, zend_exception_get_default(), NULL TSRMLS_CC); php_com_exception_class_entry->ce_flags |= ZEND_ACC_FINAL; - php_com_exception_class_entry->constructor->common.fn_flags |= ZEND_ACC_PROTECTED; +/* php_com_exception_class_entry->constructor->common.fn_flags |= ZEND_ACC_PROTECTED; */ INIT_CLASS_ENTRY(ce, "com_safearray_proxy", NULL); php_com_saproxy_class_entry = zend_register_internal_class(&ce TSRMLS_CC); php_com_saproxy_class_entry->ce_flags |= ZEND_ACC_FINAL; -// php_com_saproxy_class_entry->constructor->common.fn_flags |= ZEND_ACC_PROTECTED; +/* php_com_saproxy_class_entry->constructor->common.fn_flags |= ZEND_ACC_PROTECTED; */ php_com_saproxy_class_entry->get_iterator = php_com_saproxy_iter_get; INIT_CLASS_ENTRY(ce, "variant", NULL); diff --git a/ext/com_dotnet/com_handlers.c b/ext/com_dotnet/com_handlers.c index cfe15d43555f..824046f0ea9e 100644 --- a/ext/com_dotnet/com_handlers.c +++ b/ext/com_dotnet/com_handlers.c @@ -49,7 +49,7 @@ static zval *com_property_read(zval *object, zval *member, int type TSRMLS_DC) convert_to_string_ex(&member); res = php_com_do_invoke(obj, Z_STRVAL_P(member), Z_STRLEN_P(member), - DISPATCH_PROPERTYGET, &v, 0, NULL TSRMLS_CC); + DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, 0, NULL TSRMLS_CC); if (res == SUCCESS) { php_com_zval_from_variant(return_value, &v, obj->code_page TSRMLS_CC); @@ -84,30 +84,6 @@ static void com_property_write(zval *object, zval *member, zval *value TSRMLS_DC } } -static HRESULT com_get_default_binding(php_com_dotnet_object *obj TSRMLS_DC) -{ - VARDESC *vardesc; - int i; - - if (!obj->typeinfo) { - return FAILURE; - } - - for (i = 0; !obj->have_default_bind; i++) { - if (FAILED(ITypeInfo_GetVarDesc(obj->typeinfo, i, &vardesc))) { - return FAILURE; - } - - if (vardesc->wVarFlags & VARFLAG_FDEFAULTBIND) { - obj->default_bind = (DISPID)vardesc->memid; - obj->have_default_bind = 1; - } - - ITypeInfo_ReleaseVarDesc(obj->typeinfo, vardesc); - } - return obj->have_default_bind ? SUCCESS : FAILURE; -} - static zval *com_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) { zval *return_value; @@ -122,14 +98,9 @@ static zval *com_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) obj = CDNO_FETCH(object); if (V_VT(&obj->v) == VT_DISPATCH) { - if (!obj->have_default_bind && !com_get_default_binding(obj TSRMLS_CC)) { - php_com_throw_exception(E_INVALIDARG, "this COM object has no default property" TSRMLS_CC); - return return_value; - } - VariantInit(&v); - if (SUCCESS == php_com_do_invoke_by_id(obj, obj->default_bind, + if (SUCCESS == php_com_do_invoke_by_id(obj, DISPID_VALUE, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, 1, &offset TSRMLS_CC)) { php_com_zval_from_variant(return_value, &v, obj->code_page TSRMLS_CC); VariantClear(&v); @@ -163,17 +134,12 @@ static void com_write_dimension(zval *object, zval *offset, zval *value TSRMLS_D obj = CDNO_FETCH(object); if (V_VT(&obj->v) == VT_DISPATCH) { - if (!obj->have_default_bind && !com_get_default_binding(obj TSRMLS_CC)) { - php_com_throw_exception(E_INVALIDARG, "this COM object has no default property" TSRMLS_CC); - return; - } - args[0] = offset; args[1] = value; VariantInit(&v); - if (SUCCESS == php_com_do_invoke_by_id(obj, obj->default_bind, + if (SUCCESS == php_com_do_invoke_by_id(obj, DISPID_VALUE, DISPATCH_METHOD|DISPATCH_PROPERTYPUT, &v, 2, args TSRMLS_CC)) { VariantClear(&v); } @@ -286,11 +252,19 @@ static void function_dtor(void *pDest) } } +static PHP_FUNCTION(com_method_handler) +{ + Z_OBJ_HANDLER_P(getThis(), call_method)( + ((zend_internal_function*)EG(function_state_ptr)->function)->function_name, + INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + static union _zend_function *com_method_get(zval *object, char *name, int len TSRMLS_DC) { zend_internal_function f, *fptr = NULL; php_com_dotnet_object *obj; union _zend_function *func; + DISPID dummy; obj = CDNO_FETCH(object); @@ -298,6 +272,10 @@ static union _zend_function *com_method_get(zval *object, char *name, int len TS return NULL; } + if (FAILED(php_com_get_id_of_name(obj, name, len, &dummy TSRMLS_CC))) { + return NULL; + } + /* check cache */ if (obj->method_cache == NULL || FAILURE == zend_hash_find(obj->method_cache, name, len, (void**)&fptr)) { f.type = ZEND_OVERLOADED_FUNCTION; @@ -306,7 +284,10 @@ static union _zend_function *com_method_get(zval *object, char *name, int len TS f.scope = obj->ce; f.fn_flags = 0; f.function_name = estrndup(name, len); + f.handler = PHP_FN(com_method_handler); + fptr = &f; + if (obj->typeinfo) { /* look for byref params */ ITypeComp *comp; @@ -346,6 +327,9 @@ static union _zend_function *com_method_get(zval *object, char *name, int len TS case DESCKIND_TYPECOMP: ITypeComp_Release(bindptr.lptcomp); break; + + case DESCKIND_NONE: + break; } if (TI) { ITypeInfo_Release(TI); @@ -356,21 +340,27 @@ static union _zend_function *com_method_get(zval *object, char *name, int len TS } } - /* save this method in the cache */ - if (!obj->method_cache) { - ALLOC_HASHTABLE(obj->method_cache); - zend_hash_init(obj->method_cache, 2, NULL, function_dtor, 0); - } + if (fptr) { + /* save this method in the cache */ + if (!obj->method_cache) { + ALLOC_HASHTABLE(obj->method_cache); + zend_hash_init(obj->method_cache, 2, NULL, function_dtor, 0); + } - zend_hash_update(obj->method_cache, name, len, &f, sizeof(f), (void**)&fptr); + zend_hash_update(obj->method_cache, name, len, &f, sizeof(f), (void**)&fptr); + } } - /* duplicate this into a new chunk of emalloc'd memory, - * since the engine will efree it */ - func = emalloc(sizeof(*fptr)); - memcpy(func, fptr, sizeof(*fptr)); + if (fptr) { + /* duplicate this into a new chunk of emalloc'd memory, + * since the engine will efree it */ + func = emalloc(sizeof(*fptr)); + memcpy(func, fptr, sizeof(*fptr)); + + return func; + } - return func; + return NULL; } static int com_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS) @@ -500,23 +490,19 @@ static int com_object_cast(zval *readobj, zval *writeobj, int type, int should_f php_com_dotnet_object *obj; VARIANT v; VARTYPE vt = VT_EMPTY; + zval free_obj; + HRESULT res = S_OK; if (should_free) { - zval_dtor(writeobj); + free_obj = *writeobj; } - ZVAL_NULL(writeobj); - obj = CDNO_FETCH(readobj); + ZVAL_NULL(writeobj); VariantInit(&v); if (V_VT(&obj->v) == VT_DISPATCH) { - - if (!obj->have_default_bind && !com_get_default_binding(obj TSRMLS_CC)) { - return FAILURE; - } - - if (FAILURE == php_com_do_invoke_by_id(obj, obj->default_bind, + if (FAILURE == php_com_do_invoke_by_id(obj, DISPID_VALUE, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, 0, NULL TSRMLS_CC)) { return FAILURE; } @@ -540,12 +526,23 @@ static int com_object_cast(zval *readobj, zval *writeobj, int type, int should_f } if (vt != VT_EMPTY) { - VariantChangeType(&v, &v, 0, vt); + res = VariantChangeType(&v, &v, 0, vt); + } + + if (SUCCEEDED(res)) { + php_com_zval_from_variant(writeobj, &v, obj->code_page TSRMLS_CC); } - php_com_zval_from_variant(writeobj, &v, obj->code_page TSRMLS_CC); VariantClear(&v); - return SUCCESS; + if (should_free) { + zval_dtor(&free_obj); + } + + if (SUCCEEDED(res)) { + return SUCCESS; + } + + return FAILURE; } static int com_object_count(zval *object, long *count TSRMLS_DC) diff --git a/ext/com_dotnet/com_typeinfo.c b/ext/com_dotnet/com_typeinfo.c index ed521d123368..181cd5e3577e 100644 --- a/ext/com_dotnet/com_typeinfo.c +++ b/ext/com_dotnet/com_typeinfo.c @@ -227,34 +227,35 @@ void php_com_typelibrary_dtor(void *pDest) PHPAPI ITypeLib *php_com_load_typelib_via_cache(char *search_string, int codepage, int *cached TSRMLS_DC) { - ITypeLib **TL; + ITypeLib **TLp; + ITypeLib *TL; char *name_dup; int l; l = strlen(search_string); if (zend_ts_hash_find(&php_com_typelibraries, search_string, l+1, - (void**)&TL) == SUCCESS) { + (void**)&TLp) == SUCCESS) { *cached = 1; /* add a reference for the caller */ - ITypeLib_AddRef(*TL); - return *TL; + ITypeLib_AddRef(*TLp); + return *TLp; } *cached = 0; name_dup = estrndup(search_string, l); - *TL = php_com_load_typelib(name_dup, codepage TSRMLS_CC); + TL = php_com_load_typelib(name_dup, codepage TSRMLS_CC); efree(name_dup); - if (*TL) { + if (TL) { if (SUCCESS == zend_ts_hash_update(&php_com_typelibraries, - search_string, l+1, (void*)*TL, sizeof(ITypeLib*), NULL)) { + search_string, l+1, (void*)TL, sizeof(ITypeLib*), NULL)) { /* add a reference for the hash table */ - ITypeLib_AddRef(*TL); + ITypeLib_AddRef(TL); } } - return *TL; + return TL; } ITypeInfo *php_com_locate_typeinfo(char *typelibname, php_com_dotnet_object *obj, char *dispname, int sink TSRMLS_DC) @@ -399,6 +400,7 @@ static const struct { { VT_VOID, "VT_VOID" }, { VT_PTR, "VT_PTR" }, { VT_HRESULT, "VT_HRESULT" }, + { VT_SAFEARRAY, "VT_SAFEARRAY" }, { 0, NULL } }; diff --git a/ext/com_dotnet/com_variant.c b/ext/com_dotnet/com_variant.c index bf401f82e83e..345591306afb 100644 --- a/ext/com_dotnet/com_variant.c +++ b/ext/com_dotnet/com_variant.c @@ -799,7 +799,8 @@ PHP_FUNCTION(variant_date_from_timestamp) } VariantInit(&res); - tmv = gmtime(×tamp); + tzset(); + tmv = localtime(×tamp); memset(&systime, 0, sizeof(systime)); systime.wDay = tmv->tm_mday; diff --git a/ext/com_dotnet/com_wrapper.c b/ext/com_dotnet/com_wrapper.c index 4ca96cc8c5f7..0a35d26d8d96 100644 --- a/ext/com_dotnet/com_wrapper.c +++ b/ext/com_dotnet/com_wrapper.c @@ -296,12 +296,16 @@ static HRESULT STDMETHODCALLTYPE disp_invokeex( } else if (wFlags & DISPATCH_PROPERTYPUT) { zend_update_property(Z_OBJCE_P(disp->object), disp->object, Z_STRVAL_PP(name), Z_STRLEN_PP(name)+1, *params[0] TSRMLS_CC); } else if (wFlags & DISPATCH_METHOD) { - if (SUCCESS == call_user_function_ex(EG(function_table), &disp->object, *name, - &retval, pdp->cArgs, params, 1, NULL TSRMLS_CC)) { - ret = S_OK; - } else { + zend_try { + if (SUCCESS == call_user_function_ex(EG(function_table), &disp->object, *name, + &retval, pdp->cArgs, params, 1, NULL TSRMLS_CC)) { + ret = S_OK; + } else { + ret = DISP_E_EXCEPTION; + } + } zend_catch { ret = DISP_E_EXCEPTION; - } + } zend_end_try(); } else { trace("Don't know how to handle this invocation %08x\n", wFlags); } diff --git a/ext/com_dotnet/php_com_dotnet_internal.h b/ext/com_dotnet/php_com_dotnet_internal.h index f24f7cfbfbc7..9cf7723818ef 100644 --- a/ext/com_dotnet/php_com_dotnet_internal.h +++ b/ext/com_dotnet/php_com_dotnet_internal.h @@ -37,10 +37,8 @@ typedef struct _php_com_dotnet_object { ITypeInfo *typeinfo; long code_page; - unsigned int have_default_bind:1; zend_class_entry *ce; - DISPID default_bind; /* default property for array accesses */ /* associated event sink */ IDispatch *sink_dispatch; diff --git a/ext/cpdf/config.m4 b/ext/cpdf/config.m4 index 95627bd97039..1b53d700a5f9 100644 --- a/ext/cpdf/config.m4 +++ b/ext/cpdf/config.m4 @@ -1,6 +1,6 @@ dnl $Id$ -AC_DEFUN(CPDF_JPEG_TEST,[ +AC_DEFUN([CPDF_JPEG_TEST],[ AC_ARG_WITH(jpeg-dir, [ --with-jpeg-dir[=DIR] CPDF: Set the path to libjpeg install prefix.],[ for i in $withval /usr/local /usr; do @@ -22,7 +22,7 @@ AC_DEFUN(CPDF_JPEG_TEST,[ ],) ]) -AC_DEFUN(CPDF_TIFF_TEST,[ +AC_DEFUN([CPDF_TIFF_TEST],[ AC_ARG_WITH(tiff-dir, [ --with-tiff-dir[=DIR] CPDF: Set the path to libtiff install prefix.],[ for i in $withval /usr/local /usr; do @@ -58,14 +58,22 @@ if test "$PHP_CPDFLIB" != "no"; then CPDFLIB_INCLUDE=$i/include PHP_CHECK_LIBRARY(cpdf, cpdf_open, [ - PHP_ADD_INCLUDE($CPDFLIB_INCLUDE) - PHP_ADD_LIBRARY_WITH_PATH(cpdf, $i/lib, CPDF_SHARED_LIBADD) - AC_DEFINE(HAVE_CPDFLIB,1,[Whether you have cpdflib]) + cpdf_libname=cpdf ], [ - AC_MSG_ERROR([Cpdflib module requires cpdflib >= 2.]) + PHP_CHECK_LIBRARY(cpdfm, cpdf_open, [ + cpdf_libname=cpdfm + ], [ + AC_MSG_ERROR([Cpdflib module requires cpdflib >= 2.]) + ], [ + -L$i/lib $CPDF_SHARED_LIBADD + ]) ], [ -L$i/lib $CPDF_SHARED_LIBADD ]) + + PHP_ADD_LIBRARY_WITH_PATH($cpdf_libname, $i/lib, CPDF_SHARED_LIBADD) + PHP_ADD_INCLUDE($CPDFLIB_INCLUDE) + AC_DEFINE(HAVE_CPDFLIB,1,[Whether you have cpdflib]) break fi done diff --git a/ext/cpdf/cpdf.c b/ext/cpdf/cpdf.c index 4c872d7cbd13..594f1ca6f74c 100644 --- a/ext/cpdf/cpdf.c +++ b/ext/cpdf/cpdf.c @@ -1286,6 +1286,10 @@ PHP_FUNCTION(cpdf_setdash) convert_to_long_ex(arg2); convert_to_long_ex(arg3); + if (!pdf->currentMemStream) { + RETURN_FALSE; + } + snprintf(buffer, BUFFERLEN, "[%d %d] 0", (int) Z_LVAL_PP(arg2), (int) Z_LVAL_PP(arg3)); cpdf_setdash(pdf, buffer); diff --git a/ext/ctype/ctype.c b/ext/ctype/ctype.c index 0e7e4699bd1e..78f6d293e3b7 100644 --- a/ext/ctype/ctype.c +++ b/ext/ctype/ctype.c @@ -97,7 +97,13 @@ PHP_MINFO_FUNCTION(ctype) return; \ switch (Z_TYPE_P(c)) { \ case IS_LONG: \ - RETURN_BOOL(iswhat(Z_LVAL_P(c))); \ + if (Z_LVAL_P(c) <= 255 && Z_LVAL_P(c) >= 0) { \ + RETURN_BOOL(iswhat(Z_LVAL_P(c))); \ + } else if (Z_LVAL_P(c) >= -128 && Z_LVAL_P(c) < 0) { \ + RETURN_BOOL(iswhat(Z_LVAL_P(c) + 256)); \ + } \ + SEPARATE_ZVAL(&c); \ + convert_to_string(c); \ case IS_STRING: \ { \ char *p; \ diff --git a/ext/curl/config.m4 b/ext/curl/config.m4 index 1e683072c5ee..0bb96eb35347 100644 --- a/ext/curl/config.m4 +++ b/ext/curl/config.m4 @@ -32,10 +32,10 @@ if test "$PHP_CURL" != "no"; then CURL_CONFIG="curl-config" AC_MSG_CHECKING(for cURL 7.10.5 or greater) - if ${CURL_DIR}/bin/curl-config --libs print > /dev/null 2>&1; then + if ${CURL_DIR}/bin/curl-config --libs > /dev/null 2>&1; then CURL_CONFIG=${CURL_DIR}/bin/curl-config else - if ${CURL_DIR}/curl-config --libs print > /dev/null 2>&1; then + if ${CURL_DIR}/curl-config --libs > /dev/null 2>&1; then CURL_CONFIG=${CURL_DIR}/curl-config fi fi diff --git a/ext/curl/interface.c b/ext/curl/interface.c index a3a67a585dc9..f678e9436411 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -49,6 +49,7 @@ #include "ext/standard/php_smart_str.h" #include "ext/standard/info.h" #include "ext/standard/file.h" +#include "ext/standard/url.h" #include "php_curl.h" static void _php_curl_close(zend_rsrc_list_entry *rsrc TSRMLS_DC); @@ -60,6 +61,26 @@ static void _php_curl_close(zend_rsrc_list_entry *rsrc TSRMLS_DC); #define CAAS(s, v) add_assoc_string_ex(return_value, s, sizeof(s), (char *) v, 1); #define CAAZ(s, v) add_assoc_zval_ex(return_value, s, sizeof(s), (zval *) v); +#define PHP_CURL_CHECK_OPEN_BASEDIR(str, len) \ + if (PG(open_basedir) && *PG(open_basedir) && \ + strncasecmp(str, "file://", sizeof("file://") - 1) == 0) \ + { \ + php_url *tmp_url; \ + \ + if (!(tmp_url = php_url_parse_ex(str, len))) { \ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid url '%s'", str); \ + RETURN_FALSE; \ + } \ + \ + if (php_check_open_basedir(tmp_url->path TSRMLS_CC) || \ + (PG(safe_mode) && !php_checkuid(tmp_url->path, "rb+", CHECKUID_CHECK_MODE_PARAM)) \ + ) { \ + php_url_free(tmp_url); \ + RETURN_FALSE; \ + } \ + php_url_free(tmp_url); \ + } + /* {{{ curl_functions[] */ function_entry curl_functions[] = { @@ -220,6 +241,9 @@ PHP_MINIT_FUNCTION(curl) REGISTER_CURL_CONSTANT(CURLOPT_UNRESTRICTED_AUTH); REGISTER_CURL_CONSTANT(CURLOPT_FTP_USE_EPRT); REGISTER_CURL_CONSTANT(CURLOPT_HTTP200ALIASES); + REGISTER_CURL_CONSTANT(CURL_TIMECOND_IFMODSINCE); + REGISTER_CURL_CONSTANT(CURL_TIMECOND_IFUNMODSINCE); + REGISTER_CURL_CONSTANT(CURL_TIMECOND_LASTMOD); #if LIBCURL_VERSION_NUM > 0x070a05 /* CURLOPT_HTTPAUTH is available since curl 7.10.6 */ REGISTER_CURL_CONSTANT(CURLOPT_HTTPAUTH); @@ -231,7 +255,11 @@ PHP_MINIT_FUNCTION(curl) REGISTER_CURL_CONSTANT(CURLAUTH_ANY); REGISTER_CURL_CONSTANT(CURLAUTH_ANYSAFE); #endif - + +#if LIBCURL_VERSION_NUM > 0x070a06 /* CURLOPT_PROXYAUTH is available since curl 7.10.7 */ + REGISTER_CURL_CONSTANT(CURLOPT_PROXYAUTH); +#endif + /* Constants effecting the way CURLOPT_CLOSEPOLICY works */ REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_LEAST_RECENTLY_USED); REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_LEAST_TRAFFIC); @@ -424,6 +452,7 @@ static size_t curl_write(char *data, size_t size, size_t nmemb, void *ctx) PHPWRITE(data, length); break; case PHP_CURL_FILE: + fflush(t->fp); return fwrite(data, size, nmemb, t->fp); case PHP_CURL_RETURN: smart_str_appendl(&t->buf, data, (int) length); @@ -455,20 +484,22 @@ static size_t curl_write(char *data, size_t size, size_t nmemb, void *ctx) fci.no_separation = 0; fci.symbol_table = NULL; + ch->in_callback = 1; error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC); + ch->in_callback = 0; if (error == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the CURLOPT_WRITEFUNCTION"); length = -1; - } else { + } else if (retval_ptr) { if (Z_TYPE_P(retval_ptr) != IS_LONG) { convert_to_long_ex(&retval_ptr); } length = Z_LVAL_P(retval_ptr); + zval_ptr_dtor(&retval_ptr); } zval_ptr_dtor(argv[0]); zval_ptr_dtor(argv[1]); - zval_ptr_dtor(&retval_ptr); break; } } @@ -525,20 +556,22 @@ static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx) fci.no_separation = 0; fci.symbol_table = NULL; + ch->in_callback = 1; error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC); + ch->in_callback = 0; if (error == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot call the CURLOPT_READFUNCTION"); - } else { + } else if (retval_ptr) { if (Z_TYPE_P(retval_ptr) == IS_STRING) { length = MIN(size * nmemb, Z_STRLEN_P(retval_ptr)); memcpy(data, Z_STRVAL_P(retval_ptr), length); } + zval_ptr_dtor(&retval_ptr); } zval_ptr_dtor(argv[0]); zval_ptr_dtor(argv[1]); zval_ptr_dtor(argv[2]); - zval_ptr_dtor(&retval_ptr); break; } } @@ -596,19 +629,21 @@ static size_t curl_write_header(char *data, size_t size, size_t nmemb, void *ctx fci.params = argv; fci.no_separation = 0; + ch->in_callback = 1; error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC); + ch->in_callback = 0; if (error == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the CURLOPT_HEADERFUNCTION"); length = -1; - } else { + } else if (retval_ptr) { if (Z_TYPE_P(retval_ptr) != IS_LONG) { convert_to_long_ex(&retval_ptr); } length = Z_LVAL_P(retval_ptr); + zval_ptr_dtor(&retval_ptr); } zval_ptr_dtor(argv[0]); zval_ptr_dtor(argv[1]); - zval_ptr_dtor(&retval_ptr); break; } @@ -744,6 +779,8 @@ static void alloc_curl_handle(php_curl **ch) (*ch)->handlers->write_header = ecalloc(1, sizeof(php_curl_write)); (*ch)->handlers->read = ecalloc(1, sizeof(php_curl_read)); + (*ch)->in_callback = 0; + memset(&(*ch)->err, 0, sizeof((*ch)->err)); zend_llist_init(&(*ch)->to_free.str, sizeof(char *), (void(*)(void *)) curl_free_string, 0); @@ -765,6 +802,11 @@ PHP_FUNCTION(curl_init) WRONG_PARAM_COUNT; } + if (argc > 0) { + convert_to_string_ex(url); + PHP_CURL_CHECK_OPEN_BASEDIR(Z_STRVAL_PP(url), Z_STRLEN_PP(url)); + } + cp = curl_easy_init(); if (!cp) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not initialize a new cURL handle"); @@ -794,13 +836,13 @@ PHP_FUNCTION(curl_init) curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER, (void *) ch); curl_easy_setopt(ch->cp, CURLOPT_DNS_USE_GLOBAL_CACHE, 1); curl_easy_setopt(ch->cp, CURLOPT_DNS_CACHE_TIMEOUT, 120); + curl_easy_setopt(ch->cp, CURLOPT_MAXREDIRS, 20); /* prevent infinite redirects */ #if defined(ZTS) curl_easy_setopt(ch->cp, CURLOPT_NOSIGNAL, 1); #endif if (argc > 0) { char *urlcopy; - convert_to_string_ex(url); urlcopy = estrndup(Z_STRVAL_PP(url), Z_STRLEN_PP(url)); curl_easy_setopt(ch->cp, CURLOPT_URL, urlcopy); @@ -846,7 +888,7 @@ PHP_FUNCTION(curl_copy_handle) } /* }}} */ -/* {{{ proto bool curl_setopt(resource ch, string option, mixed value) +/* {{{ proto bool curl_setopt(resource ch, int option, mixed value) Set an option for a CURL transfer */ PHP_FUNCTION(curl_setopt) { @@ -912,6 +954,9 @@ PHP_FUNCTION(curl_setopt) case CURLOPT_FTP_USE_EPRT: #if LIBCURL_VERSION_NUM > 0x070a05 /* CURLOPT_HTTPAUTH is available since curl 7.10.6 */ case CURLOPT_HTTPAUTH: +#endif +#if LIBCURL_VERSION_NUM > 0x070a06 /* CURLOPT_PROXYAUTH is available since curl 7.10.7 */ + case CURLOPT_PROXYAUTH: #endif case CURLOPT_UNRESTRICTED_AUTH: case CURLOPT_PORT: @@ -944,8 +989,12 @@ PHP_FUNCTION(curl_setopt) char *copystr = NULL; convert_to_string_ex(zvalue); - copystr = estrndup(Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue)); + if (option == CURLOPT_URL) { + PHP_CURL_CHECK_OPEN_BASEDIR(Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue)); + } + + copystr = estrndup(Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue)); error = curl_easy_setopt(ch->cp, option, copystr); zend_llist_add_element(&ch->to_free.str, ©str); @@ -1074,18 +1123,22 @@ PHP_FUNCTION(curl_setopt) zend_hash_get_current_key_ex(postfields, &string_key, &string_key_len, &num_key, 0, NULL); postval = Z_STRVAL_PP(current); + + /* The arguments after _NAMELENGTH and _CONTENTSLENGTH + * must be explicitly cast to long in curl_formadd + * use since curl needs a long not an int. */ if (*postval == '@') { error = curl_formadd(&first, &last, CURLFORM_COPYNAME, string_key, - CURLFORM_NAMELENGTH, string_key_len - 1, + CURLFORM_NAMELENGTH, (long)string_key_len - 1, CURLFORM_FILE, ++postval, CURLFORM_END); } else { error = curl_formadd(&first, &last, CURLFORM_COPYNAME, string_key, - CURLFORM_NAMELENGTH, string_key_len - 1, + CURLFORM_NAMELENGTH, (long)string_key_len - 1, CURLFORM_COPYCONTENTS, postval, - CURLFORM_CONTENTSLENGTH, Z_STRLEN_PP(current), + CURLFORM_CONTENTSLENGTH, (long)Z_STRLEN_PP(current), CURLFORM_END); } } @@ -1326,10 +1379,13 @@ PHP_FUNCTION(curl_getinfo) switch (option) { case CURLINFO_EFFECTIVE_URL: case CURLINFO_CONTENT_TYPE: { - char *s_code; + char *s_code = NULL; - curl_easy_getinfo(ch->cp, option, &s_code); - RETURN_STRING(s_code, 1); + if (curl_easy_getinfo(ch->cp, option, &s_code) == CURLE_OK && s_code) { + RETURN_STRING(s_code, 1); + } else { + RETURN_FALSE; + } break; } case CURLINFO_HTTP_CODE: @@ -1338,10 +1394,13 @@ PHP_FUNCTION(curl_getinfo) case CURLINFO_FILETIME: case CURLINFO_SSL_VERIFYRESULT: case CURLINFO_REDIRECT_COUNT: { - long code; + long code = 0; - curl_easy_getinfo(ch->cp, option, &code); - RETURN_LONG(code); + if (curl_easy_getinfo(ch->cp, option, &code) == CURLE_OK) { + RETURN_LONG(code); + } else { + RETURN_FALSE; + } break; } case CURLINFO_TOTAL_TIME: @@ -1356,10 +1415,13 @@ PHP_FUNCTION(curl_getinfo) case CURLINFO_CONTENT_LENGTH_UPLOAD: case CURLINFO_STARTTRANSFER_TIME: case CURLINFO_REDIRECT_TIME: { - double code; + double code = 0.0; - curl_easy_getinfo(ch->cp, option, &code); - RETURN_DOUBLE(code); + if (curl_easy_getinfo(ch->cp, option, &code) == CURLE_OK) { + RETURN_DOUBLE(code); + } else { + RETURN_FALSE; + } break; } } @@ -1414,6 +1476,12 @@ PHP_FUNCTION(curl_close) } ZEND_FETCH_RESOURCE(ch, php_curl *, zid, -1, le_curl_name, le_curl); + + if (ch->in_callback) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attempt to close CURL handle from a callback"); + return; + } + if (ch->uses) { ch->uses--; } else { diff --git a/ext/curl/php_curl.h b/ext/curl/php_curl.h index d2a14c43b7ec..2f8ba6111f89 100644 --- a/ext/curl/php_curl.h +++ b/ext/curl/php_curl.h @@ -121,6 +121,7 @@ typedef struct { php_curl_handlers *handlers; long id; unsigned int uses; + zend_bool in_callback; } php_curl; typedef struct { diff --git a/ext/curl/streams.c b/ext/curl/streams.c index 4e709e9485cc..2c127e3fdb18 100644 --- a/ext/curl/streams.c +++ b/ext/curl/streams.c @@ -299,7 +299,7 @@ php_stream *php_curl_stream_opener(php_stream_wrapper *wrapper, char *filename, curl_easy_setopt(curlstream->curl, CURLOPT_PROGRESSDATA, stream); curl_easy_setopt(curlstream->curl, CURLOPT_NOPROGRESS, 0); - curl_easy_setopt(curlstream->curl, CURLOPT_USERAGENT, "PHP/" PHP_VERSION); + curl_easy_setopt(curlstream->curl, CURLOPT_USERAGENT, FG(user_agent) ? FG(user_agent) : "PHP/" PHP_VERSION); /* TODO: read cookies and options from context */ diff --git a/ext/dba/config.m4 b/ext/dba/config.m4 index a0a248c7dd3e..a636d7fcc30d 100644 --- a/ext/dba/config.m4 +++ b/ext/dba/config.m4 @@ -4,26 +4,29 @@ dnl dnl Suppose we need FlatFile if no support or only CDB is used. -AC_DEFUN(PHP_DBA_STD_BEGIN,[ +AC_DEFUN([PHP_DBA_STD_BEGIN],[ unset THIS_INCLUDE THIS_LIBS THIS_LFLAGS THIS_PREFIX THIS_RESULT ]) -AC_DEFUN(PHP_TEMP_LDFLAGS,[ +AC_DEFUN([PHP_TEMP_LDFLAGS],[ old_LDFLAGS=$LDFLAGS LDFLAGS="$1 $LDFLAGS" - $2 + old_LIBS=$LIBS + LIBS="$2 $LIBS" + $3 LDFLAGS=$old_LDFLAGS + LIBS=$old_LIBS ]) dnl Assign INCLUDE/LFLAGS from PREFIX -AC_DEFUN(PHP_DBA_STD_ASSIGN,[ +AC_DEFUN([PHP_DBA_STD_ASSIGN],[ if test -n "$THIS_PREFIX" && test "$THIS_PREFIX" != "/usr"; then THIS_LFLAGS=$THIS_PREFIX/lib fi ]) dnl Standard check -AC_DEFUN(PHP_DBA_STD_CHECK,[ +AC_DEFUN([PHP_DBA_STD_CHECK],[ THIS_RESULT="yes" if test -z "$THIS_INCLUDE"; then AC_MSG_ERROR([DBA: Could not find necessary header file(s).]) @@ -34,14 +37,14 @@ AC_DEFUN(PHP_DBA_STD_CHECK,[ ]) dnl Attach THIS_x to DBA_x -AC_DEFUN(PHP_DBA_STD_ATTACH,[ +AC_DEFUN([PHP_DBA_STD_ATTACH],[ PHP_ADD_LIBRARY_WITH_PATH($THIS_LIBS, $THIS_LFLAGS, DBA_SHARED_LIBADD) unset THIS_INCLUDE THIS_LIBS THIS_LFLAGS THIS_PREFIX ]) dnl Print the result message dnl parameters(name [, full name [, empty or error message]]) -AC_DEFUN(AC_DBA_STD_RESULT,[ +AC_DEFUN([AC_DBA_STD_RESULT],[ THIS_NAME=[]translit($1,a-z0-9-,A-Z0-9_) if test -n "$2"; then THIS_FULL_NAME="$2" @@ -113,7 +116,6 @@ AC_ARG_WITH(gdbm, done if test -n "$THIS_INCLUDE"; then - unset ac_cv_lib_gdbm_gdbm_open PHP_CHECK_LIBRARY(gdbm, gdbm_open, [ AC_DEFINE_UNQUOTED(GDBM_INCLUDE_FILE, "$THIS_INCLUDE", [ ]) AC_DEFINE(DBA_GDBM, 1, [ ]) @@ -166,10 +168,10 @@ AC_DBA_STD_RESULT(ndbm) dnl Berkeley specific (library and version test) dnl parameters(version, library list, function) -AC_DEFUN(PHP_DBA_DB_CHECK,[ +AC_DEFUN([PHP_DBA_DB_CHECK],[ for LIB in $2; do if test -f $THIS_PREFIX/lib/lib$LIB.a -o -f $THIS_PREFIX/lib/lib$LIB.$SHLIB_SUFFIX_NAME; then - PHP_TEMP_LDFLAGS(-L$THIS_PREFIX/lib -l$LIB,[ + PHP_TEMP_LDFLAGS(-L$THIS_PREFIX/lib, -l$LIB,[ AC_TRY_LINK([ #include "$THIS_INCLUDE" ],[ @@ -256,7 +258,7 @@ AC_ARG_WITH(db4, break fi done - PHP_DBA_DB_CHECK(4, db-4.2 db-4.1 db-4.0 db-4 db4 db, [(void)db_create((DB**)0, (DB_ENV*)0, 0)]) + PHP_DBA_DB_CHECK(4, db-4.3 db-4.2 db-4.1 db-4.0 db-4 db4 db, [(void)db_create((DB**)0, (DB_ENV*)0, 0)]) fi ]) AC_DBA_STD_RESULT(db4,Berkeley DB4) @@ -378,7 +380,7 @@ AC_ARG_WITH(dbm, ]) AC_DBA_STD_RESULT(dbm) -AC_DEFUN(PHP_DBA_BUILTIN_CDB,[ +AC_DEFUN([PHP_DBA_BUILTIN_CDB],[ AC_DEFINE(DBA_CDB_BUILTIN, 1, [ ]) AC_DEFINE(DBA_CDB_MAKE, 1, [ ]) AC_DEFINE(DBA_CDB, 1, [ ]) @@ -424,7 +426,7 @@ AC_ARG_WITH(cdb, ]) AC_DBA_STD_RESULT(cdb) -AC_DEFUN(PHP_DBA_BUILTIN_INI,[ +AC_DEFUN([PHP_DBA_BUILTIN_INI],[ AC_DEFINE(DBA_INIFILE, 1, [ ]) ini_sources="libinifile/inifile.c" THIS_RESULT="builtin" @@ -442,7 +444,7 @@ AC_ARG_WITH(inifile, ]) AC_DBA_STD_RESULT(inifile,INI File) -AC_DEFUN(PHP_DBA_BUILTIN_FLATFILE,[ +AC_DEFUN([PHP_DBA_BUILTIN_FLATFILE],[ AC_DEFINE(DBA_FLATFILE, 1, [ ]) flat_sources="libflatfile/flatfile.c" THIS_RESULT="builtin" diff --git a/ext/dba/tests/dba_cdb_make.phpt b/ext/dba/tests/dba_cdb_make.phpt index 77f764dbe08c..04df9252d800 100644 --- a/ext/dba/tests/dba_cdb_make.phpt +++ b/ext/dba/tests/dba_cdb_make.phpt @@ -14,7 +14,7 @@ magic_quotes_runtime=1 require_once('test.inc'); echo "database handler: $handler\n"; // print md5 checksum of test.cdb which is generated by cdb_make program - var_dump(md5(implode('',file(dirname(__FILE__).'/test.cdb')))); + var_dump(md5_file(dirname(__FILE__).'/test.cdb')); if (($db_make=dba_open($db_file, "n", $handler))!==FALSE) { dba_insert("1", "1", $db_make); dba_insert("2", "2", $db_make); @@ -26,7 +26,7 @@ magic_quotes_runtime=1 // dba_replace cdb_make doesn't know replace dba_close($db_make); // write md5 checksum of generated database file - var_dump(md5(implode('',file($db_file)))); + var_dump(md5_file($db_file)); // no need to test created database: this is done by dba_cdb_read.phpt } else { echo "Error creating database\n"; @@ -34,5 +34,5 @@ magic_quotes_runtime=1 ?> --EXPECT-- database handler: cdb_make -string(32) "723d19f39c1b15b3b455dd64323148d1" -string(32) "723d19f39c1b15b3b455dd64323148d1" \ No newline at end of file +string(32) "12fc5ba2b9dcfef2480e5324eeb5f3e5" +string(32) "12fc5ba2b9dcfef2480e5324eeb5f3e5" \ No newline at end of file diff --git a/ext/dbase/dbase.c b/ext/dbase/dbase.c index 5bb109de84e0..15d9f4f00ea2 100644 --- a/ext/dbase/dbase.c +++ b/ext/dbase/dbase.c @@ -129,6 +129,11 @@ PHP_FUNCTION(dbase_open) convert_to_string_ex(dbf_name); convert_to_long_ex(options); + if (Z_LVAL_PP(options) == 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot open %s in write-only mode", Z_STRVAL_PP(dbf_name)); + RETURN_FALSE; + } + if (PG(safe_mode) && (!php_checkuid(Z_STRVAL_PP(dbf_name), NULL, CHECKUID_CHECK_FILE_AND_DIR))) { RETURN_FALSE; } diff --git a/ext/dbase/tests/bug31754.phpt b/ext/dbase/tests/bug31754.phpt new file mode 100644 index 000000000000..32f802b57bb5 --- /dev/null +++ b/ext/dbase/tests/bug31754.phpt @@ -0,0 +1,26 @@ +--TEST-- +Bug #31754: (dbase_open() fails for mode = 1) +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Warning: dbase_open(): Cannot open /tmp/bug31754.dbf in write-only mode in %sbug31754.php on line %d diff --git a/ext/dio/dio.c b/ext/dio/dio.c index 5f965766abef..0435957f0555 100644 --- a/ext/dio/dio.c +++ b/ext/dio/dio.c @@ -88,8 +88,10 @@ ZEND_GET_MODULE(dio) static void _dio_close_fd(zend_rsrc_list_entry *rsrc TSRMLS_DC) { php_fd_t *f = (php_fd_t *) rsrc->ptr; - close(f->fd); - free(f); + if (f) { + close(f->fd); + free(f); + } } #define RDIOC(c) REGISTER_LONG_CONSTANT(#c, c, CONST_CS | CONST_PERSISTENT) @@ -158,10 +160,13 @@ PHP_MINFO_FUNCTION(dio) php_info_print_table_end(); } -static void new_php_fd(php_fd_t **f, int fd) +static int new_php_fd(php_fd_t **f, int fd) { - *f = malloc(sizeof(php_fd_t)); + if (!(*f = malloc(sizeof(php_fd_t)))) { + return 0; + } (*f)->fd = fd; + return 1; } /* {{{ proto resource dio_open(string filename, int flags[, int mode]) @@ -194,7 +199,10 @@ PHP_FUNCTION(dio_open) RETURN_FALSE; } - new_php_fd(&f, fd); + + if (!new_php_fd(&f, fd)) { + RETURN_FALSE; + } ZEND_REGISTER_RESOURCE(return_value, f, le_fd); } /* }}} */ @@ -215,6 +223,11 @@ PHP_FUNCTION(dio_read) ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd); + if (bytes <= 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0."); + RETURN_FALSE; + } + data = emalloc(bytes + 1); res = read(f->fd, data, bytes); if (res <= 0) { @@ -244,6 +257,11 @@ PHP_FUNCTION(dio_write) return; } + if (trunc_len < 0 || trunc_len > data_len) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "length must be greater or equal to zero and less then the length of the specified string."); + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd); res = write(f->fd, data, trunc_len ? trunc_len : data_len); @@ -426,7 +444,9 @@ PHP_FUNCTION(dio_fcntl) RETURN_FALSE; } - new_php_fd(&new_f, fcntl(f->fd, cmd, Z_LVAL_P(arg))); + if (!new_php_fd(&new_f, fcntl(f->fd, cmd, Z_LVAL_P(arg)))) { + RETURN_FALSE; + } ZEND_REGISTER_RESOURCE(return_value, new_f, le_fd); break; } @@ -591,6 +611,8 @@ PHP_FUNCTION(dio_tcsetattr) RETURN_FALSE; } + memset(&newtio, 0, sizeof(newtio)); + tcgetattr(f->fd, &newtio); newtio.c_cflag = BAUD | CRTSCTS | DATABITS | STOPBITS | PARITYON | PARITY | CLOCAL | CREAD; newtio.c_iflag = IGNPAR; newtio.c_oflag = 0; diff --git a/ext/dom/EXPERIMENTAL b/ext/dom/EXPERIMENTAL deleted file mode 100644 index 293159a693de..000000000000 --- a/ext/dom/EXPERIMENTAL +++ /dev/null @@ -1,5 +0,0 @@ -this module is experimental, -its functions may change their names -or move to extension all together -so do not rely to much on them -you have been warned! diff --git a/ext/dom/attr.c b/ext/dom/attr.c index ceb97b5940ae..b598c18a56af 100644 --- a/ext/dom/attr.c +++ b/ext/dom/attr.c @@ -88,7 +88,7 @@ PHP_METHOD(domattr, __construct) /* }}} end DOMAttr::__construct */ -/* {{{ proto name string +/* {{{ name string readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-1112119403 Since: @@ -114,7 +114,7 @@ int dom_attr_name_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto specified boolean +/* {{{ specified boolean readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-862529273 Since: @@ -131,7 +131,7 @@ int dom_attr_specified_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto value string +/* {{{ value string readonly=no URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-221662474 Since: @@ -200,7 +200,7 @@ int dom_attr_value_write(dom_object *obj, zval *newval TSRMLS_DC) -/* {{{ proto ownerElement DOMElement +/* {{{ ownerElement DOMElement readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Attr-ownerElement Since: DOM Level 2 @@ -236,7 +236,7 @@ int dom_attr_owner_element_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto schemaTypeInfo DOMTypeInfo +/* {{{ schemaTypeInfo DOMTypeInfo readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Attr-schemaTypeInfo Since: DOM Level 3 diff --git a/ext/dom/characterdata.c b/ext/dom/characterdata.c index 7eba640c083d..5a26fcbac1e5 100644 --- a/ext/dom/characterdata.c +++ b/ext/dom/characterdata.c @@ -44,7 +44,7 @@ zend_function_entry php_dom_characterdata_class_functions[] = { {NULL, NULL, NULL} }; -/* {{{ proto data string +/* {{{ data string readonly=no URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-72AB8359 Since: @@ -105,7 +105,7 @@ int dom_characterdata_data_write(dom_object *obj, zval *newval TSRMLS_DC) /* }}} */ -/* {{{ proto length long +/* {{{ length long readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-7D61178C Since: @@ -140,7 +140,7 @@ int dom_characterdata_length_read(dom_object *obj, zval **retval TSRMLS_DC) /* }}} */ -/* {{{ proto string dom_characterdata_substring_data(long offset, long count); +/* {{{ proto string dom_characterdata_substring_data(int offset, int count); URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-6531BCCF Since: */ @@ -215,7 +215,7 @@ PHP_FUNCTION(dom_characterdata_append_data) /* }}} end dom_characterdata_append_data */ -/* {{{ proto void dom_characterdata_insert_data(long offset, string arg); +/* {{{ proto void dom_characterdata_insert_data(int offset, string arg); URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-3EDB695F Since: */ @@ -264,7 +264,7 @@ PHP_FUNCTION(dom_characterdata_insert_data) /* }}} end dom_characterdata_insert_data */ -/* {{{ proto void dom_characterdata_delete_data(long offset, long count); +/* {{{ proto void dom_characterdata_delete_data(int offset, int count); URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-7C603781 Since: */ @@ -320,7 +320,7 @@ PHP_FUNCTION(dom_characterdata_delete_data) /* }}} end dom_characterdata_delete_data */ -/* {{{ proto void dom_characterdata_replace_data(long offset, long count, string arg); +/* {{{ proto void dom_characterdata_replace_data(int offset, int count, string arg); URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-E5CBA7FB Since: */ diff --git a/ext/dom/config.m4 b/ext/dom/config.m4 index 82c97e6bd34c..d228f5fb879d 100644 --- a/ext/dom/config.m4 +++ b/ext/dom/config.m4 @@ -10,7 +10,11 @@ if test -z "$PHP_LIBXML_DIR"; then [ --with-libxml-dir[=DIR] DOM: libxml2 install prefix.], no, no) fi -if test "$PHP_DOM" != "no" && test "$PHP_LIBXML" != "no"; then +if test "$PHP_DOM" != "no"; then + + if test "$PHP_LIBXML" = "no"; then + AC_MSG_ERROR([DOM extension requires LIBXML extension, add --enable-libxml]) + fi PHP_SETUP_LIBXML(DOM_SHARED_LIBADD, [ AC_DEFINE(HAVE_DOM,1,[ ]) diff --git a/ext/dom/document.c b/ext/dom/document.c index 0be049fea636..5c2e62c708c3 100644 --- a/ext/dom/document.c +++ b/ext/dom/document.c @@ -88,7 +88,7 @@ zend_function_entry php_dom_document_class_functions[] = { {NULL, NULL, NULL} }; -/* {{{ proto docType DOMDocumentType +/* {{{ docType DOMDocumentType readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-B63ED1A31 Since: @@ -124,7 +124,7 @@ int dom_document_doctype_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto implementation DOMImplementation +/* {{{ implementation DOMImplementation readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1B793EBA Since: @@ -140,7 +140,7 @@ int dom_document_implementation_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto documentElement DOMElement +/* {{{ documentElement DOMElement readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-87CD092 Since: @@ -174,7 +174,7 @@ int dom_document_document_element_read(dom_object *obj, zval **retval TSRMLS_DC) /* }}} */ -/* {{{ proto actualEncoding string +/* {{{ actualEncoding string readonly=no URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-actualEncoding Since: DOM Level 3 @@ -195,7 +195,7 @@ int dom_document_actual_encoding_write(dom_object *obj, zval *newval TSRMLS_DC) /* }}} */ -/* {{{ proto encoding string +/* {{{ encoding string URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-encoding Since: DOM Level 3 */ @@ -268,7 +268,7 @@ int dom_document_encoding_write(dom_object *obj, zval *newval TSRMLS_DC) -/* {{{ proto standalone boolean +/* {{{ standalone boolean readonly=no URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-standalone Since: DOM Level 3 @@ -334,7 +334,7 @@ int dom_document_standalone_write(dom_object *obj, zval *newval TSRMLS_DC) -/* {{{ proto version string +/* {{{ version string readonly=no URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-version Since: DOM Level 3 @@ -399,7 +399,7 @@ int dom_document_version_write(dom_object *obj, zval *newval TSRMLS_DC) /* }}} */ -/* {{{ proto strictErrorChecking boolean +/* {{{ strictErrorChecking boolean readonly=no URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-strictErrorChecking Since: DOM Level 3 @@ -444,7 +444,7 @@ int dom_document_strict_error_checking_write(dom_object *obj, zval *newval TSRML /* }}} */ -/* {{{ proto formatOutput boolean +/* {{{ formatOutput boolean readonly=no */ int dom_document_format_output_read(dom_object *obj, zval **retval TSRMLS_DC) @@ -486,7 +486,7 @@ int dom_document_format_output_write(dom_object *obj, zval *newval TSRMLS_DC) } /* }}} */ -/* {{{ proto validateOnParse boolean +/* {{{ validateOnParse boolean readonly=no */ int dom_document_validate_on_parse_read(dom_object *obj, zval **retval TSRMLS_DC) @@ -529,7 +529,7 @@ int dom_document_validate_on_parse_write(dom_object *obj, zval *newval TSRMLS_DC /* }}} */ -/* {{{ proto resolveExternals boolean +/* {{{ resolveExternals boolean readonly=no */ int dom_document_resolve_externals_read(dom_object *obj, zval **retval TSRMLS_DC) @@ -572,7 +572,7 @@ int dom_document_resolve_externals_write(dom_object *obj, zval *newval TSRMLS_DC /* }}} */ -/* {{{ proto preserveWhiteSpace boolean +/* {{{ preserveWhiteSpace boolean readonly=no */ int dom_document_preserve_whitespace_read(dom_object *obj, zval **retval TSRMLS_DC) @@ -615,7 +615,7 @@ int dom_document_preserve_whitespace_write(dom_object *obj, zval *newval TSRMLS_ /* }}} */ -/* {{{ proto substituteEntities boolean +/* {{{ substituteEntities boolean readonly=no */ int dom_document_substitue_entities_read(dom_object *obj, zval **retval TSRMLS_DC) @@ -658,7 +658,7 @@ int dom_document_substitue_entities_write(dom_object *obj, zval *newval TSRMLS_D /* }}} */ -/* {{{ proto documentURI string +/* {{{ documentURI string readonly=no URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-documentURI Since: DOM Level 3 @@ -724,7 +724,7 @@ int dom_document_document_uri_write(dom_object *obj, zval *newval TSRMLS_DC) -/* {{{ proto config DOMConfiguration +/* {{{ config DOMConfiguration readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-config Since: DOM Level 3 @@ -1016,7 +1016,7 @@ PHP_FUNCTION(dom_document_get_elements_by_tag_name) php_dom_create_interator(return_value, DOM_NODELIST TSRMLS_CC); namednode = (dom_object *)zend_objects_get_address(return_value TSRMLS_CC); local = xmlCharStrndup(name, name_len); - dom_namednode_iter(intern, 0, namednode, NULL, local, NULL); + dom_namednode_iter(intern, 0, namednode, NULL, local, NULL TSRMLS_CC); } /* }}} end dom_document_get_elements_by_tag_name */ @@ -1063,7 +1063,7 @@ PHP_FUNCTION(dom_document_import_node) /* }}} end dom_document_import_node */ -/* {{{ proto DOMElement dom_document_create_element_ns(string namespaceURI, string qualifiedName); +/* {{{ proto DOMElement dom_document_create_element_ns(string namespaceURI, string qualifiedName [,string value]); URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-DocCrElNS Since: DOM Level 2 */ @@ -1073,13 +1073,13 @@ PHP_FUNCTION(dom_document_create_element_ns) xmlDocPtr docp; xmlNodePtr nodep = NULL; xmlNsPtr nsptr = NULL; - int ret, uri_len = 0, name_len = 0; - char *uri, *name; + int ret, uri_len = 0, name_len = 0, value_len = 0; + char *uri, *name, *value = NULL; char *localname = NULL, *prefix = NULL; int errorcode; dom_object *intern; - if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os!s", &id, dom_document_class_entry, &uri, &uri_len, &name, &name_len) == FAILURE) { + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os!s|s", &id, dom_document_class_entry, &uri, &uri_len, &name, &name_len, &value, &value_len) == FAILURE) { return; } @@ -1089,7 +1089,7 @@ PHP_FUNCTION(dom_document_create_element_ns) if (errorcode == 0) { if (xmlValidateName((xmlChar *) localname, 0) == 0) { - nodep = xmlNewDocNode (docp, NULL, localname, NULL); + nodep = xmlNewDocNode (docp, NULL, localname, value); if (nodep != NULL && uri != NULL) { nsptr = xmlSearchNsByHref (nodep->doc, nodep, uri); if (nsptr == NULL) { @@ -1216,7 +1216,7 @@ PHP_FUNCTION(dom_document_get_elements_by_tag_name_ns) namednode = (dom_object *)zend_objects_get_address(return_value TSRMLS_CC); local = xmlCharStrndup(name, name_len); nsuri = xmlCharStrndup(uri, uri_len); - dom_namednode_iter(intern, 0, namednode, NULL, local, nsuri); + dom_namednode_iter(intern, 0, namednode, NULL, local, nsuri TSRMLS_CC); } /* }}} end dom_document_get_elements_by_tag_name_ns */ @@ -1544,7 +1544,7 @@ static void dom_parse_document(INTERNAL_FUNCTION_PARAMETERS, int mode) { } /* }}} end dom_parser_document */ -/* {{{ proto boolean|DOMNode dom_document_load(string source); +/* {{{ proto DOMNode dom_document_load(string source); URL: http://www.w3.org/TR/DOM-Level-3-LS/load-save.html#LS-DocumentLS-load Since: DOM Level 3 */ @@ -1554,7 +1554,7 @@ PHP_METHOD(domdocument, load) } /* }}} end dom_document_load */ -/* {{{ proto boolean|DOMNode dom_document_loadxml(string source); +/* {{{ proto DOMNode dom_document_loadxml(string source); URL: http://www.w3.org/TR/DOM-Level-3-LS/load-save.html#LS-DocumentLS-loadXML Since: DOM Level 3 */ @@ -1564,7 +1564,7 @@ PHP_METHOD(domdocument, loadXML) } /* }}} end dom_document_loadxml */ -/* {{{ proto long dom_document_save(string file); +/* {{{ proto int dom_document_save(string file); Convenience method to save to file */ PHP_FUNCTION(dom_document_save) @@ -2022,7 +2022,7 @@ static void dom_load_html(INTERNAL_FUNCTION_PARAMETERS, int mode) } } -/* {{{ proto boolean|DOMNode dom_document_load_html_file(string source); +/* {{{ proto DOMNode dom_document_load_html_file(string source); Since: DOM extended */ PHP_METHOD(domdocument, loadHTMLFile) @@ -2031,7 +2031,7 @@ PHP_METHOD(domdocument, loadHTMLFile) } /* }}} end dom_document_load_html_file */ -/* {{{ proto boolean|DOMNode dom_document_load_html(string source); +/* {{{ proto DOMNode dom_document_load_html(string source); Since: DOM extended */ PHP_METHOD(domdocument, loadHTML) @@ -2040,7 +2040,7 @@ PHP_METHOD(domdocument, loadHTML) } /* }}} end dom_document_load_html */ -/* {{{ proto long dom_document_save_html_file(string file); +/* {{{ proto int dom_document_save_html_file(string file); Convenience method to save to file as html */ PHP_FUNCTION(dom_document_save_html_file) diff --git a/ext/dom/documenttype.c b/ext/dom/documenttype.c index bf3e5cf3bece..d3100b0845aa 100644 --- a/ext/dom/documenttype.c +++ b/ext/dom/documenttype.c @@ -38,7 +38,7 @@ zend_function_entry php_dom_documenttype_class_functions[] = { {NULL, NULL, NULL} }; -/* {{{ proto name string +/* {{{ name string readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1844763134 Since: @@ -64,7 +64,7 @@ int dom_documenttype_name_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto entities DOMNamedNodeMap +/* {{{ entities DOMNamedNodeMap readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1788794630 Since: @@ -88,7 +88,7 @@ int dom_documenttype_entities_read(dom_object *obj, zval **retval TSRMLS_DC) entityht = (xmlHashTable *) doctypep->entities; intern = (dom_object *)zend_objects_get_address(*retval TSRMLS_CC); - dom_namednode_iter(obj, XML_ENTITY_NODE, intern, entityht, NULL, NULL); + dom_namednode_iter(obj, XML_ENTITY_NODE, intern, entityht, NULL, NULL TSRMLS_CC); return SUCCESS; } @@ -97,7 +97,7 @@ int dom_documenttype_entities_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto notations DOMNamedNodeMap +/* {{{ notations DOMNamedNodeMap readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-D46829EF Since: @@ -121,7 +121,7 @@ int dom_documenttype_notations_read(dom_object *obj, zval **retval TSRMLS_DC) notationht = (xmlHashTable *) doctypep->notations; intern = (dom_object *)zend_objects_get_address(*retval TSRMLS_CC); - dom_namednode_iter(obj, XML_NOTATION_NODE, intern, notationht, NULL, NULL); + dom_namednode_iter(obj, XML_NOTATION_NODE, intern, notationht, NULL, NULL TSRMLS_CC); return SUCCESS; } @@ -130,7 +130,7 @@ int dom_documenttype_notations_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto publicId string +/* {{{ publicId string readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-Core-DocType-publicId Since: DOM Level 2 @@ -160,7 +160,7 @@ int dom_documenttype_public_id_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto systemId string +/* {{{ systemId string readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-Core-DocType-systemId Since: DOM Level 2 @@ -189,7 +189,7 @@ int dom_documenttype_system_id_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto internalSubset string +/* {{{ internalSubset string readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-Core-DocType-internalSubset Since: DOM Level 2 diff --git a/ext/dom/dom_ce.h b/ext/dom/dom_ce.h index ba6d05f72167..dc730c2f6205 100644 --- a/ext/dom/dom_ce.h +++ b/ext/dom/dom_ce.h @@ -21,37 +21,37 @@ #ifndef DOM_CE_H #define DOM_CE_H -zend_class_entry *dom_domexception_class_entry; -zend_class_entry *dom_domstringlist_class_entry; -zend_class_entry *dom_namelist_class_entry; -zend_class_entry *dom_domimplementationlist_class_entry; -zend_class_entry *dom_domimplementationsource_class_entry; -zend_class_entry *dom_domimplementation_class_entry; -zend_class_entry *dom_documentfragment_class_entry; -zend_class_entry *dom_document_class_entry; -zend_class_entry *dom_nodelist_class_entry; -zend_class_entry *dom_namednodemap_class_entry; -zend_class_entry *dom_characterdata_class_entry; -zend_class_entry *dom_attr_class_entry; -zend_class_entry *dom_element_class_entry; -zend_class_entry *dom_text_class_entry; -zend_class_entry *dom_comment_class_entry; -zend_class_entry *dom_typeinfo_class_entry; -zend_class_entry *dom_userdatahandler_class_entry; -zend_class_entry *dom_domerror_class_entry; -zend_class_entry *dom_domerrorhandler_class_entry; -zend_class_entry *dom_domlocator_class_entry; -zend_class_entry *dom_domconfiguration_class_entry; -zend_class_entry *dom_cdatasection_class_entry; -zend_class_entry *dom_documenttype_class_entry; -zend_class_entry *dom_notation_class_entry; -zend_class_entry *dom_entity_class_entry; -zend_class_entry *dom_entityreference_class_entry; -zend_class_entry *dom_processinginstruction_class_entry; -zend_class_entry *dom_string_extend_class_entry; +extern zend_class_entry *dom_domexception_class_entry; +extern zend_class_entry *dom_domstringlist_class_entry; +extern zend_class_entry *dom_namelist_class_entry; +extern zend_class_entry *dom_domimplementationlist_class_entry; +extern zend_class_entry *dom_domimplementationsource_class_entry; +extern zend_class_entry *dom_domimplementation_class_entry; +extern zend_class_entry *dom_documentfragment_class_entry; +extern zend_class_entry *dom_document_class_entry; +extern zend_class_entry *dom_nodelist_class_entry; +extern zend_class_entry *dom_namednodemap_class_entry; +extern zend_class_entry *dom_characterdata_class_entry; +extern zend_class_entry *dom_attr_class_entry; +extern zend_class_entry *dom_element_class_entry; +extern zend_class_entry *dom_text_class_entry; +extern zend_class_entry *dom_comment_class_entry; +extern zend_class_entry *dom_typeinfo_class_entry; +extern zend_class_entry *dom_userdatahandler_class_entry; +extern zend_class_entry *dom_domerror_class_entry; +extern zend_class_entry *dom_domerrorhandler_class_entry; +extern zend_class_entry *dom_domlocator_class_entry; +extern zend_class_entry *dom_domconfiguration_class_entry; +extern zend_class_entry *dom_cdatasection_class_entry; +extern zend_class_entry *dom_documenttype_class_entry; +extern zend_class_entry *dom_notation_class_entry; +extern zend_class_entry *dom_entity_class_entry; +extern zend_class_entry *dom_entityreference_class_entry; +extern zend_class_entry *dom_processinginstruction_class_entry; +extern zend_class_entry *dom_string_extend_class_entry; #if defined(LIBXML_XPATH_ENABLED) -zend_class_entry *dom_xpath_class_entry; +extern zend_class_entry *dom_xpath_class_entry; #endif -zend_class_entry *dom_namespace_node_class_entry; +extern zend_class_entry *dom_namespace_node_class_entry; #endif /* DOM_CE_H */ diff --git a/ext/dom/domerror.c b/ext/dom/domerror.c index 002632e8632c..7d3433f03ae5 100644 --- a/ext/dom/domerror.c +++ b/ext/dom/domerror.c @@ -41,7 +41,7 @@ zend_function_entry php_dom_domerror_class_functions[] = { /* {{{ attribute protos, not implemented yet */ -/* {{{ proto severity unsigned short +/* {{{ severity unsigned short readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ERROR-DOMError-severity Since: @@ -57,7 +57,7 @@ int dom_domerror_severity_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto message string +/* {{{ message string readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ERROR-DOMError-message Since: @@ -73,7 +73,7 @@ int dom_domerror_message_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto type string +/* {{{ type string readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ERROR-DOMError-type Since: @@ -89,7 +89,7 @@ int dom_domerror_type_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto relatedException object +/* {{{ relatedException object readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ERROR-DOMError-relatedException Since: @@ -105,7 +105,7 @@ int dom_domerror_related_exception_read(dom_object *obj, zval **retval TSRMLS_DC -/* {{{ proto relatedData domobject +/* {{{ relatedData domobject readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ERROR-DOMError-relatedData Since: @@ -121,7 +121,7 @@ int dom_domerror_related_data_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto location domlocator +/* {{{ location domlocator readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ERROR-DOMError-location Since: diff --git a/ext/dom/domimplementationlist.c b/ext/dom/domimplementationlist.c index 7a71e46c4b4f..23f414a2378b 100644 --- a/ext/dom/domimplementationlist.c +++ b/ext/dom/domimplementationlist.c @@ -42,7 +42,7 @@ zend_function_entry php_dom_domimplementationlist_class_functions[] = { /* {{{ attribute protos, not implemented yet */ -/* {{{ proto length unsigned long +/* {{{ length unsigned long readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#DOMImplementationList-length Since: @@ -59,7 +59,7 @@ int dom_domimplementationlist_length_read(dom_object *obj, zval **retval TSRMLS_ -/* {{{ proto domdomimplementation dom_domimplementationlist_item(unsigned long index); +/* {{{ proto domdomimplementation dom_domimplementationlist_item(int index); URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#DOMImplementationList-item Since: */ diff --git a/ext/dom/domlocator.c b/ext/dom/domlocator.c index eae848f94eb5..3b62342b36bf 100644 --- a/ext/dom/domlocator.c +++ b/ext/dom/domlocator.c @@ -41,7 +41,7 @@ zend_function_entry php_dom_domlocator_class_functions[] = { /* {{{ attribute protos, not implemented yet */ -/* {{{ proto line_number long +/* {{{ line_number long readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#DOMLocator-line-number Since: @@ -57,7 +57,7 @@ int dom_domlocator_line_number_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto column_number long +/* {{{ column_number long readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#DOMLocator-column-number Since: @@ -73,7 +73,7 @@ int dom_domlocator_column_number_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto offset long +/* {{{ offset long readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#DOMLocator-offset Since: @@ -89,7 +89,7 @@ int dom_domlocator_offset_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto related_node node +/* {{{ related_node node readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#DOMLocator-node Since: @@ -105,7 +105,7 @@ int dom_domlocator_related_node_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto uri string +/* {{{ uri string readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#DOMLocator-uri Since: diff --git a/ext/dom/domstringlist.c b/ext/dom/domstringlist.c index b75a7cc63c8c..5d56fc64a5a8 100644 --- a/ext/dom/domstringlist.c +++ b/ext/dom/domstringlist.c @@ -42,7 +42,7 @@ zend_function_entry php_dom_domstringlist_class_functions[] = { /* {{{ attribute protos, not implemented yet */ -/* {{{ proto length unsigned long +/* {{{ length unsigned long readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#DOMStringList-length Since: @@ -59,7 +59,7 @@ int dom_domstringlist_length_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto domstring dom_domstringlist_item(unsigned long index); +/* {{{ proto domstring dom_domstringlist_item(int index); URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#DOMStringList-item Since: */ diff --git a/ext/dom/element.c b/ext/dom/element.c index e5f15b02c5f6..09ba77df0c83 100644 --- a/ext/dom/element.c +++ b/ext/dom/element.c @@ -137,7 +137,7 @@ PHP_METHOD(domelement, __construct) } /* }}} end DOMElement::__construct */ -/* {{{ proto tagName string +/* {{{ tagName string readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-104682815 Since: @@ -174,7 +174,7 @@ int dom_element_tag_name_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto schemaTypeInfo typeinfo +/* {{{ schemaTypeInfo typeinfo readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Element-schemaTypeInfo Since: DOM Level 3 @@ -250,7 +250,7 @@ PHP_FUNCTION(dom_element_set_attribute) } attr = xmlHasProp(nodep,name); - if (attr != NULL) { + if (attr != NULL && attr->type != XML_ATTRIBUTE_DECL) { node_list_unlink(attr->children TSRMLS_CC); } attr = xmlSetProp(nodep, name, value); @@ -294,13 +294,14 @@ PHP_FUNCTION(dom_element_remove_attribute) RETURN_FALSE; } - /* TODO: DTD defined attributes are handled special */ - if (php_dom_object_get_data((xmlNodePtr) attrp) == NULL) { - node_list_unlink(attrp->children TSRMLS_CC); - xmlUnlinkNode((xmlNodePtr) attrp); - xmlFreeProp(attrp); - } else { - xmlUnlinkNode((xmlNodePtr) attrp); + if (attrp->type != XML_ATTRIBUTE_DECL) { + if (php_dom_object_get_data((xmlNodePtr) attrp) == NULL) { + node_list_unlink(attrp->children TSRMLS_CC); + xmlUnlinkNode((xmlNodePtr) attrp); + xmlFreeProp(attrp); + } else { + xmlUnlinkNode((xmlNodePtr) attrp); + } } RETURN_TRUE; @@ -368,7 +369,7 @@ PHP_FUNCTION(dom_element_set_attribute_node) } existattrp = xmlHasProp(nodep, attrp->name); - if (existattrp != NULL) { + if (existattrp != NULL && existattrp->type != XML_ATTRIBUTE_DECL) { if ((oldobj = php_dom_object_get_data((xmlNodePtr) existattrp)) != NULL && ((php_libxml_node_ptr *)oldobj->ptr)->node == (xmlNodePtr) attrp) { @@ -455,7 +456,7 @@ PHP_FUNCTION(dom_element_get_elements_by_tag_name) php_dom_create_interator(return_value, DOM_NODELIST TSRMLS_CC); namednode = (dom_object *)zend_objects_get_address(return_value TSRMLS_CC); local = xmlCharStrndup(name, name_len); - dom_namednode_iter(intern, 0, namednode, NULL, local, NULL); + dom_namednode_iter(intern, 0, namednode, NULL, local, NULL TSRMLS_CC); } /* }}} end dom_element_get_elements_by_tag_name */ @@ -540,7 +541,7 @@ PHP_FUNCTION(dom_element_set_attribute_ns) if (errorcode == 0) { if (uri_len > 0) { nodep = (xmlNodePtr) xmlHasNsProp(elemp, localname, uri); - if (nodep != NULL) { + if (nodep != NULL && nodep->type != XML_ATTRIBUTE_DECL) { node_list_unlink(nodep->children TSRMLS_CC); } @@ -578,7 +579,7 @@ PHP_FUNCTION(dom_element_set_attribute_ns) } } else { attr = xmlHasProp(elemp, localname); - if (attr != NULL) { + if (attr != NULL && attr->type != XML_ATTRIBUTE_DECL) { node_list_unlink(attr->children TSRMLS_CC); } attr = xmlSetProp(elemp, localname, value); @@ -642,7 +643,7 @@ PHP_FUNCTION(dom_element_remove_attribute_ns) } } - if (attrp) { + if (attrp && attrp->type != XML_ATTRIBUTE_DECL) { if (php_dom_object_get_data((xmlNodePtr) attrp) == NULL) { node_list_unlink(attrp->children TSRMLS_CC); xmlUnlinkNode((xmlNodePtr) attrp); @@ -726,7 +727,7 @@ PHP_FUNCTION(dom_element_set_attribute_node_ns) existattrp = xmlHasProp(nodep, attrp->name); } - if (existattrp != NULL) { + if (existattrp != NULL && existattrp->type != XML_ATTRIBUTE_DECL) { if ((oldobj = php_dom_object_get_data((xmlNodePtr) existattrp)) != NULL && ((php_libxml_node_ptr *)oldobj->ptr)->node == (xmlNodePtr) attrp) { @@ -777,7 +778,7 @@ PHP_FUNCTION(dom_element_get_elements_by_tag_name_ns) namednode = (dom_object *)zend_objects_get_address(return_value TSRMLS_CC); local = xmlCharStrndup(name, name_len); nsuri = xmlCharStrndup(uri, uri_len); - dom_namednode_iter(intern, 0, namednode, NULL, local, nsuri); + dom_namednode_iter(intern, 0, namednode, NULL, local, nsuri TSRMLS_CC); } /* }}} end dom_element_get_elements_by_tag_name_ns */ diff --git a/ext/dom/entity.c b/ext/dom/entity.c index 6da6b4e95936..f5da4cca6b30 100644 --- a/ext/dom/entity.c +++ b/ext/dom/entity.c @@ -39,7 +39,7 @@ zend_function_entry php_dom_entity_class_functions[] = { {NULL, NULL, NULL} }; -/* {{{ proto publicId string +/* {{{ publicId string readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-D7303025 Since: @@ -69,7 +69,7 @@ int dom_entity_public_id_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto systemId string +/* {{{ systemId string readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-D7C29F3E Since: @@ -99,7 +99,7 @@ int dom_entity_system_id_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto notationName string +/* {{{ notationName string readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-6ABAEB38 Since: @@ -132,7 +132,7 @@ int dom_entity_notation_name_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto actualEncoding string +/* {{{ actualEncoding string readonly=no URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Entity3-actualEncoding Since: DOM Level 3 @@ -153,7 +153,7 @@ int dom_entity_actual_encoding_write(dom_object *obj, zval *newval TSRMLS_DC) -/* {{{ proto encoding string +/* {{{ encoding string readonly=no URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Entity3-encoding Since: DOM Level 3 @@ -174,7 +174,7 @@ int dom_entity_encoding_write(dom_object *obj, zval *newval TSRMLS_DC) -/* {{{ proto version string +/* {{{ version string readonly=no URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Entity3-version Since: DOM Level 3 diff --git a/ext/dom/namednodemap.c b/ext/dom/namednodemap.c index 2bc585f018b1..c3d1f1648dbd 100644 --- a/ext/dom/namednodemap.c +++ b/ext/dom/namednodemap.c @@ -46,7 +46,7 @@ zend_function_entry php_dom_namednodemap_class_functions[] = { {NULL, NULL, NULL} }; -/* {{{ proto length int +/* {{{ length int readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-6D0FB19E Since: diff --git a/ext/dom/namelist.c b/ext/dom/namelist.c index c4462ef31b1a..39ca0e1e2579 100644 --- a/ext/dom/namelist.c +++ b/ext/dom/namelist.c @@ -41,7 +41,7 @@ zend_function_entry php_dom_namelist_class_functions[] = { {NULL, NULL, NULL} }; -/* {{{ proto length int +/* {{{ length int readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#NameList-length Since: diff --git a/ext/dom/node.c b/ext/dom/node.c index e646a604fcdf..e1fe97de2565 100644 --- a/ext/dom/node.c +++ b/ext/dom/node.c @@ -72,7 +72,7 @@ static void dom_reconcile_ns(xmlDocPtr doc, xmlNodePtr nodep) { } } -/* {{{ proto nodeName string +/* {{{ nodeName string readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-F68D095 Since: @@ -164,7 +164,7 @@ int dom_node_node_name_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto nodeValue string +/* {{{ nodeValue string readonly=no URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-F68D080 Since: @@ -260,7 +260,7 @@ int dom_node_node_value_write(dom_object *obj, zval *newval TSRMLS_DC) -/* {{{ proto nodeType int +/* {{{ nodeType int readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-111237558 Since: @@ -292,7 +292,7 @@ int dom_node_node_type_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto parentNode DomNode +/* {{{ parentNode DomNode readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1060184317 Since: @@ -327,7 +327,7 @@ int dom_node_parent_node_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto childNodes DomNodeList +/* {{{ childNodes DomNodeList readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1451460987 Since: @@ -351,7 +351,7 @@ int dom_node_child_nodes_read(dom_object *obj, zval **retval TSRMLS_DC) } else { php_dom_create_interator(*retval, DOM_NODELIST TSRMLS_CC); intern = (dom_object *)zend_objects_get_address(*retval TSRMLS_CC); - dom_namednode_iter(obj, XML_ELEMENT_NODE, intern, NULL, NULL, NULL); + dom_namednode_iter(obj, XML_ELEMENT_NODE, intern, NULL, NULL, NULL TSRMLS_CC); } return SUCCESS; @@ -361,7 +361,7 @@ int dom_node_child_nodes_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto firstChild DomNode +/* {{{ firstChild DomNode readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-169727388 Since: @@ -399,7 +399,7 @@ int dom_node_first_child_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto lastChild DomNode +/* {{{ lastChild DomNode readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-61AD09FB Since: @@ -437,7 +437,7 @@ int dom_node_last_child_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto previousSibling DomNode +/* {{{ previousSibling DomNode readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-640FB3C8 Since: @@ -472,7 +472,7 @@ int dom_node_previous_sibling_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto nextSibling DomNode +/* {{{ nextSibling DomNode readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-6AC54C2F Since: @@ -507,7 +507,7 @@ int dom_node_next_sibling_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto attributes DomNamedNodeMap +/* {{{ attributes DomNamedNodeMap readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-84CF096 Since: @@ -529,7 +529,7 @@ int dom_node_attributes_read(dom_object *obj, zval **retval TSRMLS_DC) if (nodep->type == XML_ELEMENT_NODE) { php_dom_create_interator(*retval, DOM_NAMEDNODEMAP TSRMLS_CC); intern = (dom_object *)zend_objects_get_address(*retval TSRMLS_CC); - dom_namednode_iter(obj, XML_ATTRIBUTE_NODE, intern, NULL, NULL, NULL); + dom_namednode_iter(obj, XML_ATTRIBUTE_NODE, intern, NULL, NULL, NULL TSRMLS_CC); } else { ZVAL_NULL(*retval); } @@ -541,7 +541,7 @@ int dom_node_attributes_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto ownerDocument DomDocument +/* {{{ ownerDocument DomDocument readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-node-ownerDoc Since: @@ -583,7 +583,7 @@ int dom_node_owner_document_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto namespaceUri string +/* {{{ namespaceUri string readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-NodeNSname Since: DOM Level 2 @@ -628,7 +628,7 @@ int dom_node_namespace_uri_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto prefix string +/* {{{ prefix string readonly=no URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-NodeNSPrefix Since: DOM Level 2 @@ -752,7 +752,7 @@ int dom_node_prefix_write(dom_object *obj, zval *newval TSRMLS_DC) -/* {{{ proto localName string +/* {{{ localName string readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-NodeNSLocalN Since: DOM Level 2 @@ -783,7 +783,7 @@ int dom_node_local_name_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto baseURI string +/* {{{ baseURI string readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-baseURI Since: DOM Level 3 @@ -817,7 +817,7 @@ int dom_node_base_uri_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto textContent string +/* {{{ textContent string readonly=no URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-textContent Since: DOM Level 3 @@ -856,7 +856,51 @@ int dom_node_text_content_write(dom_object *obj, zval *newval TSRMLS_DC) /* }}} */ +static xmlNodePtr _php_dom_insert_fragment(xmlNodePtr nodep, xmlNodePtr prevsib, + xmlNodePtr nextsib, xmlNodePtr fragment, + dom_object *intern, dom_object *childobj TSRMLS_DC) +{ + xmlNodePtr newchild, node; + + newchild = fragment->children; + + if (newchild) { + if (prevsib == NULL) { + nodep->children = newchild; + } else { + prevsib->next = newchild; + } + newchild->prev = prevsib; + if (nextsib == NULL) { + nodep->last = fragment->last; + } else { + fragment->last->next = nextsib; + nextsib->prev = fragment->last; + } + node = newchild; + while (node != NULL) { + node->parent = nodep; + if (node->doc != nodep->doc) { + xmlSetTreeDoc(node, nodep->doc); + if (node->_private != NULL) { + childobj = node->_private; + childobj->document = intern->document; + php_libxml_increment_doc_ref((php_libxml_node_object *)childobj, NULL TSRMLS_CC); + } + } + if (node == fragment->last) { + break; + } + node = node->next; + } + + fragment->children = NULL; + fragment->last = NULL; + } + + return newchild; +} /* {{{ proto domnode dom_node_insert_before(DomNode newChild, DomNode refChild); URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-952280727 @@ -948,7 +992,7 @@ PHP_FUNCTION(dom_node_insert_before) lastattr = xmlHasProp(refp->parent, child->name); else lastattr = xmlHasNsProp(refp->parent, child->name, child->ns->href); - if (lastattr != NULL) { + if (lastattr != NULL && lastattr->type != XML_ATTRIBUTE_DECL) { if (lastattr != (xmlAttrPtr) child) { xmlUnlinkNode((xmlNodePtr) lastattr); php_libxml_node_free_resource((xmlNodePtr) lastattr TSRMLS_CC); @@ -958,32 +1002,7 @@ PHP_FUNCTION(dom_node_insert_before) } } } else if (child->type == XML_DOCUMENT_FRAG_NODE) { - xmlNodePtr fragment; - - fragment = child; - new_child = child->children; - child = new_child; - while (child->next != NULL) { - child->parent = parentp; - if (child->doc != parentp->doc) { - xmlSetTreeDoc(child, parentp->doc); - } - child = child->next; - } - child->parent = parentp; - if (child->doc != parentp->doc) { - xmlSetTreeDoc(child, parentp->doc); - } - - if (refp->prev != NULL) { - refp->prev->next = new_child; - } else { - parentp->children = new_child; - } - new_child->prev = refp->prev; - refp->prev = child; - child->next = refp; - fragment->children = NULL; + new_child = _php_dom_insert_fragment(parentp, refp->prev, refp, child, intern, childobj TSRMLS_CC); } if (new_child == NULL) { @@ -1015,7 +1034,7 @@ PHP_FUNCTION(dom_node_insert_before) lastattr = xmlHasProp(parentp, child->name); else lastattr = xmlHasNsProp(parentp, child->name, child->ns->href); - if (lastattr != NULL) { + if (lastattr != NULL && lastattr->type != XML_ATTRIBUTE_DECL) { if (lastattr != (xmlAttrPtr) child) { xmlUnlinkNode((xmlNodePtr) lastattr); php_libxml_node_free_resource((xmlNodePtr) lastattr TSRMLS_CC); @@ -1025,32 +1044,7 @@ PHP_FUNCTION(dom_node_insert_before) } } } else if (child->type == XML_DOCUMENT_FRAG_NODE) { - xmlNodePtr fragment; - - fragment = child; - - new_child = child->children; - if (parentp->children == NULL) { - parentp->children = new_child; - } else { - child = parentp->last; - child->next = new_child; - new_child->prev = child; - } - child = new_child; - while (child->next != NULL) { - child->parent = parentp; - if (child->doc != parentp->doc) { - xmlSetTreeDoc(child, parentp->doc); - } - child = child->next; - } - child->parent = parentp; - if (child->doc != parentp->doc) { - xmlSetTreeDoc(child, parentp->doc); - } - parentp->last = child; - fragment->children = NULL; + new_child = _php_dom_insert_fragment(parentp, parentp->last, NULL, child, intern, childobj TSRMLS_CC); } if (new_child == NULL) { new_child = xmlAddChild(parentp, child); @@ -1129,9 +1123,21 @@ PHP_FUNCTION(dom_node_replace_child) } if (foundoldchild) { + xmlNodePtr node; zval *rv = NULL; - if (oldchild != newchild) { - xmlNodePtr node; + + if (newchild->type == XML_DOCUMENT_FRAG_NODE) { + xmlNodePtr prevsib, nextsib; + prevsib = oldchild->prev; + nextsib = oldchild->next; + + xmlUnlinkNode(oldchild); + + newchild = _php_dom_insert_fragment(nodep, prevsib, nextsib, newchild, intern, newchildobj TSRMLS_CC); + if (newchild) { + dom_reconcile_ns(nodep->doc, newchild); + } + } else if (oldchild != newchild) { if (newchild->doc == NULL && nodep->doc != NULL) { xmlSetTreeDoc(newchild, nodep->doc); newchildobj->document = intern->document; @@ -1146,7 +1152,6 @@ PHP_FUNCTION(dom_node_replace_child) php_dom_throw_error(NOT_FOUND_ERR, dom_get_strict_error(intern->document) TSRMLS_CC); RETURN_FALSE; } - } /* }}} end dom_node_replace_child */ @@ -1281,38 +1286,14 @@ PHP_FUNCTION(dom_node_append_child) lastattr = xmlHasProp(nodep, child->name); else lastattr = xmlHasNsProp(nodep, child->name, child->ns->href); - if (lastattr != NULL) { + if (lastattr != NULL && lastattr->type != XML_ATTRIBUTE_DECL) { if (lastattr != (xmlAttrPtr) child) { xmlUnlinkNode((xmlNodePtr) lastattr); php_libxml_node_free_resource((xmlNodePtr) lastattr TSRMLS_CC); } } } else if (child->type == XML_DOCUMENT_FRAG_NODE) { - xmlNodePtr fragment; - - fragment = child; - new_child = child->children; - if (nodep->children == NULL) { - nodep->children = new_child; - } else { - child = nodep->last; - child->next = new_child; - new_child->prev = child; - } - child = new_child; - while (child->next != NULL) { - child->parent = nodep; - if (child->doc != nodep->doc) { - xmlSetTreeDoc(child, nodep->doc); - } - child = child->next; - } - child->parent = nodep; - if (child->doc != nodep->doc) { - xmlSetTreeDoc(child, nodep->doc); - } - nodep->last = child; - fragment->children = NULL; + new_child = _php_dom_insert_fragment(nodep, nodep->last, NULL, child, intern, childobj TSRMLS_CC); } if (new_child == NULL) { diff --git a/ext/dom/nodelist.c b/ext/dom/nodelist.c index 72c388fc015f..9421fac1157d 100644 --- a/ext/dom/nodelist.c +++ b/ext/dom/nodelist.c @@ -40,7 +40,7 @@ zend_function_entry php_dom_nodelist_class_functions[] = { {NULL, NULL, NULL} }; -/* {{{ proto length int +/* {{{ length int readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-203510337 Since: diff --git a/ext/dom/notation.c b/ext/dom/notation.c index 6dfbfcb22f49..2cf1c0751c52 100644 --- a/ext/dom/notation.c +++ b/ext/dom/notation.c @@ -41,7 +41,7 @@ zend_function_entry php_dom_notation_class_functions[] = { /* {{{ attribute protos, not implemented yet */ -/* {{{ proto publicId string +/* {{{ publicId string readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-54F2B4D0 Since: @@ -71,7 +71,7 @@ int dom_notation_public_id_read(dom_object *obj, zval **retval TSRMLS_DC) -/* {{{ proto systemId string +/* {{{ systemId string readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-E8AAB1D0 Since: diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index 8c2857e64f89..62d6d5332c14 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -34,7 +34,42 @@ #define PHP_XPATH 1 #define PHP_XPTR 2 +zend_class_entry *dom_node_class_entry; +zend_class_entry *dom_domexception_class_entry; +zend_class_entry *dom_domstringlist_class_entry; +zend_class_entry *dom_namelist_class_entry; +zend_class_entry *dom_domimplementationlist_class_entry; +zend_class_entry *dom_domimplementationsource_class_entry; +zend_class_entry *dom_domimplementation_class_entry; +zend_class_entry *dom_documentfragment_class_entry; +zend_class_entry *dom_document_class_entry; +zend_class_entry *dom_nodelist_class_entry; +zend_class_entry *dom_namednodemap_class_entry; +zend_class_entry *dom_characterdata_class_entry; +zend_class_entry *dom_attr_class_entry; +zend_class_entry *dom_element_class_entry; +zend_class_entry *dom_text_class_entry; +zend_class_entry *dom_comment_class_entry; +zend_class_entry *dom_typeinfo_class_entry; +zend_class_entry *dom_userdatahandler_class_entry; +zend_class_entry *dom_domerror_class_entry; +zend_class_entry *dom_domerrorhandler_class_entry; +zend_class_entry *dom_domlocator_class_entry; +zend_class_entry *dom_domconfiguration_class_entry; +zend_class_entry *dom_cdatasection_class_entry; +zend_class_entry *dom_documenttype_class_entry; +zend_class_entry *dom_notation_class_entry; +zend_class_entry *dom_entity_class_entry; +zend_class_entry *dom_entityreference_class_entry; +zend_class_entry *dom_processinginstruction_class_entry; +zend_class_entry *dom_string_extend_class_entry; +#if defined(LIBXML_XPATH_ENABLED) +zend_class_entry *dom_xpath_class_entry; +#endif +zend_class_entry *dom_namespace_node_class_entry; + zend_object_handlers dom_object_handlers; +zend_object_handlers dom_ze1_object_handlers; static HashTable classes; @@ -199,6 +234,38 @@ static void dom_register_prop_handler(HashTable *prop_handler, char *name, dom_r } /* }}} */ +static zval **dom_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC) +{ + dom_object *obj; + zval tmp_member; + zval **retval = NULL; + dom_prop_handler *hnd; + zend_object_handlers *std_hnd; + int ret = FAILURE; + + if (member->type != IS_STRING) { + tmp_member = *member; + zval_copy_ctor(&tmp_member); + convert_to_string(&tmp_member); + member = &tmp_member; + } + + obj = (dom_object *)zend_objects_get_address(object TSRMLS_CC); + + if (obj->prop_handler != NULL) { + ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd); + } + if (ret == FAILURE) { + std_hnd = zend_get_std_object_handlers(); + retval = std_hnd->get_property_ptr_ptr(object, member TSRMLS_CC); + } + + if (member == &tmp_member) { + zval_dtor(member); + } + return retval; +} + /* {{{ dom_read_property */ zval *dom_read_property(zval *object, zval *member, int type TSRMLS_DC) { @@ -327,13 +394,14 @@ zend_object_value dom_objects_store_clone_obj(zval *zobject TSRMLS_DC) zend_object_value retval; void *new_object; dom_object *intern; + dom_object *old_object; struct _store_object *obj; zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); obj = &EG(objects_store).object_buckets[handle].bucket.obj; if (obj->clone == NULL) { - zend_error(E_CORE_ERROR, "Trying to clone uncloneable object of class %s", Z_OBJCE_P(zobject)->name); + php_error(E_ERROR, "Trying to clone an uncloneable object of class %s", Z_OBJCE_P(zobject)->name); } obj->clone(obj->object, &new_object TSRMLS_CC); @@ -343,14 +411,32 @@ zend_object_value dom_objects_store_clone_obj(zval *zobject TSRMLS_DC) intern->handle = retval.handle; retval.handlers = Z_OBJ_HT_P(zobject); + old_object = (dom_object *) obj->object; + zend_objects_clone_members(&intern->std, retval, &old_object->std, intern->handle TSRMLS_CC); + return retval; } +zend_object_value dom_objects_ze1_clone_obj(zval *zobject TSRMLS_DC) +{ + php_error(E_ERROR, "Cannot clone object of class %s due to 'zend.ze1_compatibility_mode'", Z_OBJCE_P(zobject)->name); + /* Return zobject->value.obj just to satisfy compiler */ + return zobject->value.obj; +} + static zend_function_entry dom_functions[] = { PHP_FE(dom_import_simplexml, NULL) {NULL, NULL, NULL} }; +static zend_object_handlers* dom_get_obj_handlers(TSRMLS_D) { + if (EG(ze1_compatibility_mode)) { + return &dom_ze1_object_handlers; + } else { + return &dom_object_handlers; + } +} + zend_module_entry dom_module_entry = { STANDARD_MODULE_HEADER, "dom", @@ -376,15 +462,20 @@ PHP_MINIT_FUNCTION(dom) memcpy(&dom_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); dom_object_handlers.read_property = dom_read_property; dom_object_handlers.write_property = dom_write_property; - dom_object_handlers.get_property_ptr_ptr = NULL; + dom_object_handlers.get_property_ptr_ptr = dom_get_property_ptr_ptr; dom_object_handlers.clone_obj = dom_objects_store_clone_obj; + memcpy(&dom_ze1_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + dom_ze1_object_handlers.read_property = dom_read_property; + dom_ze1_object_handlers.write_property = dom_write_property; + dom_object_handlers.get_property_ptr_ptr = dom_get_property_ptr_ptr; + dom_ze1_object_handlers.clone_obj = dom_objects_ze1_clone_obj; + zend_hash_init(&classes, 0, NULL, NULL, 1); INIT_CLASS_ENTRY(ce, "DOMException", php_dom_domexception_class_functions); dom_domexception_class_entry = zend_register_internal_class_ex(&ce, zend_exception_get_default(), NULL TSRMLS_CC); dom_domexception_class_entry->ce_flags |= ZEND_ACC_FINAL; - dom_domexception_class_entry->constructor->common.fn_flags |= ZEND_ACC_PROTECTED; zend_declare_property_long(dom_domexception_class_entry, "code", sizeof("code")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC); REGISTER_DOM_CLASS(ce, "DOMStringList", NULL, php_dom_domstringlist_class_functions, dom_domstringlist_class_entry); @@ -806,7 +897,7 @@ void dom_objects_free_storage(void *object TSRMLS_DC) } /* }}} */ -void dom_namednode_iter(dom_object *basenode, int ntype, dom_object *intern, xmlHashTablePtr ht, xmlChar *local, xmlChar *ns) +void dom_namednode_iter(dom_object *basenode, int ntype, dom_object *intern, xmlHashTablePtr ht, xmlChar *local, xmlChar *ns TSRMLS_DC) { dom_nnodemap_object *mapptr; zval *baseobj = NULL; @@ -817,7 +908,7 @@ void dom_namednode_iter(dom_object *basenode, int ntype, dom_object *intern, xml baseobj->type = IS_OBJECT; baseobj->is_ref = 1; baseobj->value.obj.handle = basenode->handle; - baseobj->value.obj.handlers = &dom_object_handlers; + baseobj->value.obj.handlers = dom_get_obj_handlers(TSRMLS_C); zval_copy_ctor(baseobj); } mapptr->baseobjptr = baseobj; @@ -829,7 +920,7 @@ void dom_namednode_iter(dom_object *basenode, int ntype, dom_object *intern, xml } -static dom_object* dom_objects_set_class(zend_class_entry *class_type TSRMLS_DC) +static dom_object* dom_objects_set_class(zend_class_entry *class_type, zend_bool hash_copy TSRMLS_DC) { zend_class_entry *base_class; zval *tmp; @@ -852,7 +943,9 @@ static dom_object* dom_objects_set_class(zend_class_entry *class_type TSRMLS_DC) ALLOC_HASHTABLE(intern->std.properties); zend_hash_init(intern->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0); - zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); + if (hash_copy) { + zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); + } return intern; } @@ -865,7 +958,7 @@ void dom_objects_clone(void *object, void **object_clone TSRMLS_DC) xmlNodePtr node; xmlNodePtr cloned_node; - clone = dom_objects_set_class(intern->std.ce TSRMLS_CC); + clone = dom_objects_set_class(intern->std.ce, 0 TSRMLS_CC); if (instanceof_function(intern->std.ce, dom_node_class_entry TSRMLS_CC)) { node = (xmlNodePtr)dom_object_get_node((dom_object *) object); @@ -877,7 +970,7 @@ void dom_objects_clone(void *object, void **object_clone TSRMLS_DC) clone->document = intern->document; } php_libxml_increment_doc_ref((php_libxml_node_object *)clone, cloned_node->doc TSRMLS_CC); - php_libxml_increment_node_ptr((php_libxml_node_object *)clone, cloned_node, NULL TSRMLS_CC); + php_libxml_increment_node_ptr((php_libxml_node_object *)clone, cloned_node, (void *)clone TSRMLS_CC); } } @@ -893,11 +986,11 @@ zend_object_value dom_objects_new(zend_class_entry *class_type TSRMLS_DC) zend_object_value retval; dom_object *intern; - intern = dom_objects_set_class(class_type TSRMLS_CC); + intern = dom_objects_set_class(class_type, 1 TSRMLS_CC); retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t)dom_objects_free_storage, dom_objects_clone TSRMLS_CC); intern->handle = retval.handle; - retval.handlers = &dom_object_handlers; + retval.handlers = dom_get_obj_handlers(TSRMLS_C); return retval; } @@ -910,11 +1003,11 @@ zend_object_value dom_xpath_objects_new(zend_class_entry *class_type TSRMLS_DC) zend_object_value retval; dom_object *intern; - intern = dom_objects_set_class(class_type TSRMLS_CC); + intern = dom_objects_set_class(class_type, 1 TSRMLS_CC); retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t)dom_xpath_objects_free_storage, dom_objects_clone TSRMLS_CC); intern->handle = retval.handle; - retval.handlers = &dom_object_handlers; + retval.handlers = dom_get_obj_handlers(TSRMLS_C); return retval; } @@ -966,7 +1059,7 @@ zend_object_value dom_nnodemap_objects_new(zend_class_entry *class_type TSRMLS_D dom_object *intern; dom_nnodemap_object *objmap; - intern = dom_objects_set_class(class_type TSRMLS_CC); + intern = dom_objects_set_class(class_type, 1 TSRMLS_CC); intern->ptr = emalloc(sizeof(dom_nnodemap_object)); objmap = (dom_nnodemap_object *)intern->ptr; objmap->baseobj = NULL; @@ -978,7 +1071,7 @@ zend_object_value dom_nnodemap_objects_new(zend_class_entry *class_type TSRMLS_D retval.handle = zend_objects_store_put(intern, dom_nnodemap_object_dtor, (zend_objects_free_object_storage_t)dom_nnodemap_objects_free_storage, dom_objects_clone TSRMLS_CC); intern->handle = retval.handle; - retval.handlers = &dom_object_handlers; + retval.handlers = dom_get_obj_handlers(TSRMLS_C); return retval; } @@ -1015,7 +1108,7 @@ zval *php_dom_create_object(xmlNodePtr obj, int *found, zval *wrapper_in, zval * return_value->type = IS_OBJECT; return_value->is_ref = 1; return_value->value.obj.handle = intern->handle; - return_value->value.obj.handlers = &dom_object_handlers; + return_value->value.obj.handlers = dom_get_obj_handlers(TSRMLS_C); zval_copy_ctor(return_value); *found = 1; return return_value; diff --git a/ext/dom/php_dom.h b/ext/dom/php_dom.h index b30a144fd202..a8ee2b95aaaa 100644 --- a/ext/dom/php_dom.h +++ b/ext/dom/php_dom.h @@ -104,7 +104,7 @@ int dom_has_feature(char *feature, char *version); int dom_node_is_read_only(xmlNodePtr node); int dom_node_children_valid(xmlNodePtr node); void php_dom_create_interator(zval *return_value, int ce_type TSRMLS_DC); -void dom_namednode_iter(dom_object *basenode, int ntype, dom_object *intern, xmlHashTablePtr ht, xmlChar *local, xmlChar *ns); +void dom_namednode_iter(dom_object *basenode, int ntype, dom_object *intern, xmlHashTablePtr ht, xmlChar *local, xmlChar *ns TSRMLS_DC); xmlNodePtr create_notation(const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID); xmlNode *php_dom_libxml_hash_iter(xmlHashTable *ht, int index); xmlNode *php_dom_libxml_notation_iter(xmlHashTable *ht, int index); diff --git a/ext/dom/processinginstruction.c b/ext/dom/processinginstruction.c index 23a3fe2900d8..5228af28a44e 100644 --- a/ext/dom/processinginstruction.c +++ b/ext/dom/processinginstruction.c @@ -82,7 +82,7 @@ PHP_METHOD(domprocessinginstruction, __construct) } /* }}} end DOMProcessingInstruction::__construct */ -/* {{{ proto target string +/* {{{ target string readonly=yes URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-1478689192 Since: @@ -108,7 +108,7 @@ int dom_processinginstruction_target_read(dom_object *obj, zval **retval TSRMLS_ -/* {{{ proto data string +/* {{{ data string readonly=no URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-837822393 Since: diff --git a/ext/dom/tests/bug28721.phpt b/ext/dom/tests/bug28721.phpt index a9aef3863f42..e8e7d867d899 100644 --- a/ext/dom/tests/bug28721.phpt +++ b/ext/dom/tests/bug28721.phpt @@ -1,7 +1,7 @@ --TEST-- Bug # 28721: (appendChild() and insertBefore() unset DOMText) --SKIPIF-- - + --FILE-- +--FILE-- +p_array[] = 'bonus'; + $this->p_array[] = 'vir'; + $this->p_array[] = 'semper'; + $this->p_array[] = 'tiro'; + + $this->p_variable = 'Cessante causa cessat effectus'; + } +} + +$z=new z(); +var_dump($z->p_array); +var_dump($z->p_variable); +?> +--EXPECTF-- +array(4) { + [0]=> + string(5) "bonus" + [1]=> + string(3) "vir" + [2]=> + string(6) "semper" + [3]=> + string(4) "tiro" +} +string(30) "Cessante causa cessat effectus" diff --git a/ext/dom/tests/bug32615.phpt b/ext/dom/tests/bug32615.phpt new file mode 100644 index 000000000000..e48973429a77 --- /dev/null +++ b/ext/dom/tests/bug32615.phpt @@ -0,0 +1,84 @@ +--TEST-- +Bug # 32615: (Replacing and inserting Fragments) +--SKIPIF-- + +--FILE-- +createDocumentFragment(); +$frag->appendChild(new DOMElement('root')); +$dom->appendChild($frag); +$root = $dom->documentElement; + +$frag->appendChild(new DOMElement('first')); +$root->appendChild($frag); + +$frag->appendChild(new DOMElement('second')); +$root->appendChild($frag); + +$node = $dom->createElement('newfirst'); +$frag->appendChild($node); +$root->replaceChild($frag, $root->firstChild); + +unset($frag); +$frag = $dom->createDocumentFragment(); + +$frag->appendChild(new DOMElement('newsecond')); +$root->replaceChild($frag, $root->lastChild); + +$node = $frag->appendChild(new DOMElement('fourth')); +$root->insertBefore($frag, NULL); + +$frag->appendChild(new DOMElement('third')); +$node = $root->insertBefore($frag, $node); + +$frag->appendChild(new DOMElement('start')); +$root->insertBefore($frag, $root->firstChild); + +$frag->appendChild(new DOMElement('newthird')); +$root->replaceChild($frag, $node); + +$frag->appendChild(new DOMElement('newfourth')); +$root->replaceChild($frag, $root->lastChild); + +$frag->appendChild(new DOMElement('first')); +$root->replaceChild($frag, $root->firstChild->nextSibling); + +$root->removeChild($root->firstChild); + +echo $dom->saveXML()."\n"; + +while ($root->hasChildNodes()) { + $root->removeChild($root->firstChild); +} + +$frag->appendChild(new DOMElement('first')); +$root->insertBefore($frag, $root->firstChild); + +$node = $frag->appendChild(new DOMElement('fourth')); +$root->appendChild($frag); + +$frag->appendChild(new DOMElement('second')); +$frag->appendChild(new DOMElement('third')); +$root->insertBefore($frag, $node); + +echo $dom->saveXML()."\n"; + +$frag = $dom->createDocumentFragment(); +$root = $dom->documentElement; +$root->replaceChild($frag, $root->firstChild); + +echo $dom->saveXML(); + +?> +--EXPECT-- + + + + + + + + + + diff --git a/ext/dom/tests/dom002.phpt b/ext/dom/tests/dom002.phpt index 2bc0717d645e..3343a1774ef9 100644 --- a/ext/dom/tests/dom002.phpt +++ b/ext/dom/tests/dom002.phpt @@ -1,7 +1,7 @@ --TEST-- Test 2: getElementsByTagName() / getElementsByTagNameNS() --SKIPIF-- - + --FILE-- string(0) "" ["file:protected"]=> - string(%d) "%s/ext/dom/tests/dom003.php" + string(%d) "%sdom003.php" ["line:protected"]=> int(8) ["trace:private"]=> - array(0) { + array(1) { + [0]=> + array(6) { + ["file"]=> + string(%d) "%sdom003.php" + ["line"]=> + int(8) + ["function"]=> + string(11) "appendChild" + ["class"]=> + string(7) "DOMNode" + ["type"]=> + string(2) "->" + ["args"]=> + array(1) { + [0]=> + object(DOMElement)#%d (0) { + } + } + } } ["code"]=> int(3) @@ -40,5 +59,6 @@ object(DOMException)#%d (6) { Fatal error: Uncaught exception 'DOMException' with message 'Hierarchy Request Error' in %sdom003.php:%d Stack trace: -#0 {main} +#0 %sdom003.php(%d): DOMNode->appendChild(Object(DOMElement)) +#1 {main} thrown in %sdom003.php on line %d diff --git a/ext/dom/tests/dom004.phpt b/ext/dom/tests/dom004.phpt index 7f36eb36925b..82b7915f6f63 100644 --- a/ext/dom/tests/dom004.phpt +++ b/ext/dom/tests/dom004.phpt @@ -3,7 +3,7 @@ Test 4: Streams Test --SKIPIF-- --FILE-- Hello world

This is a not well-formed
-html files with undeclared entities  +html files with undeclared entities 

--- save as HTML diff --git a/ext/dom/tests/dom_xinclude.phpt b/ext/dom/tests/dom_xinclude.phpt index 859dd545832b..92df048bc550 100644 --- a/ext/dom/tests/dom_xinclude.phpt +++ b/ext/dom/tests/dom_xinclude.phpt @@ -3,7 +3,7 @@ Test: Xinclude and Streams --SKIPIF-- --FILE-- diff --git a/ext/enchant/enchant.c b/ext/enchant/enchant.c deleted file mode 100755 index b92fa9d468bf..000000000000 --- a/ext/enchant/enchant.c +++ /dev/null @@ -1,731 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available at through the world-wide-web at | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Pierre-Alain Joye | - | Ilia Alshanetsky | - +----------------------------------------------------------------------+ - - $Id$ -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include "enchant.h" -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "php_enchant.h" - - -typedef EnchantBroker * EnchantBrokerPtr; -typedef struct _broker_struct enchant_broker; -typedef struct _dict_struct enchant_dict; - -typedef enchant_broker * enchant_brokerPtr; -typedef enchant_dict * enchant_dictPtr; - -typedef struct _broker_struct { - EnchantBroker *pbroker; - enchant_dict **dict; - unsigned int dictcnt; - zval *rsrc_id; -} _enchant_broker; - -typedef struct _dict_struct { - unsigned int id; - EnchantDict *pdict; - enchant_broker *pbroker; - zval *rsrc_id; - enchant_dict *next; - enchant_dict *prev; -} _enchant_dict; - - -/* True global resources - no need for thread safety here */ -static int le_enchant_broker; -static int le_enchant_dict; - -/* If you declare any globals in php_enchant.h uncomment this:*/ -/*ZEND_DECLARE_MODULE_GLOBALS(enchant)*/ - -/* {{{ enchant_functions[] - * - * Every user visible function must have an entry in enchant_functions[]. - */ -function_entry enchant_functions[] = { - PHP_FE(enchant_broker_init, NULL) - PHP_FE(enchant_broker_free, NULL) - PHP_FE(enchant_broker_get_error, NULL) - PHP_FE(enchant_broker_request_dict, NULL) - PHP_FE(enchant_broker_request_pwl_dict, NULL) - PHP_FE(enchant_broker_free_dict, NULL) - PHP_FE(enchant_broker_dict_exists, NULL) - PHP_FE(enchant_broker_set_ordering, NULL) - PHP_FE(enchant_broker_describe, NULL) - PHP_FE(enchant_dict_check, NULL) - PHP_FE(enchant_dict_suggest, NULL) - PHP_FE(enchant_dict_add_to_personal, NULL) - PHP_FE(enchant_dict_add_to_session, NULL) - PHP_FE(enchant_dict_is_in_session, NULL) - PHP_FE(enchant_dict_store_replacement, NULL) - PHP_FE(enchant_dict_get_error, NULL) - PHP_FE(enchant_dict_describe, NULL) - PHP_FE(enchant_dict_quick_check, third_arg_force_ref) - - {NULL, NULL, NULL} /* Must be the last line in enchant_functions[] */ -}; -/* }}} */ - -/* {{{ enchant_module_entry - */ -zend_module_entry enchant_module_entry = { -#if ZEND_MODULE_API_NO >= 20010901 - STANDARD_MODULE_HEADER, -#endif - "enchant", - enchant_functions, - PHP_MINIT(enchant), - PHP_MSHUTDOWN(enchant), - NULL, /* Replace with NULL if there's nothing to do at request start */ - NULL, /* Replace with NULL if there's nothing to do at request end */ - PHP_MINFO(enchant), -#if ZEND_MODULE_API_NO >= 20010901 - "0.1", /* Replace with version number for your extension */ -#endif - STANDARD_MODULE_PROPERTIES -}; -/* }}} */ - -#ifdef COMPILE_DL_ENCHANT -ZEND_GET_MODULE(enchant) -#endif - -static void -enumerate_providers_fn (const char * const name, - const char * const desc, - const char * const file, - void * ud) -{ - zval *zdesc = (zval *) ud; - zval *tmp_array; - - MAKE_STD_ZVAL(tmp_array); - array_init(tmp_array); - - add_assoc_string(tmp_array, "name", (char *)name, 1); - add_assoc_string(tmp_array, "desc", (char *)desc, 1); - add_assoc_string(tmp_array, "file", (char *)file, 1); - - if (Z_TYPE_P(zdesc)!=IS_ARRAY) { - array_init(zdesc); - } - - add_next_index_zval(zdesc, tmp_array); -} - -static void -describe_dict_fn (const char * const lang, - const char * const name, - const char * const desc, - const char * const file, - void * ud) -{ - zval *zdesc = (zval *) ud; - array_init(zdesc); - add_assoc_string(zdesc, "lang", (char *)lang, 1); - add_assoc_string(zdesc, "name", (char *)name, 1); - add_assoc_string(zdesc, "desc", (char *)desc, 1); - add_assoc_string(zdesc, "file", (char *)file, 1); -} - -static void php_enchant_broker_free(zend_rsrc_list_entry *rsrc TSRMLS_DC) -{ - if (rsrc->ptr) { - enchant_broker *broker = (enchant_broker *)rsrc->ptr; - if (broker) { - if (broker->pbroker) { - if (broker->dictcnt && broker->dict) { - if (broker->dict) { - int total, tofree; - tofree = total = broker->dictcnt-1; - do { - zend_list_delete(Z_RESVAL_P(broker->dict[total]->rsrc_id)); - efree(broker->dict[total]); - total--; - } while (total>=0); - } - efree(broker->dict); - broker->dict = NULL; - } - enchant_broker_free(broker->pbroker); - } - efree(broker); - } - } -} - -static void php_enchant_dict_free(zend_rsrc_list_entry *rsrc TSRMLS_DC) -{ - if (rsrc->ptr) { - enchant_dict *pdict = (enchant_dict *)rsrc->ptr; - if (pdict) { - if (pdict->pdict && pdict->pbroker) { - enchant_broker_free_dict(pdict->pbroker->pbroker, pdict->pdict); - } - if (pdict->id) { - pdict->pbroker->dict[pdict->id-1]->next = NULL; - } - } - } -} - -/* {{{ PHP_MINIT_FUNCTION - */ -PHP_MINIT_FUNCTION(enchant) -{ - le_enchant_broker = zend_register_list_destructors_ex(php_enchant_broker_free, NULL, "enchant broker", module_number); - le_enchant_dict = zend_register_list_destructors_ex(php_enchant_dict_free, NULL, "enchant dict", module_number); - - return SUCCESS; -} -/* }}} */ - -/* {{{ PHP_MSHUTDOWN_FUNCTION - */ -PHP_MSHUTDOWN_FUNCTION(enchant) -{ - return SUCCESS; -} -/* }}} */ - -/* {{{ PHP_MINFO_FUNCTION - */ -static void __enumerate_providers_fn (const char * const name, - const char * const desc, - const char * const file, - void * ud) -{ - php_info_print_table_row(3, name, desc, file); -} -/* }}} */ - -/* {{{ PHP_MINFO_FUNCTION - */ -PHP_MINFO_FUNCTION(enchant) -{ - EnchantBroker *pbroker; - - pbroker = enchant_broker_init(); - php_info_print_table_start(); - php_info_print_table_header(2, "enchant support", "enabled"); - php_info_print_table_row(2, "Version", "@version@"); - php_info_print_table_row(2, "Revision", "$Revision$"); - php_info_print_table_end(); - - php_info_print_table_start(); - enchant_broker_describe(pbroker, __enumerate_providers_fn, NULL); - php_info_print_table_end(); - enchant_broker_free(pbroker); -} -/* }}} */ - -#define PHP_ENCHANT_GET_BROKER \ - ZEND_FETCH_RESOURCE(pbroker, enchant_broker *, &broker, -1, "enchant_broker", le_enchant_broker); \ - if (!pbroker || !pbroker->pbroker) { \ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", "Resource broker invalid"); \ - RETURN_FALSE; \ - } - -#define PHP_ENCHANT_GET_DICT \ - ZEND_FETCH_RESOURCE(pdict, enchant_dict *, &dict, -1, "enchant dict", le_enchant_dict); \ - if (!pdict || !pdict->pdict) { \ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", "Invalid dictionary resource."); \ - RETURN_FALSE; \ - } - -/* {{{ proto resource enchant_broker_init() - create a new broker object capable of requesting */ -PHP_FUNCTION(enchant_broker_init) -{ - enchant_broker *broker; - EnchantBroker *pbroker; - - if (ZEND_NUM_ARGS()) { - ZEND_WRONG_PARAM_COUNT(); - } - - pbroker = enchant_broker_init(); - - if (pbroker) { - broker = (enchant_broker *) emalloc(sizeof(enchant_broker)); - broker->pbroker = pbroker; - broker->dict = NULL; - broker->dictcnt = 0; - ZEND_REGISTER_RESOURCE(return_value, broker, le_enchant_broker); - broker->rsrc_id = return_value; - } else { - RETURN_FALSE; - } -} -/* }}} */ - -/* {{{ proto boolean enchant_free(resource broker) - Destroys the broker object and its dictionnaries */ -PHP_FUNCTION(enchant_broker_free) -{ - zval *broker; - enchant_broker *pbroker; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &broker) == FAILURE) { - RETURN_FALSE; - } - PHP_ENCHANT_GET_BROKER; - - zend_list_delete(Z_RESVAL_P(broker)); - RETURN_TRUE; -} -/* }}} */ - -/* {{{ proto string enchant_broker_get_error(resource broker) - Returns the last error of the broker */ -PHP_FUNCTION(enchant_broker_get_error) -{ - zval *broker; - enchant_broker *pbroker; - char *msg; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &broker) == FAILURE) { - RETURN_FALSE; - } - - PHP_ENCHANT_GET_BROKER; - - msg = enchant_broker_get_error(pbroker->pbroker); - if (msg) { - RETURN_STRING((char *)msg, 1); - } - RETURN_FALSE; -} -/* }}} */ - -/* {{{ proto resource enchant_broker_request_dict(resource broker, string tag) - create a new dictionary using tag, the non-empty language tag you wish to request - a dictionary for ("en_US", "de_DE", ...) */ -PHP_FUNCTION(enchant_broker_request_dict) -{ - zval *broker; - enchant_broker *pbroker; - enchant_dict *dict; - EnchantDict *d; - char *tag; - int taglen; - int pos; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &broker, &tag, &taglen) == FAILURE) { - RETURN_FALSE; - } - - PHP_ENCHANT_GET_BROKER; - - d = enchant_broker_request_dict(pbroker->pbroker, (const char *)tag); - if (d) { - if (pbroker->dictcnt) { - pbroker->dict = (enchant_dict **)erealloc(pbroker->dict, sizeof(enchant_dict *) * pbroker->dictcnt); - pos = pbroker->dictcnt++; - } else { - pbroker->dict = (enchant_dict **)emalloc(sizeof(enchant_dict *)); - pos = 0; - pbroker->dictcnt++; - } - - dict = pbroker->dict[pos] = (enchant_dict *)emalloc(sizeof(enchant_dict)); - dict->id = pos; - dict->pbroker = pbroker; - dict->pdict = d; - dict->rsrc_id = return_value; - dict->prev = pos ? pbroker->dict[pos-1] : NULL; - dict->next = NULL; - pbroker->dict[pos] = dict; - - if (pos) { - pbroker->dict[pos-1]->next = dict; - } - - ZEND_REGISTER_RESOURCE(return_value, dict, le_enchant_dict); - } else { - RETURN_FALSE; - } -} -/* }}} */ - -/* {{{ proto resource enchant_broker_request_pwl_dict(resource dict, string filename) - creates a dictionary using a PWL file. A PWL file is personal word file one word per line. - It must exist before the call.*/ -PHP_FUNCTION(enchant_broker_request_pwl_dict) -{ - zval *broker; - enchant_broker *pbroker; - enchant_dict *dict; - EnchantDict *d; - char *pwl; - int pwllen; - int pos; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &broker, &pwl, &pwllen) == FAILURE) { - RETURN_FALSE; - } - - if ((PG(safe_mode) && (!php_checkuid(pwl, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(pwl TSRMLS_CC)) { - RETURN_FALSE; - } - - PHP_ENCHANT_GET_BROKER; - - d = enchant_broker_request_pwl_dict(pbroker->pbroker, (const char *)pwl); - if (d) { - if (pbroker->dictcnt) { - pos = pbroker->dictcnt++; - pbroker->dict = (enchant_dict **)erealloc(pbroker->dict, sizeof(enchant_dict *) * pbroker->dictcnt); - } else { - pbroker->dict = (enchant_dict **)emalloc(sizeof(enchant_dict *)); - pos = 0; - pbroker->dictcnt++; - } - dict = pbroker->dict[pos] = (enchant_dict *)emalloc(sizeof(enchant_dict)); - dict->id = pos; - dict->pbroker = pbroker; - dict->pdict = d; - dict->rsrc_id = return_value; - dict->prev = pos?pbroker->dict[pos-1]:NULL; - dict->next = NULL; - pbroker->dict[pos] = dict; - if (pos) { - pbroker->dict[pos-1]->next = dict; - } - ZEND_REGISTER_RESOURCE(return_value, dict, le_enchant_dict); - } else { - RETURN_FALSE; - } -} -/* }}} */ - -/* {{{ proto resource enchant_broker_free_dict(resource dict) - Free the dictionary resource */ -PHP_FUNCTION(enchant_broker_free_dict) -{ - zval *dict; - enchant_dict *pdict; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &dict) == FAILURE) { - RETURN_FALSE; - } - - PHP_ENCHANT_GET_DICT; - - zend_list_delete(Z_RESVAL_P(dict)); - RETURN_TRUE; -} -/* }}} */ - -/* {{{ proto bool enchant_broker_dict_exists(resource broker, string tag) - Wether a dictionary exists or not. Using non-empty tag */ -PHP_FUNCTION(enchant_broker_dict_exists) -{ - zval *broker; - char *tag; - int taglen; - enchant_broker * pbroker; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &broker, &tag, &taglen) == FAILURE) { - RETURN_FALSE; - } - - PHP_ENCHANT_GET_BROKER; - - RETURN_BOOL(enchant_broker_dict_exists(pbroker->pbroker, tag)); -} -/* }}} */ - - -/* {{{ proto bool enchant_broker_set_ordering(resource broker, string tag, string ordering) - Declares a preference of dictionaries to use for the language - described/referred to by 'tag'. The ordering is a comma delimited - list of provider names. As a special exception, the "*" tag can - be used as a language tag to declare a default ordering for any - language that does not explictly declare an ordering. */ - -PHP_FUNCTION(enchant_broker_set_ordering) -{ - zval *broker; - char *pordering; - int porderinglen; - char *ptag; - int ptaglen; - enchant_broker * pbroker; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &broker, &ptag, &ptaglen, &pordering, &porderinglen) == FAILURE) { - RETURN_FALSE; - } - - PHP_ENCHANT_GET_BROKER; - - enchant_broker_set_ordering(pbroker->pbroker, ptag, pordering); - RETURN_TRUE; -} -/* }}} */ - -/* {{{ proto array enchant_broker_describe(resource broker) - Enumerates the Enchant providers and tells - you some rudimentary information about them. The same info is provided through phpinfo() */ -PHP_FUNCTION(enchant_broker_describe) -{ - EnchantBrokerDescribeFn describetozval = enumerate_providers_fn; - zval *broker; - enchant_broker * pbroker; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &broker) == FAILURE) { - RETURN_FALSE; - } - - PHP_ENCHANT_GET_BROKER; - - enchant_broker_describe(pbroker->pbroker, describetozval, (void *)return_value); -} -/* }}} */ - -/* {{{ proto bool enchant_dict_quick_check(resource dict, string word [, array &suggestions]) - If the word is correctly spelled return true, otherwise return false, if suggestions variable - is provided, fill it with spelling alternatives. */ -PHP_FUNCTION(enchant_dict_quick_check) -{ - zval *dict, *sugg = NULL; - char *word; - int wordlen; - enchant_dict *pdict; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|z/", &dict, &word, &wordlen, &sugg) == FAILURE) { - RETURN_FALSE; - } - - if (sugg) { - zval_dtor(sugg); - } - - PHP_ENCHANT_GET_DICT; - - if (enchant_dict_check(pdict->pdict, word, wordlen) > 0) { - if (!sugg && ZEND_NUM_ARGS() == 2) { - RETURN_FALSE; - } - - int n_sugg; - char **suggs; - - array_init(sugg); - - suggs = enchant_dict_suggest(pdict->pdict, word, wordlen, &n_sugg); - if (suggs && n_sugg) { - int i; - for (i = 0; i < n_sugg; i++) { - add_next_index_string(sugg, suggs[i], 1); - } - enchant_dict_free_suggestions(pdict->pdict, suggs); - } - - - RETURN_FALSE; - } - RETURN_TRUE; -} -/* }}} */ - -/* {{{ proto bool enchant_dict_check(resource dict, string word) - If the word is correctly spelled return true, otherwise return false */ -PHP_FUNCTION(enchant_dict_check) -{ - zval *dict; - char *word; - int wordlen; - enchant_dict *pdict; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &dict, &word, &wordlen) == FAILURE) { - RETURN_FALSE; - } - - PHP_ENCHANT_GET_DICT; - - RETURN_BOOL(!enchant_dict_check(pdict->pdict, word, wordlen)); -} -/* }}} */ - -/* {{{ proto array enchant_dict_suggest(resource dict, string word) - Will return a list of values if any of those pre-conditions are not met.*/ -PHP_FUNCTION(enchant_dict_suggest) -{ - zval *dict; - char *word; - int wordlen; - char **suggs; - enchant_dict *pdict; - int n_sugg; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &dict, &word, &wordlen) == FAILURE) { - RETURN_FALSE; - } - - PHP_ENCHANT_GET_DICT; - - suggs = enchant_dict_suggest(pdict->pdict, word, wordlen, &n_sugg); - if (suggs && n_sugg) { - int i; - - array_init(return_value); - for (i = 0; i < n_sugg; i++) { - add_next_index_string(return_value, suggs[i], 1); - } - - enchant_dict_free_suggestions(pdict->pdict, suggs); - } -} -/* }}} */ - -/* {{{ proto void enchant_dict_add_to_personal(resource dict, string word) - add 'word' to personal word list */ -PHP_FUNCTION(enchant_dict_add_to_personal) -{ - zval *dict; - char *word; - int wordlen; - enchant_dict *pdict; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &dict, &word, &wordlen) == FAILURE) { - RETURN_FALSE; - } - - PHP_ENCHANT_GET_DICT; - - enchant_dict_add_to_personal(pdict->pdict, word, wordlen); -} -/* }}} */ - -/* {{{ proto void enchant_dict_add_to_session(resource dict, string word) - add 'word' to this spell-checking session */ -PHP_FUNCTION(enchant_dict_add_to_session) -{ - zval *dict; - char *word; - int wordlen; - enchant_dict *pdict; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &dict, &word, &wordlen) == FAILURE) { - RETURN_FALSE; - } - - PHP_ENCHANT_GET_DICT; - - enchant_dict_add_to_session(pdict->pdict, word, wordlen); -} -/* }}} */ - -/* {{{ proto bool enchant_dict_is_in_session(resource dict, string word) - whether or not 'word' exists in this spelling-session */ -PHP_FUNCTION(enchant_dict_is_in_session) -{ - zval *dict; - char *word; - int wordlen; - enchant_dict *pdict; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &dict, &word, &wordlen) == FAILURE) { - RETURN_FALSE; - } - - PHP_ENCHANT_GET_DICT; - - RETURN_BOOL(enchant_dict_is_in_session(pdict->pdict, word, wordlen)); -} -/* }}} */ - -/* {{{ proto void enchant_dict_store_replacement(resource dict, string mis, string cor) - add a correction for 'mis' using 'cor'. - Notes that you replaced @mis with @cor, so it's possibly more likely - that future occurrences of @mis will be replaced with @cor. So it might - bump @cor up in the suggestion list.*/ -PHP_FUNCTION(enchant_dict_store_replacement) -{ - zval *dict; - char *mis, *cor; - int mislen, corlen; - - enchant_dict *pdict; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &dict, &mis, &mislen, &cor, &corlen) == FAILURE) { - RETURN_FALSE; - } - - PHP_ENCHANT_GET_DICT; - - enchant_dict_store_replacement(pdict->pdict, mis, mislen, cor, corlen); -} -/* }}} */ - -/* {{{ proto string enchant_dict_get_error(resource dict) - Returns the last error of the current spelling-session */ -PHP_FUNCTION(enchant_dict_get_error) -{ - zval *dict; - enchant_dict *pdict; - char *msg; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &dict) == FAILURE) { - RETURN_FALSE; - } - - PHP_ENCHANT_GET_DICT; - - msg = enchant_dict_get_error(pdict->pdict); - if (msg) { - RETURN_STRING((char *)msg, 1); - } - - RETURN_FALSE; -} -/* }}} */ - -/* {{{ proto array enchant_dict_describe(resource dict) - Describes an individual dictionary 'dict' */ -PHP_FUNCTION(enchant_dict_describe) -{ - zval *dict; - enchant_dict *pdict; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &dict) == FAILURE) { - RETURN_FALSE; - } - - PHP_ENCHANT_GET_DICT; - - enchant_dict_describe(pdict->pdict, describe_dict_fn, (void *)return_value); -} -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/enchant/package.xml b/ext/enchant/package.xml deleted file mode 100755 index 0c4e50207b2f..000000000000 --- a/ext/enchant/package.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - enchant - libenchant binder, support near all spelling tools - - - pajoye - Pierre-Alain Joye - paj@pearfr.org - lead - - - iliaa - Ilia Alshanetsky - ilia@php.net - developer - - - Enchant is a binder for libenchant. Libenchant provides a common -API for many spell libraries: -- aspell/pspell (intended to replace ispell) -- hspell (hebrew) -- ispell -- myspell (OpenOffice project, mozilla) -- uspell (primarily Yiddish, Hebrew, and Eastern European languages) -A plugin system allows to add custom spell support. -see www.abisource.com/enchant/ - PHP - - beta - 0.2.1 - 2004-03-11 - - Fix possible leak in suggestions result -- Move to beta status - - - - - - - - - - - - - - - - - - - - - - alpha - 0.2.0 - - Add Ilia Alshanetsky as maintainer -- Cleanup sources codes (ilia) -- Add enchant_dict_quick_check (ilia) - - - 0.1 - alpha - 2003-03-08 - Initial release - - - - diff --git a/ext/enchant/php_enchant.h b/ext/enchant/php_enchant.h deleted file mode 100644 index e0d98730cae5..000000000000 --- a/ext/enchant/php_enchant.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 4 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2003 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available at through the world-wide-web at | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Pierre-Alain Joye | - +----------------------------------------------------------------------+ - - $Id$ -*/ - -#ifndef PHP_ENCHANT_H -#define PHP_ENCHANT_H - -extern zend_module_entry enchant_module_entry; -#define phpext_enchant_ptr &enchant_module_entry - -#ifdef PHP_WIN32 -#define PHP_ENCHANT_API __declspec(dllexport) -#else -#define PHP_ENCHANT_API -#endif - -#ifdef ZTS -#include "TSRM.h" -#endif - -static void php_enchant_broker_free(zend_rsrc_list_entry *rsrc TSRMLS_DC); -static void php_enchant_dict_free(zend_rsrc_list_entry *rsrc TSRMLS_DC); - -PHP_MINIT_FUNCTION(enchant); -PHP_MSHUTDOWN_FUNCTION(enchant); -PHP_MINFO_FUNCTION(enchant); - -PHP_FUNCTION(enchant_broker_init); -PHP_FUNCTION(enchant_broker_free); -PHP_FUNCTION(enchant_broker_get_error); -PHP_FUNCTION(enchant_broker_request_dict); -PHP_FUNCTION(enchant_broker_request_pwl_dict); -PHP_FUNCTION(enchant_broker_free_dict); -PHP_FUNCTION(enchant_broker_dict_exists); -PHP_FUNCTION(enchant_broker_set_ordering); -PHP_FUNCTION(enchant_broker_describe); - -PHP_FUNCTION(enchant_dict_check); -PHP_FUNCTION(enchant_dict_suggest); -PHP_FUNCTION(enchant_dict_add_to_personal); -PHP_FUNCTION(enchant_dict_add_to_session); -PHP_FUNCTION(enchant_dict_is_in_session); -PHP_FUNCTION(enchant_dict_store_replacement); -PHP_FUNCTION(enchant_dict_get_error); -PHP_FUNCTION(enchant_dict_describe); -PHP_FUNCTION(enchant_dict_quick_check); - -#ifdef ZTS -#define ENCHANT_G(v) TSRMG(enchant_globals_id, zend_enchant_globals *, v) -#else -#define ENCHANT_G(v) (enchant_globals.v) -#endif - -#endif /* PHP_ENCHANT_H */ - - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * indent-tabs-mode: t - * End: - */ - diff --git a/ext/ereg/ereg.c b/ext/ereg/ereg.c index cf8e15cd95b2..6c4124576ca7 100644 --- a/ext/ereg/ereg.c +++ b/ext/ereg/ereg.c @@ -33,6 +33,8 @@ typedef struct { int cflags; } reg_cache; +static int reg_magic = 0; + /* {{{ _php_regcomp */ static int _php_regcomp(regex_t *preg, const char *pattern, int cflags) @@ -42,8 +44,39 @@ static int _php_regcomp(regex_t *preg, const char *pattern, int cflags) reg_cache *rc = NULL; TSRMLS_FETCH(); - if(zend_hash_find(®(ht_rc), (char *) pattern, patlen+1, (void **) &rc) == FAILURE || - rc->cflags != cflags) { + if(zend_hash_find(®(ht_rc), (char *) pattern, patlen+1, (void **) &rc) == SUCCESS + && rc->cflags == cflags) { +#ifdef HAVE_REGEX_T_RE_MAGIC + /* + * We use a saved magic number to see whether cache is corrupted, and if it + * is, we flush it and compile the pattern from scratch. + */ + if (rc->preg.re_magic != reg_magic) { + zend_hash_clean(®(ht_rc)); + } else { + memcpy(preg, &rc->preg, sizeof(*preg)); + return r; + } + } + + r = regcomp(preg, pattern, cflags); + if(!r) { + reg_cache rcp; + + rcp.cflags = cflags; + memcpy(&rcp.preg, preg, sizeof(*preg)); + /* + * Since we don't have access to the actual MAGIC1 definition in the private + * header file, we save the magic value immediately after compilation. Hopefully, + * it's good. + */ + if (!reg_magic) reg_magic = preg->re_magic; + zend_hash_update(®(ht_rc), (char *) pattern, patlen+1, + (void *) &rcp, sizeof(rcp), NULL); + } +#else + memcpy(preg, &rc->preg, sizeof(*preg)); + } else { r = regcomp(preg, pattern, cflags); if(!r) { reg_cache rcp; @@ -51,12 +84,10 @@ static int _php_regcomp(regex_t *preg, const char *pattern, int cflags) rcp.cflags = cflags; memcpy(&rcp.preg, preg, sizeof(*preg)); zend_hash_update(®(ht_rc), (char *) pattern, patlen+1, - (void *) &rcp, sizeof(rcp), NULL); + (void *) &rcp, sizeof(rcp), NULL); } - } else { - memcpy(preg, &rc->preg, sizeof(*preg)); } - +#endif return r; } /* }}} */ diff --git a/ext/ereg/regex/engine.c b/ext/ereg/regex/engine.c index c4bdc8079f07..0682267f6180 100644 --- a/ext/ereg/regex/engine.c +++ b/ext/ereg/regex/engine.c @@ -270,7 +270,7 @@ sopno stopst; /* figure out what it matched */ switch (OP(m->g->strip[ss])) { case OEND: - assert(nope); + assert(PHP_REGEX_NOPE); break; case OCHAR: sp++; @@ -286,7 +286,7 @@ sopno stopst; break; case OBACK_: case O_BACK: - assert(nope); + assert(PHP_REGEX_NOPE); break; /* cases where length of match is hard to find */ case OQUEST_: @@ -389,7 +389,7 @@ sopno stopst; case OOR1: case OOR2: case O_CH: - assert(nope); + assert(PHP_REGEX_NOPE); break; case OLPAREN: i = OPND(m->g->strip[ss]); @@ -402,7 +402,7 @@ sopno stopst; m->pmatch[i].rm_eo = sp - m->offp; break; default: /* uh oh */ - assert(nope); + assert(PHP_REGEX_NOPE); break; } } @@ -606,12 +606,12 @@ sopno lev; /* PLUS nesting level */ return(NULL); break; default: /* uh oh */ - assert(nope); + assert(PHP_REGEX_NOPE); break; } /* "can't happen" */ - assert(nope); + assert(PHP_REGEX_NOPE); /* NOTREACHED */ return((unsigned char *)NULL); /* dummy */ } @@ -914,7 +914,7 @@ register states aft; /* states already known reachable after */ FWD(aft, aft, 1); break; default: /* ooooops... */ - assert(nope); + assert(PHP_REGEX_NOPE); break; } } diff --git a/ext/ereg/regex/regexec.c b/ext/ereg/regex/regexec.c index c8cb8fdf5644..bbfe094c96ca 100644 --- a/ext/ereg/regex/regexec.c +++ b/ext/ereg/regex/regexec.c @@ -16,7 +16,7 @@ #include "utils.h" #include "regex2.h" -static int nope = 0; /* for use in asserts; shuts lint up */ +#define PHP_REGEX_NOPE 0; /* for use in asserts; shuts lint up */ /* macros for manipulating states, small version */ #define states unsigned diff --git a/ext/exif/exif.c b/ext/exif/exif.c index 80e5ec2fda7c..65e1ffff2299 100644 --- a/ext/exif/exif.c +++ b/ext/exif/exif.c @@ -66,7 +66,7 @@ #include "ext/standard/php_image.h" #include "ext/standard/info.h" -#if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING) +#if defined(PHP_WIN32) || (HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)) #define EXIF_USE_MBSTRING 1 #else #define EXIF_USE_MBSTRING 0 @@ -76,6 +76,9 @@ #include "ext/mbstring/mbstring.h" #endif +/* needed for ssize_t definition */ +#include + typedef unsigned char uchar; #ifndef safe_emalloc @@ -93,12 +96,13 @@ typedef unsigned char uchar; #define EFREE_IF(ptr) if (ptr) efree(ptr) +#define MAX_IFD_NESTING_LEVEL 100 + static ZEND_BEGIN_ARG_INFO(exif_thumbnail_force_ref, 1) ZEND_ARG_PASS_INFO(0) ZEND_END_ARG_INFO(); - /* {{{ exif_functions[] */ function_entry exif_functions[] = { @@ -1442,6 +1446,7 @@ typedef struct { /* for parsing */ int read_thumbnail; int read_all; + int ifd_nesting_level; /* internal */ file_section_list file; } image_info_type; @@ -2711,6 +2716,13 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha size_t byte_count, offset_val, fpos, fgot; xp_field_type *tmp_xp; + /* Protect against corrupt headers */ + if (ImageInfo->ifd_nesting_level > MAX_IFD_NESTING_LEVEL) { + exif_error_docref("exif_read_data#error_ifd" TSRMLS_CC, ImageInfo, E_WARNING, "corrupt EXIF header: maximum directory nesting level reached"); + return FALSE; + } + ImageInfo->ifd_nesting_level++; + tag = php_ifd_get16u(dir_entry, ImageInfo->motorola_intel); format = php_ifd_get16u(dir_entry+2, ImageInfo->motorola_intel); components = php_ifd_get32u(dir_entry+4, ImageInfo->motorola_intel); @@ -2724,6 +2736,11 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha byte_count = components * php_tiff_bytes_per_format[format]; + if ((ssize_t)byte_count < 0) { + exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "Process tag(x%04X=%s): Illegal byte_count(%ld)", tag, exif_get_tagname(tag, tagname, -12, tag_table TSRMLS_CC), byte_count); + return FALSE; + } + if (byte_count > 4) { offset_val = php_ifd_get32u(dir_entry+8, ImageInfo->motorola_intel); /* If its bigger than 4 bytes, the dir entry contains an offset. */ @@ -2734,7 +2751,7 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha // JPEG does not use absolute pointers instead its pointers are relative to the start // of the TIFF header in APP1 section. */ - if (offset_val+byte_count>ImageInfo->FileSize || (ImageInfo->FileType!=IMAGE_FILETYPE_TIFF_II && ImageInfo->FileType!=IMAGE_FILETYPE_TIFF_MM)) { + if (offset_val+byte_count>ImageInfo->FileSize || (ImageInfo->FileType!=IMAGE_FILETYPE_TIFF_II && ImageInfo->FileType!=IMAGE_FILETYPE_TIFF_MM && ImageInfo->FileType!=IMAGE_FILETYPE_JPEG)) { if (value_ptr < dir_entry) { /* we can read this if offset_val > 0 */ /* some files have their values in other parts of the file */ @@ -3727,7 +3744,11 @@ static int exif_read_file(image_info_type *ImageInfo, char *FileName, int read_t if (php_stream_is(ImageInfo->infile, PHP_STREAM_IS_STDIO)) { if (VCWD_STAT(FileName, &st) >= 0) { /* Store file date/time. */ +#ifdef NETWARE + ImageInfo->FileDateTime = st.st_mtime.tv_sec; +#else ImageInfo->FileDateTime = st.st_mtime; +#endif ImageInfo->FileSize = st.st_size; /*exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "Opened stream is file: %d", ImageInfo->FileSize);*/ } @@ -3739,6 +3760,8 @@ static int exif_read_file(image_info_type *ImageInfo, char *FileName, int read_t } } + ImageInfo->ifd_nesting_level = 0; + /* Scan the JPEG headers. */ ret = exif_scan_FILE_header(ImageInfo TSRMLS_CC); @@ -3776,7 +3799,7 @@ PHP_FUNCTION(exif_read_data) } } for (i=0; i= 20010901 "0.1", /* Replace with version number for your extension */ @@ -128,35 +128,6 @@ PHP_MINIT_FUNCTION(fam) } /* }}} */ -/* {{{ PHP_MSHUTDOWN_FUNCTION - */ -PHP_MSHUTDOWN_FUNCTION(fam) -{ - /* uncomment this line if you have INI entries - UNREGISTER_INI_ENTRIES(); - */ - return SUCCESS; -} -/* }}} */ - -/* Remove if there's nothing to do at request start */ -/* {{{ PHP_RINIT_FUNCTION - */ -PHP_RINIT_FUNCTION(fam) -{ - return SUCCESS; -} -/* }}} */ - -/* Remove if there's nothing to do at request end */ -/* {{{ PHP_RSHUTDOWN_FUNCTION - */ -PHP_RSHUTDOWN_FUNCTION(fam) -{ - return SUCCESS; -} -/* }}} */ - /* {{{ PHP_MINFO_FUNCTION */ PHP_MINFO_FUNCTION(fam) diff --git a/ext/fam/php_fam.h b/ext/fam/php_fam.h index d234ea92a7a5..28c4e97851eb 100644 --- a/ext/fam/php_fam.h +++ b/ext/fam/php_fam.h @@ -35,9 +35,6 @@ extern zend_module_entry fam_module_entry; #endif PHP_MINIT_FUNCTION(fam); -PHP_MSHUTDOWN_FUNCTION(fam); -PHP_RINIT_FUNCTION(fam); -PHP_RSHUTDOWN_FUNCTION(fam); PHP_MINFO_FUNCTION(fam); PHP_FUNCTION(fam_open); diff --git a/ext/fbsql/php_fbsql.c b/ext/fbsql/php_fbsql.c index 18c00ddc1e9e..6b24109aadb3 100644 --- a/ext/fbsql/php_fbsql.c +++ b/ext/fbsql/php_fbsql.c @@ -477,11 +477,11 @@ PHP_MINFO_FUNCTION(fbsql) if (FB_SQL_G(allowPersistent)) { - sprintf(buf, "%ld", FB_SQL_G(persistentCount)); + snprintf(buf, sizeof(buf), "%ld", FB_SQL_G(persistentCount)); php_info_print_table_row(2, "Active Persistent Links", buf); } - sprintf(buf, "%ld", FB_SQL_G(linkCount)); + snprintf(buf, sizeof(buf), "%ld", FB_SQL_G(linkCount)); php_info_print_table_row(2, "Active Links", buf); /* @@ -525,7 +525,9 @@ static void php_fbsql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) if (userName == NULL) userName = FB_SQL_G(userName); if (userPassword == NULL) userPassword = FB_SQL_G(userPassword); - sprintf(name, "fbsql_%s_%s_%s", hostName, userName, userPassword); + if (snprintf(name, sizeof(name), "fbsql_%s_%s_%s", hostName, userName, userPassword) < 0) { + RETURN_FALSE; + } if (!FB_SQL_G(allowPersistent)) { persistent=0; @@ -836,9 +838,21 @@ PHP_FUNCTION(fbsql_set_transaction) WRONG_PARAM_COUNT; break; } + + if (Z_LVAL_PP(Locking) < 0 || Z_LVAL_PP(Locking) > 2) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid locking type."); + RETURN_FALSE; + } + if (Z_LVAL_PP(Isolation) < 0 || Z_LVAL_PP(Isolation) > 4) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid isolation type."); + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE2(phpLink, PHPFBLink *, fbsql_link_index, -1, "FrontBase-Link", le_link, le_plink); - sprintf(strSQL, "SET TRANSACTION LOCKING %s, ISOLATION %s;", strLocking[Z_LVAL_PP(Locking)], strIsolation[Z_LVAL_PP(Isolation)]); + if (snprintf(strSQL, sizeof(strSQL) , "SET TRANSACTION LOCKING %s, ISOLATION %s;", strLocking[Z_LVAL_PP(Locking)], strIsolation[Z_LVAL_PP(Isolation)]) < 0) { + RETURN_FALSE; + } md = fbcdcExecuteDirectSQL(phpLink->connection, strSQL); fbcmdRelease(md); @@ -1472,7 +1486,9 @@ PHP_FUNCTION(fbsql_change_user) convert_to_string_ex(password); userPassword = Z_STRVAL_PP(password); - sprintf(buffer, "SET AUTHORIZATION %s;", userName); + if (snprintf(buffer, sizeof(buffer), "SET AUTHORIZATION %s;", userName) < 0) { + RETURN_FALSE; + } phpfbQuery(INTERNAL_FUNCTION_PARAM_PASSTHRU, buffer, phpLink); if (Z_LVAL_P(return_value)) @@ -1851,6 +1867,24 @@ int mdOk(PHPFBLink* link, FBCMetaData* md, char* sql) fbcemdRelease(emd); result = 0; } + else if (fbcmdWarningsFound(md)) + { + FBCErrorMetaData* emd = fbcdcErrorMetaData(c, md); + char* emg = fbcemdAllErrorMessages(emd); + if (FB_SQL_G(generateWarnings)) + { + if (emg) + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Warning in statement: '%s' %s", sql, emg); + else + php_error_docref(NULL TSRMLS_CC, E_WARNING, "No message"); + } + link->errorText = strdup(emg); + link->errorNo = fbcemdErrorCodeAtIndex(emd, 0); + free(emg); + fbcemdRelease(emd); + result = 1; + } + return result; return result; } /* }}} */ @@ -1879,9 +1913,12 @@ static void phpfbQuery(INTERNAL_FUNCTION_PARAMETERS, char* sql, PHPFBLink* link) md = meta; tp = fbcmdStatementType(md); - - if ((tp[0] == 'C') || (tp[0] == 'R')) - { + if (tp == NULL) { + fbcmdRelease(meta); + ZVAL_BOOL(return_value, 1) + } + else if ((tp[0] == 'C') || (tp[0] == 'R')) + { if (sR == 1 && md) fbcmdRelease(md); ZVAL_BOOL(return_value, 1) } @@ -2139,7 +2176,9 @@ PHP_FUNCTION(fbsql_list_fields) RETURN_FALSE; } - sprintf(sql, "SELECT * FROM %s WHERE 1=0;", tableName); + if (snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE 1=0;", tableName) < 0) { + RETURN_FALSE; + } phpfbQuery(INTERNAL_FUNCTION_PARAM_PASSTHRU, sql, phpLink); } @@ -2323,7 +2362,7 @@ void phpfbColumnAsString(PHPFBResult* result, int column, void* data , int* leng { int v = *((int*)data); char b[128]; - sprintf(b, "%d", v); + snprintf(b, sizeof(b), "%d", v); phpfbestrdup(b, length, value); } break; @@ -2332,7 +2371,7 @@ void phpfbColumnAsString(PHPFBResult* result, int column, void* data , int* leng { short int v = *((FBTinyInteger*)data); char b[128]; - sprintf(b, "%d", v); + snprintf(b, sizeof(b), "%d", v); phpfbestrdup(b, length, value); } break; @@ -2343,9 +2382,9 @@ void phpfbColumnAsString(PHPFBResult* result, int column, void* data , int* leng FBLongInteger v = *((FBLongInteger*)data); char b[128]; #ifdef PHP_WIN32 - sprintf(b, "%I64i", v); + snprintf(b, sizeof(b), "%I64i", v); #else - sprintf(b, "%ll", v); + snprintf(b, sizeof(b), "%ll", v); #endif phpfbestrdup(b, length, value); } @@ -2355,7 +2394,7 @@ void phpfbColumnAsString(PHPFBResult* result, int column, void* data , int* leng { short v = *((short*)data); char b[128]; - sprintf(b, "%d", v); + snprintf(b, sizeof(b), "%d", v); phpfbestrdup(b, length, value); } break; @@ -2368,7 +2407,7 @@ void phpfbColumnAsString(PHPFBResult* result, int column, void* data , int* leng { double v = *((double*)data); char b[128]; - sprintf(b, "%f", v); + snprintf(b, sizeof(b), "%f", v); phpfbestrdup(b, length, value); } break; @@ -2423,7 +2462,7 @@ void phpfbColumnAsString(PHPFBResult* result, int column, void* data , int* leng *length = l*2+3+1; if (value) { - char* r = safe_emalloc(l, 2, 1); + char* r = safe_emalloc(l, 2, 4); r[0] = 'B'; r[1] = '\''; for (i = 0; i < nBits; i++) @@ -2455,7 +2494,7 @@ void phpfbColumnAsString(PHPFBResult* result, int column, void* data , int* leng { char b[128]; int v = *((unsigned int*)data); - sprintf(b, "%d", v); + snprintf(b, sizeof(b), "%d", v); phpfbestrdup(b, length, value); } break; @@ -2464,7 +2503,7 @@ void phpfbColumnAsString(PHPFBResult* result, int column, void* data , int* leng { char b[128]; double seconds = *((double*)data); - sprintf(b, "%f", seconds); + snprintf(b, sizeof(b), "%f", seconds); phpfbestrdup(b, length, value); } break; diff --git a/ext/fdf/fdf.c b/ext/fdf/fdf.c index e3568b199abb..db3a88e6d7df 100644 --- a/ext/fdf/fdf.c +++ b/ext/fdf/fdf.c @@ -871,7 +871,10 @@ PHP_FUNCTION(fdf_save_string) struct stat stat; char *buf; - fstat(fileno(fp), &stat); + if (fstat(fileno(fp), &stat) == -1) { + RETVAL_FALSE; + goto err; + } buf = emalloc(stat.st_size +1); fread(buf, stat.st_size, 1, fp); buf[stat.st_size] = '\0'; @@ -889,7 +892,7 @@ PHP_FUNCTION(fdf_save_string) if(err != FDFErcOK) { FDF_FAILURE(err); } - +err: if(temp_filename) { unlink(temp_filename); efree(temp_filename); diff --git a/ext/fileinfo/CREDITS b/ext/fileinfo/CREDITS deleted file mode 100644 index 6251d1b110bb..000000000000 --- a/ext/fileinfo/CREDITS +++ /dev/null @@ -1,2 +0,0 @@ -fileinfo -Ilia Alshanetsky diff --git a/ext/fileinfo/EXPERIMENTAL b/ext/fileinfo/EXPERIMENTAL deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/ext/fileinfo/config.m4 b/ext/fileinfo/config.m4 deleted file mode 100644 index 4aba3745dbfa..000000000000 --- a/ext/fileinfo/config.m4 +++ /dev/null @@ -1,54 +0,0 @@ -dnl $Id$ -dnl config.m4 for extension fileinfo - -PHP_ARG_WITH(fileinfo, for fileinfo support, -[ --with-fileinfo=DIR Include fileinfo support]) - -if test "$PHP_FILEINFO" != "no"; then - SEARCH_PATH="/usr/local /usr" - SEARCH_FOR="/include/magic.h" - if test -r $PHP_FILEINFO/$SEARCH_FOR; then - FILEINFO_DIR=$PHP_FILEINFO - else - AC_MSG_CHECKING([for magic files in default path]) - for i in $SEARCH_PATH ; do - if test -r $i/$SEARCH_FOR; then - FILEINFO_DIR=$i - AC_MSG_RESULT(found in $i) - fi - done - fi - - if test -z "$FILEINFO_DIR"; then - AC_MSG_RESULT([not found]) - AC_MSG_ERROR([Please reinstall the libmagic distribution]) - fi - - PHP_ADD_INCLUDE($FILEINFO_DIR/include) - - LIBNAME=magic - LIBSYMBOL=magic_open - - PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, - [ - PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $FILEINFO_DIR/lib, FILEINFO_SHARED_LIBADD) - AC_DEFINE(HAVE_FILEINFOLIB,1,[ ]) - ],[ - AC_MSG_ERROR([wrong magic lib version or lib not found]) - ],[ - -L$FILEINFO_DIR/lib -lm -ldl - ]) - - MAGIC_MIME_LOCATIONS="/usr/local/share/file/magic /usr/share/file/magic /etc/magic" - for i in $MAGIC_MIME_LOCATIONS; do - if test -f $i; then - PHP_DEFAULT_MAGIC_FILE=$i - break - fi - done - AC_DEFINE_UNQUOTED(PHP_DEFAULT_MAGIC_FILE,"$PHP_DEFAULT_MAGIC_FILE",[magic file path]) - - PHP_SUBST(FILEINFO_SHARED_LIBADD) - - PHP_NEW_EXTENSION(fileinfo, fileinfo.c, $ext_shared) -fi diff --git a/ext/fileinfo/fileinfo.c b/ext/fileinfo/fileinfo.c deleted file mode 100644 index 627e74053357..000000000000 --- a/ext/fileinfo/fileinfo.c +++ /dev/null @@ -1,433 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Ilia Alshanetsky | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -/* - * HOWMANY specifies the maximum offset libmagic will look at - * this is currently hardcoded in the libmagic source but not exported - */ -#ifndef HOWMANY -#define HOWMANY 65536 -#endif - - -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "ext/standard/file.h" /* needed for context stuff */ -#include "php_fileinfo.h" -#include "fopen_wrappers.h" /* needed for is_url */ - -struct php_fileinfo { - long options; - struct magic_set *magic; -}; - -#ifndef PHP_DEFAULT_MAGIC_FILE -#define PHP_DEFAULT_MAGIC_FILE NULL -#endif - -#ifdef ZEND_ENGINE_2 - -static zend_object_handlers finfo_object_handlers; -zend_class_entry *finfo_class_entry; - -struct finfo_object { - zend_object zo; - struct php_fileinfo *ptr; -}; - -#define FILEINFO_DECLARE_INIT_OBJECT(object) \ - zval *object = getThis(); - -#define FILEINFO_REGISTER_OBJECT(_object, _ptr) \ -{ \ - struct finfo_object *obj; \ - obj = (struct finfo_object*)zend_object_store_get_object(_object TSRMLS_CC); \ - obj->ptr = _ptr; \ -} - -#define FILEINFO_FROM_OBJECT(finfo, object) \ -{ \ - struct finfo_object *obj = zend_object_store_get_object(object TSRMLS_CC); \ - finfo = obj->ptr; \ - if (!finfo) { \ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The invalid fileinfo object."); \ - RETURN_FALSE; \ - } \ -} - -/* {{{ finfo_objects_dtor - */ -static void finfo_objects_dtor(void *object, zend_object_handle handle TSRMLS_DC) -{ - struct finfo_object *intern = (struct finfo_object *) object; - - if (intern->ptr) { - magic_close(intern->ptr->magic); - efree(intern->ptr); - } - - efree(intern); -} -/* }}} */ - -/* {{{ finfo_objects_new - */ -PHP_FILEINFO_API zend_object_value finfo_objects_new(zend_class_entry *class_type TSRMLS_DC) -{ - zend_object_value retval; - struct finfo_object *intern; - - intern = emalloc(sizeof(struct finfo_object)); - intern->zo.ce = class_type; - intern->zo.in_get = 0; - intern->zo.in_set = 0; - intern->zo.properties = NULL; - intern->ptr = NULL; - - retval.handle = zend_objects_store_put(intern, finfo_objects_dtor, NULL, NULL TSRMLS_CC); - retval.handlers = (zend_object_handlers *) &finfo_object_handlers; - - return retval; -} -/* }}} */ - -/* {{{ finfo_class_functions - */ -function_entry finfo_class_functions[] = { - ZEND_ME_MAPPING(finfo, finfo_open, NULL) - ZEND_ME_MAPPING(set_flags, finfo_set_flags,NULL) - ZEND_ME_MAPPING(file, finfo_file, NULL) - ZEND_ME_MAPPING(buffer, finfo_buffer, NULL) - {NULL, NULL, NULL} -}; -/* }}} */ - -#else - -#define FILEINFO_REGISTER_OBJECT(_object, _ptr) {} -#define FILEINFO_FROM_OBJECT(socket_id, object) {} - -#define FILEINFO_DECLARE_INIT_OBJECT(object) -#define object 0 - -#endif - -#define FINFO_SET_OPTION(magic, options) \ - if (magic_setflags(magic, options) == -1) { \ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to set option '%ld' %d:%s", \ - options, magic_errno(magic), magic_error(magic)); \ - RETURN_FALSE; \ - } - -/* True global resources - no need for thread safety here */ -static int le_fileinfo; - -void finfo_resource_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC) -{ - if (rsrc->ptr) { - struct php_fileinfo *finfo = (struct php_fileinfo *) rsrc->ptr; - magic_close(finfo->magic); - efree(rsrc->ptr); - rsrc->ptr = NULL; - } -} - -/* {{{ fileinfo_functions[] - */ -function_entry fileinfo_functions[] = { - PHP_FE(finfo_open, NULL) - PHP_FE(finfo_close, NULL) - PHP_FE(finfo_set_flags, NULL) - PHP_FE(finfo_file, NULL) - PHP_FE(finfo_buffer, NULL) - {NULL, NULL, NULL} -}; -/* }}} */ - -/* {{{ PHP_MINIT_FUNCTION - */ -PHP_MINIT_FUNCTION(finfo) -{ -#ifdef ZEND_ENGINE_2 - zend_class_entry _finfo_class_entry; - INIT_CLASS_ENTRY(_finfo_class_entry, "finfo", finfo_class_functions); - _finfo_class_entry.create_object = finfo_objects_new; - finfo_class_entry = zend_register_internal_class(&_finfo_class_entry TSRMLS_CC); - - /* copy the standard object handlers to you handler table */ - memcpy(&finfo_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); -#endif /* ZEND_ENGINE_2 */ - - le_fileinfo = zend_register_list_destructors_ex(finfo_resource_destructor, NULL, "file_info", module_number); - - REGISTER_LONG_CONSTANT("FILEINFO_NONE", MAGIC_NONE, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("FILEINFO_SYMLINK", MAGIC_SYMLINK, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("FILEINFO_MIME", MAGIC_MIME, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("FILEINFO_COMPRESS", MAGIC_COMPRESS, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("FILEINFO_DEVICES", MAGIC_DEVICES, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("FILEINFO_CONTINUE", MAGIC_CONTINUE, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("FILEINFO_PRESERVE_ATIME", MAGIC_PRESERVE_ATIME, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("FILEINFO_RAW", MAGIC_RAW, CONST_CS|CONST_PERSISTENT); - - return SUCCESS; -} -/* }}} */ - -/* {{{ fileinfo_module_entry - */ -zend_module_entry fileinfo_module_entry = { -#if ZEND_MODULE_API_NO >= 20010901 - STANDARD_MODULE_HEADER, -#endif - "fileinfo", - fileinfo_functions, - PHP_MINIT(finfo), - NULL, - NULL, - NULL, - PHP_MINFO(fileinfo), -#if ZEND_MODULE_API_NO >= 20010901 - "0.1", /* Replace with version number for your extension */ -#endif - STANDARD_MODULE_PROPERTIES -}; -/* }}} */ - -#ifdef COMPILE_DL_FILEINFO -ZEND_GET_MODULE(fileinfo) -#endif - -/* {{{ PHP_MINFO_FUNCTION - */ -PHP_MINFO_FUNCTION(fileinfo) -{ - php_info_print_table_start(); - php_info_print_table_header(2, "fileinfo support", "enabled"); - php_info_print_table_end(); -} -/* }}} */ - -/* {{{ proto resource finfo_open([int options [, string arg]]) - Create a new fileinfo resource. */ -PHP_FUNCTION(finfo_open) -{ - long options = MAGIC_NONE; - char *file = PHP_DEFAULT_MAGIC_FILE; - int file_len = 0; - struct php_fileinfo *finfo; - FILEINFO_DECLARE_INIT_OBJECT(object) - char resolved_path[MAXPATHLEN]; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ls", &options, &file, &file_len) == FAILURE) { - RETURN_FALSE; - } - - if (file_len) { /* user specified filed, perform open_basedir checks */ - if (!VCWD_REALPATH(file, resolved_path)) { - RETURN_FALSE; - } - file = resolved_path; - - if ((PG(safe_mode) && (!php_checkuid(file, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(file TSRMLS_CC)) { - RETURN_FALSE; - } - } - - finfo = emalloc(sizeof(struct php_fileinfo)); - - finfo->options = options; - finfo->magic = magic_open(options); - - if (finfo->magic == NULL) { - efree(finfo); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid mode '%ld'.", options); - RETURN_FALSE; - } - - if (magic_load(finfo->magic, file) == -1) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to load magic database at '%s'.", file); - efree(finfo); - magic_close(finfo->magic); - RETURN_FALSE; - } - - if (object) { - FILEINFO_REGISTER_OBJECT(object, finfo); - } else { - ZEND_REGISTER_RESOURCE(return_value, finfo, le_fileinfo); - } -} -/* }}} */ - -/* {{{ proto resource finfo_close(resource finfo) - Close fileinfo resource. */ -PHP_FUNCTION(finfo_close) -{ - struct php_fileinfo *finfo; - zval *zfinfo; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zfinfo) == FAILURE) { - RETURN_FALSE; - } - ZEND_FETCH_RESOURCE(finfo, struct php_fileinfo *, &zfinfo, -1, "file_info", le_fileinfo); - - zend_list_delete(Z_RESVAL_P(zfinfo)); - - RETURN_TRUE; -} -/* }}} */ - -/* {{{ proto bool finfo_set_flags(resource finfo, int options) - Set libmagic configuration options. */ -PHP_FUNCTION(finfo_set_flags) -{ - long options; - struct php_fileinfo *finfo; - zval *zfinfo; - FILEINFO_DECLARE_INIT_OBJECT(object) - - if (object) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &options) == FAILURE) { - RETURN_FALSE; - } - FILEINFO_FROM_OBJECT(finfo, object); - } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl", &zfinfo, &options) == FAILURE) { - RETURN_FALSE; - } - ZEND_FETCH_RESOURCE(finfo, struct php_fileinfo *, &zfinfo, -1, "file_info", le_fileinfo); - } - - FINFO_SET_OPTION(finfo->magic, options) - finfo->options = options; - - RETURN_TRUE; -} -/* }}} */ - -static void _php_finfo_get_type(INTERNAL_FUNCTION_PARAMETERS, int mode) -{ - long options = 0; - char *buffer, *tmp, *ret_val; - int buffer_len; - struct php_fileinfo *finfo; - zval *zfinfo, *zcontext = NULL; - FILEINFO_DECLARE_INIT_OBJECT(object) - - if (object) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lbz", &buffer, &buffer_len, &options, &zcontext) == FAILURE) { - RETURN_FALSE; - } - FILEINFO_FROM_OBJECT(finfo, object); - } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs|lbz", &zfinfo, &buffer, &buffer_len, &options, &zcontext) == FAILURE) { - RETURN_FALSE; - } - ZEND_FETCH_RESOURCE(finfo, struct php_fileinfo *, &zfinfo, -1, "file_info", le_fileinfo); - } - - /* Set options for the current file/buffer. */ - if (options) { - FINFO_SET_OPTION(finfo->magic, options) - } - - if (mode) { /* file */ - /* determine if the file is a local file or remote URL */ - char *tmp2; - php_stream_wrapper *wrap = php_stream_locate_url_wrapper(buffer, &tmp2, 0 TSRMLS_DC); - if (wrap && wrap->is_url) { -#ifdef ZEND_ENGINE_2 - php_stream_context *context = php_stream_context_from_zval(zcontext, 0); -#else - php_stream_context *context = NULL; -#endif - php_stream *stream = php_stream_open_wrapper_ex(buffer, "rb", - ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, context); - if (!stream) { - RETURN_FALSE; - } - buffer_len = php_stream_copy_to_mem(stream, &tmp, HOWMANY, 0); - php_stream_close(stream); - - if (buffer_len == 0) { - RETURN_FALSE; - } - } else { /* local file */ - char resolved_path[MAXPATHLEN]; - if (!VCWD_REALPATH(buffer, resolved_path)) { - RETURN_FALSE; - } - - ret_val = (char *) magic_file(finfo->magic, buffer); - goto common; - } - } else { /* buffer */ - tmp = buffer; - } - - ret_val = (char *) magic_buffer(finfo->magic, tmp, buffer_len); - if (mode) { - efree(tmp); - } -common: - /* Restore options */ - if (options) { - FINFO_SET_OPTION(finfo->magic, finfo->options) - } - - if (!ret_val) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed identify data %d:%s", - magic_errno(finfo->magic), magic_error(finfo->magic)); - RETURN_FALSE; - } else { - RETURN_STRING(ret_val, 1); - } -} - -/* {{{ proto string finfo_file(resource finfo, char *file_name [, int options [, resource context]]) - Return information about a file. */ -PHP_FUNCTION(finfo_file) -{ - _php_finfo_get_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); -} -/* }}} */ - -/* {{{ proto string finfo_buffer(resource finfo, char *string [, int options]) - Return infromation about a string buffer. */ -PHP_FUNCTION(finfo_buffer) -{ - _php_finfo_get_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); -} -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/fileinfo/fileinfo.php b/ext/fileinfo/fileinfo.php deleted file mode 100644 index 1ee9efbeb85e..000000000000 --- a/ext/fileinfo/fileinfo.php +++ /dev/null @@ -1,29 +0,0 @@ -buffer(file_get_contents($file)) . "\n"; -} -?> diff --git a/ext/fileinfo/package.xml b/ext/fileinfo/package.xml deleted file mode 100644 index 4b4b085c10c8..000000000000 --- a/ext/fileinfo/package.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - Fileinfo - libmagic bindings - - - iliaa - Ilia Alshanetsky - ilia@php.net - lead - - - -This extension allows retrieval of information regarding vast majority of file. -This information may include dimensions, quality, length etc... - -Additionally it can also be used to retrieve the mime type for a particular -file and for text files proper language encoding. - - PHP - - beta - 0.2 - 2004-05-26 - - Fixed bug that caused PHP to refuse to recognize fileinfo.so. - - - - - - - - - - - - - - diff --git a/ext/fileinfo/php_fileinfo.h b/ext/fileinfo/php_fileinfo.h deleted file mode 100644 index 66c562172d7a..000000000000 --- a/ext/fileinfo/php_fileinfo.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Ilia Alshanetsky | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifndef PHP_FILEINFO_H -#define PHP_FILEINFO_H - -extern zend_module_entry fileinfo_module_entry; -#define phpext_fileinfo_ptr &fileinfo_module_entry - -#ifdef PHP_WIN32 -#define PHP_FILEINFO_API __declspec(dllexport) -#else -#define PHP_FILEINFO_API -#endif - -#ifdef ZTS -#include "TSRM.h" -#endif - -PHP_MINFO_FUNCTION(fileinfo); - -PHP_FUNCTION(finfo_open); -PHP_FUNCTION(finfo_close); -PHP_FUNCTION(finfo_set_flags); -PHP_FUNCTION(finfo_file); -PHP_FUNCTION(finfo_buffer); - -#ifdef ZTS -#define FILEINFO_G(v) TSRMG(fileinfo_globals_id, zend_fileinfo_globals *, v) -#else -#define FILEINFO_G(v) (fileinfo_globals.v) -#endif - -#endif /* PHP_FILEINFO_H */ - - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/filepro/filepro.c b/ext/filepro/filepro.c index 2821c9aa163d..737a1e0c0dfa 100644 --- a/ext/filepro/filepro.c +++ b/ext/filepro/filepro.c @@ -96,11 +96,43 @@ PHP_MINIT_FUNCTION(filepro) fp_globals = (fp_global_struct *) LocalAlloc(LPTR, sizeof(fp_global_struct)); TlsSetValue(FPTls, (void *) fp_globals); #endif + + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_RINIT_FUNCTION + */ +PHP_RINIT_FUNCTION(filepro) +{ FP_GLOBAL(fp_database)=NULL; FP_GLOBAL(fp_fcount)=-1; FP_GLOBAL(fp_keysize)=-1; FP_GLOBAL(fp_fieldlist)=NULL; + + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_RSHUTDOWN_FUNCTION + */ +PHP_RSHUTDOWN_FUNCTION(filepro) +{ + FP_FIELD *tmp, *next; + if (FP_GLOBAL(fp_database)) { + efree(FP_GLOBAL(fp_database)); + } + + if (FP_GLOBAL(fp_fieldlist)) { + for (tmp = FP_GLOBAL(fp_fieldlist); tmp;) { + efree(tmp->name); + efree(tmp->format); + next = tmp->next; + efree(tmp); + tmp=next; + } + } return SUCCESS; } /* }}} */ @@ -143,7 +175,15 @@ function_entry filepro_functions[] = { zend_module_entry filepro_module_entry = { STANDARD_MODULE_HEADER, - "filepro", filepro_functions, PHP_MINIT(filepro), PHP_MSHUTDOWN(filepro), NULL, NULL, NULL, NO_VERSION_YET, STANDARD_MODULE_PROPERTIES + "filepro", + filepro_functions, + PHP_MINIT(filepro), + PHP_MSHUTDOWN(filepro), + PHP_RINIT(filepro), + PHP_RSHUTDOWN(filepro), + NULL, + NO_VERSION_YET, + STANDARD_MODULE_PROPERTIES }; @@ -214,6 +254,8 @@ PHP_FUNCTION(filepro) tmp = FP_GLOBAL(fp_fieldlist); while (tmp != NULL) { next = tmp->next; + efree(tmp->name); + efree(tmp->format); efree(tmp); tmp = next; } diff --git a/ext/filepro/php_filepro.h b/ext/filepro/php_filepro.h index 31a72c464161..85ff69b605a2 100644 --- a/ext/filepro/php_filepro.h +++ b/ext/filepro/php_filepro.h @@ -41,6 +41,8 @@ PHP_FUNCTION(filepro_fieldcount); PHP_FUNCTION(filepro_retrieve); PHP_MINIT_FUNCTION(filepro); +PHP_RINIT_FUNCTION(filepro); +PHP_RSHUTDOWN_FUNCTION(filepro); PHP_MSHUTDOWN_FUNCTION(filepro); #else #define phpext_filepro_ptr NULL diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c index 687dd19f0c08..208b6e79e740 100644 --- a/ext/ftp/ftp.c +++ b/ext/ftp/ftp.c @@ -42,13 +42,9 @@ #ifdef USE_WINSOCK /* Modified to use Winsock (NOVSOCK2.H), atleast for now */ #include #else -#ifdef NEW_LIBC #include #include #include -#else -#include -#endif #endif #else #ifdef HAVE_SYS_TYPES_H @@ -77,7 +73,7 @@ #include "ext/standard/fsock.h" /* Additional headers for NetWare */ -#if defined(NETWARE) && defined(NEW_LIBC) && !defined(USE_WINSOCK) +#if defined(NETWARE) && !defined(USE_WINSOCK) #include #endif @@ -842,7 +838,9 @@ ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, } if (type == FTPTYPE_ASCII) { +#ifndef PHP_WIN32 char *s; +#endif char *ptr = data->buf; char *e = ptr + rcvd; /* logic depends on the OS EOL @@ -850,26 +848,15 @@ ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, * Everything Else \n */ #ifdef PHP_WIN32 - while ((s = strpbrk(ptr, "\r\n"))) { - if (*s == '\n') { - php_stream_putc(outstream, '\r'); - } else if (*s == '\r' && *(s + 1) == '\n') { - s++; - } - s++; - php_stream_write(outstream, ptr, (s - ptr)); - if (*(s - 1) == '\r') { - php_stream_putc(outstream, '\n'); - } - ptr = s; - } + php_stream_write(outstream, ptr, (e - ptr)); + ptr = e; #else - while ((s = memchr(ptr, '\r', (e - ptr)))) { + while (e > ptr && (s = memchr(ptr, '\r', (e - ptr)))) { php_stream_write(outstream, ptr, (s - ptr)); if (*(s + 1) == '\n') { s++; + php_stream_putc(outstream, '\n'); } - php_stream_putc(outstream, '\n'); ptr = s + 1; } #endif @@ -1236,19 +1223,11 @@ ftp_getresp(ftpbuf_t *ftp) int my_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len) { - fd_set write_set; - struct timeval tv; int n, size, sent; size = len; while (size) { - tv.tv_sec = ftp->timeout_sec; - tv.tv_usec = 0; - - FD_ZERO(&write_set); - FD_SET(s, &write_set); - - n = select(s + 1, NULL, &write_set, NULL, &tv); + n = php_pollfd_for_ms(s, POLLOUT, ftp->timeout_sec * 1000); if (n < 1) { @@ -1288,17 +1267,9 @@ my_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len) int my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len) { - fd_set read_set; - struct timeval tv; int n, nr_bytes; - tv.tv_sec = ftp->timeout_sec; - tv.tv_usec = 0; - - FD_ZERO(&read_set); - FD_SET(s, &read_set); - - n = select(s + 1, &read_set, NULL, NULL, &tv); + n = php_pollfd_for_ms(s, PHP_POLLREADABLE, ftp->timeout_sec * 1000); if (n < 1) { #if !defined(PHP_WIN32) && !(defined(NETWARE) && defined(USE_WINSOCK)) if (n == 0) { @@ -1328,16 +1299,9 @@ my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len) int data_available(ftpbuf_t *ftp, php_socket_t s) { - fd_set read_set; - struct timeval tv; int n; - tv.tv_sec = 0; - tv.tv_usec = 1; - - FD_ZERO(&read_set); - FD_SET(s, &read_set); - n = select(s + 1, &read_set, NULL, NULL, &tv); + n = php_pollfd_for_ms(s, PHP_POLLREADABLE, 1000); if (n < 1) { #if !defined(PHP_WIN32) && !(defined(NETWARE) && defined(USE_WINSOCK)) if (n == 0) { @@ -1355,16 +1319,9 @@ data_available(ftpbuf_t *ftp, php_socket_t s) int data_writeable(ftpbuf_t *ftp, php_socket_t s) { - fd_set write_set; - struct timeval tv; int n; - tv.tv_sec = 0; - tv.tv_usec = 1; - - FD_ZERO(&write_set); - FD_SET(s, &write_set); - n = select(s + 1, NULL, &write_set, NULL, &tv); + n = php_pollfd_for_ms(s, POLLOUT, 1000); if (n < 1) { #ifndef PHP_WIN32 if (n == 0) { @@ -1383,16 +1340,9 @@ data_writeable(ftpbuf_t *ftp, php_socket_t s) int my_accept(ftpbuf_t *ftp, php_socket_t s, struct sockaddr *addr, socklen_t *addrlen) { - fd_set accept_set; - struct timeval tv; int n; - tv.tv_sec = ftp->timeout_sec; - tv.tv_usec = 0; - FD_ZERO(&accept_set); - FD_SET(s, &accept_set); - - n = select(s + 1, &accept_set, NULL, NULL, &tv); + n = php_pollfd_for_ms(s, PHP_POLLREADABLE, ftp->timeout_sec * 1000); if (n < 1) { #if !defined(PHP_WIN32) && !(defined(NETWARE) && defined(USE_WINSOCK)) if (n == 0) { diff --git a/ext/ftp/php_ftp.c b/ext/ftp/php_ftp.c index 0466ed99aa4f..4fa30ef73865 100644 --- a/ext/ftp/php_ftp.c +++ b/ext/ftp/php_ftp.c @@ -25,14 +25,8 @@ #include "php.h" -#ifdef NETWARE -#ifdef USE_WINSOCK +#if defined(NETWARE) && defined(USE_WINSOCK) #include -#else -#ifndef NEW_LIBC -#include -#endif -#endif #endif #if HAVE_OPENSSL_EXT @@ -685,6 +679,10 @@ PHP_FUNCTION(ftp_get) resumepos = 0; } +#ifdef PHP_WIN32 + mode = FTPTYPE_IMAGE; +#endif + if (ftp->autoseek && resumepos) { outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt+" : "rb+", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL); if (outstream == NULL) { @@ -743,7 +741,9 @@ PHP_FUNCTION(ftp_nb_get) if (!ftp->autoseek && resumepos == PHP_FTP_AUTORESUME) { resumepos = 0; } - +#ifdef PHP_WIN32 + mode = FTPTYPE_IMAGE; +#endif if (ftp->autoseek && resumepos) { outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt+" : "rb+", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL); if (outstream == NULL) { diff --git a/ext/gd/config.m4 b/ext/gd/config.m4 index 05e406cb0b60..94559535b7b8 100644 --- a/ext/gd/config.m4 +++ b/ext/gd/config.m4 @@ -47,7 +47,7 @@ dnl dnl Checks for the configure options dnl -AC_DEFUN(PHP_GD_JPEG,[ +AC_DEFUN([PHP_GD_JPEG],[ if test "$PHP_JPEG_DIR" != "no"; then for i in $PHP_JPEG_DIR /usr/local /usr; do @@ -72,7 +72,7 @@ AC_DEFUN(PHP_GD_JPEG,[ fi ]) -AC_DEFUN(PHP_GD_PNG,[ +AC_DEFUN([PHP_GD_PNG],[ if test "$PHP_PNG_DIR" != "no"; then for i in $PHP_PNG_DIR /usr/local /usr; do @@ -107,7 +107,7 @@ AC_DEFUN(PHP_GD_PNG,[ fi ]) -AC_DEFUN(PHP_GD_XPM,[ +AC_DEFUN([PHP_GD_XPM],[ if test "$PHP_XPM_DIR" != "no"; then for i in $PHP_XPM_DIR /usr/local /usr/X11R6 /usr; do @@ -141,7 +141,7 @@ AC_DEFUN(PHP_GD_XPM,[ fi ]) -AC_DEFUN(PHP_GD_FREETYPE1,[ +AC_DEFUN([PHP_GD_FREETYPE1],[ if test "$PHP_TTF" != "no"; then if test "$PHP_FREETYPE_DIR" = "no" -o "$PHP_FREETYPE_DIR" = ""; then if test -n "$PHP_TTF"; then @@ -176,7 +176,7 @@ AC_DEFUN(PHP_GD_FREETYPE1,[ fi ]) -AC_DEFUN(PHP_GD_FREETYPE2,[ +AC_DEFUN([PHP_GD_FREETYPE2],[ if test "$PHP_FREETYPE_DIR" != "no"; then for i in $PHP_FREETYPE_DIR /usr/local /usr; do @@ -201,7 +201,7 @@ AC_DEFUN(PHP_GD_FREETYPE2,[ fi ]) -AC_DEFUN(PHP_GD_T1LIB,[ +AC_DEFUN([PHP_GD_T1LIB],[ if test "$PHP_T1LIB" != "no"; then for i in $PHP_T1LIB /usr/local /usr; do @@ -225,19 +225,19 @@ AC_DEFUN(PHP_GD_T1LIB,[ fi ]) -AC_DEFUN(PHP_GD_TTSTR,[ +AC_DEFUN([PHP_GD_TTSTR],[ if test "$PHP_GD_NATIVE_TTF" = "yes"; then AC_DEFINE(USE_GD_IMGSTRTTF, 1, [ ]) fi ]) -AC_DEFUN(PHP_GD_JISX0208,[ +AC_DEFUN([PHP_GD_JISX0208],[ if test "$PHP_GD_JIS_CONV" = "yes"; then USE_GD_JIS_CONV=1 fi ]) -AC_DEFUN(PHP_GD_CHECK_VERSION,[ +AC_DEFUN([PHP_GD_CHECK_VERSION],[ PHP_CHECK_LIBRARY(gd, gdImageString16, [AC_DEFINE(HAVE_LIBGD13, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) PHP_CHECK_LIBRARY(gd, gdImagePaletteCopy, [AC_DEFINE(HAVE_LIBGD15, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) PHP_CHECK_LIBRARY(gd, gdImageCreateFromPng, [AC_DEFINE(HAVE_GD_PNG, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) @@ -258,7 +258,9 @@ AC_DEFUN(PHP_GD_CHECK_VERSION,[ PHP_CHECK_LIBRARY(gd, gdImageColorResolve, [AC_DEFINE(HAVE_GDIMAGECOLORRESOLVE, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) PHP_CHECK_LIBRARY(gd, gdImageGifCtx, [AC_DEFINE(HAVE_GD_GIF_CTX, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) PHP_CHECK_LIBRARY(gd, gdCacheCreate, [AC_DEFINE(HAVE_GD_CACHE_CREATE, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) - PHP_CHECK_LIBRARY(gd, gdFontCacheShutdown, [AC_DEFINE(HAVE_GD_THREAD_SAFE, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) + PHP_CHECK_LIBRARY(gd, gdFontCacheShutdown, [AC_DEFINE(HAVE_GD_FONTCACHESHUTDOWN,1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) + PHP_CHECK_LIBRARY(gd, gdFreeFontCache, [AC_DEFINE(HAVE_GD_FREEFONTCACHE, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) + PHP_CHECK_LIBRARY(gd, gdNewDynamicCtxEx, [AC_DEFINE(HAVE_GD_DYNAMIC_CTX_EX, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) ]) dnl @@ -272,7 +274,7 @@ if test "$PHP_GD" = "yes"; then libgd/gdxpm.c libgd/gdfontt.c libgd/gdfonts.c libgd/gdfontmb.c libgd/gdfontl.c \ libgd/gdfontg.c libgd/gdtables.c libgd/gdft.c libgd/gdcache.c libgd/gdkanji.c \ libgd/wbmp.c libgd/gd_wbmp.c libgd/gdhelpers.c libgd/gd_topal.c libgd/gd_gif_in.c \ - libgd/xbm.c" + libgd/xbm.c libgd/gd_gif_out.c " dnl check for fabsf and floorf which are available since C99 AC_CHECK_FUNCS(fabsf floorf) @@ -306,7 +308,11 @@ dnl These are always available with bundled library AC_DEFINE(HAVE_GD_XBM, 1, [ ]) AC_DEFINE(HAVE_GD_BUNDLED, 1, [ ]) AC_DEFINE(HAVE_GD_GIF_READ, 1, [ ]) + AC_DEFINE(HAVE_GD_GIF_CREATE, 1, [ ]) AC_DEFINE(HAVE_GD_IMAGEELLIPSE, 1, [ ]) + AC_DEFINE(HAVE_GD_FONTCACHESHUTDOWN,1, [ ]) + AC_DEFINE(HAVE_GD_DYNAMIC_CTX_EX, 1, [ ]) + AC_DEFINE(HAVE_GD_GIF_CTX, 1, [ ]) dnl Make sure the libgd/ is first in the include path GDLIB_CFLAGS="-DHAVE_LIBPNG" diff --git a/ext/gd/config.w32 b/ext/gd/config.w32 index 3d9b375a50c4..691ac497edc1 100644 --- a/ext/gd/config.w32 +++ b/ext/gd/config.w32 @@ -7,13 +7,19 @@ if (PHP_GD != "no") { if (CHECK_LIB("libjpeg.lib", "gd", PHP_GD) && CHECK_LIB("freetype2.lib", "gd", PHP_GD) && CHECK_LIB("libpng.lib", "gd", PHP_GD) && - CHECK_LIB("zlib.lib", "gd", PHP_GD + ";..\\zlib;" + php_usual_lib_suspects) && - CHECK_HEADER_ADD_INCLUDE("gd.h", "CFLAGS_GD", PHP_GD + ";ext\\gd\\libgd")) { + CHECK_LIB("T1_StaticMD.lib", "gd", PHP_GD) && + CHECK_HEADER_ADD_INCLUDE("gd.h", "CFLAGS_GD", PHP_GD + ";ext\\gd\\libgd") && + CHECK_HEADER_ADD_INCLUDE("t1lib.h", "CFLAGS_GD", PHP_GD + ";" + PHP_PHP_BUILD + "\\include\\t1lib") + ) { + + if (PHP_ZLIB == "no" || PHP_ZLIB_SHARED) { + CHECK_LIB("zlib.lib", "gd", PHP_GD + ";..\\zlib;" + php_usual_lib_suspects); + } EXTENSION("gd", "gd.c gdttf.c", null, "-Iext/gd/libgd", "php_gd2.dll"); ADD_SOURCES("ext/gd/libgd", "gd2copypal.c gd_arc_f_buggy.c gd.c \ gdcache.c gdfontg.c gdfontl.c gdfontmb.c gdfonts.c gdfontt.c \ - gdft.c gd_gd2.c gd_gd.c gd_gif_in.c gdhelpers.c gd_io.c gd_io_dp.c \ + gdft.c gd_gd2.c gd_gd.c gd_gif_in.c gd_gif_out.c gdhelpers.c gd_io.c gd_io_dp.c \ gd_io_file.c gd_io_ss.c gd_jpeg.c gdkanji.c gd_png.c gd_ss.c \ gdtables.c gd_topal.c gd_wbmp.c gdxpm.c wbmp.c xbm.c", "gd"); AC_DEFINE('HAVE_LIBGD', 1, 'GD support'); @@ -21,6 +27,7 @@ if (PHP_GD != "no") { /D HAVE_GD_BUNDLED=1 \ /D HAVE_GD_GD2 \ /D HAVE_GD_GIF_READ=1 \ +/D HAVE_GD_GIF_CREATE=1 \ /D HAVE_GDIMAGECOLORRESOLVE=1 \ /D HAVE_GD_IMAGESETBRUSH=1 \ /D HAVE_GD_IMAGESETTILE=1 \ @@ -39,6 +46,7 @@ if (PHP_GD != "no") { /D HAVE_LIBPNG \ /D USE_GD_IMGSTRTTF \ /D USE_GD_IOCTX \ +/D HAVE_LIBT1 \ /D MSWIN32 \ "); } else { diff --git a/ext/gd/gd.c b/ext/gd/gd.c index 9627d2cdf393..d5b722c00dae 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -35,6 +35,7 @@ #include "SAPI.h" #include "php_gd.h" #include "ext/standard/info.h" +#include "php_open_temporary_file.h" #if HAVE_SYS_WAIT_H # include @@ -115,6 +116,10 @@ extern int gdImageColorResolve(gdImagePtr, int, int, int); int gdImageColorClosestHWB(gdImagePtr im, int r, int g, int b); #endif +#ifndef HAVE_GD_DYNAMIC_CTX_EX +#define gdNewDynamicCtxEx(len, data, val) gdNewDynamicCtx(len, data) +#endif + /* Section Filters Declarations */ /* IMPORTANT NOTE FOR NEW FILTER * Do not forget to update: @@ -330,9 +335,9 @@ zend_module_entry gd_module_entry = { "gd", gd_functions, PHP_MINIT(gd), + PHP_MSHUTDOWN(gd), NULL, - NULL, -#if HAVE_LIBGD20 && HAVE_GD_STRINGFT +#if HAVE_LIBGD20 && HAVE_GD_STRINGFT && (HAVE_GD_FONTCACHESHUTDOWN || HAVE_GD_FREEFONTCACHE) PHP_RSHUTDOWN(gd), #else NULL, @@ -368,6 +373,18 @@ static void php_free_gd_font(zend_rsrc_list_entry *rsrc TSRMLS_DC) } /* }}} */ +/* {{{ PHP_MSHUTDOWN_FUNCTION + */ +PHP_MSHUTDOWN_FUNCTION(gd) +{ +#if HAVE_LIBT1 + T1_CloseLib(); +#endif + return SUCCESS; +} +/* }}} */ + + /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(gd) @@ -439,10 +456,10 @@ PHP_MINIT_FUNCTION(gd) /* {{{ PHP_RSHUTDOWN_FUNCTION */ -#if HAVE_LIBGD20 && HAVE_GD_STRINGFT +#if HAVE_LIBGD20 && HAVE_GD_STRINGFT && (HAVE_GD_FONTCACHESHUTDOWN || HAVE_GD_FREEFONTCACHE) PHP_RSHUTDOWN_FUNCTION(gd) { -#if defined(HAVE_GD_THREAD_SAFE) || defined(HAVE_GD_BUNDLED) +#if HAVE_GD_FONTCACHESHUTDOWN gdFontCacheShutdown(); #else gdFreeFontCache(); @@ -453,7 +470,7 @@ PHP_RSHUTDOWN_FUNCTION(gd) /* }}} */ #if HAVE_GD_BUNDLED -#define PHP_GD_VERSION_STRING "bundled (2.0.23 compatible)" +#define PHP_GD_VERSION_STRING "bundled (2.0.28 compatible)" #elif HAVE_LIBGD20 #define PHP_GD_VERSION_STRING "2.0 or higher" #elif HAVE_GDIMAGECOLORRESOLVE @@ -1343,7 +1360,7 @@ static int _php_image_type (char data[8]) #ifdef HAVE_GD_WBMP else { gdIOCtx *io_ctx; - io_ctx = gdNewDynamicCtx(8, data); + io_ctx = gdNewDynamicCtxEx(8, data, 0); if (io_ctx) { if (getmbi((int(*)(void *)) gdGetC, io_ctx) == 0 && skipheader((int(*)(void *)) gdGetC, io_ctx) == 0 ) { #if HAVE_LIBGD204 @@ -1375,7 +1392,7 @@ gdImagePtr _php_image_create_from_string(zval **data, char *tn, gdImagePtr (*ioc gdImagePtr im; gdIOCtx *io_ctx; - io_ctx = gdNewDynamicCtx (Z_STRLEN_PP(data), Z_STRVAL_PP(data)); + io_ctx = gdNewDynamicCtxEx(Z_STRLEN_PP(data), Z_STRVAL_PP(data), 0); if (!io_ctx) { return NULL; @@ -1530,7 +1547,7 @@ static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type, goto out_err; } - io_ctx = gdNewDynamicCtx(buff_size, buff); + io_ctx = gdNewDynamicCtxEx(buff_size, buff, 0); if (!io_ctx) { php_error_docref(NULL TSRMLS_CC, E_WARNING,"Cannot allocate GD IO context"); goto out_err; @@ -1762,8 +1779,9 @@ static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char int b; FILE *tmp; char buf[4096]; + char *path; - tmp = tmpfile(); + tmp = php_open_temporary_file(NULL, NULL, &path TSRMLS_CC); if (tmp == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open temporary file"); RETURN_FALSE; @@ -1818,7 +1836,8 @@ static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char } fclose(tmp); - /* the temporary file is automatically deleted */ + VCWD_UNLINK((const char *)path); /* make sure that the temporary file is removed */ + efree(path); } RETURN_TRUE; } @@ -3051,7 +3070,7 @@ PHP_FUNCTION(imagesy) #ifdef ENABLE_GD_TTF #if HAVE_LIBGD20 && HAVE_LIBFREETYPE && HAVE_GD_STRINGFTEX -/* {{{ proto array imageftbbox(int size, int angle, string font_file, string text[, array extrainfo]) +/* {{{ proto array imageftbbox(float size, float angle, string font_file, string text [, array extrainfo]) Give the bounding box of a text using fonts via freetype2 */ PHP_FUNCTION(imageftbbox) { @@ -3059,7 +3078,7 @@ PHP_FUNCTION(imageftbbox) } /* }}} */ -/* {{{ proto array imagefttext(resource im, int size, int angle, int x, int y, int col, string font_file, string text, [array extrainfo]) +/* {{{ proto array imagefttext(resource im, float size, float angle, int x, int y, int col, string font_file, string text [, array extrainfo]) Write text to the image using fonts via freetype2 */ PHP_FUNCTION(imagefttext) { @@ -3068,7 +3087,7 @@ PHP_FUNCTION(imagefttext) /* }}} */ #endif -/* {{{ proto array imagettfbbox(int size, int angle, string font_file, string text) +/* {{{ proto array imagettfbbox(float size, float angle, string font_file, string text) Give the bounding box of a text using TrueType fonts */ PHP_FUNCTION(imagettfbbox) { @@ -3076,7 +3095,7 @@ PHP_FUNCTION(imagettfbbox) } /* }}} */ -/* {{{ proto array imagettftext(resource im, int size, int angle, int x, int y, int col, string font_file, string text) +/* {{{ proto array imagettftext(resource im, float size, float angle, int x, int y, int col, string font_file, string text) Write text to the image using a TrueType font */ PHP_FUNCTION(imagettftext) { @@ -3088,13 +3107,13 @@ PHP_FUNCTION(imagettftext) */ static void php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int mode, int extended) { - zval **IM, **PTSIZE, **ANGLE, **X, **Y, **C, **FONTNAME, **COL, **EXT = NULL; + zval *IM, *EXT = NULL; gdImagePtr im=NULL; - int col, x, y, l=0, i, brect[8]; + int col = -1, x = -1, y = -1, str_len, fontname_len, i, brect[8]; double ptsize, angle; unsigned char *str = NULL, *fontname = NULL; char *error = NULL; - int argc; + int argc = ZEND_NUM_ARGS(); #if HAVE_GD_STRINGFTEX gdFTStringExtra strex = {0}; #endif @@ -3103,85 +3122,65 @@ static void php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int mode, int assert(!extended); #endif - argc = ZEND_NUM_ARGS(); - if (mode == TTFTEXT_BBOX) { - if (argc < 4 || argc > 5 || zend_get_parameters_ex(argc, &PTSIZE, &ANGLE, &FONTNAME, &C, &EXT) == FAILURE) { + if (argc < 4 || argc > ((extended) ? 5 : 4)) { ZEND_WRONG_PARAM_COUNT(); + } else if (zend_parse_parameters(argc TSRMLS_CC, "ddss|a", &ptsize, &angle, &fontname, &fontname_len, &str, &str_len, &EXT) == FAILURE) { + RETURN_FALSE; } } else { - if (argc < 8 || argc > 9 || zend_get_parameters_ex(argc, &IM, &PTSIZE, &ANGLE, &X, &Y, &COL, &FONTNAME, &C, &EXT) == FAILURE) { + if (argc < 8 || argc > ((extended) ? 9 : 8)) { ZEND_WRONG_PARAM_COUNT(); + } else if (zend_parse_parameters(argc TSRMLS_CC, "rddlllss|a", &IM, &ptsize, &angle, &x, &y, &col, &fontname, &fontname_len, &str, &str_len, &EXT) == FAILURE) { + RETURN_FALSE; } - ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); + ZEND_FETCH_RESOURCE(im, gdImagePtr, &IM, -1, "Image", le_gd); } - convert_to_double_ex(PTSIZE); - convert_to_double_ex(ANGLE); - convert_to_string_ex(FONTNAME); - convert_to_string_ex(C); - - if (mode == TTFTEXT_BBOX) { - im = NULL; - col = x = y = -1; - } else { - convert_to_long_ex(X); - convert_to_long_ex(Y); - convert_to_long_ex(COL); - col = Z_LVAL_PP(COL); - y = Z_LVAL_PP(Y); - x = Z_LVAL_PP(X); + /* convert angle to radians */ + angle = angle * (M_PI/180); #if HAVE_GD_STRINGFTEX - if (EXT) { - /* parse extended info */ - - HashPosition pos; - - convert_to_array_ex(EXT); - - /* walk the assoc array */ - zend_hash_internal_pointer_reset_ex(HASH_OF(*EXT), &pos); - do { - zval ** item; - char * key; - ulong num_key; - - if (zend_hash_get_current_key_ex(HASH_OF(*EXT), &key, NULL, &num_key, 0, &pos) != HASH_KEY_IS_STRING) { - continue; - } - - if (zend_hash_get_current_data_ex(HASH_OF(*EXT), (void **) &item, &pos) == FAILURE) { - continue; - } - - if (strcmp("linespacing", key) == 0) { - convert_to_double_ex(item); - strex.flags |= gdFTEX_LINESPACE; - strex.linespacing = Z_DVAL_PP(item); - } + if (extended && EXT) { /* parse extended info */ + HashPosition pos; + + /* walk the assoc array */ + zend_hash_internal_pointer_reset_ex(HASH_OF(EXT), &pos); + do { + zval ** item; + char * key; + ulong num_key; + + if (zend_hash_get_current_key_ex(HASH_OF(EXT), &key, NULL, &num_key, 0, &pos) != HASH_KEY_IS_STRING) { + continue; + } - } while (zend_hash_move_forward_ex(HASH_OF(*EXT), &pos) == SUCCESS); - } -#endif + if (zend_hash_get_current_data_ex(HASH_OF(EXT), (void **) &item, &pos) == FAILURE) { + continue; + } + + if (strcmp("linespacing", key) == 0) { + convert_to_double_ex(item); + strex.flags |= gdFTEX_LINESPACE; + strex.linespacing = Z_DVAL_PP(item); + } + } while (zend_hash_move_forward_ex(HASH_OF(EXT), &pos) == SUCCESS); } - - ptsize = Z_DVAL_PP(PTSIZE); - angle = Z_DVAL_PP(ANGLE) * (M_PI / 180); /* convert to radians */ - - str = (unsigned char *) Z_STRVAL_PP(C); - l = strlen(str); +#endif #ifdef VIRTUAL_DIR { char tmp_font_path[MAXPATHLEN]; - if (VCWD_REALPATH(Z_STRVAL_PP(FONTNAME), tmp_font_path)) { - fontname = (unsigned char *) Z_STRVAL_PP(FONTNAME); + + if (VCWD_REALPATH(fontname, tmp_font_path)) { + fontname = (unsigned char *) fontname; + } else { + fontname = NULL; } } #else - fontname = (unsigned char *) Z_STRVAL_PP(FONTNAME); + fontname = (unsigned char *) fontname; #endif #ifdef USE_GD_IMGSTRTTF @@ -3472,7 +3471,7 @@ PHP_FUNCTION(imagepstext) #else if (_fg < 0 || _fg > gdImageColorsTotal(bg_img)) { #endif - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Foreground color index %d out of range", _fg); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Foreground color index %ld out of range", _fg); RETURN_FALSE; } @@ -3481,7 +3480,7 @@ PHP_FUNCTION(imagepstext) #else if (_bg < 0 || _bg > gdImageColorsTotal(bg_img)) { #endif - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Background color index %d out of range", _bg); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Background color index %ld out of range", _bg); RETURN_FALSE; } @@ -3523,7 +3522,7 @@ PHP_FUNCTION(imagepstext) T1_AASetLevel(T1_AA_HIGH); break; default: - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value %d as number of steps for antialiasing", aa_steps); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value %ld as number of steps for antialiasing", aa_steps); RETURN_FALSE; } diff --git a/ext/gd/gd.dsp b/ext/gd/gd.dsp index d787286c7ef2..6a998e19a998 100644 --- a/ext/gd/gd.dsp +++ b/ext/gd/gd.dsp @@ -43,8 +43,8 @@ RSC=rc.exe # PROP Intermediate_Dir "Release_TS" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" -# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\..\zlib" /I "..\..\TSRM" /D ZEND_DEBUG=0 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "COMPILE_DL_GD" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_GD_GIF_READ=1 /D HAVE_GDIMAGECOLORRESOLVE=1 /D "HAVE_GD_PNG" /D "HAVE_GD_JPG" /D "HAVE_GD_WBMP" /D "HAVE_GD_XBM" /D HAVE_LIBGD13=1 /D HAVE_LIBGD=1 /D HAVE_LIBGD15=1 /D HAVE_LIBGD204=1 /FR /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\..\zlib" /I "..\..\TSRM" /I "libgd" /D ZEND_DEBUG=0 /D HAVE_LIBGD15=1 /D HAVE_LIBGD204=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "COMPILE_DL_GD" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_GD_GIF_READ=1 /D HAVE_GDIMAGECOLORRESOLVE=1 /D "HAVE_GD_PNG" /D "HAVE_GD_JPG" /D "HAVE_GD_WBMP" /D "HAVE_GD_XBM" /D HAVE_LIBGD=1 /D HAVE_LIBGD13=1 /D HAVE_LIBGD20=1 /D "USE_GD_IOCTX" /D HAVE_LIBFREETYPE=1 /D "USE_GD_IMGSTRTTF" /D HAVE_GD_STRINGTTF=1 /D HAVE_GD_BUNDLED=1 /D "MSWIN32" /D "HAVE_LIBPNG" /D "HAVE_LIBJPEG" /D "HAVE_GD_GD2" /D HAVE_GD_STRINGFTEX=1 /D HAVE_GD_IMAGESETBRUSH=1 /D HAVE_GD_IMAGESETTILE=1 /FR /FD /c +# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\..\zlib" /I "..\..\TSRM" /D ZEND_DEBUG=0 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "COMPILE_DL_GD" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_GD_GIF_READ=1 /D HAVE_GD_GIF_CREATE=1 /D HAVE_GDIMAGECOLORRESOLVE=1 /D "HAVE_GD_PNG" /D "HAVE_GD_JPG" /D "HAVE_GD_WBMP" /D "HAVE_GD_XBM" /D HAVE_LIBGD13=1 /D HAVE_LIBGD=1 /D HAVE_LIBGD15=1 /D HAVE_LIBGD204=1 /FR /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\..\zlib" /I "..\..\TSRM" /I "libgd" /D ZEND_DEBUG=0 /D HAVE_LIBGD15=1 /D HAVE_LIBGD204=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "COMPILE_DL_GD" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_GD_GIF_READ=1 /D HAVE_GD_GIF_CREATE=1 /D HAVE_GDIMAGECOLORRESOLVE=1 /D "HAVE_GD_PNG" /D "HAVE_GD_JPG" /D "HAVE_GD_WBMP" /D "HAVE_GD_XBM" /D HAVE_LIBGD=1 /D HAVE_LIBGD13=1 /D HAVE_LIBGD20=1 /D "USE_GD_IOCTX" /D HAVE_LIBFREETYPE=1 /D "USE_GD_IMGSTRTTF" /D HAVE_GD_STRINGTTF=1 /D HAVE_GD_BUNDLED=1 /D "MSWIN32" /D "HAVE_LIBPNG" /D "HAVE_LIBJPEG" /D "HAVE_GD_GD2" /D HAVE_GD_STRINGFTEX=1 /D HAVE_GD_IMAGESETBRUSH=1 /D HAVE_GD_IMAGESETTILE=1 /FR /FD /c # SUBTRACT CPP /YX # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 @@ -73,8 +73,8 @@ LINK32=link.exe # PROP Intermediate_Dir "Debug_TS" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" -# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\..\zlib" /I "..\..\TSRM" /D ZEND_DEBUG=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "COMPILE_DL_GD" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_GD_GIF_READ=1 /D HAVE_GDIMAGECOLORRESOLVE=1 /D "HAVE_GD_PNG" /D "HAVE_GD_JPG" /D "HAVE_GD_WBMP" /D HAVE_LIBGD13=1 /D HAVE_LIBGD=1 /D HAVE_LIBGD15=1 /D HAVE_LIBGD204=1 /FR /YX /FD /c -# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\..\zlib" /I "..\..\TSRM" /I "libgd" /D ZEND_DEBUG=1 /D "HAVE_LIBGD15" /D HAVE_LIBGD204=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "COMPILE_DL_GD" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_GD_GIF_READ=1 /D HAVE_GDIMAGECOLORRESOLVE=1 /D "HAVE_GD_PNG" /D "HAVE_GD_JPG" /D "HAVE_GD_WBMP" /D HAVE_LIBGD=1 /D HAVE_LIBGD13=1 /D HAVE_LIBGD20=1 /D "USE_GD_IOCTX" /D HAVE_LIBFREETYPE=1 /D "USE_GD_IMGSTRTTF" /D HAVE_GD_STRINGTTF=1 /D HAVE_GD_BUNDLED=1 /D "MSWIN32" /D "HAVE_LIBPNG" /D "HAVE_LIBJPEG" /D "HAVE_GD_GD2" /D HAVE_GD_STRINGFTEX=1 /D HAVE_GD_IMAGESETBRUSH=1 /D HAVE_GD_IMAGESETTILE=1 /FR /FD /c +# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\..\zlib" /I "..\..\TSRM" /D ZEND_DEBUG=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "COMPILE_DL_GD" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_GD_GIF_READ=1 /D HAVE_GD_GIF_CREATE=1 /D HAVE_GDIMAGECOLORRESOLVE=1 /D "HAVE_GD_PNG" /D "HAVE_GD_JPG" /D "HAVE_GD_WBMP" /D HAVE_LIBGD13=1 /D HAVE_LIBGD=1 /D HAVE_LIBGD15=1 /D HAVE_LIBGD204=1 /FR /YX /FD /c +# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\..\zlib" /I "..\..\TSRM" /I "libgd" /D ZEND_DEBUG=1 /D "HAVE_LIBGD15" /D HAVE_LIBGD204=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "COMPILE_DL_GD" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_GD_GIF_READ=1 /D HAVE_GD_GIF_CREATE=1 /D HAVE_GDIMAGECOLORRESOLVE=1 /D "HAVE_GD_PNG" /D "HAVE_GD_JPG" /D "HAVE_GD_WBMP" /D HAVE_LIBGD=1 /D HAVE_LIBGD13=1 /D HAVE_LIBGD20=1 /D "USE_GD_IOCTX" /D HAVE_LIBFREETYPE=1 /D "USE_GD_IMGSTRTTF" /D HAVE_GD_STRINGTTF=1 /D HAVE_GD_BUNDLED=1 /D "MSWIN32" /D "HAVE_LIBPNG" /D "HAVE_LIBJPEG" /D "HAVE_GD_GD2" /D HAVE_GD_STRINGFTEX=1 /D HAVE_GD_IMAGESETBRUSH=1 /D HAVE_GD_IMAGESETTILE=1 /FR /FD /c # SUBTRACT CPP /YX # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 @@ -213,6 +213,10 @@ SOURCE=.\libgd\gd_gd2.c SOURCE=.\libgd\gd_gif_in.c # End Source File # Begin Source File + +SOURCE=.\libgd\gd_gif_out.c +# End Source File +# Begin Source File SOURCE=.\libgd\gd_io.c diff --git a/ext/gd/gdcache.c b/ext/gd/gdcache.c index fa82de5f40e3..63df228de9f2 100644 --- a/ext/gd/gdcache.c +++ b/ext/gd/gdcache.c @@ -42,7 +42,7 @@ #if PHP_WIN32 #define ENABLE_GD_TTF #else -#include "php_config.h" +#include #endif #if (HAVE_LIBTTF | HAVE_LIBFREETYPE) && !defined(HAVE_GD_CACHE_CREATE) diff --git a/ext/gd/gdttf.c b/ext/gd/gdttf.c index b38b182317e2..56154835d28f 100644 --- a/ext/gd/gdttf.c +++ b/ext/gd/gdttf.c @@ -9,7 +9,7 @@ #if PHP_WIN32 #include "config.w32.h" #else -#include "php_config.h" +#include #endif #if HAVE_LIBTTF && !defined(USE_GD_IMGSTRTTF) #include diff --git a/ext/gd/libgd/gd.c b/ext/gd/libgd/gd.c index c127928cba52..794ba3581a83 100644 --- a/ext/gd/libgd/gd.c +++ b/ext/gd/libgd/gd.c @@ -1735,8 +1735,8 @@ void gdImageFilledEllipse (gdImagePtr im, int mx, int my, int w, int h, int c) rx = r << 1; ry = 0; x = a; - old_y2=-1; - old_y1=-1; + old_y2=-2; + old_y1=-2; while (x > 0){ if (r > 0) { my1++;my2--; @@ -1882,14 +1882,24 @@ void gdImageFill(gdImagePtr im, int x, int y, int nc) struct seg *stack; struct seg *sp; + int alphablending_bak; + + alphablending_bak = im->alphaBlendingFlag; + im->alphaBlendingFlag = 0; + if (nc==gdTiled){ _gdImageFillTiled(im,x,y,nc); + im->alphaBlendingFlag = alphablending_bak; return; } wx2=im->sx;wy2=im->sy; oc = gdImageGetPixel(im, x, y); - if (oc==nc || x<0 || x>wx2 || y<0 || y>wy2) return; + + if (oc==nc || x<0 || x>wx2 || y<0 || y>wy2) { + im->alphaBlendingFlag = alphablending_bak; + return; + } stack = (struct seg *)safe_emalloc(sizeof(struct seg), ((int)(im->sy*im->sx)/4), 1); sp = stack; @@ -1929,6 +1939,7 @@ skip: for (x++; x<=x2 && (gdImageGetPixel(im, x, y)!=oc); x++); } while (x<=x2); } efree(stack); + im->alphaBlendingFlag = alphablending_bak; } void _gdImageFillTiled(gdImagePtr im, int x, int y, int nc) @@ -2013,31 +2024,78 @@ skip: for (x++; x<=x2 && (pts[y][x] || gdImageGetPixel(im,x, y)!=oc); x++); } - void gdImageRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color) { int x1h = x1, x1v = x1, y1h = y1, y1v = y1, x2h = x2, x2v = x2, y2h = y2, y2v = y2; int thick = im->thick; + int half1 = 1; + int t; + + if (y2 < y1) { + t=y1; + y1 = y2; + y2 = t; + + t = x1; + x1 = x2; + x2 = t; + } + x1h = x1; x1v = x1; y1h = y1; y1v = y1; x2h = x2; x2v = x2; y2h = y2; y2v = y2; if (thick > 1) { - int half = thick / 2; - int half1 = thick - half; + int cx, cy, x1ul, y1ul, x2lr, y2lr; + int half = thick >> 1; + half1 = thick - half; + x1ul = x1 - half; + y1ul = y1 - half; + + x2lr = x2 + half; + y2lr = y2 + half; - if (y1 < y2) { - y1v = y1h - half; - y2v = y2h + half1 - 1; - } else { - y1v = y1h + half1 - 1; - y2v = y2h - half; + cy = y1ul + thick; + while (cy-- > y1ul) { + cx = x1ul - 1; + while (cx++ < x2lr) { + gdImageSetPixel(im, cx, cy, color); + } + } + + cy = y2lr - thick; + while (cy++ < y2lr) { + cx = x1ul - 1; + while (cx++ < x2lr) { + gdImageSetPixel(im, cx, cy, color); + } + } + + cy = y1ul + thick - 1; + while (cy++ < y2lr -thick) { + cx = x1ul - 1; + while (cx++ < x1ul + thick) { + gdImageSetPixel(im, cx, cy, color); + } } - } - gdImageLine(im, x1h, y1h, x2h, y1h, color); - gdImageLine(im, x1h, y2h, x2h, y2h, color); - gdImageLine(im, x1v, y1v, x1v, y2v, color); - gdImageLine(im, x2v, y1v, x2v, y2v, color); + cy = y1ul + thick - 1; + while (cy++ < y2lr -thick) { + cx = x2lr - thick - 1; + while (cx++ < x2lr) { + gdImageSetPixel(im, cx, cy, color); + } + } + + return; + } else { + y1v = y1h + 1; + y2v = y2h - 1; + gdImageLine(im, x1h, y1h, x2h, y1h, color); + gdImageLine(im, x1h, y2h, x2h, y2h, color); + gdImageLine(im, x1v, y1v, x1v, y2v, color); + gdImageLine(im, x2v, y1v, x2v, y2v, color); + } } + void gdImageFilledRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color) { int x, y; @@ -3766,9 +3824,9 @@ int gdImageSelectiveBlur( gdImagePtr src) int gdImageEdgeDetectQuick(gdImagePtr src) { - float filter[3][3] = {{1.0,1.0,1.0}, - {0.0,0.0,0.0}, - {-1.0,-1.0,-1.0}}; + float filter[3][3] = {{-1.0,0.0,-1.0}, + {0.0,4.0,0.0}, + {-1.0,0.0,-1.0}}; return gdImageConvolution(src, filter, 1, 127); } @@ -3784,9 +3842,9 @@ int gdImageGaussianBlur(gdImagePtr im) int gdImageEmboss(gdImagePtr im) { - float filter[3][3] = {{-1.0,0.0,-1.0}, - {0.0,4.0,0.0}, - {-1.0,0.0,-1.0}}; + float filter[3][3] = {{1.0,1.0,1.0}, + {0.0,0.0,0.0}, + {-1.0,-1.0,-1.0}}; return gdImageConvolution(im, filter, 1, 127); } diff --git a/ext/gd/libgd/gd.h b/ext/gd/libgd/gd.h index f0fdb6b284cd..c7e12ac6355c 100644 --- a/ext/gd/libgd/gd.h +++ b/ext/gd/libgd/gd.h @@ -407,8 +407,11 @@ void gdImageColorDeallocate(gdImagePtr im, int color); conversion to palette is not great (for small images it can be negative) and the quality loss is ugly. */ +gdImagePtr gdImageCreatePaletteFromTrueColor (gdImagePtr im, int ditherFlag, int colorsWanted); + void gdImageTrueColorToPalette(gdImagePtr im, int ditherFlag, int colorsWanted); + /* An attempt at getting the results of gdImageTrueColorToPalette to look a bit more like the original (im1 is the original and im2 is the palette version */ @@ -428,6 +431,8 @@ void gdImageColorTransparent(gdImagePtr im, int color); void gdImagePaletteCopy(gdImagePtr dst, gdImagePtr src); void gdImagePng(gdImagePtr im, FILE *out); void gdImagePngCtx(gdImagePtr im, gdIOCtx *out); +void gdImageGif(gdImagePtr im, FILE *out); +void gdImageGifCtx(gdImagePtr im, gdIOCtx *out); /* 2.0.12: Compression level: 0-9 or -1, where 0 is NO COMPRESSION at all, * 1 is FASTEST but produces larger files, 9 provides the best * compression (smallest files) but takes a long time to compress, and diff --git a/ext/gd/libgd/gd_gif_out.c b/ext/gd/libgd/gd_gif_out.c new file mode 100644 index 000000000000..49da75f96f97 --- /dev/null +++ b/ext/gd/libgd/gd_gif_out.c @@ -0,0 +1,759 @@ +#include +#include +#include +#include +#include "gd.h" + +/* Code drawn from ppmtogif.c, from the pbmplus package +** +** Based on GIFENCOD by David Rowley . A +** Lempel-Zim compression based on "compress". +** +** Modified by Marcel Wijkstra +** +** Copyright (C) 1989 by Jef Poskanzer. +** +** Permission to use, copy, modify, and distribute this software and its +** documentation for any purpose and without fee is hereby granted, provided +** that the above copyright notice appear in all copies and that both that +** copyright notice and this permission notice appear in supporting +** documentation. This software is provided "as is" without express or +** implied warranty. +** +** The Graphics Interchange Format(c) is the Copyright property of +** CompuServe Incorporated. GIF(sm) is a Service Mark property of +** CompuServe Incorporated. +*/ + +/* + * a code_int must be able to hold 2**GIFBITS values of type int, and also -1 + */ +typedef int code_int; + +#ifdef SIGNED_COMPARE_SLOW +typedef unsigned long int count_int; +typedef unsigned short int count_short; +#else /*SIGNED_COMPARE_SLOW*/ +typedef long int count_int; +#endif /*SIGNED_COMPARE_SLOW*/ + +/* 2.0.28: threadsafe */ + +#define maxbits GIFBITS + +/* should NEVER generate this code */ +#define maxmaxcode ((code_int)1 << GIFBITS) + +#define HSIZE 5003 /* 80% occupancy */ +#define hsize HSIZE /* Apparently invariant, left over from + compress */ + +typedef struct { + int Width, Height; + int curx, cury; + long CountDown; + int Pass; + int Interlace; + int n_bits; /* number of bits/code */ + code_int maxcode; /* maximum code, given n_bits */ + count_int htab [HSIZE]; + unsigned short codetab [HSIZE]; + code_int free_ent; /* first unused entry */ + /* + * block compression parameters -- after all codes are used up, + * and compression rate changes, start over. + */ + int clear_flg; + int offset; + long int in_count; /* length of input */ + long int out_count; /* # of codes output (for debugging) */ + + int g_init_bits; + gdIOCtx * g_outfile; + + int ClearCode; + int EOFCode; + unsigned long cur_accum; + int cur_bits; + /* + * Number of characters so far in this 'packet' + */ + int a_count; + /* + * Define the storage for the packet accumulator + */ + char accum[ 256 ]; +} GifCtx; + +static int gifPutWord(int w, gdIOCtx *out); +static int colorstobpp(int colors); +static void BumpPixel (GifCtx *ctx); +static int GIFNextPixel (gdImagePtr im, GifCtx *ctx); +static void GIFEncode (gdIOCtxPtr fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im); +static void compress (int init_bits, gdIOCtx *outfile, gdImagePtr im, GifCtx *ctx); +static void output (code_int code, GifCtx *ctx); +static void cl_block (GifCtx *ctx); +static void cl_hash (register count_int chsize, GifCtx *ctx); +static void char_init (GifCtx *ctx); +static void char_out (int c, GifCtx *ctx); +static void flush_char (GifCtx *ctx); +void * gdImageGifPtr (gdImagePtr im, int *size) +{ + void *rv; + gdIOCtx *out = gdNewDynamicCtx (2048, NULL); + gdImageGifCtx (im, out); + rv = gdDPExtractData (out, size); + out->gd_free (out); + return rv; +} + +void gdImageGif (gdImagePtr im, FILE * outFile) +{ + gdIOCtx *out = gdNewFileCtx (outFile); + gdImageGifCtx (im, out); + out->gd_free (out); +} + +void gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out) +{ + gdImagePtr pim = 0, tim = im; + int interlace, transparent, BitsPerPixel; + interlace = im->interlace; + transparent = im->transparent; + if (im->trueColor) { + /* Expensive, but the only way that produces an + acceptable result: mix down to a palette + based temporary image. */ + pim = gdImageCreatePaletteFromTrueColor(im, 1, 256); + if (!pim) { + return; + } + tim = pim; + } + BitsPerPixel = colorstobpp(tim->colorsTotal); + /* All set, let's do it. */ + GIFEncode( + out, tim->sx, tim->sy, interlace, 0, transparent, BitsPerPixel, + tim->red, tim->green, tim->blue, tim); + if (pim) { + /* Destroy palette based temporary image. */ + gdImageDestroy( pim); + } +} + +static int +colorstobpp(int colors) +{ + int bpp = 0; + + if ( colors <= 2 ) + bpp = 1; + else if ( colors <= 4 ) + bpp = 2; + else if ( colors <= 8 ) + bpp = 3; + else if ( colors <= 16 ) + bpp = 4; + else if ( colors <= 32 ) + bpp = 5; + else if ( colors <= 64 ) + bpp = 6; + else if ( colors <= 128 ) + bpp = 7; + else if ( colors <= 256 ) + bpp = 8; + return bpp; + } + +/***************************************************************************** + * + * GIFENCODE.C - GIF Image compression interface + * + * GIFEncode( FName, GHeight, GWidth, GInterlace, Background, Transparent, + * BitsPerPixel, Red, Green, Blue, gdImagePtr ) + * + *****************************************************************************/ + +#define TRUE 1 +#define FALSE 0 +/* + * Bump the 'curx' and 'cury' to point to the next pixel + */ +static void +BumpPixel(GifCtx *ctx) +{ + /* + * Bump the current X position + */ + ++(ctx->curx); + + /* + * If we are at the end of a scan line, set curx back to the beginning + * If we are interlaced, bump the cury to the appropriate spot, + * otherwise, just increment it. + */ + if( ctx->curx == ctx->Width ) { + ctx->curx = 0; + + if( !ctx->Interlace ) + ++(ctx->cury); + else { + switch( ctx->Pass ) { + + case 0: + ctx->cury += 8; + if( ctx->cury >= ctx->Height ) { + ++(ctx->Pass); + ctx->cury = 4; + } + break; + + case 1: + ctx->cury += 8; + if( ctx->cury >= ctx->Height ) { + ++(ctx->Pass); + ctx->cury = 2; + } + break; + + case 2: + ctx->cury += 4; + if( ctx->cury >= ctx->Height ) { + ++(ctx->Pass); + ctx->cury = 1; + } + break; + + case 3: + ctx->cury += 2; + break; + } + } + } +} + +/* + * Return the next pixel from the image + */ +static int +GIFNextPixel(gdImagePtr im, GifCtx *ctx) +{ + int r; + + if( ctx->CountDown == 0 ) + return EOF; + + --(ctx->CountDown); + + r = gdImageGetPixel(im, ctx->curx, ctx->cury); + + BumpPixel(ctx); + + return r; +} + +/* public */ + +static void +GIFEncode(gdIOCtxPtr fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im) +{ + int B; + int RWidth, RHeight; + int LeftOfs, TopOfs; + int Resolution; + int ColorMapSize; + int InitCodeSize; + int i; + GifCtx ctx; + ctx.Interlace = GInterlace; + ctx.in_count = 1; + memset(&ctx, 0, sizeof(ctx)); + ColorMapSize = 1 << BitsPerPixel; + + RWidth = ctx.Width = GWidth; + RHeight = ctx.Height = GHeight; + LeftOfs = TopOfs = 0; + + Resolution = BitsPerPixel; + + /* + * Calculate number of bits we are expecting + */ + ctx.CountDown = (long)ctx.Width * (long)ctx.Height; + + /* + * Indicate which pass we are on (if interlace) + */ + ctx.Pass = 0; + + /* + * The initial code size + */ + if( BitsPerPixel <= 1 ) + InitCodeSize = 2; + else + InitCodeSize = BitsPerPixel; + + /* + * Set up the current x and y position + */ + ctx.curx = ctx.cury = 0; + + /* + * Write the Magic header + */ + gdPutBuf(Transparent < 0 ? "GIF87a" : "GIF89a", 6, fp ); + + /* + * Write out the screen width and height + */ + gifPutWord( RWidth, fp ); + gifPutWord( RHeight, fp ); + + /* + * Indicate that there is a global colour map + */ + B = 0x80; /* Yes, there is a color map */ + + /* + * OR in the resolution + */ + B |= (Resolution - 1) << 5; + + /* + * OR in the Bits per Pixel + */ + B |= (BitsPerPixel - 1); + + /* + * Write it out + */ + gdPutC( B, fp ); + + /* + * Write out the Background colour + */ + gdPutC( Background, fp ); + + /* + * Byte of 0's (future expansion) + */ + gdPutC( 0, fp ); + + /* + * Write out the Global Colour Map + */ + for( i=0; i= 0 ) { + gdPutC( '!', fp ); + gdPutC( 0xf9, fp ); + gdPutC( 4, fp ); + gdPutC( 1, fp ); + gdPutC( 0, fp ); + gdPutC( 0, fp ); + gdPutC( (unsigned char) Transparent, fp ); + gdPutC( 0, fp ); + } + + /* + * Write an Image separator + */ + gdPutC( ',', fp ); + + /* + * Write the Image header + */ + + gifPutWord( LeftOfs, fp ); + gifPutWord( TopOfs, fp ); + gifPutWord( ctx.Width, fp ); + gifPutWord( ctx.Height, fp ); + + /* + * Write out whether or not the image is interlaced + */ + if( ctx.Interlace ) + gdPutC( 0x40, fp ); + else + gdPutC( 0x00, fp ); + + /* + * Write out the initial code size + */ + gdPutC( InitCodeSize, fp ); + + /* + * Go and actually compress the data + */ + compress( InitCodeSize+1, fp, im, &ctx ); + + /* + * Write out a Zero-length packet (to end the series) + */ + gdPutC( 0, fp ); + + /* + * Write the GIF file terminator + */ + gdPutC( ';', fp ); +} + +/*************************************************************************** + * + * GIFCOMPR.C - GIF Image compression routines + * + * Lempel-Ziv compression based on 'compress'. GIF modifications by + * David Rowley (mgardi@watdcsu.waterloo.edu) + * + ***************************************************************************/ + +/* + * General DEFINEs + */ + +#define GIFBITS 12 + +#ifdef NO_UCHAR + typedef char char_type; +#else /*NO_UCHAR*/ + typedef unsigned char char_type; +#endif /*NO_UCHAR*/ + +/* + * + * GIF Image compression - modified 'compress' + * + * Based on: compress.c - File compression ala IEEE Computer, June 1984. + * + * By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) + * Jim McKie (decvax!mcvax!jim) + * Steve Davies (decvax!vax135!petsd!peora!srd) + * Ken Turkowski (decvax!decwrl!turtlevax!ken) + * James A. Woods (decvax!ihnp4!ames!jaw) + * Joe Orost (decvax!vax135!petsd!joe) + * + */ +#include + +#define ARGVAL() (*++(*argv) || (--argc && *++argv)) + +#ifdef COMPATIBLE /* But wrong! */ +# define MAXCODE(n_bits) ((code_int) 1 << (n_bits) - 1) +#else /*COMPATIBLE*/ +# define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1) +#endif /*COMPATIBLE*/ + +#define HashTabOf(i) ctx->htab[i] +#define CodeTabOf(i) ctx->codetab[i] + + +/* + * To save much memory, we overlay the table used by compress() with those + * used by decompress(). The tab_prefix table is the same size and type + * as the codetab. The tab_suffix table needs 2**GIFBITS characters. We + * get this from the beginning of htab. The output stack uses the rest + * of htab, and contains characters. There is plenty of room for any + * possible stack (stack used to be 8000 characters). + */ + +#define tab_prefixof(i) CodeTabOf(i) +#define tab_suffixof(i) ((char_type*)(htab))[i] +#define de_stack ((char_type*)&tab_suffixof((code_int)1<g_init_bits = init_bits; + ctx->g_outfile = outfile; + + /* + * Set up the necessary values + */ + ctx->offset = 0; + ctx->out_count = 0; + ctx->clear_flg = 0; + ctx->in_count = 1; + ctx->maxcode = MAXCODE(ctx->n_bits = ctx->g_init_bits); + + ctx->ClearCode = (1 << (init_bits - 1)); + ctx->EOFCode = ctx->ClearCode + 1; + ctx->free_ent = ctx->ClearCode + 2; + + char_init(ctx); + + ent = GIFNextPixel( im, ctx ); + + hshift = 0; + for ( fcode = (long) hsize; fcode < 65536L; fcode *= 2L ) + ++hshift; + hshift = 8 - hshift; /* set hash code range bound */ + + hsize_reg = hsize; + cl_hash( (count_int) hsize_reg, ctx ); /* clear hash table */ + + output( (code_int)ctx->ClearCode, ctx ); + +#ifdef SIGNED_COMPARE_SLOW + while ( (c = GIFNextPixel( im )) != (unsigned) EOF ) { +#else /*SIGNED_COMPARE_SLOW*/ + while ( (c = GIFNextPixel( im, ctx )) != EOF ) { /* } */ +#endif /*SIGNED_COMPARE_SLOW*/ + + ++(ctx->in_count); + + fcode = (long) (((long) c << maxbits) + ent); + i = (((code_int)c << hshift) ^ ent); /* xor hashing */ + + if ( HashTabOf (i) == fcode ) { + ent = CodeTabOf (i); + continue; + } else if ( (long)HashTabOf (i) < 0 ) /* empty slot */ + goto nomatch; + disp = hsize_reg - i; /* secondary hash (after G. Knott) */ + if ( i == 0 ) + disp = 1; +probe: + if ( (i -= disp) < 0 ) + i += hsize_reg; + + if ( HashTabOf (i) == fcode ) { + ent = CodeTabOf (i); + continue; + } + if ( (long)HashTabOf (i) > 0 ) + goto probe; +nomatch: + output ( (code_int) ent, ctx ); + ++(ctx->out_count); + ent = c; +#ifdef SIGNED_COMPARE_SLOW + if ( (unsigned) ctx->free_ent < (unsigned) maxmaxcode) { +#else /*SIGNED_COMPARE_SLOW*/ + if ( ctx->free_ent < maxmaxcode ) { /* } */ +#endif /*SIGNED_COMPARE_SLOW*/ + CodeTabOf (i) = ctx->free_ent++; /* code -> hashtable */ + HashTabOf (i) = fcode; + } else + cl_block(ctx); + } + /* + * Put out the final code. + */ + output( (code_int)ent, ctx ); + ++(ctx->out_count); + output( (code_int) ctx->EOFCode, ctx ); +} + +/***************************************************************** + * TAG( output ) + * + * Output the given code. + * Inputs: + * code: A n_bits-bit integer. If == -1, then EOF. This assumes + * that n_bits =< (long)wordsize - 1. + * Outputs: + * Outputs code to the file. + * Assumptions: + * Chars are 8 bits long. + * Algorithm: + * Maintain a GIFBITS character long buffer (so that 8 codes will + * fit in it exactly). Use the VAX insv instruction to insert each + * code in turn. When the buffer fills up empty it and start over. + */ + +static unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, + 0x001F, 0x003F, 0x007F, 0x00FF, + 0x01FF, 0x03FF, 0x07FF, 0x0FFF, + 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; + +static void +output(code_int code, GifCtx *ctx) +{ + ctx->cur_accum &= masks[ ctx->cur_bits ]; + + if( ctx->cur_bits > 0 ) + ctx->cur_accum |= ((long)code << ctx->cur_bits); + else + ctx->cur_accum = code; + + ctx->cur_bits += ctx->n_bits; + + while( ctx->cur_bits >= 8 ) { + char_out( (unsigned int)(ctx->cur_accum & 0xff), ctx ); + ctx->cur_accum >>= 8; + ctx->cur_bits -= 8; + } + + /* + * If the next entry is going to be too big for the code size, + * then increase it, if possible. + */ + if ( ctx->free_ent > ctx->maxcode || ctx->clear_flg ) { + + if( ctx->clear_flg ) { + + ctx->maxcode = MAXCODE (ctx->n_bits = ctx->g_init_bits); + ctx->clear_flg = 0; + + } else { + + ++(ctx->n_bits); + if ( ctx->n_bits == maxbits ) + ctx->maxcode = maxmaxcode; + else + ctx->maxcode = MAXCODE(ctx->n_bits); + } + } + + if( code == ctx->EOFCode ) { + /* + * At EOF, write the rest of the buffer. + */ + while( ctx->cur_bits > 0 ) { + char_out( (unsigned int)(ctx->cur_accum & 0xff), ctx); + ctx->cur_accum >>= 8; + ctx->cur_bits -= 8; + } + + flush_char(ctx); + + } +} + +/* + * Clear out the hash table + */ +static void +cl_block (GifCtx *ctx) /* table clear for block compress */ +{ + + cl_hash ( (count_int) hsize, ctx ); + ctx->free_ent = ctx->ClearCode + 2; + ctx->clear_flg = 1; + + output( (code_int)ctx->ClearCode, ctx); +} + +static void +cl_hash(register count_int chsize, GifCtx *ctx) /* reset code table */ + +{ + + register count_int *htab_p = ctx->htab+chsize; + + register long i; + register long m1 = -1; + + i = chsize - 16; + do { /* might use Sys V memset(3) here */ + *(htab_p-16) = m1; + *(htab_p-15) = m1; + *(htab_p-14) = m1; + *(htab_p-13) = m1; + *(htab_p-12) = m1; + *(htab_p-11) = m1; + *(htab_p-10) = m1; + *(htab_p-9) = m1; + *(htab_p-8) = m1; + *(htab_p-7) = m1; + *(htab_p-6) = m1; + *(htab_p-5) = m1; + *(htab_p-4) = m1; + *(htab_p-3) = m1; + *(htab_p-2) = m1; + *(htab_p-1) = m1; + htab_p -= 16; + } while ((i -= 16) >= 0); + + for ( i += 16; i > 0; --i ) + *--htab_p = m1; +} + +/****************************************************************************** + * + * GIF Specific routines + * + ******************************************************************************/ + +/* + * Set up the 'byte output' routine + */ +static void +char_init(GifCtx *ctx) +{ + ctx->a_count = 0; +} + +/* + * Add a character to the end of the current packet, and if it is 254 + * characters, flush the packet to disk. + */ +static void +char_out(int c, GifCtx *ctx) +{ + ctx->accum[ ctx->a_count++ ] = c; + if( ctx->a_count >= 254 ) + flush_char(ctx); +} + +/* + * Flush the packet to disk, and reset the accumulator + */ +static void +flush_char(GifCtx *ctx) +{ + if( ctx->a_count > 0 ) { + gdPutC( ctx->a_count, ctx->g_outfile ); + gdPutBuf( ctx->accum, ctx->a_count, ctx->g_outfile ); + ctx->a_count = 0; + } +} + +static int gifPutWord(int w, gdIOCtx *out) +{ + /* Byte order is little-endian */ + gdPutC(w & 0xFF, out); + gdPutC((w >> 8) & 0xFF, out); + return 0; +} + + diff --git a/ext/gd/libgd/gd_topal.c b/ext/gd/libgd/gd_topal.c index 60dbb6de6561..15eed3e11ee7 100644 --- a/ext/gd/libgd/gd_topal.c +++ b/ext/gd/libgd/gd_topal.c @@ -1,11 +1,13 @@ +/* TODO: oim and nim in the lower level functions; + correct use of stub (sigh). */ + /* 2.0.12: a new adaptation from the same original, this time - * by Barend Gahrels. My attempt to incorporate alpha channel - * into the result worked poorly and degraded the quality of - * palette conversion even when the source contained no - * alpha channel data. This version does not attempt to produce - * an output file with transparency in some of the palette - * indexes, which, in practice, doesn't look so hot anyway. TBB - */ + by Barend Gehrels. My attempt to incorporate alpha channel + into the result worked poorly and degraded the quality of + palette conversion even when the source contained no + alpha channel data. This version does not attempt to produce + an output file with transparency in some of the palette + indexes, which, in practice, doesn't look so hot anyway. TBB */ /* * gd_topal, adapted from jquant2.c @@ -41,16 +43,15 @@ * If it is not working, it's not Thomas G. Lane's fault. */ -/* - * SETTING THIS ONE CAUSES STRIPED IMAGE - * to be done: solve this - * #define ORIGINAL_LIB_JPEG_REVERSE_ODD_ROWS +/* + SETTING THIS ONE CAUSES STRIPED IMAGE + to be done: solve this + #define ORIGINAL_LIB_JPEG_REVERSE_ODD_ROWS */ +#include #include "gd.h" #include "gdhelpers.h" -#include -#include /* (Re)define some defines known by libjpeg */ #define QUANT_2PASS_SUPPORTED @@ -111,6 +112,8 @@ #define FAR #endif + + #ifndef boolean #define boolean int #endif @@ -123,8 +126,9 @@ #define FALSE 0 #endif -#define input_buf (im->tpixels) -#define output_buf (im->pixels) + +#define input_buf (oim->tpixels) +#define output_buf (nim->pixels) #endif @@ -148,7 +152,7 @@ * color space, and repeatedly splits the "largest" remaining box until we * have as many boxes as desired colors. Then the mean color in each * remaining box becomes one of the possible output colors. - * + * * The second pass over the image maps each input pixel to the closest output * color (optionally after applying a Floyd-Steinberg dithering correction). * This mapping is logically trivial, but making it go fast enough requires @@ -294,32 +298,34 @@ typedef INT32 LOCFSERROR; /* be sure calculation temps are big enough */ typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */ + /* Private subobject */ typedef struct { #ifdef ORIGINAL_LIB_JPEG - struct jpeg_color_quantizer pub; /* public fields */ + struct jpeg_color_quantizer pub; /* public fields */ - /* Space for the eventually created colormap is stashed here */ - JSAMPARRAY sv_colormap; /* colormap allocated at init time */ - int desired; /* desired # of colors = size of colormap */ - boolean needs_zeroed; /* TRUE if next pass must zero histogram */ + /* Space for the eventually created colormap is stashed here */ + JSAMPARRAY sv_colormap; /* colormap allocated at init time */ + int desired; /* desired # of colors = size of colormap */ + boolean needs_zeroed; /* TRUE if next pass must zero histogram */ #endif - /* Variables for accumulating image statistics */ - hist3d histogram; /* pointer to the histogram */ + /* Variables for accumulating image statistics */ + hist3d histogram; /* pointer to the histogram */ - /* Variables for Floyd-Steinberg dithering */ - FSERRPTR fserrors; /* accumulated errors */ + /* Variables for Floyd-Steinberg dithering */ + FSERRPTR fserrors; /* accumulated errors */ - boolean on_odd_row; /* flag to remember which row we are on */ - int *error_limiter; /* table for clamping the applied error */ + boolean on_odd_row; /* flag to remember which row we are on */ + int *error_limiter; /* table for clamping the applied error */ #ifndef ORIGINAL_LIB_JPEG - int *error_limiter_storage; /* gdMalloc'd storage for the above */ + int *error_limiter_storage; /* gdMalloc'd storage for the above */ #endif -} my_cquantizer; +} +my_cquantizer; typedef my_cquantizer *my_cquantize_ptr; @@ -335,57 +341,62 @@ typedef my_cquantizer *my_cquantize_ptr; METHODDEF (void) #ifndef ORIGINAL_LIB_JPEG -prescan_quantize (gdImagePtr im, my_cquantize_ptr cquantize) +prescan_quantize (gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize) { #else -prescan_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) +prescan_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) { - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; #endif - register JSAMPROW ptr; - register histptr histp; - register hist3d histogram = cquantize->histogram; - int row; - JDIMENSION col; + register JSAMPROW ptr; + register histptr histp; + register hist3d histogram = cquantize->histogram; + int row; + JDIMENSION col; #ifdef ORIGINAL_LIB_JPEG - JDIMENSION width = cinfo->output_width; + JDIMENSION width = cinfo->output_width; #else - int width = im->sx; - int num_rows = im->sy; + int width = oim->sx; + int num_rows = oim->sy; #endif - for (row = 0; row < num_rows; row++) { - ptr = input_buf[row]; - for (col = width; col > 0; col--) { + for (row = 0; row < num_rows; row++) + { + ptr = input_buf[row]; + for (col = width; col > 0; col--) + { #ifdef ORIGINAL_LIB_JPEG - int r = GETJSAMPLE(ptr[0]) >> C0_SHIFT; - int g = GETJSAMPLE(ptr[1]) >> C1_SHIFT; - int b = GETJSAMPLE(ptr[2]) >> C2_SHIFT; + int r = GETJSAMPLE (ptr[0]) >> C0_SHIFT; + int g = GETJSAMPLE (ptr[1]) >> C1_SHIFT; + int b = GETJSAMPLE (ptr[2]) >> C2_SHIFT; #else - int r = gdTrueColorGetRed(*ptr) >> C0_SHIFT; - int g = gdTrueColorGetGreen(*ptr) >> C1_SHIFT; - int b = gdTrueColorGetBlue(*ptr) >> C2_SHIFT; - /* 2.0.12: Steven Brown: support a single totally transparent color in the original. */ - if ((im->transparent >= 0) && (*ptr == im->transparent)) { - ptr++; - continue; - } + int r = gdTrueColorGetRed (*ptr) >> C0_SHIFT; + int g = gdTrueColorGetGreen (*ptr) >> C1_SHIFT; + int b = gdTrueColorGetBlue (*ptr) >> C2_SHIFT; + /* 2.0.12: Steven Brown: support a single totally transparent + color in the original. */ + if ((oim->transparent >= 0) && (*ptr == oim->transparent)) + { + ptr++; + continue; + } #endif - /* get pixel value and index into the histogram */ - histp = &histogram[r][g][b]; - /* increment, check for overflow and undo increment if so. */ - if (++(*histp) == 0) { - (*histp)--; - } + /* get pixel value and index into the histogram */ + histp = &histogram[r][g][b]; + /* increment, check for overflow and undo increment if so. */ + if (++(*histp) == 0) + (*histp)--; #ifdef ORIGINAL_LIB_JPEG - ptr += 3; + ptr += 3; #else - ptr++; + ptr++; #endif - } } + } } + /* * Next we have the really interesting routines: selection of a colormap * given the completed histogram. @@ -395,35 +406,38 @@ prescan_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY outpu typedef struct { - /* The bounds of the box (inclusive); expressed as histogram indexes */ - int c0min, c0max; - int c1min, c1max; - int c2min, c2max; - /* The volume (actually 2-norm) of the box */ - INT32 volume; - /* The number of nonzero histogram cells within this box */ - long colorcount; -} box; + /* The bounds of the box (inclusive); expressed as histogram indexes */ + int c0min, c0max; + int c1min, c1max; + int c2min, c2max; + /* The volume (actually 2-norm) of the box */ + INT32 volume; + /* The number of nonzero histogram cells within this box */ + long colorcount; +} +box; typedef box *boxptr; + LOCAL (boxptr) find_biggest_color_pop (boxptr boxlist, int numboxes) /* Find the splittable box with the largest color population */ /* Returns NULL if no splittable boxes remain */ { - register boxptr boxp; - register int i; - register long maxc = 0; - boxptr which = NULL; - - for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { - if (boxp->colorcount > maxc && boxp->volume > 0) { - which = boxp; - maxc = boxp->colorcount; - } + register boxptr boxp; + register int i; + register long maxc = 0; + boxptr which = NULL; + + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) + { + if (boxp->colorcount > maxc && boxp->volume > 0) + { + which = boxp; + maxc = boxp->colorcount; } - - return which; + } + return which; } @@ -431,320 +445,333 @@ LOCAL (boxptr) find_biggest_volume (boxptr boxlist, int numboxes) /* Find the splittable box with the largest (scaled) volume */ /* Returns NULL if no splittable boxes remain */ { - register boxptr boxp; - register int i; - register INT32 maxv = 0; - boxptr which = NULL; - - for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { - if (boxp->volume > maxv) { - which = boxp; - maxv = boxp->volume; - } + register boxptr boxp; + register int i; + register INT32 maxv = 0; + boxptr which = NULL; + + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) + { + if (boxp->volume > maxv) + { + which = boxp; + maxv = boxp->volume; } - - return which; + } + return which; } LOCAL (void) #ifndef ORIGINAL_LIB_JPEG - update_box (gdImagePtr im, my_cquantize_ptr cquantize, boxptr boxp) + update_box (gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize, boxptr boxp) { #else update_box (j_decompress_ptr cinfo, boxptr boxp) /* Shrink the min/max bounds of a box to enclose only nonzero elements, */ /* and recompute its volume and population */ { - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; #endif - hist3d histogram = cquantize->histogram; - histptr histp; - int c0, c1, c2; - int c0min, c0max, c1min, c1max, c2min, c2max; - INT32 dist0, dist1, dist2; - long ccount; - - c0min = boxp->c0min; - c0max = boxp->c0max; - c1min = boxp->c1min; - c1max = boxp->c1max; - c2min = boxp->c2min; - c2max = boxp->c2max; - - if (c0max > c0min) { - for (c0 = c0min; c0 <= c0max; c0++) { - for (c1 = c1min; c1 <= c1max; c1++) { - histp = &histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++) { - if (*histp++ != 0) { - boxp->c0min = c0min = c0; - goto have_c0min; - } - } - } - } + hist3d histogram = cquantize->histogram; + histptr histp; + int c0, c1, c2; + int c0min, c0max, c1min, c1max, c2min, c2max; + INT32 dist0, dist1, dist2; + long ccount; + + c0min = boxp->c0min; + c0max = boxp->c0max; + c1min = boxp->c1min; + c1max = boxp->c1max; + c2min = boxp->c2min; + c2max = boxp->c2max; + + if (c0max > c0min) + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) + { + histp = &histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) + { + boxp->c0min = c0min = c0; + goto have_c0min; + } } have_c0min: - if (c0max > c0min) { - for (c0 = c0max; c0 >= c0min; c0--) { - for (c1 = c1min; c1 <= c1max; c1++) { - histp = &histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++) { - if (*histp++ != 0) { - boxp->c0max = c0max = c0; - goto have_c0max; - } - } - } - } + if (c0max > c0min) + for (c0 = c0max; c0 >= c0min; c0--) + for (c1 = c1min; c1 <= c1max; c1++) + { + histp = &histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) + { + boxp->c0max = c0max = c0; + goto have_c0max; + } } have_c0max: - if (c1max > c1min) { - for (c1 = c1min; c1 <= c1max; c1++) { - for (c0 = c0min; c0 <= c0max; c0++) { - histp = &histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++) { - if (*histp++ != 0) { - boxp->c1min = c1min = c1; - goto have_c1min; - } - } - } - } + if (c1max > c1min) + for (c1 = c1min; c1 <= c1max; c1++) + for (c0 = c0min; c0 <= c0max; c0++) + { + histp = &histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) + { + boxp->c1min = c1min = c1; + goto have_c1min; + } } have_c1min: - if (c1max > c1min) { - for (c1 = c1max; c1 >= c1min; c1--) { - for (c0 = c0min; c0 <= c0max; c0++) { - histp = &histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++) { - if (*histp++ != 0) { - boxp->c1max = c1max = c1; - goto have_c1max; - } - } - } - } + if (c1max > c1min) + for (c1 = c1max; c1 >= c1min; c1--) + for (c0 = c0min; c0 <= c0max; c0++) + { + histp = &histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) + { + boxp->c1max = c1max = c1; + goto have_c1max; + } } have_c1max: - if (c2max > c2min) { - for (c2 = c2min; c2 <= c2max; c2++) { - for (c0 = c0min; c0 <= c0max; c0++) { - histp = &histogram[c0][c1min][c2]; - for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) { - if (*histp != 0) { - boxp->c2min = c2min = c2; - goto have_c2min; - } - } - } - } + if (c2max > c2min) + for (c2 = c2min; c2 <= c2max; c2++) + for (c0 = c0min; c0 <= c0max; c0++) + { + histp = &histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) + { + boxp->c2min = c2min = c2; + goto have_c2min; + } } have_c2min: - if (c2max > c2min) { - for (c2 = c2max; c2 >= c2min; c2--) { - for (c0 = c0min; c0 <= c0max; c0++) { - histp = &histogram[c0][c1min][c2]; - for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) { - if (*histp != 0) { - boxp->c2max = c2max = c2; - goto have_c2max; - } - } - } - } + if (c2max > c2min) + for (c2 = c2max; c2 >= c2min; c2--) + for (c0 = c0min; c0 <= c0max; c0++) + { + histp = &histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) + { + boxp->c2max = c2max = c2; + goto have_c2max; + } } have_c2max: - /* Update box volume. - * We use 2-norm rather than real volume here; this biases the method - * against making long narrow boxes, and it has the side benefit that - * a box is splittable iff norm > 0. - * Since the differences are expressed in histogram-cell units, - * we have to shift back to JSAMPLE units to get consistent distances; - * after which, we scale according to the selected distance scale factors. - */ - dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE; - dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE; - dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE; - boxp->volume = dist0 * dist0 + dist1 * dist1 + dist2 * dist2; - - /* Now scan remaining volume of box and compute population */ - ccount = 0; - for (c0 = c0min; c0 <= c0max; c0++) { - for (c1 = c1min; c1 <= c1max; c1++) { - histp = &histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++, histp++) { - if (*histp != 0) { - ccount++; - } - } - } - } - boxp->colorcount = ccount; + /* Update box volume. + * We use 2-norm rather than real volume here; this biases the method + * against making long narrow boxes, and it has the side benefit that + * a box is splittable iff norm > 0. + * Since the differences are expressed in histogram-cell units, + * we have to shift back to JSAMPLE units to get consistent distances; + * after which, we scale according to the selected distance scale factors. + */ + dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE; + dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE; + dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE; + boxp->volume = dist0 * dist0 + dist1 * dist1 + dist2 * dist2; + + /* Now scan remaining volume of box and compute population */ + ccount = 0; + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) + { + histp = &histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++, histp++) + if (*histp != 0) + { + ccount++; + } + } + boxp->colorcount = ccount; } LOCAL (int) #ifdef ORIGINAL_LIB_JPEG -median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes, int desired_colors) +median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes, + int desired_colors) #else -median_cut (gdImagePtr im, my_cquantize_ptr cquantize, boxptr boxlist, int numboxes, int desired_colors) +median_cut (gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize, + boxptr boxlist, int numboxes, int desired_colors) #endif /* Repeatedly select and split the largest box until we have enough boxes */ { - int n, lb; - int c0, c1, c2, cmax; - register boxptr b1, b2; - - while (numboxes < desired_colors) { - /* Select box to split. - * Current algorithm: by population for first half, then by volume. - */ - if (numboxes * 2 <= desired_colors) { - b1 = find_biggest_color_pop(boxlist, numboxes); - } else { - b1 = find_biggest_volume(boxlist, numboxes); - } - if (b1 == NULL) { /* no splittable boxes left! */ - break; - } - b2 = &boxlist[numboxes]; /* where new box will go */ - /* Copy the color bounds to the new box. */ - b2->c0max = b1->c0max; - b2->c1max = b1->c1max; - b2->c2max = b1->c2max; - b2->c0min = b1->c0min; - b2->c1min = b1->c1min; - b2->c2min = b1->c2min; - /* Choose which axis to split the box on. - * Current algorithm: longest scaled axis. - * See notes in update_box about scaling distances. - */ - c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE; - c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE; - c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE; - /* We want to break any ties in favor of green, then red, blue last. - * This code does the right thing for R,G,B or B,G,R color orders only. - */ + int n, lb; + int c0, c1, c2, cmax; + register boxptr b1, b2; + + while (numboxes < desired_colors) + { + /* Select box to split. + * Current algorithm: by population for first half, then by volume. + */ + if (numboxes * 2 <= desired_colors) + { + b1 = find_biggest_color_pop (boxlist, numboxes); + } + else + { + b1 = find_biggest_volume (boxlist, numboxes); + } + if (b1 == NULL) /* no splittable boxes left! */ + break; + b2 = &boxlist[numboxes]; /* where new box will go */ + /* Copy the color bounds to the new box. */ + b2->c0max = b1->c0max; + b2->c1max = b1->c1max; + b2->c2max = b1->c2max; + b2->c0min = b1->c0min; + b2->c1min = b1->c1min; + b2->c2min = b1->c2min; + /* Choose which axis to split the box on. + * Current algorithm: longest scaled axis. + * See notes in update_box about scaling distances. + */ + c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE; + c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE; + c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE; + /* We want to break any ties in favor of green, then red, blue last. + * This code does the right thing for R,G,B or B,G,R color orders only. + */ #if RGB_RED == 0 - cmax = c1; - n = 1; - if (c0 > cmax) { - cmax = c0; - n = 0; - } - if (c2 > cmax) { - n = 2; - } + cmax = c1; + n = 1; + if (c0 > cmax) + { + cmax = c0; + n = 0; + } + if (c2 > cmax) + { + n = 2; + } #else - cmax = c1; - n = 1; - if (c2 > cmax) { - cmax = c2; - n = 2; - } - if (c0 > cmax) { - n = 0; - } + cmax = c1; + n = 1; + if (c2 > cmax) + { + cmax = c2; + n = 2; + } + if (c0 > cmax) + { + n = 0; + } #endif - /* Choose split point along selected axis, and update box bounds. - * Current algorithm: split at halfway point. - * (Since the box has been shrunk to minimum volume, - * any split will produce two nonempty subboxes.) - * Note that lb value is max for lower box, so must be < old max. - */ - switch (n) { - case 0: - lb = (b1->c0max + b1->c0min) / 2; - b1->c0max = lb; - b2->c0min = lb + 1; - break; - case 1: - lb = (b1->c1max + b1->c1min) / 2; - b1->c1max = lb; - b2->c1min = lb + 1; - break; - case 2: - lb = (b1->c2max + b1->c2min) / 2; - b1->c2max = lb; - b2->c2min = lb + 1; - break; - } - /* Update stats for boxes */ + /* Choose split point along selected axis, and update box bounds. + * Current algorithm: split at halfway point. + * (Since the box has been shrunk to minimum volume, + * any split will produce two nonempty subboxes.) + * Note that lb value is max for lower box, so must be < old max. + */ + switch (n) + { + case 0: + lb = (b1->c0max + b1->c0min) / 2; + b1->c0max = lb; + b2->c0min = lb + 1; + break; + case 1: + lb = (b1->c1max + b1->c1min) / 2; + b1->c1max = lb; + b2->c1min = lb + 1; + break; + case 2: + lb = (b1->c2max + b1->c2min) / 2; + b1->c2max = lb; + b2->c2min = lb + 1; + break; + } + /* Update stats for boxes */ #ifdef ORIGINAL_LIB_JPEG - update_box(cinfo, b1); - update_box(cinfo, b2); + update_box (cinfo, b1); + update_box (cinfo, b2); #else - update_box(im, cquantize, b1); - update_box(im, cquantize, b2); + update_box (oim, nim, cquantize, b1); + update_box (oim, nim, cquantize, b2); #endif - numboxes++; - } - - return numboxes; + numboxes++; + } + return numboxes; } LOCAL (void) #ifndef ORIGINAL_LIB_JPEG - compute_color (gdImagePtr im, my_cquantize_ptr cquantize, boxptr boxp, int icolor) + compute_color (gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize, + boxptr boxp, int icolor) { #else - compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor) + compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor) /* Compute representative color for a box, put it in colormap[icolor] */ { - /* Current algorithm: mean weighted by pixels (not colors) */ - /* Note it is important to get the rounding correct! */ - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + /* Current algorithm: mean weighted by pixels (not colors) */ + /* Note it is important to get the rounding correct! */ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; #endif - hist3d histogram = cquantize->histogram; - histptr histp; - int c0, c1, c2; - int c0min, c0max, c1min, c1max, c2min, c2max; - long count = 0; - long total = 0; - long c0total = 0; - long c1total = 0; - long c2total = 0; - - c0min = boxp->c0min; - c0max = boxp->c0max; - c1min = boxp->c1min; - c1max = boxp->c1max; - c2min = boxp->c2min; - c2max = boxp->c2max; - - for (c0 = c0min; c0 <= c0max; c0++) { - for (c1 = c1min; c1 <= c1max; c1++) { - histp = &histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++) { - if ((count = *histp++) != 0) { - total += count; - c0total += ((c0 << C0_SHIFT) + ((1 << C0_SHIFT) >> 1)) * count; - c1total += ((c1 << C1_SHIFT) + ((1 << C1_SHIFT) >> 1)) * count; - c2total += ((c2 << C2_SHIFT) + ((1 << C2_SHIFT) >> 1)) * count; - } - } - } - } + hist3d histogram = cquantize->histogram; + histptr histp; + int c0, c1, c2; + int c0min, c0max, c1min, c1max, c2min, c2max; + long count = 0; /* 2.0.28: = 0 */ + long total = 0; + long c0total = 0; + long c1total = 0; + long c2total = 0; + + c0min = boxp->c0min; + c0max = boxp->c0max; + c1min = boxp->c1min; + c1max = boxp->c1max; + c2min = boxp->c2min; + c2max = boxp->c2max; + + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) + { + histp = &histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + { + if ((count = *histp++) != 0) + { + total += count; + c0total += + ((c0 << C0_SHIFT) + ((1 << C0_SHIFT) >> 1)) * count; + c1total += + ((c1 << C1_SHIFT) + ((1 << C1_SHIFT) >> 1)) * count; + c2total += + ((c2 << C2_SHIFT) + ((1 << C2_SHIFT) >> 1)) * count; + } + } + } #ifdef ORIGINAL_LIB_JPEG - cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total >> 1)) / total); - cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total >> 1)) / total); - cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total >> 1)) / total); + cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total >> 1)) / total); + cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total >> 1)) / total); + cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total >> 1)) / total); #else - /* 2.0.16: Paul den Dulk found an occasion where total can be 0 */ - if (count) { - im->red[icolor] = (int) ((c0total + (total >> 1)) / total); - im->green[icolor] = (int) ((c1total + (total >> 1)) / total); - im->blue[icolor] = (int) ((c2total + (total >> 1)) / total); - } else { - im->red[icolor] = 255; - im->green[icolor] = 255; - im->blue[icolor] = 255; - } + /* 2.0.16: Paul den Dulk found an occasion where total can be 0 */ + if (count) + { + nim->red[icolor] = (int) ((c0total + (total >> 1)) / total); + nim->green[icolor] = (int) ((c1total + (total >> 1)) / total); + nim->blue[icolor] = (int) ((c2total + (total >> 1)) / total); + } + else + { + nim->red[icolor] = 255; + nim->green[icolor] = 255; + nim->blue[icolor] = 255; + } #endif } @@ -753,65 +780,64 @@ LOCAL (void) #ifdef ORIGINAL_LIB_JPEG select_colors (j_decompress_ptr cinfo, int desired_colors) #else -select_colors (gdImagePtr im, my_cquantize_ptr cquantize, int desired_colors) +select_colors (gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize, int desired_colors) #endif /* Master routine for color selection */ { - boxptr boxlist; - int numboxes; - int i; + boxptr boxlist; + int numboxes; + int i; - /* Allocate workspace for box list */ + /* Allocate workspace for box list */ #ifdef ORIGINAL_LIB_JPEG - boxlist = (boxptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * SIZEOF (box)); + boxlist = (boxptr) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * SIZEOF (box)); #else - boxlist = (boxptr) safe_emalloc(desired_colors, sizeof(box), 1); + boxlist = (boxptr) safe_emalloc(desired_colors, sizeof (box), 1); #endif - /* Initialize one box containing whole space */ - numboxes = 1; - boxlist[0].c0min = 0; - boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT; - boxlist[0].c1min = 0; - boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT; - boxlist[0].c2min = 0; - boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT; + /* Initialize one box containing whole space */ + numboxes = 1; + boxlist[0].c0min = 0; + boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT; + boxlist[0].c1min = 0; + boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT; + boxlist[0].c2min = 0; + boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT; #ifdef ORIGINAL_LIB_JPEG - /* Shrink it to actually-used volume and set its statistics */ - update_box(cinfo, &boxlist[0]); - /* Perform median-cut to produce final box list */ - numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors); - /* Compute the representative color for each box, fill colormap */ - for (i = 0; i < numboxes; i++) { - compute_color(cinfo, &boxlist[i], i); - } - cinfo->actual_number_of_colors = numboxes; - TRACEMS1(cinfo, 1, JTRC_QUANT_SELECTED, numboxes); + /* Shrink it to actually-used volume and set its statistics */ + update_box (cinfo, &boxlist[0]); + /* Perform median-cut to produce final box list */ + numboxes = median_cut (cinfo, boxlist, numboxes, desired_colors); + /* Compute the representative color for each box, fill colormap */ + for (i = 0; i < numboxes; i++) + compute_color (cinfo, &boxlist[i], i); + cinfo->actual_number_of_colors = numboxes; + TRACEMS1 (cinfo, 1, JTRC_QUANT_SELECTED, numboxes); #else - /* Shrink it to actually-used volume and set its statistics */ - update_box(im, cquantize, &boxlist[0]); - /* Perform median-cut to produce final box list */ - numboxes = median_cut(im, cquantize, boxlist, numboxes, desired_colors); - /* Compute the representative color for each box, fill colormap */ - for (i = 0; i < numboxes; i++) { - compute_color(im, cquantize, &boxlist[i], i); - } - im->colorsTotal = numboxes; - - /* If we had a pure transparency color, add it as the last palette entry. - * Skip incrementing the color count so that the dither / matching phase - * won't use it on pixels that shouldn't have been transparent. We'll - * increment it after all that finishes. - */ - if (im->transparent >= 0) { - /* Save the transparent color. */ - im->red[im->colorsTotal] = gdTrueColorGetRed(im->transparent); - im->green[im->colorsTotal] = gdTrueColorGetGreen(im->transparent); - im->blue[im->colorsTotal] = gdTrueColorGetBlue(im->transparent); - im->alpha[im->colorsTotal] = gdAlphaTransparent; - im->open[im->colorsTotal] = 0; - } - - gdFree(boxlist); + /* Shrink it to actually-used volume and set its statistics */ + update_box (oim, nim, cquantize, &boxlist[0]); + /* Perform median-cut to produce final box list */ + numboxes = median_cut (oim, nim, cquantize, boxlist, numboxes, desired_colors); + /* Compute the representative color for each box, fill colormap */ + for (i = 0; i < numboxes; i++) + compute_color (oim, nim, cquantize, &boxlist[i], i); + nim->colorsTotal = numboxes; + + /* If we had a pure transparency color, add it as the last palette entry. + * Skip incrementing the color count so that the dither / matching phase + * won't use it on pixels that shouldn't have been transparent. We'll + * increment it after all that finishes. */ + if (oim->transparent >= 0) + { + /* Save the transparent color. */ + nim->red[nim->colorsTotal] = gdTrueColorGetRed (oim->transparent); + nim->green[nim->colorsTotal] = gdTrueColorGetGreen (oim->transparent); + nim->blue[nim->colorsTotal] = gdTrueColorGetBlue (oim->transparent); + nim->alpha[nim->colorsTotal] = gdAlphaTransparent; + nim->open[nim->colorsTotal] = 0; + } + + gdFree (boxlist); #endif } @@ -895,11 +921,11 @@ select_colors (gdImagePtr im, my_cquantize_ptr cquantize, int desired_colors) LOCAL (int) find_nearby_colors ( #ifdef ORIGINAL_LIB_JPEG - j_decompress_ptr cinfo, + j_decompress_ptr cinfo, #else - gdImagePtr im, my_cquantize_ptr cquantize, + gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize, #endif - int minc0, int minc1, int minc2, JSAMPLE colorlist[]) + int minc0, int minc1, int minc2, JSAMPLE colorlist[]) /* Locate the colormap entries close enough to an update box to be candidates * for the nearest entry to some cell(s) in the update box. The update box * is specified by the center coordinates of its first cell. The number of @@ -910,148 +936,173 @@ find_nearby_colors ( */ { #ifdef ORIGINAL_LIB_JPEG - int numcolors = cinfo->actual_number_of_colors; + int numcolors = cinfo->actual_number_of_colors; #else - int numcolors = im->colorsTotal; + int numcolors = nim->colorsTotal; #endif - int maxc0, maxc1, maxc2; - int centerc0, centerc1, centerc2; - int i, x, ncolors; - INT32 minmaxdist, min_dist, max_dist, tdist; - INT32 mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */ - - /* Compute true coordinates of update box's upper corner and center. - * Actually we compute the coordinates of the center of the upper-corner - * histogram cell, which are the upper bounds of the volume we care about. - * Note that since ">>" rounds down, the "center" values may be closer to - * min than to max; hence comparisons to them must be "<=", not "<". - */ - maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT)); - centerc0 = (minc0 + maxc0) >> 1; - maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT)); - centerc1 = (minc1 + maxc1) >> 1; - maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT)); - centerc2 = (minc2 + maxc2) >> 1; - - /* For each color in colormap, find: - * 1. its minimum squared-distance to any point in the update box - * (zero if color is within update box); - * 2. its maximum squared-distance to any point in the update box. - * Both of these can be found by considering only the corners of the box. - * We save the minimum distance for each color in mindist[]; - * only the smallest maximum distance is of interest. - */ - minmaxdist = 0x7FFFFFFFL; - - for (i = 0; i < numcolors; i++) { - /* We compute the squared-c0-distance term, then add in the other two. */ + int maxc0, maxc1, maxc2; + int centerc0, centerc1, centerc2; + int i, x, ncolors; + INT32 minmaxdist, min_dist, max_dist, tdist; + INT32 mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */ + + /* Compute true coordinates of update box's upper corner and center. + * Actually we compute the coordinates of the center of the upper-corner + * histogram cell, which are the upper bounds of the volume we care about. + * Note that since ">>" rounds down, the "center" values may be closer to + * min than to max; hence comparisons to them must be "<=", not "<". + */ + maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT)); + centerc0 = (minc0 + maxc0) >> 1; + maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT)); + centerc1 = (minc1 + maxc1) >> 1; + maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT)); + centerc2 = (minc2 + maxc2) >> 1; + + /* For each color in colormap, find: + * 1. its minimum squared-distance to any point in the update box + * (zero if color is within update box); + * 2. its maximum squared-distance to any point in the update box. + * Both of these can be found by considering only the corners of the box. + * We save the minimum distance for each color in mindist[]; + * only the smallest maximum distance is of interest. + */ + minmaxdist = 0x7FFFFFFFL; + + for (i = 0; i < numcolors; i++) + { + /* We compute the squared-c0-distance term, then add in the other two. */ #ifdef ORIGINAL_LIB_JPEG - x = GETJSAMPLE(cinfo->colormap[0][i]); + x = GETJSAMPLE (cinfo->colormap[0][i]); #else - x = im->red[i]; + x = nim->red[i]; #endif - if (x < minc0) { - tdist = (x - minc0) * C0_SCALE; - min_dist = tdist * tdist; - tdist = (x - maxc0) * C0_SCALE; - max_dist = tdist * tdist; - } else if (x > maxc0) { - tdist = (x - maxc0) * C0_SCALE; - min_dist = tdist * tdist; - tdist = (x - minc0) * C0_SCALE; - max_dist = tdist * tdist; - } else { - /* within cell range so no contribution to min_dist */ - min_dist = 0; - if (x <= centerc0) { - tdist = (x - maxc0) * C0_SCALE; - max_dist = tdist * tdist; - } else { - tdist = (x - minc0) * C0_SCALE; - max_dist = tdist * tdist; - } - } + if (x < minc0) + { + tdist = (x - minc0) * C0_SCALE; + min_dist = tdist * tdist; + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist * tdist; + } + else if (x > maxc0) + { + tdist = (x - maxc0) * C0_SCALE; + min_dist = tdist * tdist; + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist * tdist; + } + else + { + /* within cell range so no contribution to min_dist */ + min_dist = 0; + if (x <= centerc0) + { + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist * tdist; + } + else + { + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist * tdist; + } + } #ifdef ORIGINAL_LIB_JPEG - x = GETJSAMPLE(cinfo->colormap[1][i]); + x = GETJSAMPLE (cinfo->colormap[1][i]); #else - x = im->green[i]; + x = nim->green[i]; #endif - if (x < minc1) { - tdist = (x - minc1) * C1_SCALE; - min_dist += tdist * tdist; - tdist = (x - maxc1) * C1_SCALE; - max_dist += tdist * tdist; - } else if (x > maxc1) { - tdist = (x - maxc1) * C1_SCALE; - min_dist += tdist * tdist; - tdist = (x - minc1) * C1_SCALE; - max_dist += tdist * tdist; - } else { - /* within cell range so no contribution to min_dist */ - if (x <= centerc1) { - tdist = (x - maxc1) * C1_SCALE; - max_dist += tdist * tdist; - } else { - tdist = (x - minc1) * C1_SCALE; - max_dist += tdist * tdist; - } - } + if (x < minc1) + { + tdist = (x - minc1) * C1_SCALE; + min_dist += tdist * tdist; + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist * tdist; + } + else if (x > maxc1) + { + tdist = (x - maxc1) * C1_SCALE; + min_dist += tdist * tdist; + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist * tdist; + } + else + { + /* within cell range so no contribution to min_dist */ + if (x <= centerc1) + { + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist * tdist; + } + else + { + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist * tdist; + } + } #ifdef ORIGINAL_LIB_JPEG - x = GETJSAMPLE (cinfo->colormap[2][i]); + x = GETJSAMPLE (cinfo->colormap[2][i]); #else - x = im->blue[i]; + x = nim->blue[i]; #endif - if (x < minc2) { - tdist = (x - minc2) * C2_SCALE; - min_dist += tdist * tdist; - tdist = (x - maxc2) * C2_SCALE; - max_dist += tdist * tdist; - } else if (x > maxc2) { - tdist = (x - maxc2) * C2_SCALE; - min_dist += tdist * tdist; - tdist = (x - minc2) * C2_SCALE; - max_dist += tdist * tdist; - } else { - /* within cell range so no contribution to min_dist */ - if (x <= centerc2) { - tdist = (x - maxc2) * C2_SCALE; - max_dist += tdist * tdist; - } else { - tdist = (x - minc2) * C2_SCALE; - max_dist += tdist * tdist; - } - } - - mindist[i] = min_dist; /* save away the results */ - if (max_dist < minmaxdist) - minmaxdist = max_dist; + if (x < minc2) + { + tdist = (x - minc2) * C2_SCALE; + min_dist += tdist * tdist; + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist * tdist; } - - /* Now we know that no cell in the update box is more than minmaxdist - * away from some colormap entry. Therefore, only colors that are - * within minmaxdist of some part of the box need be considered. - */ - ncolors = 0; - for (i = 0; i < numcolors; i++) { - if (mindist[i] <= minmaxdist) { - colorlist[ncolors++] = (JSAMPLE) i; - } + else if (x > maxc2) + { + tdist = (x - maxc2) * C2_SCALE; + min_dist += tdist * tdist; + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist * tdist; + } + else + { + /* within cell range so no contribution to min_dist */ + if (x <= centerc2) + { + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist * tdist; + } + else + { + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist * tdist; + } } - return ncolors; + + mindist[i] = min_dist; /* save away the results */ + if (max_dist < minmaxdist) + minmaxdist = max_dist; + } + + /* Now we know that no cell in the update box is more than minmaxdist + * away from some colormap entry. Therefore, only colors that are + * within minmaxdist of some part of the box need be considered. + */ + ncolors = 0; + for (i = 0; i < numcolors; i++) + { + if (mindist[i] <= minmaxdist) + colorlist[ncolors++] = (JSAMPLE) i; + } + return ncolors; } LOCAL (void) find_best_colors ( #ifdef ORIGINAL_LIB_JPEG - j_decompress_ptr cinfo, + j_decompress_ptr cinfo, #else - gdImagePtr im, my_cquantize_ptr cquantize, + gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize, #endif - int minc0, int minc1, int minc2, - int numcolors, JSAMPLE colorlist[], - JSAMPLE bestcolor[]) + int minc0, int minc1, int minc2, + int numcolors, JSAMPLE colorlist[], + JSAMPLE bestcolor[]) /* Find the closest colormap entry for each cell in the update box, * given the list of candidate colors prepared by find_nearby_colors. * Return the indexes of the closest entries in the bestcolor[] array. @@ -1059,158 +1110,169 @@ LOCAL (void) find_best_colors ( * find the distance from a colormap entry to successive cells in the box. */ { - int ic0, ic1, ic2; - int i, icolor; - register INT32 *bptr; /* pointer into bestdist[] array */ - JSAMPLE *cptr; /* pointer into bestcolor[] array */ - INT32 dist0, dist1; /* initial distance values */ - register INT32 dist2; /* current distance in inner loop */ - INT32 xx0, xx1; /* distance increments */ - register INT32 xx2; - INT32 inc0, inc1, inc2; /* initial values for increments */ - /* This array holds the distance to the nearest-so-far color for each cell */ - INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; - - /* Initialize best-distance for each cell of the update box */ - bptr = bestdist; - for (i = BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS - 1; i >= 0; i--) { - *bptr++ = 0x7FFFFFFFL; - } - - /* For each color selected by find_nearby_colors, - * compute its distance to the center of each cell in the box. - * If that's less than best-so-far, update best distance and color number. - */ - - /* Nominal steps between cell centers ("x" in Thomas article) */ -#define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE) -#define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE) -#define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE) - - for (i = 0; i < numcolors; i++) { - int r, g, b; + int ic0, ic1, ic2; + int i, icolor; + register INT32 *bptr; /* pointer into bestdist[] array */ + JSAMPLE *cptr; /* pointer into bestcolor[] array */ + INT32 dist0, dist1; /* initial distance values */ + register INT32 dist2; /* current distance in inner loop */ + INT32 xx0, xx1; /* distance increments */ + register INT32 xx2; + INT32 inc0, inc1, inc2; /* initial values for increments */ + /* This array holds the distance to the nearest-so-far color for each cell */ + INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; + + /* Initialize best-distance for each cell of the update box */ + bptr = bestdist; + for (i = BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS - 1; i >= 0; i--) + *bptr++ = 0x7FFFFFFFL; + + /* For each color selected by find_nearby_colors, + * compute its distance to the center of each cell in the box. + * If that's less than best-so-far, update best distance and color number. + */ + + /* Nominal steps between cell centers ("x" in Thomas article) */ +#define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE) +#define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE) +#define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE) + + for (i = 0; i < numcolors; i++) + { + int r, g, b; #ifdef ORIGINAL_LIB_JPEG - icolor = GETJSAMPLE(colorlist[i]); - r = GETJSAMPLE(cinfo->colormap[0][icolor]); - g = GETJSAMPLE(cinfo->colormap[1][icolor]); - b = GETJSAMPLE(cinfo->colormap[2][icolor]); + + icolor = GETJSAMPLE (colorlist[i]); + r = GETJSAMPLE (cinfo->colormap[0][icolor]); + g = GETJSAMPLE (cinfo->colormap[1][icolor]); + b = GETJSAMPLE (cinfo->colormap[2][icolor]); #else - icolor = colorlist[i]; - r = im->red[icolor]; - g = im->green[icolor]; - b = im->blue[icolor]; + icolor = colorlist[i]; + r = nim->red[icolor]; + g = nim->green[icolor]; + b = nim->blue[icolor]; #endif - /* Compute (square of) distance from minc0/c1/c2 to this color */ - inc0 = (minc0 - r) * C0_SCALE; - dist0 = inc0 * inc0; - inc1 = (minc1 - g) * C1_SCALE; - dist0 += inc1 * inc1; - inc2 = (minc2 - b) * C2_SCALE; - dist0 += inc2 * inc2; - /* Form the initial difference increments */ - inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0; - inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1; - inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2; - /* Now loop over all cells in box, updating distance per Thomas method */ - bptr = bestdist; - cptr = bestcolor; - xx0 = inc0; - for (ic0 = BOX_C0_ELEMS - 1; ic0 >= 0; ic0--) { - dist1 = dist0; - xx1 = inc1; - for (ic1 = BOX_C1_ELEMS - 1; ic1 >= 0; ic1--) { - dist2 = dist1; - xx2 = inc2; - for (ic2 = BOX_C2_ELEMS - 1; ic2 >= 0; ic2--) { - if (dist2 < *bptr) { - *bptr = dist2; - *cptr = (JSAMPLE) icolor; - } - dist2 += xx2; - xx2 += 2 * STEP_C2 * STEP_C2; - bptr++; - cptr++; - } - dist1 += xx1; - xx1 += 2 * STEP_C1 * STEP_C1; - } - dist0 += xx0; - xx0 += 2 * STEP_C0 * STEP_C0; + /* Compute (square of) distance from minc0/c1/c2 to this color */ + inc0 = (minc0 - r) * C0_SCALE; + dist0 = inc0 * inc0; + inc1 = (minc1 - g) * C1_SCALE; + dist0 += inc1 * inc1; + inc2 = (minc2 - b) * C2_SCALE; + dist0 += inc2 * inc2; + /* Form the initial difference increments */ + inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0; + inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1; + inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2; + /* Now loop over all cells in box, updating distance per Thomas method */ + bptr = bestdist; + cptr = bestcolor; + xx0 = inc0; + for (ic0 = BOX_C0_ELEMS - 1; ic0 >= 0; ic0--) + { + dist1 = dist0; + xx1 = inc1; + for (ic1 = BOX_C1_ELEMS - 1; ic1 >= 0; ic1--) + { + dist2 = dist1; + xx2 = inc2; + for (ic2 = BOX_C2_ELEMS - 1; ic2 >= 0; ic2--) + { + if (dist2 < *bptr) + { + *bptr = dist2; + *cptr = (JSAMPLE) icolor; + } + dist2 += xx2; + xx2 += 2 * STEP_C2 * STEP_C2; + bptr++; + cptr++; } + dist1 += xx1; + xx1 += 2 * STEP_C1 * STEP_C1; + } + dist0 += xx0; + xx0 += 2 * STEP_C0 * STEP_C0; } + } } LOCAL (void) fill_inverse_cmap ( #ifdef ORIGINAL_LIB_JPEG - j_decompress_ptr cinfo, + j_decompress_ptr cinfo, #else - gdImagePtr im, my_cquantize_ptr cquantize, + gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize, #endif - int c0, int c1, int c2) + int c0, int c1, int c2) /* Fill the inverse-colormap entries in the update box that contains */ -/* histogram cell c0/c1/c2. (Only that one cell MUST be filled, but */ +/* histogram cell c0/c1/c2. (Only that one cell MUST be filled, but */ /* we can fill as many others as we wish.) */ { #ifdef ORIGINAL_LIB_JPEG - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; #endif - hist3d histogram = cquantize->histogram; - int minc0, minc1, minc2; /* lower left corner of update box */ - int ic0, ic1, ic2; - register JSAMPLE *cptr; /* pointer into bestcolor[] array */ - register histptr cachep; /* pointer into main cache array */ - /* This array lists the candidate colormap indexes. */ - JSAMPLE colorlist[MAXNUMCOLORS]; - int numcolors; /* number of candidate colors */ - /* This array holds the actually closest colormap index for each cell. */ - JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; - - /* Convert cell coordinates to update box ID */ - c0 >>= BOX_C0_LOG; - c1 >>= BOX_C1_LOG; - c2 >>= BOX_C2_LOG; - - /* Compute true coordinates of update box's origin corner. - * Actually we compute the coordinates of the center of the corner - * histogram cell, which are the lower bounds of the volume we care about. - */ - minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1); - minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1); - minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1); - - /* Determine which colormap entries are close enough to be candidates - * for the nearest entry to some cell in the update box. - */ + hist3d histogram = cquantize->histogram; + int minc0, minc1, minc2; /* lower left corner of update box */ + int ic0, ic1, ic2; + register JSAMPLE *cptr; /* pointer into bestcolor[] array */ + register histptr cachep; /* pointer into main cache array */ + /* This array lists the candidate colormap indexes. */ + JSAMPLE colorlist[MAXNUMCOLORS]; + int numcolors; /* number of candidate colors */ + /* This array holds the actually closest colormap index for each cell. */ + JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; + + /* Convert cell coordinates to update box ID */ + c0 >>= BOX_C0_LOG; + c1 >>= BOX_C1_LOG; + c2 >>= BOX_C2_LOG; + + /* Compute true coordinates of update box's origin corner. + * Actually we compute the coordinates of the center of the corner + * histogram cell, which are the lower bounds of the volume we care about. + */ + minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1); + minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1); + minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1); + + /* Determine which colormap entries are close enough to be candidates + * for the nearest entry to some cell in the update box. + */ #ifdef ORIGINAL_LIB_JPEG - numcolors = find_nearby_colors(cinfo, minc0, minc1, minc2, colorlist); + numcolors = find_nearby_colors (cinfo, minc0, minc1, minc2, colorlist); - /* Determine the actually nearest colors. */ - find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist, bestcolor); + /* Determine the actually nearest colors. */ + find_best_colors (cinfo, minc0, minc1, minc2, numcolors, colorlist, + bestcolor); #else - numcolors = find_nearby_colors(im, cquantize, minc0, minc1, minc2, colorlist); - find_best_colors(im, cquantize, minc0, minc1, minc2, numcolors, colorlist, bestcolor); + numcolors = + find_nearby_colors (oim, nim, cquantize, minc0, minc1, minc2, colorlist); + find_best_colors (oim, nim, cquantize, minc0, minc1, minc2, numcolors, + colorlist, bestcolor); #endif - /* Save the best color numbers (plus 1) in the main cache array */ - c0 <<= BOX_C0_LOG; /* convert ID back to base cell indexes */ - c1 <<= BOX_C1_LOG; - c2 <<= BOX_C2_LOG; - cptr = bestcolor; - for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) { - for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) { - cachep = &histogram[c0 + ic0][c1 + ic1][c2]; - for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) { + /* Save the best color numbers (plus 1) in the main cache array */ + c0 <<= BOX_C0_LOG; /* convert ID back to base cell indexes */ + c1 <<= BOX_C1_LOG; + c2 <<= BOX_C2_LOG; + cptr = bestcolor; + for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) + { + for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) + { + cachep = &histogram[c0 + ic0][c1 + ic1][c2]; + for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) + { #ifdef ORIGINAL_LIB_JPEG - *cachep++ = (histcell) (GETJSAMPLE (*cptr++) + 1); + *cachep++ = (histcell) (GETJSAMPLE (*cptr++) + 1); #else - *cachep++ = (histcell) ((*cptr++) + 1); + *cachep++ = (histcell) ((*cptr++) + 1); #endif - } - } + } } + } } @@ -1220,287 +1282,304 @@ fill_inverse_cmap ( METHODDEF (void) #ifndef ORIGINAL_LIB_JPEG -pass2_no_dither (gdImagePtr im, my_cquantize_ptr cquantize) +pass2_no_dither (gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize) { - register int *inptr; - register unsigned char *outptr; - int width = im->sx; - int num_rows = im->sy; + register int *inptr; + register unsigned char *outptr; + int width = oim->sx; + int num_rows = oim->sy; #else -pass2_no_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) +pass2_no_dither (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* This version performs no dithering */ { - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - register JSAMPROW inptr, outptr; - JDIMENSION width = cinfo->output_width; + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register JSAMPROW inptr, outptr; + JDIMENSION width = cinfo->output_width; #endif - hist3d histogram = cquantize->histogram; - register int c0, c1, c2; - int row; - JDIMENSION col; - register histptr cachep; - - - for (row = 0; row < num_rows; row++) { - inptr = input_buf[row]; - outptr = output_buf[row]; - for (col = width; col > 0; col--){ - /* get pixel value and index into the cache */ - int r, g, b; + hist3d histogram = cquantize->histogram; + register int c0, c1, c2; + int row; + JDIMENSION col; + register histptr cachep; + + + for (row = 0; row < num_rows; row++) + { + inptr = input_buf[row]; + outptr = output_buf[row]; + for (col = width; col > 0; col--) + { + /* get pixel value and index into the cache */ + int r, g, b; #ifdef ORIGINAL_LIB_JPEG - r = GETJSAMPLE(*inptr++); - g = GETJSAMPLE(*inptr++); - b = GETJSAMPLE(*inptr++); + r = GETJSAMPLE (*inptr++); + g = GETJSAMPLE (*inptr++); + b = GETJSAMPLE (*inptr++); #else - r = gdTrueColorGetRed(*inptr); - g = gdTrueColorGetGreen(*inptr); - b = gdTrueColorGetBlue(*inptr++); - - /* If the pixel is transparent, we assign it the palette index that - * will later be added at the end of the palette as the transparent - * index. - */ - if ((im->transparent >= 0) && (im->transparent == *(inptr - 1))) { - *outptr++ = im->colorsTotal; - continue; - } + r = gdTrueColorGetRed (*inptr); + g = gdTrueColorGetGreen (*inptr); + /* + 2.0.24: inptr must not be incremented until after + transparency check, if any. Thanks to "Super Pikeman." + */ + b = gdTrueColorGetBlue (*inptr); + + /* If the pixel is transparent, we assign it the palette index that + * will later be added at the end of the palette as the transparent + * index. */ + if ((oim->transparent >= 0) && (oim->transparent == *(inptr - 1))) + { + *outptr++ = nim->colorsTotal; + inptr++; + continue; + } + inptr++; #endif - c0 = r >> C0_SHIFT; - c1 = g >> C1_SHIFT; - c2 = b >> C2_SHIFT; - cachep = &histogram[c0][c1][c2]; - /* If we have not seen this color before, find nearest colormap entry - * and update the cache - */ - if (*cachep == 0) { + c0 = r >> C0_SHIFT; + c1 = g >> C1_SHIFT; + c2 = b >> C2_SHIFT; + cachep = &histogram[c0][c1][c2]; + /* If we have not seen this color before, find nearest colormap entry */ + /* and update the cache */ + if (*cachep == 0) #ifdef ORIGINAL_LIB_JPEG - fill_inverse_cmap(cinfo, c0, c1, c2); + fill_inverse_cmap (cinfo, c0, c1, c2); #else - fill_inverse_cmap(im, cquantize, c0, c1, c2); + fill_inverse_cmap (oim, nim, cquantize, c0, c1, c2); #endif - } - /* Now emit the colormap index for this cell */ + /* Now emit the colormap index for this cell */ #ifdef ORIGINAL_LIB_JPEG - *outptr++ = (JSAMPLE) (*cachep - 1); + *outptr++ = (JSAMPLE) (*cachep - 1); #else - *outptr++ = (*cachep - 1); + *outptr++ = (*cachep - 1); #endif - } } + } } METHODDEF (void) #ifndef ORIGINAL_LIB_JPEG -pass2_fs_dither (gdImagePtr im, my_cquantize_ptr cquantize) +pass2_fs_dither (gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize) { #else -pass2_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) +pass2_fs_dither (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* This version performs Floyd-Steinberg dithering */ { - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - JSAMPROW inptr; /* => current input pixel */ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPROW inptr; /* => current input pixel */ #endif - hist3d histogram = cquantize->histogram; - register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */ - LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */ - LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */ - register FSERRPTR errorptr; /* => fserrors[] at column before current */ - histptr cachep; - int dir; /* +1 or -1 depending on direction */ - int dir3; /* 3*dir, for advancing inptr & errorptr */ - int row; - JDIMENSION col; + hist3d histogram = cquantize->histogram; + register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */ + LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */ + LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */ + register FSERRPTR errorptr; /* => fserrors[] at column before current */ + histptr cachep; + int dir; /* +1 or -1 depending on direction */ + int dir3; /* 3*dir, for advancing inptr & errorptr */ + int row; + JDIMENSION col; #ifdef ORIGINAL_LIB_JPEG - JSAMPROW outptr; /* => current output pixel */ - JDIMENSION width = cinfo->output_width; - JSAMPLE *range_limit = cinfo->sample_range_limit; - JSAMPROW colormap0 = cinfo->colormap[0]; - JSAMPROW colormap1 = cinfo->colormap[1]; - JSAMPROW colormap2 = cinfo->colormap[2]; + JSAMPROW outptr; /* => current output pixel */ + JDIMENSION width = cinfo->output_width; + JSAMPLE *range_limit = cinfo->sample_range_limit; + JSAMPROW colormap0 = cinfo->colormap[0]; + JSAMPROW colormap1 = cinfo->colormap[1]; + JSAMPROW colormap2 = cinfo->colormap[2]; #else - int *inptr; /* => current input pixel */ - unsigned char *outptr; /* => current output pixel */ - int width = im->sx; - int num_rows = im->sy; - int *colormap0 = im->red; - int *colormap1 = im->green; - int *colormap2 = im->blue; + int *inptr; /* => current input pixel */ + unsigned char *outptr; /* => current output pixel */ + int width = oim->sx; + int num_rows = oim->sy; + int *colormap0 = nim->red; + int *colormap1 = nim->green; + int *colormap2 = nim->blue; #endif - int *error_limit = cquantize->error_limiter; - - - SHIFT_TEMPS for (row = 0; row < num_rows; row++) { - inptr = input_buf[row]; - outptr = output_buf[row]; - if (cquantize->on_odd_row) { - /* work right to left in this row */ - inptr += (width - 1) * 3; /* so point to rightmost pixel */ - outptr += width - 1; - dir = -1; - dir3 = -3; - errorptr = cquantize->fserrors + (width + 1) * 3; /* => entry after last column */ + int *error_limit = cquantize->error_limiter; + + + SHIFT_TEMPS for (row = 0; row < num_rows; row++) + { + inptr = input_buf[row]; + outptr = output_buf[row]; + if (cquantize->on_odd_row) + { + /* work right to left in this row */ + inptr += (width - 1) * 3; /* so point to rightmost pixel */ + outptr += width - 1; + dir = -1; + dir3 = -3; + errorptr = cquantize->fserrors + (width + 1) * 3; /* => entry after last column */ #ifdef ORIGINAL_LIB_JPEG_REVERSE_ODD_ROWS - cquantize->on_odd_row = FALSE; /* flip for next time */ + cquantize->on_odd_row = FALSE; /* flip for next time */ #endif - } else { - /* work left to right in this row */ - dir = 1; - dir3 = 3; - errorptr = cquantize->fserrors; /* => entry before first real column */ + } + else + { + /* work left to right in this row */ + dir = 1; + dir3 = 3; + errorptr = cquantize->fserrors; /* => entry before first real column */ #ifdef ORIGINAL_LIB_JPEG_REVERSE_ODD_ROWS - cquantize->on_odd_row = TRUE; /* flip for next time */ + cquantize->on_odd_row = TRUE; /* flip for next time */ #endif - } - /* Preset error values: no error propagated to first pixel from left */ - cur0 = cur1 = cur2 = 0; - /* and no error propagated to row below yet */ - belowerr0 = belowerr1 = belowerr2 = 0; - bpreverr0 = bpreverr1 = bpreverr2 = 0; - - for (col = width; col > 0; col--) { - /* If this pixel is transparent, we want to assign it to the special - * transparency color index past the end of the palette rather than - * go through matching / dithering. */ - if ((im->transparent >= 0) && (*inptr == im->transparent)) { - *outptr = im->colorsTotal; - errorptr[0] = 0; - errorptr[1] = 0; - errorptr[2] = 0; - errorptr[3] = 0; - inptr += dir; - outptr += dir; - errorptr += dir3; - continue; - } - /* curN holds the error propagated from the previous pixel on the - * current line. Add the error propagated from the previous line - * to form the complete error correction term for this pixel, and - * round the error term (which is expressed * 16) to an integer. - * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct - * for either sign of the error value. - * Note: errorptr points to *previous* column's array entry. - */ - cur0 = RIGHT_SHIFT (cur0 + errorptr[dir3 + 0] + 8, 4); - cur1 = RIGHT_SHIFT (cur1 + errorptr[dir3 + 1] + 8, 4); - cur2 = RIGHT_SHIFT (cur2 + errorptr[dir3 + 2] + 8, 4); - /* Limit the error using transfer function set by init_error_limit. - * See comments with init_error_limit for rationale. - */ - cur0 = error_limit[cur0]; - cur1 = error_limit[cur1]; - cur2 = error_limit[cur2]; - /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. - * The maximum error is +- MAXJSAMPLE (or less with error limiting); - * this sets the required size of the range_limit array. - */ + } + /* Preset error values: no error propagated to first pixel from left */ + cur0 = cur1 = cur2 = 0; + /* and no error propagated to row below yet */ + belowerr0 = belowerr1 = belowerr2 = 0; + bpreverr0 = bpreverr1 = bpreverr2 = 0; + + for (col = width; col > 0; col--) + { + + /* If this pixel is transparent, we want to assign it to the special + * transparency color index past the end of the palette rather than + * go through matching / dithering. */ + if ((oim->transparent >= 0) && (*inptr == oim->transparent)) + { + *outptr = nim->colorsTotal; + errorptr[0] = 0; + errorptr[1] = 0; + errorptr[2] = 0; + errorptr[3] = 0; + inptr += dir; + outptr += dir; + errorptr += dir3; + continue; + } + /* curN holds the error propagated from the previous pixel on the + * current line. Add the error propagated from the previous line + * to form the complete error correction term for this pixel, and + * round the error term (which is expressed * 16) to an integer. + * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct + * for either sign of the error value. + * Note: errorptr points to *previous* column's array entry. + */ + cur0 = RIGHT_SHIFT (cur0 + errorptr[dir3 + 0] + 8, 4); + cur1 = RIGHT_SHIFT (cur1 + errorptr[dir3 + 1] + 8, 4); + cur2 = RIGHT_SHIFT (cur2 + errorptr[dir3 + 2] + 8, 4); + /* Limit the error using transfer function set by init_error_limit. + * See comments with init_error_limit for rationale. + */ + cur0 = error_limit[cur0]; + cur1 = error_limit[cur1]; + cur2 = error_limit[cur2]; + /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. + * The maximum error is +- MAXJSAMPLE (or less with error limiting); + * this sets the required size of the range_limit array. + */ #ifdef ORIGINAL_LIB_JPEG - cur0 += GETJSAMPLE (inptr[0]); - cur1 += GETJSAMPLE (inptr[1]); - cur2 += GETJSAMPLE (inptr[2]); - cur0 = GETJSAMPLE (range_limit[cur0]); - cur1 = GETJSAMPLE (range_limit[cur1]); - cur2 = GETJSAMPLE (range_limit[cur2]); + cur0 += GETJSAMPLE (inptr[0]); + cur1 += GETJSAMPLE (inptr[1]); + cur2 += GETJSAMPLE (inptr[2]); + cur0 = GETJSAMPLE (range_limit[cur0]); + cur1 = GETJSAMPLE (range_limit[cur1]); + cur2 = GETJSAMPLE (range_limit[cur2]); #else - cur0 += gdTrueColorGetRed (*inptr); - cur1 += gdTrueColorGetGreen (*inptr); - cur2 += gdTrueColorGetBlue (*inptr); - range_limit (cur0); - range_limit (cur1); - range_limit (cur2); + cur0 += gdTrueColorGetRed (*inptr); + cur1 += gdTrueColorGetGreen (*inptr); + cur2 += gdTrueColorGetBlue (*inptr); + range_limit (cur0); + range_limit (cur1); + range_limit (cur2); #endif - /* Index into the cache with adjusted pixel value */ - cachep = &histogram[cur0 >> C0_SHIFT][cur1 >> C1_SHIFT][cur2 >> C2_SHIFT]; - /* If we have not seen this color before, find nearest colormap */ - /* entry and update the cache */ - if (*cachep == 0) { + /* Index into the cache with adjusted pixel value */ + cachep = + &histogram[cur0 >> C0_SHIFT][cur1 >> C1_SHIFT][cur2 >> C2_SHIFT]; + /* If we have not seen this color before, find nearest colormap */ + /* entry and update the cache */ + if (*cachep == 0) #ifdef ORIGINAL_LIB_JPEG - fill_inverse_cmap(cinfo, cur0 >> C0_SHIFT, cur1 >> C1_SHIFT, cur2 >> C2_SHIFT); + fill_inverse_cmap (cinfo, cur0 >> C0_SHIFT, cur1 >> C1_SHIFT, + cur2 >> C2_SHIFT); #else - fill_inverse_cmap(im, cquantize, cur0 >> C0_SHIFT, cur1 >> C1_SHIFT, cur2 >> C2_SHIFT); + fill_inverse_cmap (oim, nim, cquantize, cur0 >> C0_SHIFT, + cur1 >> C1_SHIFT, cur2 >> C2_SHIFT); #endif - } - /* Now emit the colormap index for this cell */ - { - register int pixcode = *cachep - 1; - *outptr = (JSAMPLE) pixcode; - /* Compute representation error for this pixel */ + /* Now emit the colormap index for this cell */ + { + register int pixcode = *cachep - 1; + *outptr = (JSAMPLE) pixcode; + /* Compute representation error for this pixel */ #define GETJSAMPLE - cur0 -= GETJSAMPLE(colormap0[pixcode]); - cur1 -= GETJSAMPLE(colormap1[pixcode]); - cur2 -= GETJSAMPLE(colormap2[pixcode]); + cur0 -= GETJSAMPLE (colormap0[pixcode]); + cur1 -= GETJSAMPLE (colormap1[pixcode]); + cur2 -= GETJSAMPLE (colormap2[pixcode]); #undef GETJSAMPLE - } - /* Compute error fractions to be propagated to adjacent pixels. - * Add these into the running sums, and simultaneously shift the - * next-line error sums left by 1 column. - */ - { - register LOCFSERROR bnexterr, delta; - - bnexterr = cur0; /* Process component 0 */ - delta = cur0 * 2; - cur0 += delta; /* form error * 3 */ - errorptr[0] = (FSERROR) (bpreverr0 + cur0); - cur0 += delta; /* form error * 5 */ - bpreverr0 = belowerr0 + cur0; - belowerr0 = bnexterr; - cur0 += delta; /* form error * 7 */ - bnexterr = cur1; /* Process component 1 */ - delta = cur1 * 2; - cur1 += delta; /* form error * 3 */ - errorptr[1] = (FSERROR) (bpreverr1 + cur1); - cur1 += delta; /* form error * 5 */ - bpreverr1 = belowerr1 + cur1; - belowerr1 = bnexterr; - cur1 += delta; /* form error * 7 */ - bnexterr = cur2; /* Process component 2 */ - delta = cur2 * 2; - cur2 += delta; /* form error * 3 */ - errorptr[2] = (FSERROR) (bpreverr2 + cur2); - cur2 += delta; /* form error * 5 */ - bpreverr2 = belowerr2 + cur2; - belowerr2 = bnexterr; - cur2 += delta; /* form error * 7 */ - } - /* At this point curN contains the 7/16 error value to be propagated - * to the next pixel on the current line, and all the errors for the - * next line have been shifted over. We are therefore ready to move on. - */ + } + /* Compute error fractions to be propagated to adjacent pixels. + * Add these into the running sums, and simultaneously shift the + * next-line error sums left by 1 column. + */ + { + register LOCFSERROR bnexterr, delta; + + bnexterr = cur0; /* Process component 0 */ + delta = cur0 * 2; + cur0 += delta; /* form error * 3 */ + errorptr[0] = (FSERROR) (bpreverr0 + cur0); + cur0 += delta; /* form error * 5 */ + bpreverr0 = belowerr0 + cur0; + belowerr0 = bnexterr; + cur0 += delta; /* form error * 7 */ + bnexterr = cur1; /* Process component 1 */ + delta = cur1 * 2; + cur1 += delta; /* form error * 3 */ + errorptr[1] = (FSERROR) (bpreverr1 + cur1); + cur1 += delta; /* form error * 5 */ + bpreverr1 = belowerr1 + cur1; + belowerr1 = bnexterr; + cur1 += delta; /* form error * 7 */ + bnexterr = cur2; /* Process component 2 */ + delta = cur2 * 2; + cur2 += delta; /* form error * 3 */ + errorptr[2] = (FSERROR) (bpreverr2 + cur2); + cur2 += delta; /* form error * 5 */ + bpreverr2 = belowerr2 + cur2; + belowerr2 = bnexterr; + cur2 += delta; /* form error * 7 */ + } + /* At this point curN contains the 7/16 error value to be propagated + * to the next pixel on the current line, and all the errors for the + * next line have been shifted over. We are therefore ready to move on. + */ #ifdef ORIGINAL_LIB_JPEG - inptr += dir3; /* Advance pixel pointers to next column */ + inptr += dir3; /* Advance pixel pointers to next column */ #else - inptr += dir; /* Advance pixel pointers to next column */ + inptr += dir; /* Advance pixel pointers to next column */ #endif - outptr += dir; - errorptr += dir3; /* advance errorptr to current column */ - } - /* Post-loop cleanup: we must unload the final error values into the - * final fserrors[] entry. Note we need not unload belowerrN because - * it is for the dummy column before or after the actual array. - */ - errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */ - errorptr[1] = (FSERROR) bpreverr1; - errorptr[2] = (FSERROR) bpreverr2; + outptr += dir; + errorptr += dir3; /* advance errorptr to current column */ } + /* Post-loop cleanup: we must unload the final error values into the + * final fserrors[] entry. Note we need not unload belowerrN because + * it is for the dummy column before or after the actual array. + */ + errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */ + errorptr[1] = (FSERROR) bpreverr1; + errorptr[2] = (FSERROR) bpreverr2; + } } /* * Initialize the error-limiting transfer function (lookup table). * The raw F-S error computation can potentially compute error values of up to - * +- MAXJSAMPLE. But we want the maximum correction applied to a pixel to be - * much less, otherwise obviously wrong pixels will be created. (Typical + * +- MAXJSAMPLE. But we want the maximum correction applied to a pixel to be + * much less, otherwise obviously wrong pixels will be created. (Typical * effects include weird fringes at color-area boundaries, isolated bright - * pixels in a dark area, etc.) The standard advice for avoiding this problem + * pixels in a dark area, etc.) The standard advice for avoiding this problem * is to ensure that the "corners" of the color cube are allocated as output * colors; then repeated errors in the same direction cannot cause cascading - * error buildup. However, that only prevents the error from getting + * error buildup. However, that only prevents the error from getting * completely out of hand; Aaron Giles reports that error limiting improves * the results even with corner colors allocated. * A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty - * well, but the smoother transfer function used below is even better. Thanks + * well, but the smoother transfer function used below is even better. Thanks * to Aaron Giles for this idea. */ @@ -1508,43 +1587,49 @@ LOCAL (void) #ifdef ORIGINAL_LIB_JPEG init_error_limit (j_decompress_ptr cinfo) #else -init_error_limit (gdImagePtr im, my_cquantize_ptr cquantize) +init_error_limit (gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize) #endif /* Allocate and fill in the error_limiter table */ { - int *table; - int in, out; + int *table; + int in, out; #ifdef ORIGINAL_LIB_JPEG - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - table = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE * 2 + 1) * SIZEOF (int)); + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + table = (int *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE * 2 + 1) * SIZEOF (int)); #else - cquantize->error_limiter_storage = (int *) safe_emalloc((MAXJSAMPLE * 2 + 1), sizeof(int), 0); - if (!cquantize->error_limiter_storage) { - return; - } - table = cquantize->error_limiter_storage; + cquantize->error_limiter_storage = + (int *) safe_emalloc ((MAXJSAMPLE * 2 + 1), sizeof (int), 0); + if (!cquantize->error_limiter_storage) + { + return; + } + table = cquantize->error_limiter_storage; #endif - table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */ - cquantize->error_limiter = table; + table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */ + cquantize->error_limiter = table; #define STEPSIZE ((MAXJSAMPLE+1)/16) - /* Map errors 1:1 up to +- MAXJSAMPLE/16 */ - out = 0; - for (in = 0; in < STEPSIZE; in++, out++){ - table[in] = out; - table[-in] = -out; - } - /* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */ - for (; in < STEPSIZE * 3; in++, out += (in & 1) ? 0 : 1) { - table[in] = out; - table[-in] = -out; - } - /* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */ - for (; in <= MAXJSAMPLE; in++) { - table[in] = out; - table[-in] = -out; - } + /* Map errors 1:1 up to +- MAXJSAMPLE/16 */ + out = 0; + for (in = 0; in < STEPSIZE; in++, out++) + { + table[in] = out; + table[-in] = -out; + } + /* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */ + for (; in < STEPSIZE * 3; in++, out += (in & 1) ? 0 : 1) + { + table[in] = out; + table[-in] = -out; + } + /* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */ + for (; in <= MAXJSAMPLE; in++) + { + table[in] = out; + table[-in] = -out; + } #undef STEPSIZE } @@ -1554,85 +1639,91 @@ init_error_limit (gdImagePtr im, my_cquantize_ptr cquantize) */ #ifdef ORIGINAL_LIB_JPEG -METHODDEF (void) finish_pass1 (j_decompress_ptr cinfo) +METHODDEF (void) +finish_pass1 (j_decompress_ptr cinfo) { - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - /* Select the representative colors and fill in cinfo->colormap */ - cinfo->colormap = cquantize->sv_colormap; - select_colors (cinfo, cquantize->desired); - /* Force next pass to zero the color index table */ - cquantize->needs_zeroed = TRUE; + /* Select the representative colors and fill in cinfo->colormap */ + cinfo->colormap = cquantize->sv_colormap; + select_colors (cinfo, cquantize->desired); + /* Force next pass to zero the color index table */ + cquantize->needs_zeroed = TRUE; } -METHODDEF (void) finish_pass2 (j_decompress_ptr cinfo) +METHODDEF (void) +finish_pass2 (j_decompress_ptr cinfo) { - /* no work */ + /* no work */ } /* * Initialize for each processing pass. */ -METHODDEF (void) start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan) +METHODDEF (void) +start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan) { - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - hist3d histogram = cquantize->histogram; - int i; - - /* Only F-S dithering or no dithering is supported. */ - /* If user asks for ordered dither, give him F-S. */ - if (cinfo->dither_mode != JDITHER_NONE) { - cinfo->dither_mode = JDITHER_FS; + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + int i; + + /* Only F-S dithering or no dithering is supported. */ + /* If user asks for ordered dither, give him F-S. */ + if (cinfo->dither_mode != JDITHER_NONE) + cinfo->dither_mode = JDITHER_FS; + + if (is_pre_scan) + { + /* Set up method pointers */ + cquantize->pub.color_quantize = prescan_quantize; + cquantize->pub.finish_pass = finish_pass1; + cquantize->needs_zeroed = TRUE; /* Always zero histogram */ + } + else + { + /* Set up method pointers */ + if (cinfo->dither_mode == JDITHER_FS) + cquantize->pub.color_quantize = pass2_fs_dither; + else + cquantize->pub.color_quantize = pass2_no_dither; + cquantize->pub.finish_pass = finish_pass2; + + /* Make sure color count is acceptable */ + i = cinfo->actual_number_of_colors; + if (i < 1) + ERREXIT1 (cinfo, JERR_QUANT_FEW_COLORS, 1); + if (i > MAXNUMCOLORS) + ERREXIT1 (cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); + + if (cinfo->dither_mode == JDITHER_FS) + { + size_t arraysize = (size_t) ((cinfo->output_width + 2) * + (3 * SIZEOF (FSERROR))); + /* Allocate Floyd-Steinberg workspace if we didn't already. */ + if (cquantize->fserrors == NULL) + cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); + /* Initialize the propagated errors to zero. */ + jzero_far ((void FAR *) cquantize->fserrors, arraysize); + /* Make the error-limit table if we didn't already. */ + if (cquantize->error_limiter == NULL) + init_error_limit (cinfo); + cquantize->on_odd_row = FALSE; } - if (is_pre_scan){ - /* Set up method pointers */ - cquantize->pub.color_quantize = prescan_quantize; - cquantize->pub.finish_pass = finish_pass1; - cquantize->needs_zeroed = TRUE; /* Always zero histogram */ - } else { - /* Set up method pointers */ - if (cinfo->dither_mode == JDITHER_FS) { - cquantize->pub.color_quantize = pass2_fs_dither; - } else { - cquantize->pub.color_quantize = pass2_no_dither; - } - cquantize->pub.finish_pass = finish_pass2; - - /* Make sure color count is acceptable */ - i = cinfo->actual_number_of_colors; - if (i < 1) { - ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 1); - } - if (i > MAXNUMCOLORS) { - ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); - } - - if (cinfo->dither_mode == JDITHER_FS) { - size_t arraysize = (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF (FSERROR))); - /* Allocate Floyd-Steinberg workspace if we didn't already. */ - if (cquantize->fserrors == NULL) { - cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); - } - /* Initialize the propagated errors to zero. */ - jzero_far((void FAR *) cquantize->fserrors, arraysize); - /* Make the error-limit table if we didn't already. */ - if (cquantize->error_limiter == NULL) { - init_error_limit(cinfo); - } - cquantize->on_odd_row = FALSE; - } - - } - /* Zero the histogram or inverse color map, if necessary */ - if (cquantize->needs_zeroed) { - for (i = 0; i < HIST_C0_ELEMS; i++) { - jzero_far((void FAR *) histogram[i], HIST_C1_ELEMS * HIST_C2_ELEMS * SIZEOF (histcell)); - } - cquantize->needs_zeroed = FALSE; + } + /* Zero the histogram or inverse color map, if necessary */ + if (cquantize->needs_zeroed) + { + for (i = 0; i < HIST_C0_ELEMS; i++) + { + jzero_far ((void FAR *) histogram[i], + HIST_C1_ELEMS * HIST_C2_ELEMS * SIZEOF (histcell)); } + cquantize->needs_zeroed = FALSE; + } } @@ -1640,24 +1731,42 @@ METHODDEF (void) start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan * Switch to a new external colormap between output passes. */ -METHODDEF (void) new_color_map_2_quant (j_decompress_ptr cinfo) +METHODDEF (void) +new_color_map_2_quant (j_decompress_ptr cinfo) { - my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; - /* Reset the inverse color map */ - cquantize->needs_zeroed = TRUE; + /* Reset the inverse color map */ + cquantize->needs_zeroed = TRUE; } #else -static void zeroHistogram (hist3d histogram) +static void +zeroHistogram (hist3d histogram) { - int i; - /* Zero the histogram or inverse color map */ - for (i = 0; i < HIST_C0_ELEMS; i++) { - memset (histogram[i], 0, HIST_C1_ELEMS * HIST_C2_ELEMS * sizeof (histcell)); - } + int i; + /* Zero the histogram or inverse color map */ + for (i = 0; i < HIST_C0_ELEMS; i++) + { + memset (histogram[i], + 0, HIST_C1_ELEMS * HIST_C2_ELEMS * sizeof (histcell)); + } } #endif +static void gdImageTrueColorToPaletteBody (gdImagePtr oim, int dither, int colorsWanted, gdImagePtr *cimP); + +gdImagePtr gdImageCreatePaletteFromTrueColor (gdImagePtr im, int dither, int colorsWanted) +{ + gdImagePtr nim; + gdImageTrueColorToPaletteBody(im, dither, colorsWanted, &nim); + return nim; +} + +void gdImageTrueColorToPalette (gdImagePtr im, int dither, int colorsWanted) +{ + gdImageTrueColorToPaletteBody(im, dither, colorsWanted, 0); +} + /* * Module initialization routine for 2-pass color quantization. */ @@ -1666,210 +1775,297 @@ static void zeroHistogram (hist3d histogram) GLOBAL (void) jinit_2pass_quantizer (j_decompress_ptr cinfo) #else -void -gdImageTrueColorToPalette (gdImagePtr im, int dither, int colorsWanted) +static void gdImageTrueColorToPaletteBody (gdImagePtr oim, int dither, int colorsWanted, gdImagePtr *cimP) #endif { - my_cquantize_ptr cquantize = NULL; - int i; + my_cquantize_ptr cquantize = NULL; + int i; #ifndef ORIGINAL_LIB_JPEG - /* Allocate the JPEG palette-storage */ - size_t arraysize; - int maxColors = gdMaxColors; - if (!im->trueColor) { - /* Nothing to do! */ - return; - } - - /* If we have a transparent color (the alphaless mode of transparency), we - * must reserve a palette entry for it at the end of the palette. */ - if (im->transparent >= 0){ - maxColors--; - } - if (colorsWanted > maxColors) { - colorsWanted = maxColors; - } - im->pixels = gdCalloc(sizeof (unsigned char *), im->sy); - for (i = 0; (i < im->sy); i++) { - im->pixels[i] = gdCalloc(sizeof (unsigned char *), im->sx); - } + /* Allocate the JPEG palette-storage */ + size_t arraysize; + int maxColors = gdMaxColors; + gdImagePtr nim; + if (cimP) { + nim = gdImageCreate(oim->sx, oim->sy); + *cimP = nim; + if (!nim) { + return; + } + } else { + nim = oim; + } + if (!oim->trueColor) + { + /* (Almost) nothing to do! */ + if (cimP) { + gdImageCopy(nim, oim, 0, 0, 0, 0, oim->sx, oim->sy); + *cimP = nim; + } + return; + } + + /* If we have a transparent color (the alphaless mode of transparency), we + * must reserve a palette entry for it at the end of the palette. */ + if (oim->transparent >= 0) + { + maxColors--; + } + if (colorsWanted > maxColors) + { + colorsWanted = maxColors; + } + if (!cimP) { + nim->pixels = gdCalloc (sizeof (unsigned char *), oim->sy); + if (!nim->pixels) + { + /* No can do */ + goto outOfMemory; + } + for (i = 0; (i < nim->sy); i++) + { + nim->pixels[i] = gdCalloc (sizeof (unsigned char *), oim->sx); + if (!nim->pixels[i]) + { + goto outOfMemory; + } + } + } #endif #ifdef ORIGINAL_LIB_JPEG - cquantize = (my_cquantize_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF (my_cquantizer)); - cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; - cquantize->pub.start_pass = start_pass_2_quant; - cquantize->pub.new_color_map = new_color_map_2_quant; - /* Make sure jdmaster didn't give me a case I can't handle */ - if (cinfo->out_color_components != 3) { - ERREXIT (cinfo, JERR_NOTIMPL); - } + cquantize = (my_cquantize_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF (my_cquantizer)); + cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; + cquantize->pub.start_pass = start_pass_2_quant; + cquantize->pub.new_color_map = new_color_map_2_quant; + /* Make sure jdmaster didn't give me a case I can't handle */ + if (cinfo->out_color_components != 3) + ERREXIT (cinfo, JERR_NOTIMPL); #else - cquantize = (my_cquantize_ptr) gdCalloc(sizeof (my_cquantizer), 1); + cquantize = (my_cquantize_ptr) gdCalloc (sizeof (my_cquantizer), 1); + if (!cquantize) + { + /* No can do */ + goto outOfMemory; + } #endif - cquantize->fserrors = NULL; /* flag optional arrays not allocated */ - cquantize->error_limiter = NULL; + cquantize->fserrors = NULL; /* flag optional arrays not allocated */ + cquantize->error_limiter = NULL; + - /* Allocate the histogram/inverse colormap storage */ + /* Allocate the histogram/inverse colormap storage */ #ifdef ORIGINAL_LIB_JPEG - cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF (hist2d)); - for (i = 0; i < HIST_C0_ELEMS; i++) { - cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C1_ELEMS * HIST_C2_ELEMS * SIZEOF (histcell)); - } - cquantize->needs_zeroed = TRUE; /* histogram is garbage now */ + cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF (hist2d)); + for (i = 0; i < HIST_C0_ELEMS; i++) + { + cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + HIST_C1_ELEMS * HIST_C2_ELEMS * SIZEOF (histcell)); + } + cquantize->needs_zeroed = TRUE; /* histogram is garbage now */ #else - cquantize->histogram = (hist3d) safe_emalloc(HIST_C0_ELEMS, sizeof(hist2d), 0); - for (i = 0; i < HIST_C0_ELEMS; i++) { - cquantize->histogram[i] = (hist2d) safe_emalloc(HIST_C1_ELEMS, HIST_C2_ELEMS * sizeof(histcell), 0); + cquantize->histogram = (hist3d) safe_emalloc (HIST_C0_ELEMS, sizeof (hist2d), 0); + for (i = 0; i < HIST_C0_ELEMS; i++) + { + cquantize->histogram[i] = + (hist2d) safe_emalloc (HIST_C1_ELEMS * HIST_C2_ELEMS, sizeof (histcell), 0); + if (!cquantize->histogram[i]) + { + goto outOfMemory; } + } #endif #ifdef ORIGINAL_LIB_JPEG - /* Allocate storage for the completed colormap, if required. - * We do this now since it is FAR storage and may affect - * the memory manager's space calculations. - */ - if (cinfo->enable_2pass_quant) { - /* Make sure color count is acceptable */ - int desired = cinfo->desired_number_of_colors; - /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */ - if (desired < 8) { - ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8); - } - /* Make sure colormap indexes can be represented by JSAMPLEs */ - if (desired > MAXNUMCOLORS) { - ERREXIT1 (cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); - } - cquantize->sv_colormap = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3); - cquantize->desired = desired; - } else { - cquantize->sv_colormap = NULL; - } - - /* Only F-S dithering or no dithering is supported. */ - /* If user asks for ordered dither, give him F-S. */ - if (cinfo->dither_mode != JDITHER_NONE) { - cinfo->dither_mode = JDITHER_FS; - } - - /* Allocate Floyd-Steinberg workspace if necessary. - * This isn't really needed until pass 2, but again it is FAR storage. - * Although we will cope with a later change in dither_mode, - * we do not promise to honor max_memory_to_use if dither_mode changes. - */ - if (cinfo->dither_mode == JDITHER_FS) { - cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF (FSERROR)))); - /* Might as well create the error-limiting table too. */ - init_error_limit(cinfo); - } + /* Allocate storage for the completed colormap, if required. + * We do this now since it is FAR storage and may affect + * the memory manager's space calculations. + */ + if (cinfo->enable_2pass_quant) + { + /* Make sure color count is acceptable */ + int desired = cinfo->desired_number_of_colors; + /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */ + if (desired < 8) + ERREXIT1 (cinfo, JERR_QUANT_FEW_COLORS, 8); + /* Make sure colormap indexes can be represented by JSAMPLEs */ + if (desired > MAXNUMCOLORS) + ERREXIT1 (cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); + cquantize->sv_colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) desired, + (JDIMENSION) 3); + cquantize->desired = desired; + } + else + cquantize->sv_colormap = NULL; + + /* Only F-S dithering or no dithering is supported. */ + /* If user asks for ordered dither, give him F-S. */ + if (cinfo->dither_mode != JDITHER_NONE) + cinfo->dither_mode = JDITHER_FS; + + /* Allocate Floyd-Steinberg workspace if necessary. + * This isn't really needed until pass 2, but again it is FAR storage. + * Although we will cope with a later change in dither_mode, + * we do not promise to honor max_memory_to_use if dither_mode changes. + */ + if (cinfo->dither_mode == JDITHER_FS) + { + cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF (FSERROR)))); + /* Might as well create the error-limiting table too. */ + init_error_limit (cinfo); + } #else - cquantize->fserrors = (FSERRPTR) gdMalloc(3 * sizeof (FSERROR)); - init_error_limit (im, cquantize); - arraysize = (size_t) ((im->sx + 2) * (3 * sizeof (FSERROR))); - gdFree(cquantize->fserrors); - /* Allocate Floyd-Steinberg workspace. */ - cquantize->fserrors = gdCalloc(arraysize, 1); - cquantize->on_odd_row = FALSE; - - /* Do the work! */ - zeroHistogram(cquantize->histogram); - prescan_quantize(im, cquantize); - /* TBB 2.0.5: pass colorsWanted, not 256! */ - select_colors(im, cquantize, colorsWanted); - zeroHistogram(cquantize->histogram); - if (dither) { - pass2_fs_dither(im, cquantize); - } else { - pass2_no_dither(im, cquantize); + cquantize->fserrors = (FSERRPTR) safe_emalloc (3, sizeof (FSERROR), 0); + init_error_limit (oim, nim, cquantize); + arraysize = (size_t) ((nim->sx + 2) * (3 * sizeof (FSERROR))); + /* Allocate Floyd-Steinberg workspace. */ + cquantize->fserrors = gdRealloc(cquantize->fserrors, arraysize); + memset(cquantize->fserrors, 0, arraysize); + if (!cquantize->fserrors) + { + goto outOfMemory; + } + cquantize->on_odd_row = FALSE; + + /* Do the work! */ + zeroHistogram (cquantize->histogram); + prescan_quantize (oim, nim, cquantize); + /* TBB 2.0.5: pass colorsWanted, not 256! */ + select_colors (oim, nim, cquantize, colorsWanted); + zeroHistogram (cquantize->histogram); + if (dither) + { + pass2_fs_dither (oim, nim, cquantize); + } + else + { + pass2_no_dither (oim, nim, cquantize); + } +#if 0 /* 2.0.12; we no longer attempt full alpha in palettes */ + if (cquantize->transparentIsPresent) + { + int mt = -1; + int mtIndex = -1; + for (i = 0; (i < im->colorsTotal); i++) + { + if (im->alpha[i] > mt) + { + mtIndex = i; + mt = im->alpha[i]; + } } -#if 0 /* 2.0.12; we no longer attempt full alpha in palettes */ - if (cquantize->transparentIsPresent) { - int mt = -1; - int mtIndex = -1; - for (i = 0; (i < im->colorsTotal); i++) { - if (im->alpha[i] > mt) { - mtIndex = i; - mt = im->alpha[i]; - } - } - for (i = 0; (i < im->colorsTotal); i++) { - if (im->alpha[i] == mt) { - im->alpha[i] = gdAlphaTransparent; - } - } + for (i = 0; (i < im->colorsTotal); i++) + { + if (im->alpha[i] == mt) + { + im->alpha[i] = gdAlphaTransparent; + } } - if (cquantize->opaqueIsPresent) { - int mo = 128; - int moIndex = -1; - for (i = 0; (i < im->colorsTotal); i++) { - if (im->alpha[i] < mo) { - moIndex = i; - mo = im->alpha[i]; - } - } - for (i = 0; (i < im->colorsTotal); i++) { - if (im->alpha[i] == mo) { - im->alpha[i] = gdAlphaOpaque; - } - } + } + if (cquantize->opaqueIsPresent) + { + int mo = 128; + int moIndex = -1; + for (i = 0; (i < im->colorsTotal); i++) + { + if (im->alpha[i] < mo) + { + moIndex = i; + mo = im->alpha[i]; + } + } + for (i = 0; (i < im->colorsTotal); i++) + { + if (im->alpha[i] == mo) + { + im->alpha[i] = gdAlphaOpaque; + } } + } #endif - /* If we had a 'transparent' color, increment the color count so it's - * officially in the palette and convert the transparent variable to point to - * an index rather than a color (Its data already exists and transparent - * pixels have already been mapped to it by this point, it is done late as to - * avoid color matching / dithering with it). */ - if (im->transparent >= 0) { - im->transparent = im->colorsTotal; - im->colorsTotal++; + /* If we had a 'transparent' color, increment the color count so it's + * officially in the palette and convert the transparent variable to point to + * an index rather than a color (Its data already exists and transparent + * pixels have already been mapped to it by this point, it is done late as to + * avoid color matching / dithering with it). */ + if (oim->transparent >= 0) + { + nim->transparent = nim->colorsTotal; + nim->colorsTotal++; + } + + /* Success! Get rid of the truecolor image data. */ + if (!cimP) { + oim->trueColor = 0; + /* Junk the truecolor pixels */ + for (i = 0; i < oim->sy; i++) + { + gdFree (oim->tpixels[i]); + } + gdFree (oim->tpixels); + oim->tpixels = 0; + } + goto success; + /* Tediously free stuff. */ +outOfMemory: + if (oim->trueColor) + { + if (!cimP) { + /* On failure only */ + for (i = 0; i < nim->sy; i++) + { + if (nim->pixels[i]) + { + gdFree (nim->pixels[i]); + } + } + if (nim->pixels) + { + gdFree (nim->pixels); + } + nim->pixels = 0; + } else { + gdImageDestroy(nim); + *cimP = 0; + } + } +success: + for (i = 0; i < HIST_C0_ELEMS; i++) + { + if (cquantize->histogram[i]) + { + gdFree (cquantize->histogram[i]); } + } + if (cquantize->histogram) + { + gdFree (cquantize->histogram); + } + if (cquantize->fserrors) + { + gdFree (cquantize->fserrors); + } + if (cquantize->error_limiter_storage) + { + gdFree (cquantize->error_limiter_storage); + } + if (cquantize) + { + gdFree (cquantize); + } - /* Success! Get rid of the truecolor image data. */ - im->trueColor = 0; - /* Junk the truecolor pixels */ - for (i = 0; i < im->sy; i++) { - gdFree(im->tpixels[i]); - } - gdFree(im->tpixels); - im->tpixels = 0; - /* Tediously free stuff. */ - - if (im->trueColor) { - /* On failure only */ - for (i = 0; i < im->sy; i++) { - if (im->pixels[i]) { - gdFree (im->pixels[i]); - } - } - if (im->pixels) { - gdFree (im->pixels); - } - im->pixels = 0; - } - - for (i = 0; i < HIST_C0_ELEMS; i++) { - if (cquantize->histogram[i]) { - gdFree(cquantize->histogram[i]); - } - } - if (cquantize->histogram) { - gdFree(cquantize->histogram); - } - if (cquantize->fserrors) { - gdFree(cquantize->fserrors); - } - if (cquantize->error_limiter_storage) { - gdFree(cquantize->error_limiter_storage); - } - if (cquantize) { - gdFree(cquantize); - } #endif } + /* bring the palette colors in im2 to be closer to im1 * */ diff --git a/ext/gd/libgd/gdft.c b/ext/gd/libgd/gdft.c index 5e74b5757f92..cf79fe31298d 100644 --- a/ext/gd/libgd/gdft.c +++ b/ext/gd/libgd/gdft.c @@ -915,7 +915,7 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, double ptsi /* EAM DEBUG */ #if (defined(FREETYPE_MAJOR) && ((FREETYPE_MAJOR == 2 && ((FREETYPE_MINOR == 1 && FREETYPE_PATCH >= 3) || FREETYPE_MINOR > 1) || FREETYPE_MAJOR > 2))) - if (font->face->charmap->encoding == FT_ENCODING_MS_SYMBOL) { + if (font->face->charmap->encoding == FT_ENCODING_MS_SYMBOL && strcmp(font->face->family_name, "Symbol") == 0) { /* I do not know the significance of the constant 0xf000. * It was determined by inspection of the character codes * stored in Microsoft font symbol. diff --git a/ext/gd/tests/bug19366.phpt b/ext/gd/tests/bug19366.phpt index 83dfa63100f8..c83d816c15b2 100644 --- a/ext/gd/tests/bug19366.phpt +++ b/ext/gd/tests/bug19366.phpt @@ -1,5 +1,5 @@ --TEST-- -gdimagefill() function (Bug #19366 (fixed in bundled libgd)) +Bug #19366 (gdimagefill() function crashes (fixed in bundled libgd)) --SKIPIF-- gd1/gd2 conversion test --SKIPIF-- jpeg conversion test --SKIPIF-- png conversion test --SKIPIF-- png conversion test --SKIPIF-- gd1/gd2 conversion test --SKIPIF-- gd1/gd2 conversion test --SKIPIF-- png conversion test --SKIPIF-- gd1/gd2 conversion test --SKIPIF-- jpeg conversion test --SKIPIF-- png conversion test --SKIPIF-- -#include #include "ext/standard/info.h" #include "php_gettext.h" @@ -57,6 +56,8 @@ function_entry php_gettext_functions[] = { }; /* }}} */ +#include + zend_module_entry php_gettext_module_entry = { STANDARD_MODULE_HEADER, "gettext", diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index f41b4063e31e..d5653f2df3c5 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -282,8 +282,8 @@ typedef void (*gmp_binary_op2_t)(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr); typedef unsigned long (*gmp_binary_ui_op2_t)(mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long); /* }}} */ -#define gmp_zval_binary_ui_op(r, a, b, o, u) gmp_zval_binary_ui_op_ex(r, a, b, o, u, 0 TSRMLS_CC) -#define gmp_zval_binary_ui_op2(r, a, b, o, u) gmp_zval_binary_ui_op2_ex(r, a, b, o, u, 0 TSRMLS_CC) +#define gmp_zval_binary_ui_op(r, a, b, o, u) gmp_zval_binary_ui_op_ex(r, a, b, o, u, 0, 0 TSRMLS_CC) +#define gmp_zval_binary_ui_op2(r, a, b, o, u) gmp_zval_binary_ui_op2_ex(r, a, b, o, u, 0, 0 TSRMLS_CC) #define gmp_binary_ui_op(op, uop) _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op, uop) #define gmp_binary_op(op) _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op, NULL) @@ -298,7 +298,7 @@ typedef unsigned long (*gmp_binary_ui_op2_t)(mpz_ptr, mpz_ptr, mpz_srcptr, unsig Execute GMP binary operation. May return GMP resource or long if operation allows this */ -static inline void gmp_zval_binary_ui_op_ex(zval *return_value, zval **a_arg, zval **b_arg, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op, int allow_ui_return TSRMLS_DC) +static inline void gmp_zval_binary_ui_op_ex(zval *return_value, zval **a_arg, zval **b_arg, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op, int allow_ui_return, int check_b_zero TSRMLS_DC) { mpz_t *gmpnum_a, *gmpnum_b, *gmpnum_result; unsigned long long_result = 0; @@ -312,8 +312,18 @@ static inline void gmp_zval_binary_ui_op_ex(zval *return_value, zval **a_arg, zv FETCH_GMP_ZVAL(gmpnum_b, b_arg); } - if (!Z_LVAL_PP(b_arg)) { - RETURN_FALSE; + if(check_b_zero) { + int b_is_zero = 0; + if(use_ui) { + b_is_zero = (Z_LVAL_PP(b_arg) == 0); + } else { + b_is_zero = !mpz_cmp_ui(*gmpnum_b, 0); + } + + if(b_is_zero) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Zero operand not allowed"); + RETURN_FALSE; + } } INIT_GMP_NUM(gmpnum_result); @@ -341,7 +351,7 @@ static inline void gmp_zval_binary_ui_op_ex(zval *return_value, zval **a_arg, zv Execute GMP binary operation which returns 2 values. May return GMP resources or longs if operation allows this. */ -static inline void gmp_zval_binary_ui_op2_ex(zval *return_value, zval **a_arg, zval **b_arg, gmp_binary_op2_t gmp_op, gmp_binary_ui_op2_t gmp_ui_op, int allow_ui_return TSRMLS_DC) +static inline void gmp_zval_binary_ui_op2_ex(zval *return_value, zval **a_arg, zval **b_arg, gmp_binary_op2_t gmp_op, gmp_binary_ui_op2_t gmp_ui_op, int allow_ui_return, int check_b_zero TSRMLS_DC) { mpz_t *gmpnum_a, *gmpnum_b, *gmpnum_result1, *gmpnum_result2; zval r; @@ -357,8 +367,18 @@ static inline void gmp_zval_binary_ui_op2_ex(zval *return_value, zval **a_arg, z FETCH_GMP_ZVAL(gmpnum_b, b_arg); } - if (!Z_LVAL_PP(b_arg)) { - RETURN_FALSE; + if(check_b_zero) { + int b_is_zero = 0; + if(use_ui) { + b_is_zero = (Z_LVAL_PP(b_arg) == 0); + } else { + b_is_zero = !mpz_cmp_ui(*gmpnum_b, 0); + } + + if(b_is_zero) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Zero operand not allowed"); + RETURN_FALSE; + } } INIT_GMP_NUM(gmpnum_result1); @@ -653,13 +673,13 @@ ZEND_FUNCTION(gmp_div_qr) switch (round) { case GMP_ROUND_ZERO: - gmp_zval_binary_ui_op2(return_value, a_arg, b_arg, mpz_tdiv_qr, (gmp_binary_ui_op2_t)mpz_tdiv_qr_ui); + gmp_zval_binary_ui_op2_ex(return_value, a_arg, b_arg, mpz_tdiv_qr, (gmp_binary_ui_op2_t)mpz_tdiv_qr_ui, 0, 1 TSRMLS_CC); break; case GMP_ROUND_PLUSINF: - gmp_zval_binary_ui_op2(return_value, a_arg, b_arg, mpz_cdiv_qr, (gmp_binary_ui_op2_t)mpz_cdiv_qr_ui); + gmp_zval_binary_ui_op2_ex(return_value, a_arg, b_arg, mpz_cdiv_qr, (gmp_binary_ui_op2_t)mpz_cdiv_qr_ui, 0, 1 TSRMLS_CC); break; case GMP_ROUND_MINUSINF: - gmp_zval_binary_ui_op2(return_value, a_arg, b_arg, mpz_fdiv_qr, (gmp_binary_ui_op2_t)mpz_fdiv_qr_ui); + gmp_zval_binary_ui_op2_ex(return_value, a_arg, b_arg, mpz_fdiv_qr, (gmp_binary_ui_op2_t)mpz_fdiv_qr_ui, 0, 1 TSRMLS_CC); break; } @@ -690,13 +710,13 @@ ZEND_FUNCTION(gmp_div_r) switch (round) { case GMP_ROUND_ZERO: - gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_tdiv_r, (gmp_binary_ui_op_t)mpz_tdiv_r_ui, 1 TSRMLS_CC); + gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_tdiv_r, (gmp_binary_ui_op_t)mpz_tdiv_r_ui, 1, 1 TSRMLS_CC); break; case GMP_ROUND_PLUSINF: - gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_cdiv_r, (gmp_binary_ui_op_t)mpz_cdiv_r_ui, 1 TSRMLS_CC); + gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_cdiv_r, (gmp_binary_ui_op_t)mpz_cdiv_r_ui, 1, 1 TSRMLS_CC); break; case GMP_ROUND_MINUSINF: - gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_fdiv_r, (gmp_binary_ui_op_t)mpz_fdiv_r_ui, 1 TSRMLS_CC); + gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_fdiv_r, (gmp_binary_ui_op_t)mpz_fdiv_r_ui, 1, 1 TSRMLS_CC); break; } } @@ -726,13 +746,13 @@ ZEND_FUNCTION(gmp_div_q) switch (round) { case GMP_ROUND_ZERO: - gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_tdiv_q, (gmp_binary_ui_op_t)mpz_tdiv_q_ui); + gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_tdiv_q, (gmp_binary_ui_op_t)mpz_tdiv_q_ui, 0, 1 TSRMLS_CC); break; case GMP_ROUND_PLUSINF: - gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_cdiv_q, (gmp_binary_ui_op_t)mpz_cdiv_q_ui); + gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_cdiv_q, (gmp_binary_ui_op_t)mpz_cdiv_q_ui, 0, 1 TSRMLS_CC); break; case GMP_ROUND_MINUSINF: - gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_fdiv_q, (gmp_binary_ui_op_t)mpz_fdiv_q_ui); + gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_fdiv_q, (gmp_binary_ui_op_t)mpz_fdiv_q_ui, 0, 1 TSRMLS_CC); break; } @@ -749,7 +769,7 @@ ZEND_FUNCTION(gmp_mod) WRONG_PARAM_COUNT; } - gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_mod, (gmp_binary_ui_op_t)mpz_mod_ui, 1 TSRMLS_CC); + gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_mod, (gmp_binary_ui_op_t)mpz_mod_ui, 1, 1 TSRMLS_CC); } /* }}} */ @@ -781,7 +801,28 @@ ZEND_FUNCTION(gmp_abs) Calculates factorial function */ ZEND_FUNCTION(gmp_fact) { - gmp_unary_ui_op(mpz_fac_ui); + zval **a_arg; + mpz_t *gmpnum_tmp; + + if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &a_arg) == FAILURE){ + WRONG_PARAM_COUNT; + } + + if (Z_TYPE_PP(a_arg) == IS_RESOURCE) { + FETCH_GMP_ZVAL(gmpnum_tmp, a_arg); + if (mpz_sgn(*gmpnum_tmp) < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING,"Number has to be greater than or equal to 0"); + RETURN_FALSE; + } + } else { + convert_to_long_ex(a_arg); + if (Z_LVAL_PP(a_arg) < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING,"Number has to be greater than or equal to 0"); + RETURN_FALSE; + } + } + + gmp_zval_unary_ui_op(return_value, a_arg, mpz_fac_ui); } /* }}} */ @@ -839,6 +880,10 @@ ZEND_FUNCTION(gmp_powm) use_ui = 1; } else { FETCH_GMP_ZVAL(gmpnum_exp, exp_arg); + if (mpz_sgn(*gmpnum_exp) < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING,"Second parameter cannot be less than 0"); + RETURN_FALSE; + } } FETCH_GMP_ZVAL(gmpnum_mod, mod_arg); @@ -862,7 +907,24 @@ ZEND_FUNCTION(gmp_powm) Takes integer part of square root of a */ ZEND_FUNCTION(gmp_sqrt) { - gmp_unary_op(mpz_sqrt); + zval **a_arg; + mpz_t *gmpnum_a, *gmpnum_result; + + if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &a_arg) == FAILURE){ + WRONG_PARAM_COUNT; + } + + FETCH_GMP_ZVAL(gmpnum_a, a_arg); + + if (mpz_sgn(*gmpnum_a) < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING,"Number has to be greater than or equal to 0"); + RETURN_FALSE; + } + + INIT_GMP_NUM(gmpnum_result); + mpz_sqrt(*gmpnum_result, *gmpnum_a); + + ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp); } /* }}} */ @@ -880,6 +942,11 @@ ZEND_FUNCTION(gmp_sqrtrem) FETCH_GMP_ZVAL(gmpnum_a, a_arg); + if (mpz_sgn(*gmpnum_a) < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING,"Number has to be greater than or equal to 0"); + RETURN_FALSE; + } + INIT_GMP_NUM(gmpnum_result1); INIT_GMP_NUM(gmpnum_result2); @@ -949,7 +1016,7 @@ ZEND_FUNCTION(gmp_gcd) WRONG_PARAM_COUNT; } - gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_gcd, (gmp_binary_ui_op_t)mpz_gcd_ui, 1 TSRMLS_CC); + gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_gcd, (gmp_binary_ui_op_t)mpz_gcd_ui, 1, 0 TSRMLS_CC); } /* }}} */ diff --git a/ext/gmp/tests/bug32773.phpt b/ext/gmp/tests/bug32773.phpt new file mode 100644 index 000000000000..0890362c7d69 --- /dev/null +++ b/ext/gmp/tests/bug32773.phpt @@ -0,0 +1,24 @@ +--TEST-- +Bug #32773 binary GMP functions returns unexpected value, when second parameter is int(0) +--SKIPIF-- + +--POST-- +--GET-- +--FILE-- + +--EXPECTF-- +10 + 0 = 10 +10 + "0" = 10 + +Warning: gmp_div(): Zero operand not allowed in %s on line %d +0 + +Warning: gmp_div_qr(): Zero operand not allowed in %s on line %d +0 diff --git a/ext/hwapi/hwapi.cpp b/ext/hwapi/hwapi.cpp index 157195ae01cf..b2530d6cf702 100644 --- a/ext/hwapi/hwapi.cpp +++ b/ext/hwapi/hwapi.cpp @@ -202,8 +202,8 @@ zend_module_entry hwapi_module_entry = { "hwapi", hwapi_functions, PHP_MINIT(hwapi), - PHP_MSHUTDOWN(hwapi), - PHP_RINIT(hwapi), + NULL, + NULL, NULL, PHP_MINFO(hwapi), NO_VERSION_YET, @@ -2224,14 +2224,6 @@ PHP_MINIT_FUNCTION(hwapi) { return SUCCESS; } -PHP_MSHUTDOWN_FUNCTION(hwapi) { - return SUCCESS; -} - -PHP_RINIT_FUNCTION(hwapi) { - return SUCCESS; -} - PHP_MINFO_FUNCTION(hwapi) { php_info_print_table_start(); php_info_print_table_row(2, "Hyperwave API Support", "enabled"); diff --git a/ext/hwapi/php_hwapi.h b/ext/hwapi/php_hwapi.h index 9c199134fddc..2c54d04fea52 100644 --- a/ext/hwapi/php_hwapi.h +++ b/ext/hwapi/php_hwapi.h @@ -66,8 +66,6 @@ extern PHP_HWAPI_API zend_hwapi_globals hwapi_globals; #endif extern PHP_MINIT_FUNCTION(hwapi); -extern PHP_MSHUTDOWN_FUNCTION(hwapi); -extern PHP_RINIT_FUNCTION(hwapi); PHP_MINFO_FUNCTION(hwapi); /* HW_API */ diff --git a/ext/iconv/config.m4 b/ext/iconv/config.m4 index 6f49e423f2a1..9be86a13cc4a 100644 --- a/ext/iconv/config.m4 +++ b/ext/iconv/config.m4 @@ -44,7 +44,7 @@ if test "$PHP_ICONV" != "no"; then else case "$iconv_lib_name" in iconv [)] - AC_MSG_CHECKING([if iconv is Konstantin Chugeuv's]) + AC_MSG_CHECKING([if iconv is Konstantin Chuguev's]) AC_TRY_LINK([#include ],[iconv_ccs_init(NULL, NULL);], [ AC_MSG_RESULT(yes) @@ -65,23 +65,26 @@ if test "$PHP_ICONV" != "no"; then esac fi + echo > ext/iconv/php_have_bsd_iconv.h + echo > ext/iconv/php_have_glibc_iconv.h + case "$iconv_impl_name" in gnu_libiconv [)] - PHP_DEFINE([PHP_ICONV_IMPL],[\"libiconv\"]) + PHP_DEFINE([PHP_ICONV_IMPL],[\"libiconv\"],[ext/iconv]) AC_DEFINE([PHP_ICONV_IMPL],["libiconv"],[Which iconv implementation to use]) ;; bsd [)] - PHP_DEFINE([HAVE_BSD_ICONV],1) - AC_DEFINE([HAVE_BSD_ICONV],1,[Konstantin Chugeuv's iconv implementation]) - PHP_DEFINE([PHP_ICONV_IMPL],[\"BSD iconv\"]) + PHP_DEFINE([HAVE_BSD_ICONV],1,[ext/iconv]) + AC_DEFINE([HAVE_BSD_ICONV],1,[Konstantin Chuguev's iconv implementation]) + PHP_DEFINE([PHP_ICONV_IMPL],[\"BSD iconv\"],[ext/iconv]) AC_DEFINE([PHP_ICONV_IMPL],["BSD iconv"],[Which iconv implementation to use]) ;; glibc [)] - PHP_DEFINE([HAVE_GLIBC_ICONV],1) + PHP_DEFINE([HAVE_GLIBC_ICONV],1,[ext/iconv]) AC_DEFINE([HAVE_GLIBC_ICONV],1,[glibc's iconv implementation]) - PHP_DEFINE([PHP_ICONV_IMPL],[\"glibc\"]) + PHP_DEFINE([PHP_ICONV_IMPL],[\"glibc\"],[ext/iconv]) AC_DEFINE([PHP_ICONV_IMPL],["glibc"],[Which iconv implementation to use]) ;; esac @@ -106,11 +109,11 @@ int main() { } ],[ AC_MSG_RESULT(yes) - PHP_DEFINE([ICONV_SUPPORTS_ERRNO],1) + PHP_DEFINE([ICONV_SUPPORTS_ERRNO],1,[ext/iconv]) AC_DEFINE([ICONV_SUPPORTS_ERRNO],1,[Whether iconv supports error no or not]) ],[ AC_MSG_RESULT(no) - PHP_DEFINE([ICONV_SUPPORTS_ERRNO],0) + PHP_DEFINE([ICONV_SUPPORTS_ERRNO],0,[ext/iconv]) AC_DEFINE([ICONV_SUPPORTS_ERRNO],0,[Whether iconv supports error no or not]) ]) @@ -120,7 +123,7 @@ int main() { #include FOO ], [], [ AC_MSG_RESULT([yes]) - PHP_DEFINE([PHP_ICONV_H_PATH], [<$PHP_ICONV_H_PATH>]) + PHP_DEFINE([PHP_ICONV_H_PATH], [<$PHP_ICONV_H_PATH>],[ext/iconv]) AC_DEFINE_UNQUOTED([PHP_ICONV_H_PATH], [<$PHP_ICONV_H_PATH>], [Path to iconv.h]) ], [ AC_MSG_RESULT([no]) diff --git a/ext/iconv/config.w32 b/ext/iconv/config.w32 index ee6213a753d4..8b38e2c37b5f 100644 --- a/ext/iconv/config.w32 +++ b/ext/iconv/config.w32 @@ -12,6 +12,10 @@ if (PHP_ICONV != "no") { AC_DEFINE("HAVE_LIBICONV", 1, "Define if libiconv is available"); AC_DEFINE("PHP_ICONV_IMPL", "\"libiconv\"", "Which iconv implementation to use"); AC_DEFINE("ICONV_SUPPORTS_ERRNO", 1, "Whether iconv supports errno or not"); + ADD_FLAG("CFLAGS_ICONV", "/D PHP_ICONV_EXPORTS "); + if (!PHP_ICONV_SHARED) { + ADD_DEF_FILE("ext\\iconv\\php_iconv.def"); + } } } diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c index 4f0905cf5970..7020ff00eff6 100644 --- a/ext/iconv/iconv.c +++ b/ext/iconv/iconv.c @@ -106,20 +106,6 @@ ZEND_GET_MODULE(iconv) #define iconv libiconv #endif -/* {{{ typedef enum php_iconv_err_t */ -typedef enum _php_iconv_err_t { - PHP_ICONV_ERR_SUCCESS = SUCCESS, - PHP_ICONV_ERR_CONVERTER = 1, - PHP_ICONV_ERR_WRONG_CHARSET = 2, - PHP_ICONV_ERR_TOO_BIG = 3, - PHP_ICONV_ERR_ILLEGAL_SEQ = 4, - PHP_ICONV_ERR_ILLEGAL_CHAR = 5, - PHP_ICONV_ERR_UNKNOWN = 6, - PHP_ICONV_ERR_MALFORMED = 7, - PHP_ICONV_ERR_ALLOC = 8 -} php_iconv_err_t; -/* }}} */ - /* {{{ typedef enum php_iconv_enc_scheme_t */ typedef enum _php_iconv_enc_scheme_t { PHP_ICONV_ENC_SCHEME_BASE64, @@ -134,8 +120,6 @@ typedef enum _php_iconv_enc_scheme_t { static php_iconv_err_t _php_iconv_appendl(smart_str *d, const char *s, size_t l, iconv_t cd); static php_iconv_err_t _php_iconv_appendc(smart_str *d, const char c, iconv_t cd); -static php_iconv_err_t php_iconv_string(const char * in_p, size_t in_len, char **out, size_t *out_len, const char *out_charset, const char *in_charset); - static void _php_iconv_show_error(php_iconv_err_t err, const char *out_charset, const char *in_charset TSRMLS_DC); static php_iconv_err_t _php_iconv_strlen(unsigned int *pretval, const char *str, size_t nbytes, const char *enc); @@ -335,7 +319,7 @@ static php_iconv_err_t _php_iconv_appendc(smart_str *d, const char c, iconv_t cd /* {{{ php_iconv_string() */ -php_iconv_err_t php_iconv_string(const char *in_p, size_t in_len, +PHP_ICONV_API php_iconv_err_t php_iconv_string(const char *in_p, size_t in_len, char **out, size_t *out_len, const char *out_charset, const char *in_charset) { @@ -532,7 +516,7 @@ static php_iconv_err_t _php_iconv_strlen(unsigned int *pretval, const char *str, #endif } - out_left = 0; + errno = out_left = 0; for (in_p = str, in_left = nbytes, cnt = 0; in_left > 0; cnt+=2) { size_t prev_in_left; @@ -563,6 +547,7 @@ static php_iconv_err_t _php_iconv_strlen(unsigned int *pretval, const char *str, break; case E2BIG: + case 0: *pretval = cnt; break; @@ -1925,24 +1910,20 @@ PHP_FUNCTION(iconv_strrpos) Composes a mime header field with field_name and field_value in a specified scheme */ PHP_FUNCTION(iconv_mime_encode) { - char *field_name; + const char *field_name = NULL; int field_name_len; - char *field_value; + const char *field_value = NULL; int field_value_len; - zval *pref; - zval val, *pval, **ppval; - char *in_charset; - char *out_charset; - long line_len = 76; - zval lfchars; - - php_iconv_enc_scheme_t scheme_id = PHP_ICONV_ENC_SCHEME_BASE64; - + zval *pref = NULL; + zval tmp_zv, *tmp_zv_p = NULL; smart_str retval = {0}; - php_iconv_err_t err; - in_charset = ICONVG(internal_encoding); + const char *in_charset = ICONVG(internal_encoding); + const char *out_charset = in_charset; + long line_len = 76; + const char *lfchars = "\r\n"; + php_iconv_enc_scheme_t scheme_id = PHP_ICONV_ENC_SCHEME_BASE64; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a", &field_name, &field_name_len, &field_value, &field_value_len, @@ -1951,65 +1932,70 @@ PHP_FUNCTION(iconv_mime_encode) RETURN_FALSE; } - if (zend_hash_find(Z_ARRVAL_P(pref), "scheme", sizeof("scheme"), (void **)&ppval) == SUCCESS) { - if (Z_TYPE_PP(ppval) == IS_STRING && Z_STRLEN_PP(ppval) > 0) { - switch (Z_STRVAL_PP(ppval)[0]) { - case 'B': case 'b': - scheme_id = PHP_ICONV_ENC_SCHEME_BASE64; - break; + if (pref != NULL) { + zval **ppval; - case 'Q': case 'q': - scheme_id = PHP_ICONV_ENC_SCHEME_QPRINT; - break; + if (zend_hash_find(Z_ARRVAL_P(pref), "scheme", sizeof("scheme"), (void **)&ppval) == SUCCESS) { + if (Z_TYPE_PP(ppval) == IS_STRING && Z_STRLEN_PP(ppval) > 0) { + switch (Z_STRVAL_PP(ppval)[0]) { + case 'B': case 'b': + scheme_id = PHP_ICONV_ENC_SCHEME_BASE64; + break; + + case 'Q': case 'q': + scheme_id = PHP_ICONV_ENC_SCHEME_QPRINT; + break; + } } } - } - - in_charset = ICONVG(internal_encoding); - if (zend_hash_find(Z_ARRVAL_P(pref), "input-charset", sizeof("input-charset"), (void **)&ppval) == SUCCESS) { - if (Z_TYPE_PP(ppval) == IS_STRING && Z_STRLEN_PP(ppval) > 0) { - in_charset = Z_STRVAL_PP(ppval); + if (zend_hash_find(Z_ARRVAL_P(pref), "input-charset", sizeof("input-charset"), (void **)&ppval) == SUCCESS) { + if (Z_TYPE_PP(ppval) == IS_STRING && Z_STRLEN_PP(ppval) > 0) { + in_charset = Z_STRVAL_PP(ppval); + } } - } - out_charset = in_charset; - if (zend_hash_find(Z_ARRVAL_P(pref), "output-charset", sizeof("output-charset"), (void **)&ppval) == SUCCESS) { - if (Z_TYPE_PP(ppval) == IS_STRING && Z_STRLEN_PP(ppval) > 0) { - out_charset = Z_STRVAL_PP(ppval); + if (zend_hash_find(Z_ARRVAL_P(pref), "output-charset", sizeof("output-charset"), (void **)&ppval) == SUCCESS) { + if (Z_TYPE_PP(ppval) == IS_STRING && Z_STRLEN_PP(ppval) > 0) { + out_charset = Z_STRVAL_PP(ppval); + } } - } - if (zend_hash_find(Z_ARRVAL_P(pref), "line-length", sizeof("line-length"), (void **)&ppval) == SUCCESS) { - pval = *ppval; - if (Z_TYPE_P(pval) != IS_LONG) { - val = *pval; - zval_copy_ctor(&val); - convert_to_long(&val); - pval = &val; - } + if (zend_hash_find(Z_ARRVAL_P(pref), "line-length", sizeof("line-length"), (void **)&ppval) == SUCCESS) { + zval val, *pval = *ppval; - line_len = Z_LVAL_P(pval); + if (Z_TYPE_P(pval) != IS_LONG) { + val = *pval; + zval_copy_ctor(&val); + convert_to_long(&val); + pval = &val; + } - if (pval == &val) { - zval_dtor(&val); + line_len = Z_LVAL_P(pval); + + if (pval == &val) { + zval_dtor(&val); + } } - } - if (zend_hash_find(Z_ARRVAL_P(pref), "line-break-chars", sizeof("line-break-chars"), (void **)&ppval) == SUCCESS) { - lfchars = **ppval; - zval_copy_ctor(&lfchars); + if (zend_hash_find(Z_ARRVAL_P(pref), "line-break-chars", sizeof("line-break-chars"), (void **)&ppval) == SUCCESS) { + if (Z_TYPE_PP(ppval) != IS_STRING) { + tmp_zv = **ppval; + zval_copy_ctor(&tmp_zv); + convert_to_string(&tmp_zv); + + lfchars = Z_STRVAL(tmp_zv); - if (Z_TYPE(lfchars) != IS_STRING) { - convert_to_string(&lfchars); + tmp_zv_p = &tmp_zv; + } else { + lfchars = Z_STRVAL_PP(ppval); + } } - } else { - ZVAL_STRING(&lfchars, "\r\n", 1); } err = _php_iconv_mime_encode(&retval, field_name, field_name_len, - field_value, field_value_len, line_len, Z_STRVAL(lfchars), scheme_id, + field_value, field_value_len, line_len, lfchars, scheme_id, out_charset, in_charset); _php_iconv_show_error(err, out_charset, in_charset TSRMLS_CC); @@ -2024,7 +2010,9 @@ PHP_FUNCTION(iconv_mime_encode) RETVAL_FALSE; } - zval_dtor(&lfchars); + if (tmp_zv_p != NULL) { + zval_dtor(tmp_zv_p); + } } /* }}} */ @@ -2344,7 +2332,7 @@ static php_iconv_err_t php_iconv_stream_filter_ctor(php_iconv_stream_filter *sel /* }}} */ /* {{{ php_iconv_stream_filter_append_bucket */ -static size_t php_iconv_stream_filter_append_bucket( +static int php_iconv_stream_filter_append_bucket( php_iconv_stream_filter *self, php_stream *stream, php_stream_filter *filter, php_stream_bucket_brigade *buckets_out, @@ -2367,7 +2355,11 @@ static size_t php_iconv_stream_filter_append_bucket( } out_buf_size = ocnt = prev_ocnt = initial_out_buf_size; - out_buf = pd = pemalloc(out_buf_size, self->persistent); + if (NULL == (out_buf = pemalloc(out_buf_size, persistent))) { + return FAILURE; + } + + pd = out_buf; if (self->stub_len > 0) { pt = self->stub; @@ -2407,14 +2399,26 @@ static size_t php_iconv_stream_filter_append_bucket( if (new_out_buf_size < out_buf_size) { /* whoa! no bigger buckets are sold anywhere... */ - new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, self->persistent TSRMLS_CC); + if (NULL == (new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, persistent TSRMLS_CC))) { + goto out_failure; + } php_stream_bucket_append(buckets_out, new_bucket TSRMLS_CC); out_buf_size = ocnt = initial_out_buf_size; - out_buf = pd = pemalloc(out_buf_size, self->persistent); + if (NULL == (out_buf = pemalloc(out_buf_size, persistent))) { + return FAILURE; + } + pd = out_buf; } else { - new_out_buf = perealloc(out_buf, new_out_buf_size, self->persistent); + if (NULL == (new_out_buf = perealloc(out_buf, new_out_buf_size, persistent))) { + if (NULL == (new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, persistent TSRMLS_CC))) { + goto out_failure; + } + + php_stream_bucket_append(buckets_out, new_bucket TSRMLS_CC); + return FAILURE; + } pd = new_out_buf + (pd - out_buf); ocnt += (new_out_buf_size - out_buf_size); out_buf = new_out_buf; @@ -2441,7 +2445,7 @@ static size_t php_iconv_stream_filter_append_bucket( while (icnt > 0) { if ((ps == NULL ? iconv(self->cd, NULL, NULL, &pd, &ocnt): - iconv(self->cd, &ps, &icnt, &pd, &ocnt)) == (size_t)-1) { + iconv(self->cd, (char **)&ps, &icnt, &pd, &ocnt)) == (size_t)-1) { #if ICONV_SUPPORTS_ERRNO switch (errno) { case EILSEQ: @@ -2472,14 +2476,26 @@ static size_t php_iconv_stream_filter_append_bucket( if (new_out_buf_size < out_buf_size) { /* whoa! no bigger buckets are sold anywhere... */ - new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, self->persistent TSRMLS_CC); + if (NULL == (new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, persistent TSRMLS_CC))) { + goto out_failure; + } php_stream_bucket_append(buckets_out, new_bucket TSRMLS_CC); out_buf_size = ocnt = initial_out_buf_size; - out_buf = pd = pemalloc(out_buf_size, self->persistent); + if (NULL == (out_buf = pemalloc(out_buf_size, persistent))) { + return FAILURE; + } + pd = out_buf; } else { - new_out_buf = perealloc(out_buf, new_out_buf_size, self->persistent); + if (NULL == (new_out_buf = perealloc(out_buf, new_out_buf_size, persistent))) { + if (NULL == (new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, persistent TSRMLS_CC))) { + goto out_failure; + } + + php_stream_bucket_append(buckets_out, new_bucket TSRMLS_CC); + return FAILURE; + } pd = new_out_buf + (pd - out_buf); ocnt += (new_out_buf_size - out_buf_size); out_buf = new_out_buf; @@ -2506,17 +2522,19 @@ static size_t php_iconv_stream_filter_append_bucket( } if (out_buf_size - ocnt > 0) { - new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, self->persistent TSRMLS_CC); + if (NULL == (new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, persistent TSRMLS_CC))) { + goto out_failure; + } php_stream_bucket_append(buckets_out, new_bucket TSRMLS_CC); } else { - pefree(out_buf, self->persistent); + pefree(out_buf, persistent); } *consumed += buf_len - icnt; return SUCCESS; out_failure: - pefree(out_buf, self->persistent); + pefree(out_buf, persistent); return FAILURE; } @@ -2531,27 +2549,32 @@ static php_stream_filter_status_t php_iconv_stream_filter_do_filter( size_t consumed = 0; php_iconv_stream_filter *self = (php_iconv_stream_filter *)filter->abstract; - if (flags != PSFS_FLAG_NORMAL) { - if (php_iconv_stream_filter_append_bucket(self, stream, filter, buckets_out, NULL, 0, &consumed, self->persistent TSRMLS_CC) != SUCCESS) { + while (buckets_in->head != NULL) { + bucket = buckets_in->head; + + php_stream_bucket_unlink(bucket TSRMLS_CC); + + if (php_iconv_stream_filter_append_bucket(self, stream, filter, + buckets_out, bucket->buf, bucket->buflen, &consumed, + php_stream_is_persistent(stream) TSRMLS_CC) != SUCCESS) { goto out_failure; } - } else { - while (buckets_in->head != NULL) { - bucket = buckets_in->head; - - php_stream_bucket_unlink(bucket TSRMLS_CC); - if (php_iconv_stream_filter_append_bucket(self, stream, filter, buckets_out, bucket->buf, bucket->buflen, &consumed, self->persistent TSRMLS_CC) != SUCCESS) { goto out_failure; - } + php_stream_bucket_delref(bucket TSRMLS_CC); + } - php_stream_bucket_delref(bucket TSRMLS_CC); + if (flags != PSFS_FLAG_NORMAL) { + if (php_iconv_stream_filter_append_bucket(self, stream, filter, + buckets_out, NULL, 0, &consumed, + php_stream_is_persistent(stream) TSRMLS_CC) != SUCCESS) { + goto out_failure; } } - if (bytes_consumed) { + if (bytes_consumed != NULL) { *bytes_consumed = consumed; } - + return PSFS_PASS_ON; out_failure: diff --git a/ext/iconv/php_iconv.def b/ext/iconv/php_iconv.def new file mode 100644 index 000000000000..2f77aa4c79ec --- /dev/null +++ b/ext/iconv/php_iconv.def @@ -0,0 +1,6 @@ +EXPORTS +_libiconv_version +libiconv_close +libiconv +libiconv_open +libiconv_set_relocation_prefix diff --git a/ext/iconv/php_iconv.h b/ext/iconv/php_iconv.h index 7479560cf188..de50e5bd343c 100644 --- a/ext/iconv/php_iconv.h +++ b/ext/iconv/php_iconv.h @@ -23,19 +23,23 @@ #define PHP_ICONV_H #ifdef PHP_WIN32 +#ifdef PHP_ICONV_EXPORTS #define PHP_ICONV_API __declspec(dllexport) #else +#define PHP_ICONV_API __declspec(dllimport) +#endif +#else #define PHP_ICONV_API #endif #ifdef PHP_ATOM_INC -#include "php_have_iconv.h" -#include "php_have_libiconv.h" -#include "php_have_glibc_iconv.h" -#include "php_have_bsd_iconv.h" -#include "php_iconv_supports_errno.h" -#include "php_php_iconv_impl.h" -#include "php_php_iconv_h_path.h" +#include "ext/iconv/php_have_iconv.h" +#include "ext/iconv/php_have_libiconv.h" +#include "ext/iconv/php_have_glibc_iconv.h" +#include "ext/iconv/php_have_bsd_iconv.h" +#include "ext/iconv/php_iconv_supports_errno.h" +#include "ext/iconv/php_php_iconv_impl.h" +#include "ext/iconv/php_php_iconv_h_path.h" #endif @@ -75,6 +79,22 @@ ZEND_END_MODULE_GLOBALS(iconv) #define ICONV_OUTPUT_ENCODING "ISO-8859-1" #define ICONV_INTERNAL_ENCODING "ISO-8859-1" +/* {{{ typedef enum php_iconv_err_t */ +typedef enum _php_iconv_err_t { + PHP_ICONV_ERR_SUCCESS = SUCCESS, + PHP_ICONV_ERR_CONVERTER = 1, + PHP_ICONV_ERR_WRONG_CHARSET = 2, + PHP_ICONV_ERR_TOO_BIG = 3, + PHP_ICONV_ERR_ILLEGAL_SEQ = 4, + PHP_ICONV_ERR_ILLEGAL_CHAR = 5, + PHP_ICONV_ERR_UNKNOWN = 6, + PHP_ICONV_ERR_MALFORMED = 7, + PHP_ICONV_ERR_ALLOC = 8 +} php_iconv_err_t; +/* }}} */ + +PHP_ICONV_API php_iconv_err_t php_iconv_string(const char * in_p, size_t in_len, char **out, size_t *out_len, const char *in_charset, const char *out_charset); + #else #define iconv_module_ptr NULL diff --git a/ext/iconv/tests/iconv004.phpt b/ext/iconv/tests/iconv004.phpt new file mode 100644 index 000000000000..0e40ed4fcc43 --- /dev/null +++ b/ext/iconv/tests/iconv004.phpt @@ -0,0 +1,10 @@ +--TEST-- +iconv_mime_encode() sanity cheeck. +--FILE-- + 1))); +?> +--EXPECT-- +string(19) ": =?ISO-8859-1?B??=" +string(19) ": =?ISO-8859-1?B??=" diff --git a/ext/iconv/tests/iconv_mime_encode.phpt b/ext/iconv/tests/iconv_mime_encode.phpt index f002ec75faf0..fd6cc6909ddb 100644 --- a/ext/iconv/tests/iconv_mime_encode.phpt +++ b/ext/iconv/tests/iconv_mime_encode.phpt @@ -23,7 +23,7 @@ for ($line_len= 0; $line_len < 80; ++$line_len) { $result = iconv_mime_encode("From", "¥µ¥ó¥×¥ëʸ»úÎó¥µ¥ó¥×¥ëʸ»úÎóÆüËÜ¸ì¥Æ¥­¥¹¥È", $preference); var_dump($result); if ($result !== false) { - list($max) = rsort(array_map("strlen", explode("\n", $result))); + $max = max(array_map("strlen", explode("\n", $result))); print "-------- "; var_dump(($max <= $line_len)); } else { diff --git a/ext/iconv/tests/translit-utf8.phpt b/ext/iconv/tests/translit-utf8.phpt index 10f9605bb1ee..64991aab8d8c 100644 --- a/ext/iconv/tests/translit-utf8.phpt +++ b/ext/iconv/tests/translit-utf8.phpt @@ -12,7 +12,7 @@ error_reporting=2047 IMAP: Include SSL support. DIR is the OpenSSL install dir.],[ - PHP_IMAP_SSL=$withval - ],[ - PHP_IMAP_SSL=no - ]) - - if test "$PHP_IMAP_SSL" = "yes"; then - PHP_IMAP_SSL=/usr - fi - - AC_MSG_CHECKING([whether SSL libraries are needed for c-client]) - +AC_DEFUN([PHP_IMAP_SSL_CHK], [ if test "$PHP_IMAP_SSL" != "no"; then - AC_MSG_RESULT([$PHP_IMAP_SSL/lib]) - AC_DEFINE(HAVE_IMAP_SSL,1,[ ]) - PHP_ADD_LIBRARY_DEFER(ssl, 1, IMAP_SHARED_LIBADD) - PHP_ADD_LIBRARY_DEFER(crypto, 1, IMAP_SHARED_LIBADD) - PHP_ADD_LIBPATH($PHP_IMAP_SSL/lib, IMAP_SHARED_LIBADD) - else - AC_MSG_RESULT(no) + PHP_SETUP_OPENSSL(IMAP_SHARED_LIBADD, + [ + AC_DEFINE(HAVE_IMAP_SSL,1,[ ]) + ], [ + AC_MSG_ERROR([OpenSSL libraries not found. + + Check the path given to --with-openssl-dir and output in config.log) + ]) + ]) + elif test -f "$IMAP_INC_DIR/linkage.c"; then + AC_EGREP_HEADER(ssl_onceonlyinit, $IMAP_INC_DIR/linkage.c, [ + AC_MSG_ERROR([This c-client library is built with SSL support. + + Add --with-imap-ssl to your configure line. Check config.log for details. + ]) + ]) fi ]) @@ -118,8 +88,14 @@ AC_DEFUN(PHP_IMAP_SSL_CHK, [ PHP_ARG_WITH(imap,for IMAP support, [ --with-imap[=DIR] Include IMAP support. DIR is the c-client install prefix.]) -if test "$PHP_IMAP" != "no"; then +PHP_ARG_WITH(kerberos,for IMAP Kerberos support, +[ --with-kerberos[=DIR] IMAP: Include Kerberos support. DIR is the Kerberos install prefix.], no, no) + +PHP_ARG_WITH(imap-ssl,for IMAP SSL support, +[ --with-imap-ssl[=DIR] IMAP: Include SSL support. DIR is the OpenSSL install prefix.], no, no) + +if test "$PHP_IMAP" != "no"; then PHP_SUBST(IMAP_SHARED_LIBADD) PHP_NEW_EXTENSION(imap, php_imap.c, $ext_shared) AC_DEFINE(HAVE_IMAP,1,[ ]) @@ -134,6 +110,12 @@ if test "$PHP_IMAP" != "no"; then fi done + dnl Check for c-client version 2004 + AC_EGREP_HEADER(mail_fetch_overview_sequence, $IMAP_INC_DIR/mail.h, [ + AC_DEFINE(HAVE_IMAP2004,1,[ ]) + ]) + + dnl Check for c-client version 2001 old_CPPFLAGS=$CPPFLAGS CPPFLAGS=-I$IMAP_INC_DIR AC_EGREP_CPP(this_is_true, [ @@ -161,7 +143,7 @@ if test "$PHP_IMAP" != "no"; then PHP_EXPAND_PATH($IMAP_DIR, IMAP_DIR) if test -z "$IMAP_DIR"; then - AC_MSG_ERROR(Cannot find rfc822.h. Please check your IMAP installation.) + AC_MSG_ERROR(Cannot find rfc822.h. Please check your c-client installation.) fi if test -r "$IMAP_DIR/c-client/c-client.a"; then @@ -177,7 +159,7 @@ if test "$PHP_IMAP" != "no"; then done if test -z "$IMAP_LIBDIR"; then - AC_MSG_ERROR(Cannot find imap library (libc-client.a). Please check your IMAP installation.) + AC_MSG_ERROR(Cannot find imap library (libc-client.a). Please check your c-client installation.) fi PHP_ADD_INCLUDE($IMAP_INC_DIR) diff --git a/ext/imap/imap.h b/ext/imap/imap.h deleted file mode 100644 index 914d12831661..000000000000 --- a/ext/imap/imap.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef _INCLUDED_IMAP_H -#define _INCLUDED_IMAP_H - -#if COMPILE_DL -#undef HAVE_IMAP -#define HAVE_IMAP 1 -#endif - -#if HAVE_IMAP - -#ifndef PHP_WIN32 -#include "build-defs.h" -#endif - -/* Functions accessable to PHP */ -extern zend_module_entry imap_module_entry; -#define imap_module_ptr &imap_module_entry - -extern PHP_MINIT_FUNCTION(imap); -extern PHP_RINIT_FUNCTION(imap); -extern PHP_RSHUTDOWN_FUNCTION(imap); -PHP_MINFO_FUNCTION(imap); -PHP_FUNCTION(imap_open); -PHP_FUNCTION(imap_popen); -PHP_FUNCTION(imap_reopen); -PHP_FUNCTION(imap_num_msg); -PHP_FUNCTION(imap_num_recent); -PHP_FUNCTION(imap_headers); -PHP_FUNCTION(imap_headerinfo); -PHP_FUNCTION(imap_rfc822_parse_headers); -PHP_FUNCTION(imap_body); -PHP_FUNCTION(imap_fetchstructure); -PHP_FUNCTION(imap_fetchbody); -PHP_FUNCTION(imap_expunge); -PHP_FUNCTION(imap_delete); -PHP_FUNCTION(imap_undelete); -PHP_FUNCTION(imap_check); -PHP_FUNCTION(imap_close); -PHP_FUNCTION(imap_mail_copy); -PHP_FUNCTION(imap_mail_move); -PHP_FUNCTION(imap_createmailbox); -PHP_FUNCTION(imap_renamemailbox); -PHP_FUNCTION(imap_deletemailbox); -PHP_FUNCTION(imap_listmailbox); -PHP_FUNCTION(imap_scanmailbox); -PHP_FUNCTION(imap_subscribe); -PHP_FUNCTION(imap_unsubscribe); -PHP_FUNCTION(imap_append); -PHP_FUNCTION(imap_ping); -PHP_FUNCTION(imap_base64); -PHP_FUNCTION(imap_qprint); -PHP_FUNCTION(imap_8bit); -PHP_FUNCTION(imap_binary); -PHP_FUNCTION(imap_mailboxmsginfo); -PHP_FUNCTION(imap_rfc822_write_address); -PHP_FUNCTION(imap_rfc822_parse_adrlist); -PHP_FUNCTION(imap_setflag_full); -PHP_FUNCTION(imap_clearflag_full); -PHP_FUNCTION(imap_sort); -PHP_FUNCTION(imap_fetchheader); -PHP_FUNCTION(imap_fetchtext); -PHP_FUNCTION(imap_uid); -PHP_FUNCTION(imap_msgno); -PHP_FUNCTION(imap_list); -PHP_FUNCTION(imap_list_full); -PHP_FUNCTION(imap_listscan); -PHP_FUNCTION(imap_lsub); -PHP_FUNCTION(imap_lsub_full); -PHP_FUNCTION(imap_create); -PHP_FUNCTION(imap_rename); -PHP_FUNCTION(imap_status); -PHP_FUNCTION(imap_bodystruct); -PHP_FUNCTION(imap_fetch_overview); -PHP_FUNCTION(imap_mail_compose); -PHP_FUNCTION(imap_alerts); -PHP_FUNCTION(imap_errors); -PHP_FUNCTION(imap_last_error); -PHP_FUNCTION(imap_mail); -PHP_FUNCTION(imap_search); -PHP_FUNCTION(imap_utf8); -PHP_FUNCTION(imap_utf7_decode); -PHP_FUNCTION(imap_utf7_encode); -PHP_FUNCTION(imap_mime_header_decode); -#else -#define imap_module_ptr NULL -#endif /* HAVE_IMAP */ - -#endif - - - - - - -#define phpext_imap_ptr imap_module_ptr - - - - - - - - diff --git a/ext/imap/php_imap.c b/ext/imap/php_imap.c index 728cd88707d9..4293379935de 100644 --- a/ext/imap/php_imap.c +++ b/ext/imap/php_imap.c @@ -57,7 +57,8 @@ MAILSTREAM DEFAULTPROTO; #endif -#define CRLF "\015\012" +#define CRLF "\015\012" +#define CRLF_LEN sizeof("\015\012") - 1 #define PHP_EXPUNGE 32768 #define PHP_IMAP_ADDRESS_SIZE_BUF 10 @@ -112,7 +113,7 @@ function_entry imap_functions[] = { PHP_FE(imap_qprint, NULL) PHP_FE(imap_8bit, NULL) PHP_FE(imap_binary, NULL) - PHP_FE(imap_utf8, NULL) + PHP_FE(imap_utf8, NULL) PHP_FE(imap_status, NULL) PHP_FE(imap_mailboxmsginfo, NULL) PHP_FE(imap_setflag_full, NULL) @@ -131,24 +132,24 @@ function_entry imap_functions[] = { PHP_FE(imap_utf7_encode, NULL) PHP_FE(imap_mime_header_decode, NULL) PHP_FE(imap_thread, NULL) - PHP_FE(imap_timeout, NULL) + PHP_FE(imap_timeout, NULL) #if defined(HAVE_IMAP2000) || defined(HAVE_IMAP2001) PHP_FE(imap_get_quota, NULL) PHP_FE(imap_get_quotaroot, NULL) PHP_FE(imap_set_quota, NULL) - PHP_FE(imap_setacl, NULL) - PHP_FE(imap_getacl, NULL) + PHP_FE(imap_setacl, NULL) + PHP_FE(imap_getacl, NULL) #endif PHP_FE(imap_mail, NULL) - PHP_FALIAS(imap_header, imap_headerinfo, NULL) - PHP_FALIAS(imap_listmailbox, imap_list, NULL) - PHP_FALIAS(imap_getmailboxes, imap_list_full, NULL) - PHP_FALIAS(imap_scanmailbox, imap_listscan, NULL) - PHP_FALIAS(imap_listsubscribed, imap_lsub, NULL) - PHP_FALIAS(imap_getsubscribed, imap_lsub_full, NULL) + PHP_FALIAS(imap_header, imap_headerinfo, NULL) + PHP_FALIAS(imap_listmailbox, imap_list, NULL) + PHP_FALIAS(imap_getmailboxes, imap_list_full, NULL) + PHP_FALIAS(imap_scanmailbox, imap_listscan, NULL) + PHP_FALIAS(imap_listsubscribed, imap_lsub, NULL) + PHP_FALIAS(imap_getsubscribed, imap_lsub_full, NULL) PHP_FALIAS(imap_fetchtext, imap_body, NULL) PHP_FALIAS(imap_scan, imap_listscan, NULL) PHP_FALIAS(imap_create, imap_createmailbox, NULL) @@ -182,6 +183,12 @@ ZEND_GET_MODULE(imap) /* True globals, no need for thread safety */ static int le_imap; +#define PHP_IMAP_CHECK_MSGNO(msgindex) \ + if ((msgindex < 1) || ((unsigned) msgindex > imap_le_struct->imap_stream->nmsgs)) { \ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad message number"); \ + RETURN_FALSE; \ + } \ + /* {{{ mail_close_it */ static void mail_close_it(zend_rsrc_list_entry *rsrc TSRMLS_DC) @@ -688,7 +695,9 @@ PHP_RSHUTDOWN_FUNCTION(imap) PHP_MINFO_FUNCTION(imap) { php_info_print_table_start(); -#if HAVE_IMAP2001 +#if HAVE_IMAP2004 + php_info_print_table_row(2, "IMAP c-Client Version", "2004"); +#elif HAVE_IMAP2001 php_info_print_table_row(2, "IMAP c-Client Version", "2001"); #elif HAVE_IMAP2000 php_info_print_table_row(2, "IMAP c-Client Version", "2000"); @@ -700,7 +709,7 @@ PHP_MINFO_FUNCTION(imap) #if HAVE_IMAP_SSL php_info_print_table_row(2, "SSL Support", "enabled"); #endif -#if HAVE_IMAP_KRB +#if HAVE_IMAP_KRB && HAVE_IMAP_AUTH_GSS php_info_print_table_row(2, "Kerberos Support", "enabled"); #endif php_info_print_table_end(); @@ -1018,6 +1027,7 @@ PHP_FUNCTION(imap_getacl) mail_parameters(NIL, SET_ACL, (void *) mail_getacl); if(!imap_getacl(imap_le_struct->imap_stream, Z_STRVAL_PP(mailbox))) { php_error(E_WARNING, "c-client imap_getacl failed"); + zval_dtor(return_value); RETURN_FALSE; } @@ -1516,12 +1526,20 @@ PHP_FUNCTION(imap_headerinfo) convert_to_long_ex(msgno); if (myargc >= 3) { - convert_to_long_ex(fromlength); + convert_to_long_ex(fromlength); + if (Z_LVAL_PP(fromlength) < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "From length has to be greater than or equal to 0"); + RETURN_FALSE; + } } else { fromlength = 0x00; } if (myargc >= 4) { convert_to_long_ex(subjectlength); + if (Z_LVAL_PP(subjectlength) < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Subject length has to be greater than or equal to 0"); + RETURN_FALSE; + } } else { subjectlength = 0x00; } @@ -1529,11 +1547,8 @@ PHP_FUNCTION(imap_headerinfo) convert_to_string_ex(defaulthost); } - if (!Z_LVAL_PP(msgno) || Z_LVAL_PP(msgno) < 1 || (unsigned) Z_LVAL_PP(msgno) > imap_le_struct->imap_stream->nmsgs) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad message number"); - RETURN_FALSE; - } - + PHP_IMAP_CHECK_MSGNO(Z_LVAL_PP(msgno)); + if (mail_fetchstructure(imap_le_struct->imap_stream, Z_LVAL_PP(msgno), NIL)) { cache = mail_elt(imap_le_struct->imap_stream, Z_LVAL_PP(msgno)); } else { @@ -1779,10 +1794,7 @@ PHP_FUNCTION(imap_fetchstructure) } else { msgindex = Z_LVAL_PP(msgno); } - if ((msgindex < 1) || ((unsigned) msgindex > imap_le_struct->imap_stream->nmsgs)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad message number"); - RETURN_FALSE; - } + PHP_IMAP_CHECK_MSGNO(msgindex); mail_fetchstructure_full(imap_le_struct->imap_stream, Z_LVAL_PP(msgno), &body , myargc == 3 ? Z_LVAL_PP(flags) : NIL); @@ -1795,7 +1807,7 @@ PHP_FUNCTION(imap_fetchstructure) } /* }}} */ -/* {{{ proto string imap_fetchbody(resource stream_id, int msg_no, int section [, int options]) +/* {{{ proto string imap_fetchbody(resource stream_id, int msg_no, string section [, int options]) Get a specific body section */ PHP_FUNCTION(imap_fetchbody) { @@ -1816,7 +1828,12 @@ PHP_FUNCTION(imap_fetchbody) if (myargc == 4) { convert_to_long_ex(flags); } - + + if (myargc < 4 || !(Z_LVAL_PP(flags) & FT_UID)) { + /* only perform the check if the msgno is a message number and not a UID */ + PHP_IMAP_CHECK_MSGNO(Z_LVAL_PP(msgno)); + } + body = mail_fetchbody_full(imap_le_struct->imap_stream, Z_LVAL_PP(msgno), Z_STRVAL_PP(sec), &len, myargc==4 ? Z_LVAL_PP(flags) : NIL); if (!body) { @@ -2451,8 +2468,13 @@ PHP_FUNCTION(imap_sort) } if (myargc >= 4) { convert_to_long_ex(flags); + if (Z_LVAL_PP(flags) < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Search options parameter has to be greater than or equal to 0"); + RETURN_FALSE; + } } if (myargc >= 5) { + convert_to_string_ex(criteria); search_criteria = estrndup(Z_STRVAL_PP(criteria), Z_STRLEN_PP(criteria)); spg = mail_criteria(search_criteria); efree(search_criteria); @@ -2512,10 +2534,7 @@ PHP_FUNCTION(imap_fetchheader) msgindex = Z_LVAL_PP(msgno); } - if ((msgindex < 1) || ((unsigned) msgindex > imap_le_struct->imap_stream->nmsgs)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad message number"); - RETURN_FALSE; - } + PHP_IMAP_CHECK_MSGNO(msgindex); RETVAL_STRING(mail_fetchheader_full(imap_le_struct->imap_stream, Z_LVAL_PP(msgno), NIL, NIL, (myargc == 3 ? Z_LVAL_PP(flags) : NIL)), 1); } @@ -2607,7 +2626,7 @@ PHP_FUNCTION(imap_status) } /* }}} */ -/* {{{ proto object imap_bodystruct(resource stream_id, int msg_no, int section) +/* {{{ proto object imap_bodystruct(resource stream_id, int msg_no, string section) Read the structure of a specified body section of a specific message */ PHP_FUNCTION(imap_bodystruct) { @@ -2634,6 +2653,10 @@ PHP_FUNCTION(imap_bodystruct) object_init(return_value); body=mail_body(imap_le_struct->imap_stream, Z_LVAL_PP(msg), Z_STRVAL_PP(section)); + if (body == NULL) { + zval_dtor(return_value); + RETURN_FALSE; + } if (body->type <= TYPEMAX) { add_property_long(return_value, "type", body->type); } @@ -2885,6 +2908,7 @@ PHP_FUNCTION(imap_mail_compose) custom_headers_param = mail_newbody_parameter(); convert_to_string_ex(env_data); custom_headers_param->value = (char *) fs_get(Z_STRLEN_PP(env_data) + 1); + custom_headers_param->attribute = NULL; memcpy(custom_headers_param->value, Z_STRVAL_PP(env_data), Z_STRLEN_PP(env_data) + 1); zend_hash_move_forward(Z_ARRVAL_PP(pvalue)); custom_headers_param->next = tmp_param; @@ -2916,7 +2940,7 @@ PHP_FUNCTION(imap_mail_compose) convert_to_string_ex(pvalue); tmp_param = mail_newbody_parameter(); tmp_param->value = cpystr(Z_STRVAL_PP(pvalue)); - tmp_param->attribute = "CHARSET"; + tmp_param->attribute = cpystr("CHARSET"); tmp_param->next = bod->parameter; bod->parameter = tmp_param; } @@ -2926,7 +2950,7 @@ PHP_FUNCTION(imap_mail_compose) while (zend_hash_get_current_data(Z_ARRVAL_PP(pvalue), (void **) &disp_data) == SUCCESS) { disp_param = mail_newbody_parameter(); zend_hash_get_current_key(Z_ARRVAL_PP(pvalue), &key, &ind, 0); - disp_param->attribute = key; + disp_param->attribute = cpystr(key); convert_to_string_ex(disp_data); disp_param->value = (char *) fs_get(Z_STRLEN_PP(disp_data) + 1); memcpy(disp_param->value, Z_STRVAL_PP(disp_data), Z_STRLEN_PP(disp_data) + 1); @@ -2960,7 +2984,7 @@ PHP_FUNCTION(imap_mail_compose) while (zend_hash_get_current_data(Z_ARRVAL_PP(pvalue), (void **) &disp_data) == SUCCESS) { disp_param = mail_newbody_parameter(); zend_hash_get_current_key(Z_ARRVAL_PP(pvalue), &key, &ind, 0); - disp_param->attribute = key; + disp_param->attribute = cpystr(key); convert_to_string_ex(disp_data); disp_param->value = (char *) fs_get(Z_STRLEN_PP(disp_data) + 1); memcpy(disp_param->value, Z_STRVAL_PP(disp_data), Z_STRLEN_PP(disp_data) + 1); @@ -2976,6 +3000,10 @@ PHP_FUNCTION(imap_mail_compose) bod->contents.text.data = (char *) fs_get(Z_STRLEN_PP(pvalue) + 1); memcpy(bod->contents.text.data, Z_STRVAL_PP(pvalue), Z_STRLEN_PP(pvalue)+1); bod->contents.text.size = Z_STRLEN_PP(pvalue); + } else { + bod->contents.text.data = (char *) fs_get(1); + memcpy(bod->contents.text.data, "", 1); + bod->contents.text.size = 0; } if (zend_hash_find(Z_ARRVAL_PP(data), "lines", sizeof("lines"), (void **) &pvalue)== SUCCESS) { convert_to_long_ex(pvalue); @@ -3018,8 +3046,9 @@ PHP_FUNCTION(imap_mail_compose) if (zend_hash_find(Z_ARRVAL_PP(data), "charset", sizeof("charset"), (void **) &pvalue)== SUCCESS) { convert_to_string_ex(pvalue); tmp_param = mail_newbody_parameter(); - tmp_param->value = cpystr(Z_STRVAL_PP(pvalue)); - tmp_param->attribute = "CHARSET"; + tmp_param->value = (char *) fs_get(Z_STRLEN_PP(pvalue) + 1); + memcpy(tmp_param->value, Z_STRVAL_PP(pvalue), Z_STRLEN_PP(pvalue) + 1); + tmp_param->attribute = cpystr("CHARSET"); tmp_param->next = bod->parameter; bod->parameter = tmp_param; } @@ -3029,7 +3058,7 @@ PHP_FUNCTION(imap_mail_compose) while (zend_hash_get_current_data(Z_ARRVAL_PP(pvalue), (void **) &disp_data) == SUCCESS) { disp_param = mail_newbody_parameter(); zend_hash_get_current_key(Z_ARRVAL_PP(pvalue), &key, &ind, 0); - disp_param->attribute = key; + disp_param->attribute = cpystr(key); convert_to_string_ex(disp_data); disp_param->value = (char *) fs_get(Z_STRLEN_PP(disp_data) + 1); memcpy(disp_param->value, Z_STRVAL_PP(disp_data), Z_STRLEN_PP(disp_data) + 1); @@ -3063,7 +3092,7 @@ PHP_FUNCTION(imap_mail_compose) while (zend_hash_get_current_data(Z_ARRVAL_PP(pvalue), (void **) &disp_data) == SUCCESS) { disp_param = mail_newbody_parameter(); zend_hash_get_current_key(Z_ARRVAL_PP(pvalue), &key, &ind, 0); - disp_param->attribute = key; + disp_param->attribute = cpystr(key); convert_to_string_ex(disp_data); disp_param->value = (char *) fs_get(Z_STRLEN_PP(disp_data) + 1); memcpy(disp_param->value, Z_STRVAL_PP(disp_data), Z_STRLEN_PP(disp_data) + 1); @@ -3079,6 +3108,10 @@ PHP_FUNCTION(imap_mail_compose) bod->contents.text.data = (char *) fs_get(Z_STRLEN_PP(pvalue) + 1); memcpy(bod->contents.text.data, Z_STRVAL_PP(pvalue), Z_STRLEN_PP(pvalue) + 1); bod->contents.text.size = Z_STRLEN_PP(pvalue); + } else { + bod->contents.text.data = (char *) fs_get(1); + memcpy(bod->contents.text.data, "", 1); + bod->contents.text.size = 0; } if (zend_hash_find(Z_ARRVAL_PP(data), "lines", sizeof("lines"), (void **) &pvalue)== SUCCESS) { convert_to_long_ex(pvalue); @@ -3092,9 +3125,14 @@ PHP_FUNCTION(imap_mail_compose) convert_to_string_ex(pvalue); bod->md5 = cpystr(Z_STRVAL_PP(pvalue)); } - - zend_hash_move_forward(Z_ARRVAL_PP(body)); } + zend_hash_move_forward(Z_ARRVAL_PP(body)); + } + + if (bod && bod->type == TYPEMULTIPART && (!bod->nested.part || !bod->nested.part->next)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot generate multipart e-mail without components."); + RETVAL_FALSE; + goto done; } rfc822_encode_body_7bit(env, topbod); @@ -3102,17 +3140,29 @@ PHP_FUNCTION(imap_mail_compose) /* add custom envelope headers */ if (custom_headers_param) { + int l = strlen(tmp) - 2, l2; + PARAMETER *tp = custom_headers_param; + /* remove last CRLF from tmp */ - tmp[strlen(tmp) - 2] = '\0'; - tempstring = emalloc(strlen(tmp) + 1); - strcpy(tempstring, tmp); + tmp[l] = '\0'; + tempstring = emalloc(l); + memcpy(tempstring, tmp, l); + do { - tempstring = erealloc(tempstring, strlen(tempstring) + strlen(custom_headers_param->value) + strlen(CRLF) + 1); - sprintf(tempstring, "%s%s%s", tempstring, custom_headers_param->value, CRLF); + l2 = strlen(custom_headers_param->value); + tempstring = erealloc(tempstring, l + l2 + CRLF_LEN + 1); + memcpy(tempstring + l, custom_headers_param->value, l2); + memcpy(tempstring + l + l2, CRLF, CRLF_LEN); + l += l2 + CRLF_LEN; } while ((custom_headers_param = custom_headers_param->next)); - mystring = emalloc(strlen(tempstring) + strlen(CRLF) + 1); - sprintf(mystring, "%s%s", tempstring, CRLF); + mail_free_body_parameter(&tp); + + mystring = emalloc(l + CRLF_LEN + 1); + memcpy(mystring, tempstring, l); + memcpy(mystring + l , CRLF, CRLF_LEN); + mystring[l + CRLF_LEN] = '\0'; + efree(tempstring); } else { mystring = emalloc(strlen(tmp) + 1); @@ -3158,37 +3208,33 @@ PHP_FUNCTION(imap_mail_compose) bod=&part->body; - tempstring=emalloc(strlen(bod->contents.text.data)+strlen(CRLF)+strlen(mystring)+1); - strcpy(tempstring, mystring); + tempstring = emalloc(strlen(bod->contents.text.data)+strlen(CRLF)+strlen(mystring)+1); + sprintf(tempstring, "%s%s%s", mystring, bod->contents.text.data, CRLF); efree(mystring); - mystring=tempstring; - sprintf(mystring, "%s%s%s", mystring, bod->contents.text.data, CRLF); - + mystring = tempstring; } while ((part = part->next)); /* until done */ /* output trailing cookie */ sprintf(tmp, "--%s--", cookie); - tempstring=emalloc(strlen(tmp)+strlen(CRLF)+strlen(mystring)+1); - strcpy(tempstring, mystring); + tempstring = emalloc(strlen(tmp)+strlen(CRLF)+strlen(mystring)+1); + sprintf(tempstring, "%s%s%s", mystring, tmp, CRLF); efree(mystring); - mystring=tempstring; - sprintf(mystring, "%s%s%s", mystring, tmp, CRLF); - + mystring = tempstring; } else if (bod) { - - tempstring=emalloc(strlen(bod->contents.text.data)+strlen(CRLF)+strlen(mystring)+1); - strcpy(tempstring, mystring); + tempstring = emalloc(strlen(bod->contents.text.data)+strlen(CRLF)+strlen(mystring)+1); + sprintf(tempstring, "%s%s%s", mystring, bod->contents.text.data, CRLF); efree(mystring); - mystring=tempstring; - sprintf(mystring, "%s%s%s", mystring, bod->contents.text.data, CRLF); - + mystring = tempstring; } else { efree(mystring); - RETURN_FALSE; + RETVAL_FALSE; + goto done; } - RETVAL_STRINGL(mystring, strlen(mystring), 1); - efree(tempstring); + RETVAL_STRING(tempstring, 0); +done: + mail_free_body(&topbod); + mail_free_envelope(&env); } /* }}} */ diff --git a/ext/imap/tests/bug31142_1.phpt b/ext/imap/tests/bug31142_1.phpt new file mode 100644 index 000000000000..efb92b7b45b2 --- /dev/null +++ b/ext/imap/tests/bug31142_1.phpt @@ -0,0 +1,59 @@ +--TEST-- +Bug #31142 test #1 (imap_mail_compose() generates incorrect output) +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +From: joe@example.com +To: foo@example.com +cc: bar@example.com +MIME-Version: 1.0 +Content-Type: MULTIPART/mixed; BOUNDARY="%s" + +--%s +Content-Type: APPLICATION/octet-stream +Content-Transfer-Encoding: BASE64 +Content-Description: some file + +QUJD + +--%s +Content-Type: TEXT/plain; CHARSET=US-ASCII +Content-Description: description3 + +contents.data3 + + + +--%s-- diff --git a/ext/imap/tests/bug31142_2.phpt b/ext/imap/tests/bug31142_2.phpt new file mode 100644 index 000000000000..2a81760a7b96 --- /dev/null +++ b/ext/imap/tests/bug31142_2.phpt @@ -0,0 +1,30 @@ +--TEST-- +Bug #31142 test #2 (imap_mail_compose() generates incorrect output) +--SKIPIF-- + +--FILE-- + +--EXPECT-- +From: host@domain.com +MIME-Version: 1.0 +Content-Type: TEXT/plain; CHARSET=iso-8859-2 +Content-Transfer-Encoding: QUOTED-PRINTABLE + +asn =C5=99kl \ No newline at end of file diff --git a/ext/informix/Makefile.frag b/ext/informix/Makefile.frag index 2da3a15e7fec..2177182f073a 100644 --- a/ext/informix/Makefile.frag +++ b/ext/informix/Makefile.frag @@ -1,3 +1,4 @@ + OVERALL_TARGET += $(srcdir)/ifx.c $(srcdir)/ifx.c: $(srcdir)/ifx.ec $(builddir)/libphpifx.a diff --git a/ext/informix/config.w32 b/ext/informix/config.w32 index b59918c4b46a..c01d3567a05f 100644 --- a/ext/informix/config.w32 +++ b/ext/informix/config.w32 @@ -17,7 +17,7 @@ if (PHP_INFORMIX != "no") { ADD_FLAG("CFLAGS_INFORMIX", "/I " + php_ifx_dir + "\\incl\\esql "); - EXTENSION('informix', 'ifx.c', null, "/D IFX_VERSION=921 /D HAVE_IFX_IUS=1", "php_ifx.dll"); + EXTENSION('informix', 'ifx.c', null, "/D IFX_VERSION=921 /D HAVE_IFX_IUS=1 /D HAVE_IFX=1", "php_ifx.dll"); MFO.WriteLine(configure_module_dirname + "\\ifx.c: " + configure_module_dirname + "\\ifx.ec"); MFO.WriteLine("\t<trans_res_id); } + + RETVAL_TRUE; + return SUCCESS; default: @@ -1856,8 +1859,6 @@ PHP_FUNCTION(ibase_execute) } ib_query->result_res_id = zend_list_insert(result, le_result); RETVAL_RESOURCE(ib_query->result_res_id); - } else { - RETVAL_TRUE; } } while (0); diff --git a/ext/interbase/interbase.c b/ext/interbase/interbase.c index ecee39b09b95..e0602ab8c369 100644 --- a/ext/interbase/interbase.c +++ b/ext/interbase/interbase.c @@ -591,7 +591,7 @@ int _php_ibase_attach_db(char **args, int *len, long *largs, isc_db_handle *db T dpb = dpb_buffer + 1; for (i = 0; i < sizeof(dpb_args); ++i) { - if (dpb_args[i] && args[i]) { + if (dpb_args[i] && args[i] && len[i]) { dpb += sprintf(dpb, "%c%c%s", dpb_args[i],(unsigned char)len[i],args[i]); } } diff --git a/ext/ldap/config.m4 b/ext/ldap/config.m4 index 2eb00971b878..9a03329012a3 100644 --- a/ext/ldap/config.m4 +++ b/ext/ldap/config.m4 @@ -2,7 +2,7 @@ dnl dnl $Id$ dnl -AC_DEFUN(PHP_LDAP_CHECKS, [ +AC_DEFUN([PHP_LDAP_CHECKS], [ if test -f $1/include/ldap.h; then LDAP_DIR=$1 LDAP_INCDIR=$1/include @@ -18,7 +18,7 @@ AC_DEFUN(PHP_LDAP_CHECKS, [ fi ]) -AC_DEFUN(PHP_LDAP_SASL_CHECKS, [ +AC_DEFUN([PHP_LDAP_SASL_CHECKS], [ if test "$1" = "yes"; then SEARCH_DIRS="/usr/local /usr" else @@ -146,7 +146,9 @@ if test "$PHP_LDAP" != "no"; then elif test -f $LDAP_LIBDIR/libclntsh.$SHLIB_SUFFIX_NAME; then PHP_ADD_LIBRARY_WITH_PATH(clntsh, $LDAP_LIBDIR, LDAP_SHARED_LIBADD) AC_DEFINE(HAVE_ORALDAP,1,[ ]) - + if test -f $LDAP_LIBDIR/libclntsh.$SHLIB_SUFFIX_NAME.10.1; then + AC_DEFINE(HAVE_ORALDAP_10,1,[ ]) + fi else AC_MSG_ERROR(Cannot find ldap libraries in $LDAP_LIBDIR.) fi @@ -169,7 +171,7 @@ if test "$PHP_LDAP" != "no"; then dnl Solaris 2.8 claims to be 2004 API, but doesn't have dnl ldap_parse_reference() nor ldap_start_tls_s() - AC_CHECK_FUNCS([ldap_parse_reference ldap_start_tls_s]) + AC_CHECK_FUNCS([ldap_parse_result ldap_parse_reference ldap_start_tls_s]) LDFLAGS=$_SAVE_LDFLAGS dnl diff --git a/ext/ldap/config.w32 b/ext/ldap/config.w32 index 4cbfbcae6250..77a34fe8c962 100644 --- a/ext/ldap/config.w32 +++ b/ext/ldap/config.w32 @@ -12,6 +12,7 @@ if (PHP_LDAP != "no") { CHECK_LIB("olber32.lib", "ldap", PHP_LDAP)) { EXTENSION('ldap', 'ldap.c'); + AC_DEFINE('HAVE_LDAP_PARSE_REFERENCE', 1); AC_DEFINE('HAVE_LDAP_START_TLS_S', 1); AC_DEFINE('HAVE_LDAP', 1); diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 119e942d5a47..c1568a7a3a28 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -30,7 +30,7 @@ #endif /* Additional headers for NetWare */ -#if defined(NETWARE) && (NEW_LIBC) +#if defined(NETWARE) #include #include #endif @@ -137,16 +137,18 @@ function_entry ldap_functions[] = { PHP_FE(ldap_compare, NULL) PHP_FE(ldap_sort, NULL) -#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP +#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 + PHP_FE(ldap_rename, NULL) PHP_FE(ldap_get_option, third_arg_force_ref) PHP_FE(ldap_set_option, NULL) - PHP_FE(ldap_parse_result, arg3to6of6_force_ref) PHP_FE(ldap_first_reference, NULL) PHP_FE(ldap_next_reference, NULL) #ifdef HAVE_LDAP_PARSE_REFERENCE PHP_FE(ldap_parse_reference, third_arg_force_ref) #endif - PHP_FE(ldap_rename, NULL) +#ifdef HAVE_LDAP_PARSE_RESULT + PHP_FE(ldap_parse_result, arg3to6of6_force_ref) +#endif #ifdef HAVE_LDAP_START_TLS_S PHP_FE(ldap_start_tls, NULL) #endif @@ -242,7 +244,7 @@ PHP_MINIT_FUNCTION(ldap) REGISTER_LONG_CONSTANT("LDAP_DEREF_FINDING", LDAP_DEREF_FINDING, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("LDAP_DEREF_ALWAYS", LDAP_DEREF_ALWAYS, CONST_PERSISTENT | CONST_CS); -#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP +#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 /* LDAP options */ REGISTER_LONG_CONSTANT("LDAP_OPT_DEREF", LDAP_OPT_DEREF, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("LDAP_OPT_SIZELIMIT", LDAP_OPT_SIZELIMIT, CONST_PERSISTENT | CONST_CS); @@ -253,7 +255,9 @@ PHP_MINIT_FUNCTION(ldap) #ifdef LDAP_OPT_RESTART REGISTER_LONG_CONSTANT("LDAP_OPT_RESTART", LDAP_OPT_RESTART, CONST_PERSISTENT | CONST_CS); #endif +#ifdef LDAP_OPT_HOST_NAME REGISTER_LONG_CONSTANT("LDAP_OPT_HOST_NAME", LDAP_OPT_HOST_NAME, CONST_PERSISTENT | CONST_CS); +#endif REGISTER_LONG_CONSTANT("LDAP_OPT_ERROR_STRING", LDAP_OPT_ERROR_STRING, CONST_PERSISTENT | CONST_CS); #ifdef LDAP_OPT_MATCHED_DN REGISTER_LONG_CONSTANT("LDAP_OPT_MATCHED_DN", LDAP_OPT_MATCHED_DN, CONST_PERSISTENT | CONST_CS); @@ -265,6 +269,13 @@ PHP_MINIT_FUNCTION(ldap) REGISTER_LONG_CONSTANT("LDAP_OPT_DEBUG_LEVEL", LDAP_OPT_DEBUG_LEVEL, CONST_PERSISTENT | CONST_CS); #endif +#ifdef HAVE_LDAP_SASL + REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_MECH", LDAP_OPT_X_SASL_MECH, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_REALM", LDAP_OPT_X_SASL_REALM, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_AUTHCID", LDAP_OPT_X_SASL_AUTHCID, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_AUTHZID", LDAP_OPT_X_SASL_AUTHZID, CONST_PERSISTENT | CONST_CS); +#endif + #ifdef ORALDAP REGISTER_LONG_CONSTANT("GSLC_SSL_NO_AUTH", GSLC_SSL_NO_AUTH, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("GSLC_SSL_ONEWAY_AUTH", GSLC_SSL_ONEWAY_AUTH, CONST_PERSISTENT | CONST_CS); @@ -437,7 +448,7 @@ PHP_FUNCTION(ldap_connect) static int _get_lderrno(LDAP *ldap) { #if !HAVE_NSLDAP -#if LDAP_API_VERSION > 2000 +#if LDAP_API_VERSION > 2000 || HAVE_ORALDAP_10 int lderr; /* New versions of OpenLDAP do it this way */ @@ -478,42 +489,122 @@ PHP_FUNCTION(ldap_bind) /* }}} */ #ifdef HAVE_LDAP_SASL +typedef struct { + char *mech; + char *realm; + char *authcid; + char *passwd; + char *authzid; +} php_ldap_bictx; + +/* {{{ _php_sasl_setdefs + */ +static php_ldap_bictx *_php_sasl_setdefs(LDAP *ld, char *sasl_mech, char *sasl_realm, char *binddn, char *pass, char *sasl_authz_id) +{ + php_ldap_bictx *ctx; + + ctx = ber_memalloc(sizeof(php_ldap_bictx)); + ctx->mech = (sasl_mech) ? ber_strdup(sasl_mech) : NULL; + ctx->realm = (sasl_realm) ? ber_strdup(sasl_realm) : NULL; + ctx->authcid = (binddn) ? ber_strdup(binddn) : NULL; + ctx->passwd = (pass) ? ber_strdup(pass) : NULL; + ctx->authzid = (sasl_authz_id) ? ber_strdup(sasl_authz_id) : NULL; + + if (ctx->mech == NULL) { + ldap_get_option(ld, LDAP_OPT_X_SASL_MECH, &ctx->mech); + } + if (ctx->realm == NULL) { + ldap_get_option(ld, LDAP_OPT_X_SASL_REALM, &ctx->realm); + } + if (ctx->authcid == NULL) { + ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHCID, &ctx->authcid); + } + if (ctx->authzid == NULL) { + ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHZID, &ctx->authzid); + } + + return ctx; +} + +/* {{{ _php_sasl_setdefs + */ +static void _php_sasl_freedefs(php_ldap_bictx *ctx) +{ + if (ctx->mech) ber_memfree(ctx->mech); + if (ctx->realm) ber_memfree(ctx->realm); + if (ctx->authcid) ber_memfree(ctx->authcid); + if (ctx->passwd) ber_memfree(ctx->passwd); + if (ctx->authzid) ber_memfree(ctx->authzid); + ber_memfree(ctx); +} + /* {{{ _php_sasl_interact - Interact function for SASL */ + Internal interact function for SASL */ static int _php_sasl_interact(LDAP *ld, unsigned flags, void *defaults, void *in) { sasl_interact_t *interact = in; - - while (interact->id != SASL_CB_LIST_END) { - const char *dflt = interact->defresult; - - interact->result = strdup((dflt && *dflt) ? dflt : ""); - interact->len = interact->result ? strlen(interact->result) : 0; - interact++; - }; + const char *p; + php_ldap_bictx *ctx = defaults; + + for (;interact->id != SASL_CB_LIST_END;interact++) { + p = NULL; + switch(interact->id) { + case SASL_CB_GETREALM: + p = ctx->realm; + break; + case SASL_CB_AUTHNAME: + p = ctx->authcid; + break; + case SASL_CB_USER: + p = ctx->authzid; + break; + case SASL_CB_PASS: + p = ctx->passwd; + break; + } + if (p) { + interact->result = p; + interact->len = strlen(interact->result); + } + } return LDAP_SUCCESS; } -/* {{{ proto bool ldap_sasl_bind(resource link) +/* {{{ proto bool ldap_sasl_bind(resource link [, string binddn, string password, string sasl_mech, string sasl_realm, string sasl_authz_id, string props]) Bind to LDAP directory using SASL */ PHP_FUNCTION(ldap_sasl_bind) { zval *link; ldap_linkdata *ld; - int rc; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &link) == FAILURE) { + char *binddn = NULL; + char *pass = NULL; + char *sasl_mech = NULL; + char *sasl_realm = NULL; + char *sasl_authz_id = NULL; + char *props = NULL; + int rc, dn_len, pass_len, mech_len, realm_len, authz_id_len, props_len; + php_ldap_bictx *ctx; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|ssssss", &link, &binddn, &dn_len, &pass, &pass_len, &sasl_mech, &mech_len, &sasl_realm, &realm_len, &sasl_authz_id, &authz_id_len, &props, &props_len) == FAILURE) { RETURN_FALSE; } ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link); - if ((rc = ldap_sasl_interactive_bind_s(ld->link, NULL, NULL, NULL, NULL, LDAP_SASL_QUIET, _php_sasl_interact, NULL)) != LDAP_SUCCESS) { + ctx = _php_sasl_setdefs(ld->link, sasl_mech, sasl_realm, binddn, pass, sasl_authz_id); + + if (props) { + ldap_set_option(ld->link, LDAP_OPT_X_SASL_SECPROPS, props); + } + + rc = ldap_sasl_interactive_bind_s(ld->link, binddn, ctx->mech, NULL, NULL, LDAP_SASL_QUIET, _php_sasl_interact, ctx); + if (rc != LDAP_SUCCESS) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc)); - RETURN_FALSE; + RETVAL_FALSE; } else { - RETURN_TRUE; + RETVAL_TRUE; } + _php_sasl_freedefs(ctx); } /* }}} */ #endif /* HAVE_LDAP_SASL */ @@ -542,7 +633,7 @@ static void php_set_opts(LDAP *ldap, int sizelimit, int timelimit, int deref) { /* sizelimit */ if (sizelimit > -1) { -#if (LDAP_API_VERSION >= 2004) || HAVE_NSLDAP +#if (LDAP_API_VERSION >= 2004) || HAVE_NSLDAP || HAVE_ORALDAP_10 ldap_set_option(ldap, LDAP_OPT_SIZELIMIT, &sizelimit); #else ldap->ld_sizelimit = sizelimit; @@ -551,7 +642,7 @@ static void php_set_opts(LDAP *ldap, int sizelimit, int timelimit, int deref) /* timelimit */ if (timelimit > -1) { -#if (LDAP_API_VERSION >= 2004) || HAVE_NSLDAP +#if (LDAP_API_VERSION >= 2004) || HAVE_NSLDAP || HAVE_ORALDAP_10 ldap_set_option(ldap, LDAP_OPT_TIMELIMIT, &timelimit); #else ldap->ld_timelimit = timelimit; @@ -560,7 +651,7 @@ static void php_set_opts(LDAP *ldap, int sizelimit, int timelimit, int deref) /* deref */ if (deref > -1) { -#if (LDAP_API_VERSION >= 2004) || HAVE_NSLDAP +#if (LDAP_API_VERSION >= 2004) || HAVE_NSLDAP || HAVE_ORALDAP_10 ldap_set_option(ldap, LDAP_OPT_DEREF, &deref); #else ldap->ld_deref = deref; @@ -636,8 +727,11 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) if (Z_TYPE_PP(link) != IS_ARRAY) { convert_to_string_ex(filter); ldap_filter = Z_STRVAL_PP(filter); - convert_to_string_ex(base_dn); - ldap_base_dn = Z_STRVAL_PP(base_dn); + + /* If anything else than string is passed, ldap_base_dn = NULL */ + if (Z_TYPE_PP(base_dn) == IS_STRING) { + ldap_base_dn = Z_STRVAL_PP(base_dn); + } } break; @@ -673,8 +767,12 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) zend_hash_internal_pointer_reset(Z_ARRVAL_PP(base_dn)); } else { nbases = 0; /* this means string, not array */ - convert_to_string_ex(base_dn); - ldap_base_dn = Z_STRLEN_PP(base_dn) < 1 ? NULL : Z_STRVAL_PP(base_dn); + /* If anything else than string is passed, ldap_base_dn = NULL */ + if (Z_TYPE_PP(base_dn) == IS_STRING) { + ldap_base_dn = Z_STRVAL_PP(base_dn); + } else { + ldap_base_dn = NULL; + } } if (Z_TYPE_PP(filter) == IS_ARRAY) { @@ -712,8 +810,13 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) if (nbases != 0) { /* base_dn an array? */ zend_hash_get_current_data(Z_ARRVAL_PP(base_dn), (void **)&entry); zend_hash_move_forward(Z_ARRVAL_PP(base_dn)); - convert_to_string_ex(entry); - ldap_base_dn = Z_STRLEN_PP(entry) < 1 ? NULL : Z_STRVAL_PP(entry); + + /* If anything else than string is passed, ldap_base_dn = NULL */ + if (Z_TYPE_PP(entry) == IS_STRING) { + ldap_base_dn = Z_STRVAL_PP(entry); + } else { + ldap_base_dn = NULL; + } } if (nfilters != 0) { /* filter an array? */ zend_hash_get_current_data(Z_ARRVAL_PP(filter), (void **)&entry); @@ -754,11 +857,6 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) return; } - /* fix to make null base_dn's work */ - if (strlen(ldap_base_dn) < 1) { - ldap_base_dn = NULL; - } - ld = (ldap_linkdata *) zend_fetch_resource(link TSRMLS_CC, -1, "ldap link", NULL, 1, le_link); if (ld == NULL) { if (ldap_attrs != NULL) { @@ -979,12 +1077,12 @@ PHP_FUNCTION(ldap_get_entries) add_index_string(tmp1, num_attrib, attribute, 1); num_attrib++; -#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || WINDOWS +#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS ldap_memfree(attribute); #endif attribute = ldap_next_attribute(ldap, ldap_result_entry, ber); } -#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || WINDOWS +#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS if (ber != NULL) ber_free(ber, 0); #endif @@ -992,7 +1090,7 @@ PHP_FUNCTION(ldap_get_entries) add_assoc_long(tmp1, "count", num_attrib); dn = ldap_get_dn(ldap, ldap_result_entry); add_assoc_string(tmp1, "dn", dn, 1); -#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || WINDOWS +#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS ldap_memfree(dn); #else free(dn); @@ -1032,7 +1130,7 @@ PHP_FUNCTION(ldap_first_attribute) ZEND_REGISTER_RESOURCE(*berp, ber, le_ber_entry); RETVAL_STRING(attribute, 1); -#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || WINDOWS +#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS ldap_memfree(attribute); #endif } @@ -1063,7 +1161,7 @@ PHP_FUNCTION(ldap_next_attribute) ZEND_REGISTER_RESOURCE(*berp, ber, le_ber_entry); RETVAL_STRING(attribute, 1); -#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || WINDOWS +#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS ldap_memfree(attribute); #endif } @@ -1110,12 +1208,12 @@ PHP_FUNCTION(ldap_get_attributes) add_index_string(return_value, num_attrib, attribute, 1); num_attrib++; -#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || WINDOWS +#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS ldap_memfree(attribute); #endif attribute = ldap_next_attribute(ld->link, resultentry->data, ber); } -#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || WINDOWS +#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS if (ber != NULL) { ber_free(ber, 0); } @@ -1223,7 +1321,7 @@ PHP_FUNCTION(ldap_get_dn) text = ldap_get_dn(ld->link, resultentry->data); if (text != NULL) { RETVAL_STRING(text, 1); -#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || WINDOWS +#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS ldap_memfree(text); #else free(text); @@ -1286,7 +1384,7 @@ PHP_FUNCTION(ldap_dn2ufn) if (ufn !=NULL) { RETVAL_STRING(ufn, 1); -#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || WINDOWS +#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS ldap_memfree(ufn); #endif } else { @@ -1606,8 +1704,7 @@ PHP_FUNCTION(ldap_sort) } /* }}} */ - -#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP +#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 /* {{{ proto bool ldap_get_option(resource link, int option, mixed retval) Get the current value of various session-wide parameters */ PHP_FUNCTION(ldap_get_option) @@ -1645,8 +1742,16 @@ PHP_FUNCTION(ldap_get_option) ZVAL_LONG(*retval, val); } break; /* options with string value */ - case LDAP_OPT_HOST_NAME: case LDAP_OPT_ERROR_STRING: +#ifdef LDAP_OPT_HOST_NAME + case LDAP_OPT_HOST_NAME: +#endif +#ifdef HAVE_LDAP_SASL + case LDAP_OPT_X_SASL_MECH: + case LDAP_OPT_X_SASL_REALM: + case LDAP_OPT_X_SASL_AUTHCID: + case LDAP_OPT_X_SASL_AUTHZID: +#endif #ifdef LDAP_OPT_MATCHED_DN case LDAP_OPT_MATCHED_DN: #endif @@ -1700,7 +1805,7 @@ PHP_FUNCTION(ldap_set_option) opt = Z_LVAL_PP(option); switch (opt) { - /* options with int value */ + /* options with int value */ case LDAP_OPT_DEREF: case LDAP_OPT_SIZELIMIT: case LDAP_OPT_TIMELIMIT: @@ -1718,8 +1823,16 @@ PHP_FUNCTION(ldap_set_option) } } break; /* options with string value */ - case LDAP_OPT_HOST_NAME: case LDAP_OPT_ERROR_STRING: +#ifdef LDAP_OPT_HOST_NAME + case LDAP_OPT_HOST_NAME: +#endif +#ifdef HAVE_LDAP_SASL + case LDAP_OPT_X_SASL_MECH: + case LDAP_OPT_X_SASL_REALM: + case LDAP_OPT_X_SASL_AUTHCID: + case LDAP_OPT_X_SASL_AUTHZID: +#endif #ifdef LDAP_OPT_MATCHED_DN case LDAP_OPT_MATCHED_DN: #endif @@ -1815,6 +1928,7 @@ PHP_FUNCTION(ldap_set_option) } /* }}} */ +#ifdef HAVE_LDAP_PARSE_RESULT /* {{{ proto bool ldap_parse_result(resource link, resource result, int errcode, string matcheddn, string errmsg, array referrals) Extract information from result */ PHP_FUNCTION(ldap_parse_result) @@ -1880,6 +1994,7 @@ PHP_FUNCTION(ldap_parse_result) RETURN_TRUE; } /* }}} */ +#endif /* {{{ proto resource ldap_first_reference(resource link, resource result) Return first reference */ @@ -1992,7 +2107,7 @@ PHP_FUNCTION(ldap_rename) convert_to_string_ex(newparent); convert_to_boolean_ex(deleteoldrdn); -#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP +#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 rc = ldap_rename_s(ld->link, Z_STRVAL_PP(dn), Z_STRVAL_PP(newrdn), Z_STRVAL_PP(newparent), Z_BVAL_PP(deleteoldrdn), NULL, NULL); #else if (Z_STRLEN_PP(newparent) != 0) { @@ -2017,7 +2132,7 @@ PHP_FUNCTION(ldap_start_tls) { zval **link; ldap_linkdata *ld; - int rc; + int rc, protocol = LDAP_VERSION3; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &link) == FAILURE) { WRONG_PARAM_COUNT; @@ -2025,7 +2140,9 @@ PHP_FUNCTION(ldap_start_tls) ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link); - if ((rc = ldap_start_tls_s(ld->link, NULL, NULL)) != LDAP_SUCCESS) { + if (((rc = ldap_set_option(ld->link, LDAP_OPT_PROTOCOL_VERSION, &protocol)) != LDAP_SUCCESS) || + ((rc = ldap_start_tls_s(ld->link, NULL, NULL)) != LDAP_SUCCESS) + ) { php_error_docref(NULL TSRMLS_CC, E_WARNING,"Unable to start TLS: %s", ldap_err2string(rc)); RETURN_FALSE; } else { @@ -2034,10 +2151,10 @@ PHP_FUNCTION(ldap_start_tls) } /* }}} */ #endif -#endif /* (LDAP_API_VERSION > 2000) || HAVE_NSLDAP */ +#endif /* (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 */ #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC) -/* {{{ proto _ldap_rebind_proc() +/* {{{ _ldap_rebind_proc() */ int _ldap_rebind_proc(LDAP *ldap, const char *url, ber_tag_t req, ber_int_t msgid, void *params) { diff --git a/ext/ldap/php_ldap.h b/ext/ldap/php_ldap.h index 7260939cbdc6..ee8b29a3ac8c 100644 --- a/ext/ldap/php_ldap.h +++ b/ext/ldap/php_ldap.h @@ -70,14 +70,18 @@ PHP_FUNCTION(ldap_error); PHP_FUNCTION(ldap_compare); PHP_FUNCTION(ldap_sort); -#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP +#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 PHP_FUNCTION(ldap_get_option); PHP_FUNCTION(ldap_set_option); -PHP_FUNCTION(ldap_parse_result); PHP_FUNCTION(ldap_first_reference); PHP_FUNCTION(ldap_next_reference); -PHP_FUNCTION(ldap_parse_reference); PHP_FUNCTION(ldap_rename); +#ifdef HAVE_LDAP_PARSE_RESULT +PHP_FUNCTION(ldap_parse_result); +#endif +#ifdef HAVE_LDAP_PARSE_REFERENCE +PHP_FUNCTION(ldap_parse_reference); +#endif #endif #if LDAP_API_VERSION > 2000 diff --git a/ext/libxml/config.w32 b/ext/libxml/config.w32 index 2edd6aad85fa..711e456f435a 100644 --- a/ext/libxml/config.w32 +++ b/ext/libxml/config.w32 @@ -15,6 +15,7 @@ if (PHP_LIBXML == "yes") { if (!PHP_LIBXML_SHARED) { ADD_DEF_FILE("ext\\libxml\\php_libxml2.def"); } + ADD_EXTENSION_DEP('libxml', 'iconv'); } } diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c index cb0519631adc..626c6b3fdc07 100644 --- a/ext/libxml/libxml.c +++ b/ext/libxml/libxml.c @@ -243,25 +243,36 @@ static void php_libxml_init_globals(php_libxml_globals *libxml_globals_p TSRMLS_ int php_libxml_streams_IO_match_wrapper(const char *filename) { + char *resolved_path; + int retval; + TSRMLS_FETCH(); if (zend_is_executing(TSRMLS_C)) { - return php_stream_locate_url_wrapper(filename, NULL, 0 TSRMLS_CC) ? 1 : 0; + resolved_path = xmlURIUnescapeString(filename, 0, NULL); + retval = php_stream_locate_url_wrapper(resolved_path, NULL, 0 TSRMLS_CC) ? 1 : 0; + if (resolved_path) { + xmlFree(resolved_path); + } + return retval; } return 0; } void *php_libxml_streams_IO_open_wrapper(const char *filename, const char *mode, const int read_only) { - char resolved_path[MAXPATHLEN + 1]; php_stream_statbuf ssbuf; php_stream_context *context = NULL; php_stream_wrapper *wrapper = NULL; - char *path_to_open = NULL; + char *resolved_path, *path_to_open = NULL; + void *ret_val = NULL; TSRMLS_FETCH(); - xmlURIUnescapeString(filename, 0, resolved_path); - path_to_open = resolved_path; + resolved_path = xmlURIUnescapeString(filename, 0, NULL); + + if (resolved_path == NULL) { + return NULL; + } /* logic copied from _php_stream_stat, but we only want to fail if the wrapper supports stat, otherwise, figure it out from @@ -271,16 +282,19 @@ void *php_libxml_streams_IO_open_wrapper(const char *filename, const char *mode, in xml processing (eg. DTD files) */ wrapper = php_stream_locate_url_wrapper(resolved_path, &path_to_open, ENFORCE_SAFE_MODE TSRMLS_CC); if (wrapper && read_only && wrapper->wops->url_stat) { - if (wrapper->wops->url_stat(wrapper, path_to_open, 0, &ssbuf, NULL TSRMLS_CC) == -1) { + if (wrapper->wops->url_stat(wrapper, path_to_open, PHP_STREAM_URL_STAT_QUIET, &ssbuf, NULL TSRMLS_CC) == -1) { + xmlFree(resolved_path); return NULL; } } if (LIBXML(stream_context)) { context = zend_fetch_resource(&LIBXML(stream_context) TSRMLS_CC, -1, "Stream-Context", NULL, 1, php_le_stream_context()); - return php_stream_open_wrapper_ex((char *)resolved_path, (char *)mode, ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL, context); } - return php_stream_open_wrapper((char *)resolved_path, (char *)mode, ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL); + + ret_val = php_stream_open_wrapper_ex(path_to_open, (char *)mode, ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL, context); + xmlFree(resolved_path); + return ret_val; } void *php_libxml_streams_IO_open_read_wrapper(const char *filename) @@ -377,7 +391,7 @@ void php_libxml_ctx_warning(void *ctx, const char *msg, ...) va_end(args); } -void php_libxml_error_handler(void *ctx, const char *msg, ...) +PHP_LIBXML_API void php_libxml_error_handler(void *ctx, const char *msg, ...) { va_list args; va_start(args, msg); @@ -424,6 +438,15 @@ PHP_LIBXML_API void php_libxml_shutdown() { } } +PHP_LIBXML_API zval *php_libxml_switch_context(zval *context TSRMLS_DC) { + zval *oldcontext; + + oldcontext = LIBXML(stream_context); + LIBXML(stream_context) = context; + return oldcontext; + +} + PHP_MINIT_FUNCTION(libxml) { php_libxml_initialize(); @@ -495,8 +518,33 @@ PHP_FUNCTION(libxml_set_streams_context) } /* }}} */ - /* {{{ Common functions shared by extensions */ +int php_libxml_xmlCheckUTF8(const unsigned char *s) +{ + int i; + unsigned char c; + + for (i = 0; (c = s[i++]);) { + if ((c & 0x80) == 0) { + } else if ((c & 0xe0) == 0xc0) { + if ((s[i++] & 0xc0) != 0x80) { + return 0; + } + } else if ((c & 0xf0) == 0xe0) { + if ((s[i++] & 0xc0) != 0x80 || (s[i++] & 0xc0) != 0x80) { + return 0; + } + } else if ((c & 0xf8) == 0xf0) { + if ((s[i++] & 0xc0) != 0x80 || (s[i++] & 0xc0) != 0x80 || (s[i++] & 0xc0) != 0x80) { + return 0; + } + } else { + return 0; + } + } + return 1; +} + int php_libxml_register_export(zend_class_entry *ce, php_libxml_export_node export_function) { php_libxml_func_handler export_hnd; @@ -568,7 +616,7 @@ int php_libxml_decrement_node_ptr(php_libxml_node_object *object TSRMLS_DC) { obj_node = (php_libxml_node_ptr *) object->node; ret_refcount = --obj_node->refcount; if (ret_refcount == 0) { - if (obj_node->node != NULL && obj_node->node->type != XML_DOCUMENT_NODE) { + if (obj_node->node != NULL) { obj_node->node->_private = NULL; } efree(obj_node); @@ -663,6 +711,10 @@ void php_libxml_node_decrement_resource(php_libxml_node_object *object TSRMLS_DC ret_refcount = php_libxml_decrement_node_ptr(object TSRMLS_CC); if (ret_refcount == 0) { php_libxml_node_free_resource(nodep TSRMLS_CC); + } else { + if (obj_node && object == obj_node->_private) { + obj_node->_private = NULL; + } } /* Safe to call as if the resource were freed then doc pointer is NULL */ php_libxml_decrement_doc_ref(object TSRMLS_CC); diff --git a/ext/libxml/php_libxml.h b/ext/libxml/php_libxml.h index ab47e202fb46..8704592f0279 100644 --- a/ext/libxml/php_libxml.h +++ b/ext/libxml/php_libxml.h @@ -22,14 +22,9 @@ #ifndef PHP_LIBXML_H #define PHP_LIBXML_H -#ifdef HAVE_LIBXML +#if HAVE_LIBXML extern zend_module_entry libxml_module_entry; #define libxml_module_ptr &libxml_module_entry -#else -#define libxml_module_ptr NULL -#endif - -#ifdef HAVE_LIBXML #ifdef PHP_WIN32 #define PHP_LIBXML_API __declspec(dllexport) @@ -67,6 +62,7 @@ typedef struct _php_libxml_node_object { typedef void * (*php_libxml_export_node) (zval *object TSRMLS_DC); PHP_FUNCTION(libxml_set_streams_context); + int php_libxml_increment_node_ptr(php_libxml_node_object *object, xmlNodePtr node, void *private_data TSRMLS_DC); int php_libxml_decrement_node_ptr(php_libxml_node_object *object TSRMLS_DC); int php_libxml_increment_doc_ref(php_libxml_node_object *object, xmlDocPtr docp TSRMLS_DC); @@ -77,13 +73,15 @@ PHP_LIBXML_API int php_libxml_register_export(zend_class_entry *ce, php_libxml_e void php_libxml_node_free_resource(xmlNodePtr node TSRMLS_DC); /* When object dtor is called as node may still be referenced */ void php_libxml_node_decrement_resource(php_libxml_node_object *object TSRMLS_DC); -void php_libxml_error_handler(void *ctx, const char *msg, ...); +PHP_LIBXML_API void php_libxml_error_handler(void *ctx, const char *msg, ...); void php_libxml_ctx_warning(void *ctx, const char *msg, ...); void php_libxml_ctx_error(void *ctx, const char *msg, ...); +PHP_LIBXML_API int php_libxml_xmlCheckUTF8(const unsigned char *s); +PHP_LIBXML_API zval *php_libxml_switch_context(zval *context TSRMLS_DC); -#endif /* HAVE_LIBXML */ - -#define phpext_libxml_ptr libxml_module_ptr +/* Init/shutdown functions*/ +PHP_LIBXML_API void php_libxml_initialize(); +PHP_LIBXML_API void php_libxml_shutdown(); #ifdef ZTS #define LIBXML(v) TSRMG(libxml_globals_id, php_libxml_globals *, v) @@ -91,8 +89,11 @@ void php_libxml_ctx_error(void *ctx, const char *msg, ...); #define LIBXML(v) (libxml_globals.v) #endif -PHP_LIBXML_API void php_libxml_initialize(); -PHP_LIBXML_API void php_libxml_shutdown(); +#else /* HAVE_LIBXML */ +#define libxml_module_ptr NULL +#endif + +#define phpext_libxml_ptr libxml_module_ptr #endif /* PHP_LIBXML_H */ diff --git a/ext/libxml/php_libxml2.def b/ext/libxml/php_libxml2.def index 9736c9fa25f1..0dd470afced2 100644 --- a/ext/libxml/php_libxml2.def +++ b/ext/libxml/php_libxml2.def @@ -13,13 +13,22 @@ __xmlGenericError __xmlGenericErrorContext __xmlGetWarningsDefaultValue __xmlIndentTreeOutput +xmlIsBaseCharGroup DATA +xmlIsCharGroup DATA +xmlIsCombiningGroup DATA +xmlIsDigitGroup DATA +xmlIsExtenderGroup DATA +xmlIsIdeographicGroup DATA +xmlIsPubidChar_tab DATA __xmlKeepBlanksDefaultValue +xmlLastError DATA __xmlLineNumbersDefaultValue __xmlLoadExtDtdDefaultValue xmlMalloc DATA xmlMallocAtomic DATA xmlMemStrdup DATA __xmlParserDebugEntities +xmlParserMaxDepth DATA __xmlParserVersion __xmlPedanticParserDefaultValue xmlRealloc DATA @@ -28,6 +37,7 @@ __xmlSaveNoEmptyTags xmlStringComment DATA xmlStringText DATA xmlStringTextNoenc DATA +xmlStructuredError DATA __xmlSubstituteEntitiesDefaultValue __xmlTreeIndentString xmlXPathNAN DATA @@ -72,6 +82,13 @@ htmlAutoCloseTag htmlCreateFileParserCtxt htmlCreateMemoryParserCtxt htmlCreatePushParserCtxt +htmlCtxtReadDoc +htmlCtxtReadFd +htmlCtxtReadFile +htmlCtxtReadIO +htmlCtxtReadMemory +htmlCtxtReset +htmlCtxtUseOptions htmlDefaultSAXHandlerInit htmlDocContentDumpFormatOutput htmlDocContentDumpOutput @@ -104,6 +121,11 @@ htmlParseDocument htmlParseElement htmlParseEntityRef htmlParseFile +htmlReadDoc +htmlReadFd +htmlReadFile +htmlReadIO +htmlReadMemory htmlSAXParseDoc htmlSAXParseFile htmlSaveFile @@ -159,6 +181,7 @@ xmlAddRef xmlAddSibling xmlAllocOutputBuffer xmlAllocParserInputBuffer +xmlAttrSerializeTxtContent xmlAutomataCompile xmlAutomataGetInitState xmlAutomataIsDeterminist @@ -181,6 +204,7 @@ xmlBufferCat xmlBufferContent xmlBufferCreate xmlBufferCreateSize +xmlBufferCreateStatic xmlBufferDump xmlBufferEmpty xmlBufferFree @@ -194,6 +218,7 @@ xmlBufferWriteChar xmlBufferWriteQuotedString xmlBuildQName xmlBuildURI +xmlByteConsumed xmlC14NDocDumpMemory xmlC14NDocSave xmlC14NDocSaveTo @@ -223,9 +248,11 @@ xmlCharEncCloseFunc xmlCharEncFirstLine xmlCharEncInFunc xmlCharEncOutFunc +xmlCharInRange xmlCharStrdup xmlCharStrndup xmlCheckFilename +xmlCheckHTTPInput xmlCheckLanguageID xmlCheckUTF8 xmlCheckVersion @@ -233,6 +260,7 @@ xmlCleanupCharEncodingHandlers xmlCleanupEncodingAliases xmlCleanupGlobals xmlCleanupInputCallbacks +xmlCleanupMemory xmlCleanupOutputCallbacks xmlCleanupParser xmlCleanupPredefinedEntities @@ -249,6 +277,7 @@ xmlCopyElementContent xmlCopyElementTable xmlCopyEntitiesTable xmlCopyEnumeration +xmlCopyError xmlCopyNamespace xmlCopyNamespaceList xmlCopyNode @@ -266,7 +295,26 @@ xmlCreateIntSubset xmlCreateMemoryParserCtxt xmlCreatePushParserCtxt xmlCreateURI +xmlCreateURLParserCtxt +xmlCtxtGetLastError +xmlCtxtReadDoc +xmlCtxtReadFd +xmlCtxtReadFile +xmlCtxtReadIO +xmlCtxtReadMemory +xmlCtxtReset +xmlCtxtResetLastError +xmlCtxtResetPush +xmlCtxtUseOptions xmlCurrentChar +xmlDictCreate +xmlDictCreateSub +xmlDictFree +xmlDictLookup +xmlDictOwns +xmlDictQLookup +xmlDictReference +xmlDictSize xmlDebugDumpAttr xmlDebugDumpAttrList xmlDebugDumpDTD @@ -282,6 +330,14 @@ xmlDefaultSAXHandlerInit xmlDelEncodingAlias xmlDeregisterNodeDefault xmlDetectCharEncoding +xmlDictCreate +xmlDictCreateSub +xmlDictFree +xmlDictLookup +xmlDictOwns +xmlDictQLookup +xmlDictReference +xmlDictSize xmlDocCopyNode xmlDocDump xmlDocDumpFormatMemory @@ -303,6 +359,7 @@ xmlElemDump xmlEncodeEntities xmlEncodeEntitiesReentrant xmlEncodeSpecialChars +xmlErrMemory xmlFileClose xmlFileMatch xmlFileOpen @@ -327,11 +384,14 @@ xmlFreeNs xmlFreeNsList xmlFreeParserCtxt xmlFreeParserInputBuffer +xmlFreePattern +xmlFreePatternList xmlFreeProp xmlFreePropList xmlFreeRMutex xmlFreeRefTable xmlFreeTextReader +xmlFreeTextWriter xmlFreeURI xmlFreeValidCtxt xmlGcMemGet @@ -356,6 +416,7 @@ xmlGetGlobalState xmlGetID xmlGetIntSubset xmlGetLastChild +xmlGetLastError xmlGetLineNo xmlGetNoNsProp xmlGetNodePath @@ -379,6 +440,9 @@ xmlHashFree xmlHashLookup xmlHashLookup2 xmlHashLookup3 +xmlHashQLookup +xmlHashQLookup2 +xmlHashQLookup3 xmlHashRemoveEntry xmlHashRemoveEntry2 xmlHashRemoveEntry3 @@ -425,6 +489,12 @@ xmlIsMixedElement xmlIsPubidChar xmlIsRef xmlIsXHTML +xmlIsBaseCharGroup DATA +xmlIsCharGroup DATA +xmlIsCombiningGroup DATA +xmlIsDigitGroup DATA +xmlIsExtenderGroup DATA +xmlIsIdeographicGroup DATA xmlKeepBlanksDefault xmlLineNumbersDefault xmlLinkGetData @@ -461,6 +531,8 @@ xmlLoadSGMLSuperCatalog xmlLockLibrary xmlLsCountNode xmlLsOneNode +xmlMallocAtomicLoc +xmlMallocLoc xmlMemDisplay xmlMemFree xmlMemGet @@ -468,6 +540,7 @@ xmlMemMalloc xmlMemRealloc xmlMemSetup xmlMemShow +xmlMemStrdupLoc xmlMemUsed xmlMemoryDump xmlMemoryStrdup @@ -501,13 +574,16 @@ xmlNanoFTPUpdateURL xmlNanoHTTPAuthHeader xmlNanoHTTPCleanup xmlNanoHTTPClose +xmlNanoHTTPEncoding xmlNanoHTTPFetch xmlNanoHTTPInit xmlNanoHTTPMethod xmlNanoHTTPMethodRedir +xmlNanoHTTPMimeType xmlNanoHTTPOpen xmlNanoHTTPOpenRedir xmlNanoHTTPRead +xmlNanoHTTPRedir xmlNanoHTTPReturnCode xmlNanoHTTPSave xmlNanoHTTPScanProxy @@ -551,11 +627,18 @@ xmlNewTextChild xmlNewTextLen xmlNewTextReader xmlNewTextReaderFilename +xmlNewTextWriter +xmlNewTextWriterDoc +xmlNewTextWriterFilename +xmlNewTextWriterMemory +xmlNewTextWriterPushParser +xmlNewTextWriterTree xmlNewValidCtxt xmlNextChar xmlNoNetExternalEntityLoader xmlNodeAddContent xmlNodeAddContentLen +xmlNodeBufGetContent xmlNodeDump xmlNodeDumpOutput xmlNodeGetBase @@ -655,6 +738,7 @@ xmlParserInputBufferCreateFile xmlParserInputBufferCreateFilename xmlParserInputBufferCreateIO xmlParserInputBufferCreateMem +xmlParserInputBufferCreateStatic xmlParserInputBufferGrow xmlParserInputBufferPush xmlParserInputBufferRead @@ -666,12 +750,32 @@ xmlParserPrintFileInfo xmlParserValidityError xmlParserValidityWarning xmlParserWarning +xmlPatternMatch +xmlPatterncompile xmlPedanticParserDefault xmlPopInput xmlPrintURI xmlPushInput xmlRMutexLock xmlRMutexUnlock +xmlReadDoc +xmlReadFd +xmlReadFile +xmlReadIO +xmlReadMemory +xmlReaderForDoc +xmlReaderForFd +xmlReaderForFile +xmlReaderForIO +xmlReaderForMemory +xmlReaderNewDoc +xmlReaderNewFd +xmlReaderNewFile +xmlReaderNewIO +xmlReaderNewMemory +xmlReaderNewWalker +xmlReaderWalker +xmlReallocLoc xmlReconciliateNs xmlRecoverDoc xmlRecoverFile @@ -712,10 +816,47 @@ xmlRelaxNGValidateFullElement xmlRelaxNGValidatePopElement xmlRelaxNGValidatePushCData xmlRelaxNGValidatePushElement +xmlRelaxParserSetFlag xmlRemoveID xmlRemoveProp xmlRemoveRef xmlReplaceNode +xmlResetError +xmlResetLastError +xmlSAX2AttributeDecl +xmlSAX2CDataBlock +xmlSAX2Characters +xmlSAX2Comment +xmlSAX2ElementDecl +xmlSAX2EndDocument +xmlSAX2EndElement +xmlSAX2EndElementNs +xmlSAX2EntityDecl +xmlSAX2ExternalSubset +xmlSAX2GetColumnNumber +xmlSAX2GetEntity +xmlSAX2GetLineNumber +xmlSAX2GetParameterEntity +xmlSAX2GetPublicId +xmlSAX2GetSystemId +xmlSAX2HasExternalSubset +xmlSAX2HasInternalSubset +xmlSAX2IgnorableWhitespace +xmlSAX2InitDefaultSAXHandler +xmlSAX2InitDocbDefaultSAXHandler +xmlSAX2InitHtmlDefaultSAXHandler +xmlSAX2InternalSubset +xmlSAX2IsStandalone +xmlSAX2NotationDecl +xmlSAX2ProcessingInstruction +xmlSAX2Reference +xmlSAX2ResolveEntity +xmlSAX2SetDocumentLocator +xmlSAX2StartDocument +xmlSAX2StartElement +xmlSAX2StartElementNs +xmlSAX2UnparsedEntityDecl +xmlSAXDefaultVersion xmlSAXParseDTD xmlSAXParseDoc xmlSAXParseEntity @@ -725,6 +866,7 @@ xmlSAXParseMemory xmlSAXParseMemoryWithData xmlSAXUserParseFile xmlSAXUserParseMemory +xmlSAXVersion xmlSaveFile xmlSaveFileEnc xmlSaveFileTo @@ -745,6 +887,7 @@ xmlSchemaFreeValidCtxt xmlSchemaFreeValue xmlSchemaGetPredefinedType xmlSchemaInitTypes +xmlSchemaNewDocParserCtxt xmlSchemaNewFacet xmlSchemaNewMemParserCtxt xmlSchemaNewParserCtxt @@ -770,6 +913,7 @@ xmlSetListDoc xmlSetNs xmlSetNsProp xmlSetProp +xmlSetStructuredErrorFunc xmlSetTreeDoc xmlSetupParserForBuffer xmlShell @@ -794,6 +938,9 @@ xmlSplitQName3 xmlSprintfElementContent xmlStopParser xmlStrEqual +xmlStrPrintf +xmlStrQEqual +xmlStrVPrintf xmlStrcasecmp xmlStrcasestr xmlStrcat @@ -803,22 +950,33 @@ xmlStrdup xmlStringCurrentChar xmlStringDecodeEntities xmlStringGetNodeList +xmlStringLenDecodeEntities xmlStringLenGetNodeList xmlStrlen xmlStrncasecmp xmlStrncat +xmlStrncatNew xmlStrncmp xmlStrndup xmlStrstr xmlStrsub xmlSubstituteEntitiesDefault xmlSwitchEncoding +xmlSwitchInputEncoding xmlSwitchToEncoding xmlTextConcat xmlTextMerge xmlTextReaderAttributeCount xmlTextReaderBaseUri xmlTextReaderClose +xmlTextReaderConstBaseUri +xmlTextReaderConstLocalName +xmlTextReaderConstName +xmlTextReaderConstNamespaceUri +xmlTextReaderConstPrefix +xmlTextReaderConstString +xmlTextReaderConstValue +xmlTextReaderConstXmlLang xmlTextReaderCurrentDoc xmlTextReaderCurrentNode xmlTextReaderDepth @@ -847,9 +1005,12 @@ xmlTextReaderMoveToNextAttribute xmlTextReaderName xmlTextReaderNamespaceUri xmlTextReaderNext +xmlTextReaderNextSibling xmlTextReaderNodeType xmlTextReaderNormalization xmlTextReaderPrefix +xmlTextReaderPreserve +xmlTextReaderPreservePattern xmlTextReaderQuoteChar xmlTextReaderRead xmlTextReaderReadAttributeValue @@ -861,8 +1022,77 @@ xmlTextReaderRelaxNGSetSchema xmlTextReaderRelaxNGValidate xmlTextReaderSetErrorHandler xmlTextReaderSetParserProp +xmlTextReaderSetStructuredErrorHandler xmlTextReaderValue xmlTextReaderXmlLang +xmlTextWriterEndAttribute +xmlTextWriterEndCDATA +xmlTextWriterEndComment +xmlTextWriterEndDTD +xmlTextWriterEndDocument +xmlTextWriterEndElement +xmlTextWriterEndPI +xmlTextWriterFlush +xmlTextWriterFullEndElement +xmlTextWriterSetIndent +xmlTextWriterSetIndentString +xmlTextWriterStartAttribute +xmlTextWriterStartAttributeNS +xmlTextWriterStartCDATA +xmlTextWriterStartComment +xmlTextWriterStartDTD +xmlTextWriterStartDTDAttlist +xmlTextWriterStartDTDElement +xmlTextWriterStartDTDEntity +xmlTextWriterStartDocument +xmlTextWriterStartElement +xmlTextWriterStartElementNS +xmlTextWriterStartPI +xmlTextWriterWriteAttribute +xmlTextWriterWriteAttributeNS +xmlTextWriterWriteBase64 +xmlTextWriterWriteBinHex +xmlTextWriterWriteCDATA +xmlTextWriterWriteComment +xmlTextWriterWriteDTD +xmlTextWriterWriteDTDAttlist +xmlTextWriterWriteDTDElement +xmlTextWriterWriteDTDEntity +xmlTextWriterWriteDTDExternalEntity +xmlTextWriterWriteDTDInternalEntity +xmlTextWriterWriteDTDNotation +xmlTextWriterWriteElement +xmlTextWriterWriteElementNS +xmlTextWriterWriteFormatAttribute +xmlTextWriterWriteFormatAttributeNS +xmlTextWriterWriteFormatCDATA +xmlTextWriterWriteFormatComment +xmlTextWriterWriteFormatDTD +xmlTextWriterWriteFormatDTDAttlist +xmlTextWriterWriteFormatDTDElement +xmlTextWriterWriteFormatDTDInternalEntity +xmlTextWriterWriteFormatElement +xmlTextWriterWriteFormatElementNS +xmlTextWriterWriteFormatPI +xmlTextWriterWriteFormatRaw +xmlTextWriterWriteFormatString +xmlTextWriterWritePI +xmlTextWriterWriteRaw +xmlTextWriterWriteRawLen +xmlTextWriterWriteString +xmlTextWriterWriteVFormatAttribute +xmlTextWriterWriteVFormatAttributeNS +xmlTextWriterWriteVFormatCDATA +xmlTextWriterWriteVFormatComment +xmlTextWriterWriteVFormatDTD +xmlTextWriterWriteVFormatDTDAttlist +xmlTextWriterWriteVFormatDTDElement +xmlTextWriterWriteVFormatDTDInternalEntity +xmlTextWriterWriteVFormatElement +xmlTextWriterWriteVFormatElementNS +xmlTextWriterWriteVFormatPI +xmlTextWriterWriteVFormatRaw +xmlTextWriterWriteVFormatString xmlThrDefBufferAllocScheme xmlThrDefDefaultBufferSize xmlThrDefDeregisterNodeDefault @@ -877,8 +1107,10 @@ xmlThrDefPedanticParserDefaultValue xmlThrDefRegisterNodeDefault xmlThrDefSaveNoEmptyTags xmlThrDefSetGenericErrorFunc +xmlThrDefSetStructuredErrorFunc xmlThrDefSubstituteEntitiesDefaultValue xmlThrDefTreeIndentString +xmlUCSIsAegeanNumbers xmlUCSIsAlphabeticPresentationForms xmlUCSIsArabic xmlUCSIsArabicPresentationFormsA @@ -893,6 +1125,7 @@ xmlUCSIsBopomofo xmlUCSIsBopomofoExtended xmlUCSIsBoxDrawing xmlUCSIsBraillePatterns +xmlUCSIsBuhid xmlUCSIsByzantineMusicalSymbols xmlUCSIsCJKCompatibility xmlUCSIsCJKCompatibilityForms @@ -942,11 +1175,14 @@ xmlUCSIsCatZp xmlUCSIsCatZs xmlUCSIsCherokee xmlUCSIsCombiningDiacriticalMarks +xmlUCSIsCombiningDiacriticalMarksforSymbols xmlUCSIsCombiningHalfMarks xmlUCSIsCombiningMarksforSymbols xmlUCSIsControlPictures xmlUCSIsCurrencySymbols +xmlUCSIsCypriotSyllabary xmlUCSIsCyrillic +xmlUCSIsCyrillicSupplement xmlUCSIsDeseret xmlUCSIsDevanagari xmlUCSIsDingbats @@ -959,12 +1195,14 @@ xmlUCSIsGeorgian xmlUCSIsGothic xmlUCSIsGreek xmlUCSIsGreekExtended +xmlUCSIsGreekandCoptic xmlUCSIsGujarati xmlUCSIsGurmukhi xmlUCSIsHalfwidthandFullwidthForms xmlUCSIsHangulCompatibilityJamo xmlUCSIsHangulJamo xmlUCSIsHangulSyllables +xmlUCSIsHanunoo xmlUCSIsHebrew xmlUCSIsHighPrivateUseSurrogates xmlUCSIsHighSurrogates @@ -975,18 +1213,26 @@ xmlUCSIsKanbun xmlUCSIsKangxiRadicals xmlUCSIsKannada xmlUCSIsKatakana +xmlUCSIsKatakanaPhoneticExtensions xmlUCSIsKhmer +xmlUCSIsKhmerSymbols xmlUCSIsLao xmlUCSIsLatin1Supplement xmlUCSIsLatinExtendedA xmlUCSIsLatinExtendedAdditional xmlUCSIsLatinExtendedB xmlUCSIsLetterlikeSymbols +xmlUCSIsLimbu +xmlUCSIsLinearBIdeograms +xmlUCSIsLinearBSyllabary xmlUCSIsLowSurrogates xmlUCSIsMalayalam xmlUCSIsMathematicalAlphanumericSymbols xmlUCSIsMathematicalOperators +xmlUCSIsMiscellaneousMathematicalSymbolsA +xmlUCSIsMiscellaneousMathematicalSymbolsB xmlUCSIsMiscellaneousSymbols +xmlUCSIsMiscellaneousSymbolsandArrows xmlUCSIsMiscellaneousTechnical xmlUCSIsMongolian xmlUCSIsMusicalSymbols @@ -996,23 +1242,40 @@ xmlUCSIsOgham xmlUCSIsOldItalic xmlUCSIsOpticalCharacterRecognition xmlUCSIsOriya +xmlUCSIsOsmanya +xmlUCSIsPhoneticExtensions xmlUCSIsPrivateUse +xmlUCSIsPrivateUseArea xmlUCSIsRunic +xmlUCSIsShavian xmlUCSIsSinhala xmlUCSIsSmallFormVariants xmlUCSIsSpacingModifierLetters xmlUCSIsSpecials xmlUCSIsSuperscriptsandSubscripts +xmlUCSIsSupplementalArrowsA +xmlUCSIsSupplementalArrowsB +xmlUCSIsSupplementalMathematicalOperators +xmlUCSIsSupplementaryPrivateUseAreaA +xmlUCSIsSupplementaryPrivateUseAreaB xmlUCSIsSyriac +xmlUCSIsTagalog +xmlUCSIsTagbanwa xmlUCSIsTags +xmlUCSIsTaiLe +xmlUCSIsTaiXuanJingSymbols xmlUCSIsTamil xmlUCSIsTelugu xmlUCSIsThaana xmlUCSIsThai xmlUCSIsTibetan +xmlUCSIsUgaritic xmlUCSIsUnifiedCanadianAboriginalSyllabics +xmlUCSIsVariationSelectors +xmlUCSIsVariationSelectorsSupplement xmlUCSIsYiRadicals xmlUCSIsYiSyllables +xmlUCSIsYijingHexagramSymbols xmlURIEscape xmlURIEscapeStr xmlURIUnescapeString @@ -1058,8 +1321,14 @@ xmlValidatePushCData xmlValidatePushElement xmlValidateQName xmlValidateRoot +xmlXIncludeFreeContext +xmlXIncludeNewContext xmlXIncludeProcess +xmlXIncludeProcessFlags +xmlXIncludeProcessNode xmlXIncludeProcessTree +xmlXIncludeProcessTreeFlags +xmlXIncludeSetFlags xmlXPathAddValues xmlXPathBooleanFunction xmlXPathCastBooleanToNumber @@ -1078,6 +1347,7 @@ xmlXPathCastToNumber xmlXPathCastToString xmlXPathCeilingFunction xmlXPathCmpNodes +xmlXPathCtxtCompile xmlXPathCompareValues xmlXPathCompile xmlXPathCompiledEval @@ -1087,6 +1357,7 @@ xmlXPathConvertBoolean xmlXPathConvertNumber xmlXPathConvertString xmlXPathCountFunction +xmlXPathCtxtCompile xmlXPathDebugDumpCompExpr xmlXPathDebugDumpObject xmlXPathDifference @@ -1094,6 +1365,7 @@ xmlXPathDistinct xmlXPathDistinctSorted xmlXPathDivValues xmlXPathEqualValues +xmlXPathErr xmlXPathEval xmlXPathEvalExpr xmlXPathEvalExpression @@ -1208,6 +1480,7 @@ xmlXPathWrapCString xmlXPathWrapExternal xmlXPathWrapNodeSet xmlXPathWrapString +xmlXPathErr xmlXPatherror xmlXPtrBuildNodeList xmlXPtrEval @@ -1230,9 +1503,69 @@ xmlXPtrNewRangePointNode xmlXPtrNewRangePoints xmlXPtrRangeToFunction xmlXPtrWrapLocationSet -_libiconv_version -libiconv_close -libiconv -libiconv_open -libiconv_set_relocation_prefix - \ No newline at end of file +xmlNewTextWriter +xmlNewTextWriterDoc +xmlNewTextWriterFilename +xmlNewTextWriterMemory +xmlNewTextWriterPushParser +xmlNewTextWriterTree +xmlFreeTextWriter +xmlTextWriterEndAttribute +xmlTextWriterEndCDATA +xmlTextWriterEndComment +xmlTextWriterEndDTD +xmlTextWriterEndDTDAttlist +xmlTextWriterEndDTDElement +xmlTextWriterEndDTDEntity +xmlTextWriterEndDocument +xmlTextWriterEndElement +xmlTextWriterEndPI +xmlTextWriterFlush +xmlTextWriterFullEndElement +xmlTextWriterSetIndent +xmlTextWriterSetIndentString +xmlTextWriterStartAttribute +xmlTextWriterStartAttributeNS +xmlTextWriterStartCDATA +xmlTextWriterStartComment +xmlTextWriterStartDTD +xmlTextWriterStartDTDAttlist +xmlTextWriterStartDTDElement +xmlTextWriterStartDTDEntity +xmlTextWriterStartDocument +xmlTextWriterStartElement +xmlTextWriterStartElementNS +xmlTextWriterStartPI +xmlTextWriterWriteAttribute +xmlTextWriterWriteAttributeNS +xmlTextWriterWriteBase64 +xmlTextWriterWriteBinHex +xmlTextWriterWriteCDATA +xmlTextWriterWriteComment +xmlTextWriterWriteDTD +xmlTextWriterWriteDTDAttlist +xmlTextWriterWriteDTDElement +xmlTextWriterWriteDTDEntity +xmlTextWriterWriteDTDExternalEntity +xmlTextWriterWriteDTDExternalEntityContents +xmlTextWriterWriteDTDInternalEntity +xmlTextWriterWriteDTDNotation +xmlTextWriterWriteElement +xmlTextWriterWriteElementNS +xmlTextWriterWriteFormatAttribute +xmlTextWriterWriteFormatAttributeNS +xmlTextWriterWriteFormatCDATA +xmlTextWriterWriteFormatComment +xmlTextWriterWriteFormatDTD +xmlTextWriterWriteFormatDTDAttlist +xmlTextWriterWriteFormatDTDElement +xmlTextWriterWriteFormatDTDInternalEntity +xmlTextWriterWriteFormatElement +xmlTextWriterWriteFormatElementNS +xmlTextWriterWriteFormatPI +xmlTextWriterWriteFormatRaw +xmlTextWriterWriteFormatString +xmlTextWriterWritePI +xmlTextWriterWriteRaw +xmlTextWriterWriteRawLen +xmlTextWriterWriteString diff --git a/ext/mbstring/config.m4 b/ext/mbstring/config.m4 index 9b437c0e07cd..5171c17f2a36 100644 --- a/ext/mbstring/config.m4 +++ b/ext/mbstring/config.m4 @@ -84,6 +84,7 @@ int main() { return foo(10, "", 3.14); } PHP_MBSTRING_ADD_CFLAG([-DNOT_RUBY]) PHP_MBSTRING_ADD_BUILD_DIR([oniguruma]) + PHP_MBSTRING_ADD_BUILD_DIR([oniguruma/enc]) PHP_MBSTRING_ADD_INCLUDE([oniguruma]) PHP_MBSTRING_ADD_CONFIG_HEADER([oniguruma/config.h]) @@ -95,7 +96,12 @@ int main() { return foo(10, "", 3.14); } oniguruma/reggnu.c oniguruma/regparse.c oniguruma/regenc.c - oniguruma/regposerr.c + oniguruma/regext.c + oniguruma/regsyntax.c + oniguruma/regtrav.c + oniguruma/regversion.c + oniguruma/st.c + oniguruma/enc/unicode.c oniguruma/enc/ascii.c oniguruma/enc/utf8.c oniguruma/enc/euc_jp.c @@ -120,6 +126,10 @@ int main() { return foo(10, "", 3.14); } oniguruma/enc/koi8.c oniguruma/enc/koi8_r.c oniguruma/enc/big5.c + oniguruma/enc/utf16_be.c + oniguruma/enc/utf16_le.c + oniguruma/enc/utf32_be.c + oniguruma/enc/utf32_le.c ]) fi ]) @@ -164,6 +174,7 @@ AC_DEFUN([PHP_MBSTRING_SETUP_LIBMBFL], [ libmbfl/filters/mbfilter_iso8859_13.c libmbfl/filters/mbfilter_iso8859_14.c libmbfl/filters/mbfilter_iso8859_15.c + libmbfl/filters/mbfilter_iso8859_16.c libmbfl/filters/mbfilter_iso8859_2.c libmbfl/filters/mbfilter_iso8859_3.c libmbfl/filters/mbfilter_iso8859_4.c @@ -261,3 +272,5 @@ if test "$PHP_MBSTRING" != "no"; then PHP_MBSTRING_SETUP_LIBMBFL PHP_MBSTRING_EXTENSION fi + +# vim600: sts=2 sw=2 et diff --git a/ext/mbstring/config.w32 b/ext/mbstring/config.w32 index 8484b4623173..665f4b4ba032 100644 --- a/ext/mbstring/config.w32 +++ b/ext/mbstring/config.w32 @@ -24,13 +24,14 @@ if (PHP_MBSTRING == "yes") { mbfilter_euc_jp.c mbfilter_euc_jp_win.c mbfilter_euc_kr.c \ mbfilter_euc_tw.c mbfilter_htmlent.c mbfilter_hz.c mbfilter_iso2022_kr.c \ mbfilter_iso8859_1.c mbfilter_iso8859_10.c mbfilter_iso8859_13.c \ - mbfilter_iso8859_14.c mbfilter_iso8859_15.c mbfilter_iso8859_2.c \ - mbfilter_iso8859_3.c mbfilter_iso8859_4.c mbfilter_iso8859_5.c \ - mbfilter_iso8859_6.c mbfilter_iso8859_7.c mbfilter_iso8859_8.c \ - mbfilter_iso8859_9.c mbfilter_jis.c mbfilter_koi8r.c mbfilter_qprint.c \ - mbfilter_sjis.c mbfilter_ucs2.c mbfilter_ucs4.c mbfilter_uhc.c \ - mbfilter_utf16.c mbfilter_utf32.c mbfilter_utf7.c mbfilter_utf7imap.c \ - mbfilter_utf8.c mbfilter_uuencode.c", "mbstring"); + mbfilter_iso8859_14.c mbfilter_iso8859_15.c mbfilter_iso8859_16.c \ + mbfilter_iso8859_2.c mbfilter_iso8859_3.c mbfilter_iso8859_4.c \ + mbfilter_iso8859_5.c mbfilter_iso8859_6.c mbfilter_iso8859_7.c \ + mbfilter_iso8859_8.c mbfilter_iso8859_9.c mbfilter_jis.c \ + mbfilter_koi8r.c mbfilter_qprint.c mbfilter_sjis.c mbfilter_ucs2.c \ + mbfilter_ucs4.c mbfilter_uhc.c mbfilter_utf16.c mbfilter_utf32.c \ + mbfilter_utf7.c mbfilter_utf7imap.c mbfilter_utf8.c \ + mbfilter_uuencode.c", "mbstring"); ADD_SOURCES("ext/mbstring/libmbfl/mbfl", "mbfilter.c mbfilter_8bit.c \ mbfilter_pass.c mbfilter_wchar.c mbfl_convert.c mbfl_encoding.c \ @@ -51,13 +52,15 @@ if (PHP_MBSTRING == "yes") { AC_DEFINE('HAVE_STDARG_PROTOTYPES', 1, 'have stdarg.h'); AC_DEFINE('HAVE_MBREGEX', 1); ADD_SOURCES("ext/mbstring/oniguruma", "regcomp.c regerror.c \ - regenc.c regexec.c reggnu.c regparse.c regposerr.c", "mbstring"); + regenc.c regexec.c reggnu.c regparse.c regposerr.c \ + regext.c regsyntax.c regtrav.c regversion.c st.c", "mbstring"); ADD_SOURCES("ext/mbstring/oniguruma/enc", "ascii.c big5.c \ euc_jp.c euc_kr.c euc_tw.c iso8859_1.c iso8859_2.c \ iso8859_3.c iso8859_4.c iso8859_5.c iso8859_6.c \ iso8859_7.c iso8859_8.c iso8859_9.c iso8859_10.c \ iso8859_11.c iso8859_13.c iso8859_14.c iso8859_15.c iso8859_16.c \ - koi8.c koi8_r.c sjis.c utf8.c", "mbstring"); + koi8.c koi8_r.c sjis.c utf8.c unicode.c utf16_be.c utf16_le.c \ + utf32_be.c utf32_le.c", "mbstring"); ADD_SOURCES("ext/mbstring", "php_mbregex.c", "mbstring"); } } diff --git a/ext/mbstring/libmbfl/configure.in b/ext/mbstring/libmbfl/configure.in index b6e5ab581a46..25d2e59373c9 100644 --- a/ext/mbstring/libmbfl/configure.in +++ b/ext/mbstring/libmbfl/configure.in @@ -28,5 +28,11 @@ AC_FUNC_MALLOC AC_FUNC_REALLOC AC_CHECK_FUNCS([strcasecmp strchr]) +AC_CHECK_PROGS([FETCH_VIA_FTP], [wget curl ncftpget]) + +if test "$FETCH_VIA_FTP" = "curl"; then + FETCH_VIA_FTP="curl -O" +fi + AC_CONFIG_FILES([Makefile mbfl/Makefile filters/Makefile nls/Makefile]) AC_OUTPUT diff --git a/ext/mbstring/libmbfl/filters/Makefile.am b/ext/mbstring/libmbfl/filters/Makefile.am index d3e5cfd257e1..aab009b9d5d2 100644 --- a/ext/mbstring/libmbfl/filters/Makefile.am +++ b/ext/mbstring/libmbfl/filters/Makefile.am @@ -1,5 +1,104 @@ -EXTRA_DIST=Makefile.bcc32 +EXTRA_DIST=Makefile.bcc32 mk_sb_tbl.awk noinst_LTLIBRARIES=libmbfl_filters.la INCLUDES=-I../mbfl libmbfl_filters_la_LDFLAGS=-version-info $(SHLIB_VERSION) -libmbfl_filters_la_SOURCES=mbfilter_cp936.c mbfilter_hz.c mbfilter_euc_tw.c mbfilter_big5.c mbfilter_euc_jp.c mbfilter_jis.c mbfilter_iso8859_1.c mbfilter_iso8859_2.c mbfilter_cp1252.c mbfilter_cp1251.c mbfilter_ascii.c mbfilter_iso8859_3.c mbfilter_iso8859_4.c mbfilter_iso8859_5.c mbfilter_iso8859_6.c mbfilter_iso8859_7.c mbfilter_iso8859_8.c mbfilter_iso8859_9.c mbfilter_iso8859_10.c mbfilter_iso8859_13.c mbfilter_iso8859_14.c mbfilter_iso8859_15.c mbfilter_htmlent.c mbfilter_byte2.c mbfilter_byte4.c mbfilter_uuencode.c mbfilter_base64.c mbfilter_sjis.c mbfilter_7bit.c mbfilter_qprint.c mbfilter_ucs4.c mbfilter_ucs2.c mbfilter_utf32.c mbfilter_utf16.c mbfilter_utf8.c mbfilter_utf7.c mbfilter_utf7imap.c mbfilter_euc_jp_win.c mbfilter_cp932.c mbfilter_euc_cn.c mbfilter_euc_kr.c mbfilter_uhc.c mbfilter_iso2022_kr.c mbfilter_cp866.c mbfilter_koi8r.c html_entities.c cp932_table.h html_entities.h mbfilter_7bit.h mbfilter_ascii.h mbfilter_base64.h mbfilter_big5.h mbfilter_byte2.h mbfilter_byte4.h mbfilter_cp1251.h mbfilter_cp1252.h mbfilter_cp866.h mbfilter_cp932.h mbfilter_cp936.h mbfilter_euc_cn.h mbfilter_euc_jp.h mbfilter_euc_jp_win.h mbfilter_euc_kr.h mbfilter_euc_tw.h mbfilter_htmlent.h mbfilter_hz.h mbfilter_iso2022_kr.h mbfilter_iso8859_1.h mbfilter_iso8859_10.h mbfilter_iso8859_13.h mbfilter_iso8859_14.h mbfilter_iso8859_15.h mbfilter_iso8859_2.h mbfilter_iso8859_3.h mbfilter_iso8859_4.h mbfilter_iso8859_5.h mbfilter_iso8859_6.h mbfilter_iso8859_7.h mbfilter_iso8859_8.h mbfilter_iso8859_9.h mbfilter_jis.h mbfilter_koi8r.h mbfilter_qprint.h mbfilter_sjis.h mbfilter_ucs2.h mbfilter_ucs4.h mbfilter_uhc.h mbfilter_utf16.h mbfilter_utf32.h mbfilter_utf7.h mbfilter_utf7imap.h mbfilter_utf8.h mbfilter_uuencode.h unicode_prop.h unicode_table_big5.h unicode_table_cns11643.h unicode_table_cp1251.h unicode_table_cp1252.h unicode_table_cp866.h unicode_table_cp932_ext.h unicode_table_cp936.h unicode_table_iso8859_10.h unicode_table_iso8859_13.h unicode_table_iso8859_14.h unicode_table_iso8859_15.h unicode_table_iso8859_2.h unicode_table_iso8859_3.h unicode_table_iso8859_4.h unicode_table_iso8859_5.h unicode_table_iso8859_6.h unicode_table_iso8859_7.h unicode_table_iso8859_8.h unicode_table_iso8859_9.h unicode_table_jis.h unicode_table_koi8r.h unicode_table_uhc.h +libmbfl_filters_la_SOURCES=mbfilter_cp936.c mbfilter_hz.c mbfilter_euc_tw.c mbfilter_big5.c mbfilter_euc_jp.c mbfilter_jis.c mbfilter_iso8859_1.c mbfilter_iso8859_2.c mbfilter_cp1252.c mbfilter_cp1251.c mbfilter_ascii.c mbfilter_iso8859_3.c mbfilter_iso8859_4.c mbfilter_iso8859_5.c mbfilter_iso8859_6.c mbfilter_iso8859_7.c mbfilter_iso8859_8.c mbfilter_iso8859_9.c mbfilter_iso8859_10.c mbfilter_iso8859_13.c mbfilter_iso8859_14.c mbfilter_iso8859_15.c mbfilter_iso8859_16.c mbfilter_htmlent.c mbfilter_byte2.c mbfilter_byte4.c mbfilter_uuencode.c mbfilter_base64.c mbfilter_sjis.c mbfilter_7bit.c mbfilter_qprint.c mbfilter_ucs4.c mbfilter_ucs2.c mbfilter_utf32.c mbfilter_utf16.c mbfilter_utf8.c mbfilter_utf7.c mbfilter_utf7imap.c mbfilter_euc_jp_win.c mbfilter_cp932.c mbfilter_euc_cn.c mbfilter_euc_kr.c mbfilter_uhc.c mbfilter_iso2022_kr.c mbfilter_cp866.c mbfilter_koi8r.c html_entities.c cp932_table.h html_entities.h mbfilter_7bit.h mbfilter_ascii.h mbfilter_base64.h mbfilter_big5.h mbfilter_byte2.h mbfilter_byte4.h mbfilter_cp1251.h mbfilter_cp1252.h mbfilter_cp866.h mbfilter_cp932.h mbfilter_cp936.h mbfilter_euc_cn.h mbfilter_euc_jp.h mbfilter_euc_jp_win.h mbfilter_euc_kr.h mbfilter_euc_tw.h mbfilter_htmlent.h mbfilter_hz.h mbfilter_iso2022_kr.h mbfilter_iso8859_1.h mbfilter_iso8859_10.h mbfilter_iso8859_13.h mbfilter_iso8859_14.h mbfilter_iso8859_15.h mbfilter_iso8859_16.h mbfilter_iso8859_2.h mbfilter_iso8859_3.h mbfilter_iso8859_4.h mbfilter_iso8859_5.h mbfilter_iso8859_6.h mbfilter_iso8859_7.h mbfilter_iso8859_8.h mbfilter_iso8859_9.h mbfilter_jis.h mbfilter_koi8r.h mbfilter_qprint.h mbfilter_sjis.h mbfilter_ucs2.h mbfilter_ucs4.h mbfilter_uhc.h mbfilter_utf16.h mbfilter_utf32.h mbfilter_utf7.h mbfilter_utf7imap.h mbfilter_utf8.h mbfilter_uuencode.h unicode_prop.h unicode_table_big5.h unicode_table_cns11643.h unicode_table_cp1251.h unicode_table_cp1252.h unicode_table_cp866.h unicode_table_cp932_ext.h unicode_table_cp936.h unicode_table_iso8859_10.h unicode_table_iso8859_13.h unicode_table_iso8859_14.h unicode_table_iso8859_15.h unicode_table_iso8859_16.h unicode_table_iso8859_2.h unicode_table_iso8859_3.h unicode_table_iso8859_4.h unicode_table_iso8859_5.h unicode_table_iso8859_6.h unicode_table_iso8859_7.h unicode_table_iso8859_8.h unicode_table_iso8859_9.h unicode_table_jis.h unicode_table_koi8r.h unicode_table_uhc.h + +mbfilter_iso8859_2.c: unicode_table_iso8859_2.h + +mbfilter_iso8859_3.c: unicode_table_iso8859_3.h + +mbfilter_iso8859_4.c: unicode_table_iso8859_4.h + +mbfilter_iso8859_5.c: unicode_table_iso8859_5.h + +mbfilter_iso8859_6.c: unicode_table_iso8859_6.h + +mbfilter_iso8859_7.c: unicode_table_iso8859_7.h + +mbfilter_iso8859_8.c: unicode_table_iso8859_8.h + +mbfilter_iso8859_9.c: unicode_table_iso8859_9.h + +mbfilter_iso8859_10.c: unicode_table_iso8859_10.h + +mbfilter_iso8859_11.c: unicode_table_iso8859_11.h + +mbfilter_iso8859_13.c: unicode_table_iso8859_13.h + +mbfilter_iso8859_14.c: unicode_table_iso8859_13.h + +mbfilter_iso8859_15.c: unicode_table_iso8859_15.h + +mbfilter_iso8859_16.c: unicode_table_iso8859_16.h + +8859-1.TXT 8859-2.TXT 8859-3.TXT 8859-4.TXT 8859-5.TXT 8859-6.TXT \ +8859-7.TXT 8859-8.TXT 8859-9.TXT 8859-10.TXT 8859-11.TXT 8859-13.TXT \ +8859-14.TXT 8859-15.TXT 8859-16.TXT: + $(FETCH_VIA_FTP) ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/$@ + +unicode_table_iso8859_1.h: mk_sb_tbl.awk + $(AWK) -v TABLE_NAME=iso8859_1_ucs_table \ + -v IFNDEF_NAME=UNICODE_TABLE_ISO8859_1_H -f mk_sb_tbl.awk 8859-1.TXT > $@ + +unicode_table_iso8859_2.h: mk_sb_tbl.awk + $(AWK) -v TABLE_NAME=iso8859_2_ucs_table \ + -v IFNDEF_NAME=UNICODE_TABLE_ISO8859_2_H -f mk_sb_tbl.awk 8859-2.TXT > $@ + +unicode_table_iso8859_3.h: mk_sb_tbl.awk + $(AWK) -v TABLE_NAME=iso8859_3_ucs_table \ + -v IFNDEF_NAME=UNICODE_TABLE_ISO8859_3_H -f mk_sb_tbl.awk 8859-3.TXT > $@ + +unicode_table_iso8859_4.h: mk_sb_tbl.awk + $(AWK) -v TABLE_NAME=iso8859_4_ucs_table \ + -v IFNDEF_NAME=UNICODE_TABLE_ISO8859_4_H -f mk_sb_tbl.awk 8859-4.TXT > $@ + +unicode_table_iso8859_5.h: mk_sb_tbl.awk + $(AWK) -v TABLE_NAME=iso8859_5_ucs_table \ + -v IFNDEF_NAME=UNICODE_TABLE_ISO8859_5_H -f mk_sb_tbl.awk 8859-5.TXT > $@ + +unicode_table_iso8859_6.h: mk_sb_tbl.awk + $(AWK) -v TABLE_NAME=iso8859_6_ucs_table \ + -v IFNDEF_NAME=UNICODE_TABLE_ISO8859_6_H -f mk_sb_tbl.awk 8859-6.TXT > $@ + +unicode_table_iso8859_7.h: mk_sb_tbl.awk + $(AWK) -v TABLE_NAME=iso8859_7_ucs_table \ + -v IFNDEF_NAME=UNICODE_TABLE_ISO8859_7_H -f mk_sb_tbl.awk 8859-7.TXT > $@ + +unicode_table_iso8859_8.h: mk_sb_tbl.awk + $(AWK) -v TABLE_NAME=iso8859_8_ucs_table \ + -v IFNDEF_NAME=UNICODE_TABLE_ISO8859_8_H -f mk_sb_tbl.awk 8859-8.TXT > $@ + +unicode_table_iso8859_9.h: mk_sb_tbl.awk + $(AWK) -v TABLE_NAME=iso8859_9_ucs_table \ + -v IFNDEF_NAME=UNICODE_TABLE_ISO8859_9_H -f mk_sb_tbl.awk 8859-9.TXT > $@ + +unicode_table_iso8859_10.h: mk_sb_tbl.awk + $(AWK) -v TABLE_NAME=iso8859_10_ucs_table \ + -v IFNDEF_NAME=UNICODE_TABLE_ISO8859_10_H -f mk_sb_tbl.awk 8859-10.TXT > $@ + +unicode_table_iso8859_11.h: mk_sb_tbl.awk + $(AWK) -v TABLE_NAME=iso8859_11_ucs_table \ + -v IFNDEF_NAME=UNICODE_TABLE_ISO8859_11_H -f mk_sb_tbl.awk 8859-11.TXT > $@ + +unicode_table_iso8859_13.h: mk_sb_tbl.awk + $(AWK) -v TABLE_NAME=iso8859_13_ucs_table \ + -v IFNDEF_NAME=UNICODE_TABLE_ISO8859_13_H -f mk_sb_tbl.awk 8859-13.TXT > $@ + +unicode_table_iso8859_14.h: mk_sb_tbl.awk + $(AWK) -v TABLE_NAME=iso8859_14_ucs_table \ + -v IFNDEF_NAME=UNICODE_TABLE_ISO8859_14_H -f mk_sb_tbl.awk 8859-14.TXT > $@ + +unicode_table_iso8859_15.h: mk_sb_tbl.awk + $(AWK) -v TABLE_NAME=iso8859_15_ucs_table \ + -v IFNDEF_NAME=UNICODE_TABLE_ISO8859_15_H -f mk_sb_tbl.awk 8859-15.TXT > $@ + +unicode_table_iso8859_16.h: mk_sb_tbl.awk + $(AWK) -v TABLE_NAME=iso8859_16_ucs_table \ + -v IFNDEF_NAME=UNICODE_TABLEISO8859_16_H -f mk_sb_tbl.awk 8859-16.TXT > $@ + +unidata: 8859-1.TXT 8859-2.TXT 8859-3.TXT 8859-4.TXT 8859-5.TXT 8859-6.TXT \ +8859-7.TXT 8859-8.TXT 8859-9.TXT 8859-10.TXT 8859-11.TXT 8859-13.TXT \ +8859-14.TXT 8859-15.TXT 8859-16.TXT + +.PHONY: unidata diff --git a/ext/mbstring/libmbfl/filters/Makefile.bcc32 b/ext/mbstring/libmbfl/filters/Makefile.bcc32 index 4219ed9061dd..32bd161093c8 100644 --- a/ext/mbstring/libmbfl/filters/Makefile.bcc32 +++ b/ext/mbstring/libmbfl/filters/Makefile.bcc32 @@ -1,6 +1,6 @@ !include ..\rules.mak.bcc32 INCLUDES=$(INCLUDES) -I../mbfl -OBJS=mbfilter_cp936.obj mbfilter_hz.obj mbfilter_euc_tw.obj mbfilter_big5.obj mbfilter_euc_jp.obj mbfilter_jis.obj mbfilter_iso8859_1.obj mbfilter_iso8859_2.obj mbfilter_cp1252.obj mbfilter_cp1251.obj mbfilter_ascii.obj mbfilter_iso8859_3.obj mbfilter_iso8859_4.obj mbfilter_iso8859_5.obj mbfilter_iso8859_6.obj mbfilter_iso8859_7.obj mbfilter_iso8859_8.obj mbfilter_iso8859_9.obj mbfilter_iso8859_10.obj mbfilter_iso8859_13.obj mbfilter_iso8859_14.obj mbfilter_iso8859_15.obj mbfilter_htmlent.obj mbfilter_byte2.obj mbfilter_byte4.obj mbfilter_uuencode.obj mbfilter_base64.obj mbfilter_sjis.obj mbfilter_7bit.obj mbfilter_qprint.obj mbfilter_ucs4.obj mbfilter_ucs2.obj mbfilter_utf32.obj mbfilter_utf16.obj mbfilter_utf8.obj mbfilter_utf7.obj mbfilter_utf7imap.obj mbfilter_euc_jp_win.obj mbfilter_cp932.obj mbfilter_euc_cn.obj mbfilter_euc_kr.obj mbfilter_uhc.obj mbfilter_iso2022_kr.obj mbfilter_cp866.obj mbfilter_koi8r.obj html_entities.obj +OBJS=mbfilter_cp936.obj mbfilter_hz.obj mbfilter_euc_tw.obj mbfilter_big5.obj mbfilter_euc_jp.obj mbfilter_jis.obj mbfilter_iso8859_1.obj mbfilter_iso8859_2.obj mbfilter_cp1252.obj mbfilter_cp1251.obj mbfilter_ascii.obj mbfilter_iso8859_3.obj mbfilter_iso8859_4.obj mbfilter_iso8859_5.obj mbfilter_iso8859_6.obj mbfilter_iso8859_7.obj mbfilter_iso8859_8.obj mbfilter_iso8859_9.obj mbfilter_iso8859_10.obj mbfilter_iso8859_13.obj mbfilter_iso8859_14.obj mbfilter_iso8859_15.obj mbfilter_iso8859_16.obj mbfilter_htmlent.obj mbfilter_byte2.obj mbfilter_byte4.obj mbfilter_uuencode.obj mbfilter_base64.obj mbfilter_sjis.obj mbfilter_7bit.obj mbfilter_qprint.obj mbfilter_ucs4.obj mbfilter_ucs2.obj mbfilter_utf32.obj mbfilter_utf16.obj mbfilter_utf8.obj mbfilter_utf7.obj mbfilter_utf7imap.obj mbfilter_euc_jp_win.obj mbfilter_cp932.obj mbfilter_euc_cn.obj mbfilter_euc_kr.obj mbfilter_uhc.obj mbfilter_iso2022_kr.obj mbfilter_cp866.obj mbfilter_koi8r.obj html_entities.obj all: $(OBJS) diff --git a/ext/mbstring/libmbfl/filters/html_entities.c b/ext/mbstring/libmbfl/filters/html_entities.c index 59eb1818d08a..5551952b1c50 100644 --- a/ext/mbstring/libmbfl/filters/html_entities.c +++ b/ext/mbstring/libmbfl/filters/html_entities.c @@ -167,6 +167,7 @@ const mbfl_html_entity_entry mbfl_html_entity_list[] = { {"Chi", 935}, {"Psi", 936}, {"Omega", 937}, + {"alpha", 945}, {"beta", 946}, {"gamma", 947}, {"delta", 948}, diff --git a/ext/mbstring/libmbfl/filters/mbfilter_htmlent.c b/ext/mbstring/libmbfl/filters/mbfilter_htmlent.c index f7e7896be6f0..40c24c3424e5 100644 --- a/ext/mbstring/libmbfl/filters/mbfilter_htmlent.c +++ b/ext/mbstring/libmbfl/filters/mbfilter_htmlent.c @@ -120,7 +120,7 @@ int mbfl_filt_conv_html_enc(int c, mbfl_convert_filter *filter) } { - int *p = tmp + sizeof(tmp); + int *p = tmp + sizeof(tmp) / sizeof(tmp[0]); CK((*filter->output_function)('#', filter->data)); @@ -145,7 +145,7 @@ int mbfl_filt_conv_html_enc(int c, mbfl_convert_filter *filter) int mbfl_filt_conv_html_enc_flush(mbfl_convert_filter *filter) { filter->status = 0; - filter->cache = 0; + filter->opaque = NULL; return 0; } @@ -158,24 +158,24 @@ static const char html_entity_chars[] = "#0123456789abcdefghijklmnopqrstuvwxyzAB void mbfl_filt_conv_html_dec_ctor(mbfl_convert_filter *filter) { filter->status = 0; - filter->cache = (int)mbfl_malloc(html_enc_buffer_size+1); + filter->opaque = mbfl_malloc(html_enc_buffer_size+1); } void mbfl_filt_conv_html_dec_dtor(mbfl_convert_filter *filter) { filter->status = 0; - if (filter->cache) + if (filter->opaque) { - mbfl_free((void*)filter->cache); + mbfl_free((void*)filter->opaque); } - filter->cache = 0; + filter->opaque = NULL; } int mbfl_filt_conv_html_dec(int c, mbfl_convert_filter *filter) { int pos, ent = 0; mbfl_html_entity_entry *entity; - char *buffer = (char*)filter->cache; + char *buffer = (char*)filter->opaque; if (!filter->status) { if (c == '&' ) { @@ -246,7 +246,7 @@ int mbfl_filt_conv_html_dec_flush(mbfl_convert_filter *filter) int status, pos = 0; char *buffer; - buffer = (char*)filter->cache; + buffer = (char*)filter->opaque; status = filter->status; /* flush fragments */ while (status--) { diff --git a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_16.c b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_16.c new file mode 100755 index 000000000000..8f12feb47e86 --- /dev/null +++ b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_16.c @@ -0,0 +1,136 @@ +/* + * "streamable kanji code filter and converter" + * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved. + * + * LICENSE NOTICES + * + * This file is part of "streamable kanji code filter and converter", + * which is distributed under the terms of GNU Lesser General Public + * License (version 2) as published by the Free Software Foundation. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with "streamable kanji code filter and converter"; + * if not, write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * + * The author of this file: + * + */ +/* + * The source code included in this files was separated from mbfilter.c + * by moriyoshi koizumi on 4 dec 2002. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "mbfilter.h" +#include "mbfilter_iso8859_16.h" +#include "unicode_table_iso8859_16.h" + +static const char *mbfl_encoding_8859_16_aliases[] = {"ISO_8859-16", NULL}; + +const mbfl_encoding mbfl_encoding_8859_16 = { + mbfl_no_encoding_8859_16, + "ISO-8859-16", + "ISO-8859-16", + (const char *(*)[])&mbfl_encoding_8859_16_aliases, + NULL, + MBFL_ENCTYPE_SBCS +}; + +const struct mbfl_identify_vtbl vtbl_identify_8859_16 = { + mbfl_no_encoding_8859_16, + mbfl_filt_ident_common_ctor, + mbfl_filt_ident_common_dtor, + mbfl_filt_ident_true +}; + +const struct mbfl_convert_vtbl vtbl_8859_16_wchar = { + mbfl_no_encoding_8859_16, + mbfl_no_encoding_wchar, + mbfl_filt_conv_common_ctor, + mbfl_filt_conv_common_dtor, + mbfl_filt_conv_8859_16_wchar, + mbfl_filt_conv_common_flush +}; + +const struct mbfl_convert_vtbl vtbl_wchar_8859_16 = { + mbfl_no_encoding_wchar, + mbfl_no_encoding_8859_16, + mbfl_filt_conv_common_ctor, + mbfl_filt_conv_common_dtor, + mbfl_filt_conv_wchar_8859_16, + mbfl_filt_conv_common_flush +}; + +#define CK(statement) do { if ((statement) < 0) return (-1); } while (0) + +/* + * ISO-8859-16 => wchar + */ +int mbfl_filt_conv_8859_16_wchar(int c, mbfl_convert_filter *filter) +{ + int s; + + if (c >= 0 && c < 0xa0) { + s = c; + } else if (c >= 0xa0 && c < 0x100) { + s = iso8859_16_ucs_table[c - 0xa0]; + if (s <= 0) { + s = c; + s &= MBFL_WCSPLANE_MASK; + s |= MBFL_WCSPLANE_8859_16; + } + } else { + s = c; + s &= MBFL_WCSGROUP_MASK; + s |= MBFL_WCSGROUP_THROUGH; + } + + CK((*filter->output_function)(s, filter->data)); + + return c; +} + +/* + * wchar => ISO-8859-16 + */ +int mbfl_filt_conv_wchar_8859_16(int c, mbfl_convert_filter *filter) +{ + int s, n; + + if (c >= 0 && c < 0xa0) { + s = c; + } else { + s = -1; + n = 95; + while (n >= 0) { + if (c == iso8859_16_ucs_table[n]) { + s = 0xa0 + n; + break; + } + n--; + } + if (s <= 0 && (c & ~MBFL_WCSPLANE_MASK) == MBFL_WCSPLANE_8859_16) { + s = c & MBFL_WCSPLANE_MASK; + } + } + + if (s >= 0) { + CK((*filter->output_function)(s, filter->data)); + } else { + if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) { + CK(mbfl_filt_conv_illegal_output(c, filter)); + } + } + + return c; +} diff --git a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_16.h b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_16.h new file mode 100755 index 000000000000..a5e2d2fbef63 --- /dev/null +++ b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_16.h @@ -0,0 +1,23 @@ +/* + * COPYRIGHT NOTICE + * + * This file is a portion of "streamable kanji code filter and converter" + * library, which is distributed under GNU Lesser General Public License + * version 2.1. + * + */ + +#ifndef MBFL_MBFILTER_ISO8859_16_H +#define MBFL_MBFILTER_ISO8859_16_H + +#include "mbfilter.h" + +extern const mbfl_encoding mbfl_encoding_8859_16; +extern const struct mbfl_identify_vtbl vtbl_identify_8859_16; +extern const struct mbfl_convert_vtbl vtbl_8859_16_wchar; +extern const struct mbfl_convert_vtbl vtbl_wchar_8859_16; + +int mbfl_filt_conv_8859_16_wchar(int c, mbfl_convert_filter *filter); +int mbfl_filt_conv_wchar_8859_16(int c, mbfl_convert_filter *filter); + +#endif /* MBFL_MBFILTER_ISO8859_16_H */ diff --git a/ext/mbstring/libmbfl/filters/mbfilter_qprint.c b/ext/mbstring/libmbfl/filters/mbfilter_qprint.c index 9b18a1cb2b99..188d088ed0a1 100644 --- a/ext/mbstring/libmbfl/filters/mbfilter_qprint.c +++ b/ext/mbstring/libmbfl/filters/mbfilter_qprint.c @@ -155,11 +155,30 @@ int mbfl_filt_conv_qprintenc_flush(mbfl_convert_filter *filter) */ int mbfl_filt_conv_qprintdec(int c, mbfl_convert_filter *filter) { - int n; + int n, m; + + static int hex2code_map[] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + }; switch (filter->status) { case 1: - if ((c >= 0x30 && c <= 0x39) || (c >= 0x41 && c <= 0x46)) { /* 0 - 9 or A - F */ + if (hex2code_map[c & 0xff] >= 0) { filter->cache = c; filter->status = 2; } else if (c == 0x0d) { /* soft line feed */ @@ -173,21 +192,13 @@ int mbfl_filt_conv_qprintdec(int c, mbfl_convert_filter *filter) } break; case 2: - n = filter->cache; - if (n >= 0x30 && n <= 0x39) { /* '0' - '9' */ - n -= 48; /* 48 = '0' */ - } else { - n -= 55; /* 55 = 'A' - 10 */ - } - n <<= 4; - if (c >= 0x30 && c <= 0x39) { /* '0' - '9' */ - n += (c - 48); - } else if (c >= 0x41 && c <= 0x46) { /* 'A' - 'F' */ - n += (c - 55); - } else { + m = hex2code_map[c & 0xff]; + if (m < 0) { CK((*filter->output_function)(0x3d, filter->data)); /* '=' */ CK((*filter->output_function)(filter->cache, filter->data)); n = c; + } else { + n = hex2code_map[filter->cache] << 4 | m; } CK((*filter->output_function)(n, filter->data)); filter->status = 0; diff --git a/ext/mbstring/libmbfl/filters/mk_sb_tbl.awk b/ext/mbstring/libmbfl/filters/mk_sb_tbl.awk new file mode 100755 index 000000000000..f0ad290e2417 --- /dev/null +++ b/ext/mbstring/libmbfl/filters/mk_sb_tbl.awk @@ -0,0 +1,65 @@ +#!/usr/bin/awk -f +# +# $Id$ +# +# Description: a script that generates a single byte code set to Unicode +# mapping table. +# + +function conv(str) { + if (!match(str, "^0[xX]")) { + return 0 + str + } + + retval = 0 + + for (i = 3; i <= length(str); i++) { + n = index("0123456789abcdefABCDEF", substr(str, i, 1)) - 1 + + if (n < 0) { + return 0 + str; + } else if (n >= 16) { + n -= 6; + } + + retval = retval * 16 + n + } + + return retval +} + +BEGIN { + FS="[ \t#]" +} + +/^#/ { + # Do nothing +} + +{ + tbl[conv($1)] = conv($2) +} + +END { + print "/* This file is automatically generated. Do not edit! */" + if (IFNDEF_NAME) { + print "#ifndef " IFNDEF_NAME + } + + print "static const int " TABLE_NAME "[] = {" + i = 160; + for (;;) { + printf("\t0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x", tbl[i++], tbl[i++], tbl[i++], tbl[i++], tbl[i++], tbl[i++], tbl[i++], tbl[i++]); + if (i != 256) { + printf(",\n"); + } else { + print "" + break; + } + } + print "};" + + if (IFNDEF_NAME) { + print "#endif /* " IFNDEF_NAME " */" + } +} diff --git a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_10.h b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_10.h index 0de0d17eb47f..2b6b78f32bd6 100644 --- a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_10.h +++ b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_10.h @@ -1,44 +1,17 @@ -/* - * "streamable kanji code filter and converter" - * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved. - * - * LICENSE NOTICES - * - * This file is part of "streamable kanji code filter and converter", - * which is distributed under the terms of GNU Lesser General Public - * License (version 2) as published by the Free Software Foundation. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with "streamable kanji code filter and converter"; - * if not, write to the Free Software Foundation, Inc., 59 Temple Place, - * Suite 330, Boston, MA 02111-1307 USA - * - * The authors of this file: PHP3 internationalization team - * You can contact the primary author 金本 茂 . - * - */ - +/* This file is automatically generated. Do not edit! */ #ifndef UNICODE_TABLE_ISO8859_10_H -#define UNICODE_TABLE_ISO8859_10_H - -static const unsigned short iso8859_10_ucs_table[] = { - 0x00A0,0x0104,0x0112,0x0122,0x0124,0x0128,0x0136,0x00A7, - 0x013B,0x0110,0x0160,0x0166,0x017D,0x00AD,0x016A,0x014A, - 0x00B0,0x0105,0x0113,0x0123,0x012B,0x0129,0x0137,0x00B7, - 0x013C,0x0111,0x0161,0x0167,0x017E,0x2015,0x016B,0x014B, - 0x0100,0x00C1,0x00C2,0x00C3,0x00C4,0x00C5,0x00C6,0x012E, - 0x010C,0x00C9,0x0118,0x00CB,0x0116,0x00CD,0x00CE,0x00CF, - 0x00D0,0x0145,0x014C,0x00D3,0x00D4,0x00D5,0x00D6,0x0168, - 0x00D8,0x0172,0x00DA,0x00DB,0x00DC,0x00DD,0x00DE,0x00DF, - 0x0101,0x00E1,0x00E2,0x00E3,0x00E4,0x00E5,0x00E6,0x012F, - 0x010D,0x00E9,0x0119,0x00EB,0x0117,0x00ED,0x00EE,0x00EF, - 0x00F0,0x0146,0x014D,0x00F3,0x00F4,0x00F5,0x00F6,0x0169, - 0x00F8,0x0173,0x00FA,0x00FB,0x00FC,0x00FD,0x00FE,0x0138 +static const int iso8859_10_ucs_table[] = { + 0x00a0, 0x0104, 0x0112, 0x0122, 0x012a, 0x0128, 0x0136, 0x00a7, + 0x013b, 0x0110, 0x0160, 0x0166, 0x017d, 0x00ad, 0x016a, 0x014a, + 0x00b0, 0x0105, 0x0113, 0x0123, 0x012b, 0x0129, 0x0137, 0x00b7, + 0x013c, 0x0111, 0x0161, 0x0167, 0x017e, 0x2015, 0x016b, 0x014b, + 0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e, + 0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x00cf, + 0x00d0, 0x0145, 0x014c, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x0168, + 0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, + 0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f, + 0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x00ef, + 0x00f0, 0x0146, 0x014d, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x0169, + 0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x0138 }; - #endif /* UNICODE_TABLE_ISO8859_10_H */ diff --git a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_13.h b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_13.h index ee69310bdb79..5822396525c5 100644 --- a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_13.h +++ b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_13.h @@ -1,44 +1,17 @@ -/* - * "streamable kanji code filter and converter" - * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved. - * - * LICENSE NOTICES - * - * This file is part of "streamable kanji code filter and converter", - * which is distributed under the terms of GNU Lesser General Public - * License (version 2) as published by the Free Software Foundation. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with "streamable kanji code filter and converter"; - * if not, write to the Free Software Foundation, Inc., 59 Temple Place, - * Suite 330, Boston, MA 02111-1307 USA - * - * The authors of this file: PHP3 internationalization team - * You can contact the primary author 金本 茂 . - * - */ - +/* This file is automatically generated. Do not edit! */ #ifndef UNICODE_TABLE_ISO8859_13_H -#define UNICODE_TABLE_ISO8859_13_H - -static const unsigned short iso8859_13_ucs_table[] = { - 0x00A0,0x201D,0x00A2,0x00A3,0x00A4,0x201E,0x00A6,0x00A7, - 0x00D8,0x00A9,0x0156,0x00AB,0x00AC,0x00AD,0x00AE,0x00C6, - 0x00B0,0x00B1,0x00B2,0x00B3,0x201C,0x00B5,0x00B6,0x00B7, - 0x00F8,0x00B9,0x0157,0x00BB,0x00BC,0x00BD,0x00BE,0x00E6, - 0x0104,0x012E,0x0100,0x0106,0x00C4,0x00C5,0x0118,0x0112, - 0x010C,0x00C9,0x0179,0x0116,0x0122,0x0136,0x012A,0x013B, - 0x0160,0x0143,0x0145,0x00D3,0x014C,0x00D5,0x00D6,0x00D7, - 0x0172,0x0141,0x015A,0x016A,0x00DC,0x017B,0x017D,0x00DF, - 0x0105,0x012F,0x0101,0x0107,0x00E4,0x00E5,0x0119,0x0113, - 0x010D,0x00E9,0x017A,0x0117,0x0123,0x0137,0x012B,0x013C, - 0x0161,0x0144,0x0146,0x00F3,0x014D,0x00F5,0x00F6,0x00F7, - 0x0173,0x0142,0x015B,0x016B,0x00FC,0x017C,0x017E,0x2019 +static const int iso8859_13_ucs_table[] = { + 0x00a0, 0x201d, 0x00a2, 0x00a3, 0x00a4, 0x201e, 0x00a6, 0x00a7, + 0x00d8, 0x00a9, 0x0156, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00c6, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x201c, 0x00b5, 0x00b6, 0x00b7, + 0x00f8, 0x00b9, 0x0157, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00e6, + 0x0104, 0x012e, 0x0100, 0x0106, 0x00c4, 0x00c5, 0x0118, 0x0112, + 0x010c, 0x00c9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012a, 0x013b, + 0x0160, 0x0143, 0x0145, 0x00d3, 0x014c, 0x00d5, 0x00d6, 0x00d7, + 0x0172, 0x0141, 0x015a, 0x016a, 0x00dc, 0x017b, 0x017d, 0x00df, + 0x0105, 0x012f, 0x0101, 0x0107, 0x00e4, 0x00e5, 0x0119, 0x0113, + 0x010d, 0x00e9, 0x017a, 0x0117, 0x0123, 0x0137, 0x012b, 0x013c, + 0x0161, 0x0144, 0x0146, 0x00f3, 0x014d, 0x00f5, 0x00f6, 0x00f7, + 0x0173, 0x0142, 0x015b, 0x016b, 0x00fc, 0x017c, 0x017e, 0x2019 }; - #endif /* UNICODE_TABLE_ISO8859_13_H */ diff --git a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_14.h b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_14.h index f0633963ff25..6bd03b367ab4 100644 --- a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_14.h +++ b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_14.h @@ -1,44 +1,17 @@ -/* - * "streamable kanji code filter and converter" - * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved. - * - * LICENSE NOTICES - * - * This file is part of "streamable kanji code filter and converter", - * which is distributed under the terms of GNU Lesser General Public - * License (version 2) as published by the Free Software Foundation. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with "streamable kanji code filter and converter"; - * if not, write to the Free Software Foundation, Inc., 59 Temple Place, - * Suite 330, Boston, MA 02111-1307 USA - * - * The authors of this file: PHP3 internationalization team - * You can contact the primary author 金本 茂 . - * - */ - +/* This file is automatically generated. Do not edit! */ #ifndef UNICODE_TABLE_ISO8859_14_H -#define UNICODE_TABLE_ISO8859_14_H - -static const unsigned short iso8859_14_ucs_table[] = { - 0x00A0,0x1E02,0x1E03,0x00A3,0x010A,0x010B,0x1E0A,0x00A7, - 0x1E80,0x00A9,0x1E82,0x1E0B,0x1EF2,0x00AD,0x00AE,0x0178, - 0x1E1E,0x1E1F,0x0120,0x0121,0x1E40,0x1E41,0x00B6,0x1E56, - 0x1E81,0x1E57,0x1E83,0x1E60,0x1EF3,0x1E84,0x1E85,0x1E61, - 0x00C0,0x00C1,0x00C2,0x00C3,0x00C4,0x00C5,0x00C6,0x00C7, - 0x00C8,0x00C9,0x00CA,0x00CB,0x00CC,0x00CD,0x00CE,0x00CF, - 0x0174,0x00D1,0x00D2,0x00D3,0x00D4,0x00D5,0x00D6,0x1E6A, - 0x00D8,0x00D9,0x00DA,0x00DB,0x00DC,0x00DD,0x0176,0x00DF, - 0x00E0,0x00E1,0x00E2,0x00E3,0x00E4,0x00E5,0x00E6,0x00E7, - 0x00E8,0x00E9,0x00EA,0x00EB,0x00EC,0x00ED,0x00EE,0x00EF, - 0x0175,0x00F1,0x00F2,0x00F3,0x00F4,0x00F5,0x00F6,0x1E6B, - 0x00F8,0x00F9,0x00FA,0x00FB,0x00FC,0x00FD,0x0177,0x00FF +static const int iso8859_14_ucs_table[] = { + 0x00a0, 0x1e02, 0x1e03, 0x00a3, 0x010a, 0x010b, 0x1e0a, 0x00a7, + 0x1e80, 0x00a9, 0x1e82, 0x1e0b, 0x1ef2, 0x00ad, 0x00ae, 0x0178, + 0x1e1e, 0x1e1f, 0x0120, 0x0121, 0x1e40, 0x1e41, 0x00b6, 0x1e56, + 0x1e81, 0x1e57, 0x1e83, 0x1e60, 0x1ef3, 0x1e84, 0x1e85, 0x1e61, + 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, + 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x0174, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x1e6a, + 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x0176, 0x00df, + 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, + 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x0175, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x1e6b, + 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x0177, 0x00ff }; - #endif /* UNICODE_TABLE_ISO8859_14_H */ diff --git a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_15.h b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_15.h index ab2f1a82b632..029a2bcfc4e4 100644 --- a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_15.h +++ b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_15.h @@ -1,44 +1,17 @@ -/* - * "streamable kanji code filter and converter" - * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved. - * - * LICENSE NOTICES - * - * This file is part of "streamable kanji code filter and converter", - * which is distributed under the terms of GNU Lesser General Public - * License (version 2) as published by the Free Software Foundation. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with "streamable kanji code filter and converter"; - * if not, write to the Free Software Foundation, Inc., 59 Temple Place, - * Suite 330, Boston, MA 02111-1307 USA - * - * The authors of this file: PHP3 internationalization team - * You can contact the primary author 金本 茂 . - * - */ - +/* This file is automatically generated. Do not edit! */ #ifndef UNICODE_TABLE_ISO8859_15_H -#define UNICODE_TABLE_ISO8859_15_H - -static const unsigned short iso8859_15_ucs_table[] = { - 0x00A0,0x00A1,0x00A2,0x00A3,0x20AC,0x00A5,0x0160,0x00A7, - 0x0161,0x00A9,0x00AA,0x00AB,0x00AC,0x00AD,0x00AE,0x00AF, - 0x00B0,0x00B1,0x00B2,0x00B3,0x017D,0x00B5,0x00B6,0x00B7, - 0x017E,0x00B9,0x00BA,0x00BB,0x0152,0x0153,0x0178,0x00BF, - 0x00C0,0x00C1,0x00C2,0x00C3,0x00C4,0x00C5,0x00C6,0x00C7, - 0x00C8,0x00C9,0x00CA,0x00CB,0x00CC,0x00CD,0x00CE,0x00CF, - 0x00D0,0x00D1,0x00D2,0x00D3,0x00D4,0x00D5,0x00D6,0x00D7, - 0x00D8,0x00D9,0x00DA,0x00DB,0x00DC,0x00DD,0x00DE,0x00DF, - 0x00E0,0x00E1,0x00E2,0x00E3,0x00E4,0x00E5,0x00E6,0x00E7, - 0x00E8,0x00E9,0x00EA,0x00EB,0x00EC,0x00ED,0x00EE,0x00EF, - 0x00F0,0x00F1,0x00F2,0x00F3,0x00F4,0x00F5,0x00F6,0x00F7, - 0x00F8,0x00F9,0x00FA,0x00FB,0x00FC,0x00FD,0x00FE,0x00FF +static const int iso8859_15_ucs_table[] = { + 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20ac, 0x00a5, 0x0160, 0x00a7, + 0x0161, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x017d, 0x00b5, 0x00b6, 0x00b7, + 0x017e, 0x00b9, 0x00ba, 0x00bb, 0x0152, 0x0153, 0x0178, 0x00bf, + 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, + 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, + 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, + 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, + 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, + 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff }; - #endif /* UNICODE_TABLE_ISO8859_15_H */ diff --git a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_16.h b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_16.h new file mode 100644 index 000000000000..555472d0dc14 --- /dev/null +++ b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_16.h @@ -0,0 +1,17 @@ +/* This file is automatically generated. Do not edit! */ +#ifndef UNICODE_TABLEISO8859_16_H +static const int iso8859_16_ucs_table[] = { + 0x00a0, 0x0104, 0x0105, 0x0141, 0x20ac, 0x201e, 0x0160, 0x00a7, + 0x0161, 0x00a9, 0x0218, 0x00ab, 0x0179, 0x00ad, 0x017a, 0x017b, + 0x00b0, 0x00b1, 0x010c, 0x0142, 0x017d, 0x201d, 0x00b6, 0x00b7, + 0x017e, 0x010d, 0x0219, 0x00bb, 0x0152, 0x0153, 0x0178, 0x017c, + 0x00c0, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0106, 0x00c6, 0x00c7, + 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x0110, 0x0143, 0x00d2, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x015a, + 0x0170, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0118, 0x021a, 0x00df, + 0x00e0, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x0107, 0x00e6, 0x00e7, + 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x0111, 0x0144, 0x00f2, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x015b, + 0x0171, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0119, 0x021b, 0x00ff +}; +#endif /* UNICODE_TABLEISO8859_16_H */ diff --git a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_2.h b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_2.h index 148fdbfff527..12bb3cb2dc3e 100644 --- a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_2.h +++ b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_2.h @@ -1,45 +1,17 @@ -/* - * "streamable kanji code filter and converter" - * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved. - * - * LICENSE NOTICES - * - * This file is part of "streamable kanji code filter and converter", - * which is distributed under the terms of GNU Lesser General Public - * License (version 2) as published by the Free Software Foundation. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with "streamable kanji code filter and converter"; - * if not, write to the Free Software Foundation, Inc., 59 Temple Place, - * Suite 330, Boston, MA 02111-1307 USA - * - * The authors of this file: PHP3 internationalization team - * You can contact the primary author 金本 茂 . - * - */ - +/* This file is automatically generated. Do not edit! */ #ifndef UNICODE_TABLE_ISO8859_2_H -#define UNICODE_TABLE_ISO8859_2_H - -static const unsigned short iso8859_2_ucs_table[] = { - 0x00A0,0x0104,0x02D8,0x0141,0x00A4,0x013D,0x015A,0x00A7, - 0x00A8,0x0160,0x015E,0x0164,0x0179,0x00AD,0x017D,0x017B, - 0x00B0,0x0105,0x02DB,0x0142,0x00B4,0x013E,0x015B,0x02C7, - 0x00B8,0x0161,0x015F,0x0165,0x017A,0x02DD,0x017E,0x017C, - 0x0154,0x00C1,0x00C2,0x0102,0x00C4,0x0139,0x0106,0x00C7, - 0x010C,0x00C9,0x0118,0x00CB,0x011A,0x00CD,0x00CE,0x010E, - 0x0110,0x0143,0x0147,0x00D3,0x00D4,0x0150,0x00D6,0x00D7, - 0x0158,0x016E,0x00DA,0x0170,0x00DC,0x00DD,0x0162,0x00DF, - 0x0155,0x00E1,0x00E2,0x0103,0x00E4,0x013A,0x0107,0x00E7, - 0x010D,0x00E9,0x0119,0x00EB,0x011B,0x00ED,0x00EE,0x010F, - 0x0111,0x0144,0x0148,0x00F3,0x00F4,0x0151,0x00F6,0x00F7, - 0x0159,0x016F,0x00FA,0x0171,0x00FC,0x00FD,0x0163,0x02D9 +static const int iso8859_2_ucs_table[] = { + 0x00a0, 0x0104, 0x02d8, 0x0141, 0x00a4, 0x013d, 0x015a, 0x00a7, + 0x00a8, 0x0160, 0x015e, 0x0164, 0x0179, 0x00ad, 0x017d, 0x017b, + 0x00b0, 0x0105, 0x02db, 0x0142, 0x00b4, 0x013e, 0x015b, 0x02c7, + 0x00b8, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c, + 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, + 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e, + 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, + 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df, + 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, + 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f, + 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, + 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9 }; - - #endif /* UNICODE_TABLE_ISO8859_2_H */ diff --git a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_3.h b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_3.h index 40aa5d635a12..f50c348affed 100644 --- a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_3.h +++ b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_3.h @@ -1,43 +1,17 @@ -/* - * "streamable kanji code filter and converter" - * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved. - * - * LICENSE NOTICES - * - * This file is part of "streamable kanji code filter and converter", - * which is distributed under the terms of GNU Lesser General Public - * License (version 2) as published by the Free Software Foundation. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with "streamable kanji code filter and converter"; - * if not, write to the Free Software Foundation, Inc., 59 Temple Place, - * Suite 330, Boston, MA 02111-1307 USA - * - * The authors of this file: PHP3 internationalization team - * You can contact the primary author 金本 茂 . - * - */ +/* This file is automatically generated. Do not edit! */ #ifndef UNICODE_TABLE_ISO8859_3_H -#define UNICODE_TABLE_ISO8859_3_H - -static const unsigned short iso8859_3_ucs_table[] = { - 0x00A0,0x0126,0x02D8,0x00A3,0x00A4,0x0000,0x0124,0x00A7, - 0x00A8,0x0130,0x015E,0x011E,0x0134,0x00AD,0x0000,0x017B, - 0x00B0,0x0127,0x00B2,0x00B3,0x00B4,0x00B5,0x0125,0x00B7, - 0x00B8,0x0131,0x015F,0x011F,0x0135,0x00BD,0x0000,0x017C, - 0x00C0,0x00C1,0x00C2,0x0000,0x00C4,0x010A,0x0108,0x00C7, - 0x00C8,0x00C9,0x00CA,0x00CB,0x00CC,0x00CD,0x00CE,0x00CF, - 0x0000,0x00D1,0x00D2,0x00D3,0x00D4,0x0120,0x00D6,0x00D7, - 0x011C,0x00D9,0x00DA,0x00DB,0x00DC,0x016C,0x015C,0x00DF, - 0x00E0,0x00E1,0x00E2,0x0000,0x00E4,0x010B,0x0109,0x00E7, - 0x00E8,0x00E9,0x00EA,0x00EB,0x00EC,0x00ED,0x00EE,0x00EF, - 0x0000,0x00F1,0x00F2,0x00F3,0x00F4,0x0121,0x00F6,0x00F7, - 0x011D,0x00F9,0x00FA,0x00FB,0x00FC,0x016D,0x015D,0x02D9 +static const int iso8859_3_ucs_table[] = { + 0x00a0, 0x0126, 0x02d8, 0x00a3, 0x00a4, 0x0000, 0x0124, 0x00a7, + 0x00a8, 0x0130, 0x015e, 0x011e, 0x0134, 0x00ad, 0x0000, 0x017b, + 0x00b0, 0x0127, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x0125, 0x00b7, + 0x00b8, 0x0131, 0x015f, 0x011f, 0x0135, 0x00bd, 0x0000, 0x017c, + 0x00c0, 0x00c1, 0x00c2, 0x0000, 0x00c4, 0x010a, 0x0108, 0x00c7, + 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x0000, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x0120, 0x00d6, 0x00d7, + 0x011c, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x016c, 0x015c, 0x00df, + 0x00e0, 0x00e1, 0x00e2, 0x0000, 0x00e4, 0x010b, 0x0109, 0x00e7, + 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x0000, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x0121, 0x00f6, 0x00f7, + 0x011d, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x016d, 0x015d, 0x02d9 }; - #endif /* UNICODE_TABLE_ISO8859_3_H */ diff --git a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_4.h b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_4.h index 4aaa276c00d6..ff7ecdb4c0b8 100644 --- a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_4.h +++ b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_4.h @@ -1,44 +1,17 @@ -/* - * "streamable kanji code filter and converter" - * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved. - * - * LICENSE NOTICES - * - * This file is part of "streamable kanji code filter and converter", - * which is distributed under the terms of GNU Lesser General Public - * License (version 2) as published by the Free Software Foundation. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with "streamable kanji code filter and converter"; - * if not, write to the Free Software Foundation, Inc., 59 Temple Place, - * Suite 330, Boston, MA 02111-1307 USA - * - * The authors of this file: PHP3 internationalization team - * You can contact the primary author 金本 茂 . - * - */ - +/* This file is automatically generated. Do not edit! */ #ifndef UNICODE_TABLE_ISO8859_4_H -#define UNICODE_TABLE_ISO8859_4_H - -static const unsigned short iso8859_4_ucs_table[] = { - 0x00A0,0x0104,0x0138,0x0156,0x00A4,0x0128,0x013B,0x00A7, - 0x00A8,0x0160,0x0112,0x0122,0x0166,0x00AD,0x017D,0x00AF, - 0x00B0,0x0105,0x02DB,0x0157,0x00B4,0x0129,0x013C,0x02C7, - 0x00B8,0x0161,0x0113,0x0123,0x0167,0x014A,0x017E,0x014B, - 0x0100,0x00C1,0x00C2,0x00C3,0x00C4,0x00C5,0x00C6,0x012E, - 0x010C,0x00C9,0x0118,0x00CB,0x0116,0x00CD,0x00CE,0x012A, - 0x0110,0x0145,0x014C,0x0136,0x00D4,0x00D5,0x00D6,0x00D7, - 0x00D8,0x0172,0x00DA,0x00DB,0x00DC,0x0168,0x016A,0x00DF, - 0x0101,0x00E1,0x00E2,0x00E3,0x00E4,0x00E5,0x00E6,0x012F, - 0x010D,0x00E9,0x0119,0x00EB,0x0117,0x00ED,0x00EE,0x012B, - 0x0111,0x0146,0x014D,0x0137,0x00F4,0x00F5,0x00F6,0x00F7, - 0x00F8,0x0173,0x00FA,0x00FB,0x00FC,0x0169,0x016B,0x02D9 +static const int iso8859_4_ucs_table[] = { + 0x00a0, 0x0104, 0x0138, 0x0156, 0x00a4, 0x0128, 0x013b, 0x00a7, + 0x00a8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00ad, 0x017d, 0x00af, + 0x00b0, 0x0105, 0x02db, 0x0157, 0x00b4, 0x0129, 0x013c, 0x02c7, + 0x00b8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014a, 0x017e, 0x014b, + 0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e, + 0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x012a, + 0x0110, 0x0145, 0x014c, 0x0136, 0x00d4, 0x00d5, 0x00d6, 0x00d7, + 0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x0168, 0x016a, 0x00df, + 0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f, + 0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x012b, + 0x0111, 0x0146, 0x014d, 0x0137, 0x00f4, 0x00f5, 0x00f6, 0x00f7, + 0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x0169, 0x016b, 0x02d9 }; - #endif /* UNICODE_TABLE_ISO8859_4_H */ diff --git a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_5.h b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_5.h index 58fc0e2adaa6..411ab84b6057 100644 --- a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_5.h +++ b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_5.h @@ -1,44 +1,17 @@ -/* - * "streamable kanji code filter and converter" - * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved. - * - * LICENSE NOTICES - * - * This file is part of "streamable kanji code filter and converter", - * which is distributed under the terms of GNU Lesser General Public - * License (version 2) as published by the Free Software Foundation. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with "streamable kanji code filter and converter"; - * if not, write to the Free Software Foundation, Inc., 59 Temple Place, - * Suite 330, Boston, MA 02111-1307 USA - * - * The authors of this file: PHP3 internationalization team - * You can contact the primary author 金本 茂 . - * - */ - +/* This file is automatically generated. Do not edit! */ #ifndef UNICODE_TABLE_ISO8859_5_H -#define UNICODE_TABLE_ISO8859_5_H - -static const unsigned short iso8859_5_ucs_table[] = { - 0x00A0,0x0401,0x0402,0x0403,0x0404,0x0405,0x0406,0x0407, - 0x0408,0x0409,0x040A,0x040B,0x040C,0x00AD,0x040E,0x040F, - 0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0416,0x0417, - 0x0418,0x0419,0x041A,0x041B,0x041C,0x041D,0x041E,0x041F, - 0x0420,0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,0x0427, - 0x0428,0x0429,0x042A,0x042B,0x042C,0x042D,0x042E,0x042F, - 0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0436,0x0437, - 0x0438,0x0439,0x043A,0x043B,0x043C,0x043D,0x043E,0x043F, - 0x0440,0x0441,0x0442,0x0443,0x0444,0x0445,0x0446,0x0447, - 0x0448,0x0449,0x044A,0x044B,0x044C,0x044D,0x044E,0x044F, - 0x2116,0x0451,0x0452,0x0453,0x0454,0x0455,0x0456,0x0457, - 0x0458,0x0459,0x045A,0x045B,0x045C,0x00A7,0x045E,0x045F +static const int iso8859_5_ucs_table[] = { + 0x00a0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, + 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x00ad, 0x040e, 0x040f, + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, + 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, + 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, + 0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, + 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x00a7, 0x045e, 0x045f }; - #endif /* UNICODE_TABLE_ISO8859_5_H */ diff --git a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_6.h b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_6.h index 9dba3ad895a9..0b3952e3a0b8 100644 --- a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_6.h +++ b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_6.h @@ -1,44 +1,17 @@ -/* - * "streamable kanji code filter and converter" - * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved. - * - * LICENSE NOTICES - * - * This file is part of "streamable kanji code filter and converter", - * which is distributed under the terms of GNU Lesser General Public - * License (version 2) as published by the Free Software Foundation. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with "streamable kanji code filter and converter"; - * if not, write to the Free Software Foundation, Inc., 59 Temple Place, - * Suite 330, Boston, MA 02111-1307 USA - * - * The authors of this file: PHP3 internationalization team - * You can contact the primary author 金本 茂 . - * - */ - +/* This file is automatically generated. Do not edit! */ #ifndef UNICODE_TABLE_ISO8859_6_H -#define UNICODE_TABLE_ISO8859_6_H - -static const unsigned short iso8859_6_ucs_table[] = { - 0x00A0,0x0000,0x0000,0x0000,0x00A4,0x0000,0x0000,0x0000, - 0x0000,0x0000,0x0000,0x0000,0x060C,0x00AD,0x0000,0x0000, - 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, - 0x0000,0x0000,0x0000,0x061B,0x0000,0x0000,0x0000,0x061F, - 0x0000,0x0621,0x0622,0x0623,0x0624,0x0625,0x0626,0x0627, - 0x0628,0x0629,0x062A,0x062B,0x062C,0x062D,0x062E,0x062F, - 0x0630,0x0631,0x0632,0x0633,0x0634,0x0635,0x0636,0x0637, - 0x0638,0x0639,0x063A,0x0000,0x0000,0x0000,0x0000,0x0000, - 0x0640,0x0641,0x0642,0x0643,0x0644,0x0645,0x0646,0x0647, - 0x0648,0x0649,0x064A,0x064B,0x064C,0x064D,0x064E,0x064F, - 0x0650,0x0651,0x0652,0x0000,0x0000,0x0000,0x0000,0x0000, - 0x0000,0x0000,0x0000,0x0000,0x060C,0x00AD,0x0000,0x0000 +static const int iso8859_6_ucs_table[] = { + 0x00a0, 0x0000, 0x0000, 0x0000, 0x00a4, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x060c, 0x00ad, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x061b, 0x0000, 0x0000, 0x0000, 0x061f, + 0x0000, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, + 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f, + 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, + 0x0638, 0x0639, 0x063a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, + 0x0648, 0x0649, 0x064a, 0x064b, 0x064c, 0x064d, 0x064e, 0x064f, + 0x0650, 0x0651, 0x0652, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; - #endif /* UNICODE_TABLE_ISO8859_6_H */ diff --git a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_7.h b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_7.h index 0dfde9bb84e7..687f4cbc744a 100644 --- a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_7.h +++ b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_7.h @@ -1,44 +1,17 @@ -/* - * "streamable kanji code filter and converter" - * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved. - * - * LICENSE NOTICES - * - * This file is part of "streamable kanji code filter and converter", - * which is distributed under the terms of GNU Lesser General Public - * License (version 2) as published by the Free Software Foundation. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with "streamable kanji code filter and converter"; - * if not, write to the Free Software Foundation, Inc., 59 Temple Place, - * Suite 330, Boston, MA 02111-1307 USA - * - * The authors of this file: PHP3 internationalization team - * You can contact the primary author 金本 茂 . - * - */ - +/* This file is automatically generated. Do not edit! */ #ifndef UNICODE_TABLE_ISO8859_7_H -#define UNICODE_TABLE_ISO8859_7_H - -static const unsigned short iso8859_7_ucs_table[] = { - 0x00A0,0x2018,0x2019,0x00A3,0x0000,0x0000,0x00A6,0x00A7, - 0x00A8,0x00A9,0x0000,0x00AB,0x00AC,0x00AD,0x0000,0x2015, - 0x00B0,0x00B1,0x00B2,0x00B3,0x0384,0x0385,0x0386,0x00B7, - 0x0388,0x0389,0x038A,0x00BB,0x038C,0x00BD,0x038E,0x038F, - 0x0390,0x0391,0x0392,0x0393,0x0394,0x0395,0x0396,0x0397, - 0x0398,0x0399,0x039A,0x039B,0x039C,0x039D,0x039E,0x039F, - 0x03A0,0x03A1,0x0000,0x03A3,0x03A4,0x03A5,0x03A6,0x03A7, - 0x03A8,0x03A9,0x03AA,0x03AB,0x03AC,0x03AD,0x03AE,0x03AF, - 0x03B0,0x03B1,0x03B2,0x03B3,0x03B4,0x03B5,0x03B6,0x03B7, - 0x03B8,0x03B9,0x03BA,0x03BB,0x03BC,0x03BD,0x03BE,0x03BF, - 0x03C0,0x03C1,0x03C2,0x03C3,0x03C4,0x03C5,0x03C6,0x03C7, - 0x03C8,0x03C9,0x03CA,0x03CB,0x03CC,0x03CD,0x03CE,0x0000 +static const int iso8859_7_ucs_table[] = { + 0x00a0, 0x2018, 0x2019, 0x00a3, 0x20ac, 0x20af, 0x00a6, 0x00a7, + 0x00a8, 0x00a9, 0x037a, 0x00ab, 0x00ac, 0x00ad, 0x0000, 0x2015, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x0384, 0x0385, 0x0386, 0x00b7, + 0x0388, 0x0389, 0x038a, 0x00bb, 0x038c, 0x00bd, 0x038e, 0x038f, + 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, + 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, + 0x03a0, 0x03a1, 0x0000, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, + 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af, + 0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, + 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, + 0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, + 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0x0000 }; - #endif /* UNICODE_TABLE_ISO8859_7_H */ diff --git a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_8.h b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_8.h index 756004f913e7..4ec6490bae49 100644 --- a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_8.h +++ b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_8.h @@ -1,44 +1,17 @@ -/* - * "streamable kanji code filter and converter" - * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved. - * - * LICENSE NOTICES - * - * This file is part of "streamable kanji code filter and converter", - * which is distributed under the terms of GNU Lesser General Public - * License (version 2) as published by the Free Software Foundation. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with "streamable kanji code filter and converter"; - * if not, write to the Free Software Foundation, Inc., 59 Temple Place, - * Suite 330, Boston, MA 02111-1307 USA - * - * The authors of this file: PHP3 internationalization team - * You can contact the primary author 金本 茂 . - * - */ - +/* This file is automatically generated. Do not edit! */ #ifndef UNICODE_TABLE_ISO8859_8_H -#define UNICODE_TABLE_ISO8859_8_H - -static const unsigned short iso8859_8_ucs_table[] = { - 0x00A0,0x0000,0x00A2,0x00A3,0x00A4,0x00A5,0x00A6,0x00A7, - 0x00A8,0x00A9,0x00D7,0x00AB,0x00AC,0x00AD,0x00AE,0x203E, - 0x00B0,0x00B1,0x00B2,0x00B3,0x00B4,0x00B5,0x00B6,0x00B7, - 0x00B8,0x00B9,0x00F7,0x00BB,0x00BC,0x00BD,0x00BE,0x0000, - 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, - 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, - 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, - 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x2017, - 0x05D0,0x05D1,0x05D2,0x05D3,0x05D4,0x05D5,0x05D6,0x05D7, - 0x05D8,0x05D9,0x05DA,0x05DB,0x05DC,0x05DD,0x05DE,0x05DF, - 0x05E0,0x05E1,0x05E2,0x05E3,0x05E4,0x05E5,0x05E6,0x05E7, - 0x05E8,0x05E9,0x05EA,0x0000,0x0000,0x0000,0x0000,0x0000 +static const int iso8859_8_ucs_table[] = { + 0x00a0, 0x0000, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, + 0x00a8, 0x00a9, 0x00d7, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, + 0x00b8, 0x00b9, 0x00f7, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2017, + 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, + 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df, + 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, + 0x05e8, 0x05e9, 0x05ea, 0x0000, 0x0000, 0x200e, 0x200f, 0x0000 }; - #endif /* UNICODE_TABLE_ISO8859_8_H */ diff --git a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_9.h b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_9.h index f39e83f45ee7..12f988ad7a2a 100644 --- a/ext/mbstring/libmbfl/filters/unicode_table_iso8859_9.h +++ b/ext/mbstring/libmbfl/filters/unicode_table_iso8859_9.h @@ -1,44 +1,17 @@ -/* - * "streamable kanji code filter and converter" - * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved. - * - * LICENSE NOTICES - * - * This file is part of "streamable kanji code filter and converter", - * which is distributed under the terms of GNU Lesser General Public - * License (version 2) as published by the Free Software Foundation. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with "streamable kanji code filter and converter"; - * if not, write to the Free Software Foundation, Inc., 59 Temple Place, - * Suite 330, Boston, MA 02111-1307 USA - * - * The authors of this file: PHP3 internationalization team - * You can contact the primary author 金本 茂 . - * - */ - +/* This file is automatically generated. Do not edit! */ #ifndef UNICODE_TABLE_ISO8859_9_H -#define UNICODE_TABLE_ISO8859_9_H - -static const unsigned short iso8859_9_ucs_table[] = { - 0x00A0,0x00A1,0x00A2,0x00A3,0x00A4,0x00A5,0x00A6,0x00A7, - 0x00A8,0x00A9,0x00AA,0x00AB,0x00AC,0x00AD,0x00AE,0x00AF, - 0x00B0,0x00B1,0x00B2,0x00B3,0x00B4,0x00B5,0x00B6,0x00B7, - 0x00B8,0x00B9,0x00BA,0x00BB,0x00BC,0x00BD,0x00BE,0x00BF, - 0x00C0,0x00C1,0x00C2,0x00C3,0x00C4,0x00C5,0x00C6,0x00C7, - 0x00C8,0x00C9,0x00CA,0x00CB,0x00CC,0x00CD,0x00CE,0x00CF, - 0x011E,0x00D1,0x00D2,0x00D3,0x00D4,0x00D5,0x00D6,0x00D7, - 0x00D8,0x00D9,0x00DA,0x00DB,0x00DC,0x0130,0x015E,0x00DF, - 0x00E0,0x00E1,0x00E2,0x00E3,0x00E4,0x00E5,0x00E6,0x00E7, - 0x00E8,0x00E9,0x00EA,0x00EB,0x00EC,0x00ED,0x00EE,0x00EF, - 0x011F,0x00F1,0x00F2,0x00F3,0x00F4,0x00F5,0x00F6,0x00F7, - 0x00F8,0x00F9,0x00FA,0x00FB,0x00FC,0x0131,0x015F,0x00FF +static const int iso8859_9_ucs_table[] = { + 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, + 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, + 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, + 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, + 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, + 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df, + 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, + 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, + 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff }; - #endif /* UNICODE_TABLE_ISO8859_9_H */ diff --git a/ext/mbstring/libmbfl/libmbfl.dsp b/ext/mbstring/libmbfl/libmbfl.dsp index bf3fe0655712..e041df02c536 100644 --- a/ext/mbstring/libmbfl/libmbfl.dsp +++ b/ext/mbstring/libmbfl/libmbfl.dsp @@ -199,6 +199,10 @@ SOURCE=.\filters\mbfilter_iso8859_15.c # End Source File # Begin Source File +SOURCE=.\filters\mbfilter_iso8859_16.c +# End Source File +# Begin Source File + SOURCE=.\filters\mbfilter_iso8859_2.c # End Source File # Begin Source File @@ -500,6 +504,10 @@ SOURCE=.\filters\mbfilter_iso8859_15.h # End Source File # Begin Source File +SOURCE=.\filters\mbfilter_iso8859_16.h +# End Source File +# Begin Source File + SOURCE=.\filters\mbfilter_iso8859_2.h # End Source File # Begin Source File @@ -708,6 +716,10 @@ SOURCE=.\filters\unicode_table_iso8859_15.h # End Source File # Begin Source File +SOURCE=.\filters\unicode_table_iso8859_16.h +# End Source File +# Begin Source File + SOURCE=.\filters\unicode_table_iso8859_2.h # End Source File # Begin Source File diff --git a/ext/mbstring/libmbfl/libmbfl.sln b/ext/mbstring/libmbfl/libmbfl.sln new file mode 100755 index 000000000000..f49f0c0d868a --- /dev/null +++ b/ext/mbstring/libmbfl/libmbfl.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 7.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmbfl", "libmbfl.vcproj", "{B3636594-A785-4270-A765-8EAE922B5207}" +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + ConfigName.0 = Debug + ConfigName.1 = Release + EndGlobalSection + GlobalSection(ProjectDependencies) = postSolution + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {B3636594-A785-4270-A765-8EAE922B5207}.Debug.ActiveCfg = Debug|Win32 + {B3636594-A785-4270-A765-8EAE922B5207}.Debug.Build.0 = Debug|Win32 + {B3636594-A785-4270-A765-8EAE922B5207}.Release.ActiveCfg = Release|Win32 + {B3636594-A785-4270-A765-8EAE922B5207}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/ext/mbstring/libmbfl/libmbfl.vcproj b/ext/mbstring/libmbfl/libmbfl.vcproj new file mode 100755 index 000000000000..29e0af0a2706 --- /dev/null +++ b/ext/mbstring/libmbfl/libmbfl.vcproj @@ -0,0 +1,650 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/mbstring/libmbfl/mbfl/Makefile.am b/ext/mbstring/libmbfl/mbfl/Makefile.am index 6f817feba248..25d673454168 100644 --- a/ext/mbstring/libmbfl/mbfl/Makefile.am +++ b/ext/mbstring/libmbfl/mbfl/Makefile.am @@ -1,6 +1,6 @@ -EXTRA_DIST=Makefile.bcc32 +EXTRA_DIST=Makefile.bcc32 mk_eaw_tbl.awk lib_LTLIBRARIES=libmbfl.la -libmbfl_la_SOURCES=mbfilter.c mbfl_string.c mbfl_language.c mbfl_encoding.c mbfl_convert.c mbfl_ident.c mbfl_memory_device.c mbfl_allocators.c mbfl_filter_output.c mbfilter_pass.c mbfilter_wchar.c mbfilter_8bit.c +libmbfl_la_SOURCES=mbfilter.c mbfl_string.c mbfl_language.c mbfl_encoding.c mbfl_convert.c mbfl_ident.c mbfl_memory_device.c mbfl_allocators.c mbfl_filter_output.c mbfilter_pass.c mbfilter_wchar.c mbfilter_8bit.c eaw_table.h libmbfl_filters_la=../filters/libmbfl_filters.la libmbfl_nls_la=../nls/libmbfl_nls.la libmbfl_la_LIBADD=$(libmbfl_filters_la) $(libmbfl_nls_la) @@ -8,6 +8,14 @@ libmbfl_la_LDFLAGS=-version-info $(SHLIB_VERSION) libmbfl_includedir=$(includedir)/mbfl libmbfl_include_HEADERS=mbfilter.h mbfl_consts.h mbfl_encoding.h mbfl_language.h mbfl_string.h mbfl_convert.h mbfl_ident.h mbfl_memory_device.h mbfl_allocators.h mbfl_defs.h mbfl_filter_output.h mbfilter_pass.h mbfilter_wchar.h mbfilter_8bit.h +mbfilter.c: eaw_table.h + +eaw_table.h: mk_eaw_tbl.awk + $(AWK) -v TABLE_NAME=mbfl_eaw_table -f mk_eaw_tbl.awk EastAsianWidth.txt > $@ + +EastAsianWidth.txt: + $(FETCH_VIA_FTP) ftp://ftp.unicode.org/Public/UNIDATA/EastAsianWidth.txt + $(libmbfl_filters_la): $(MAKE) -C `dirname $(libmbfl_filters_la)` diff --git a/ext/mbstring/libmbfl/mbfl/eaw_table.h b/ext/mbstring/libmbfl/mbfl/eaw_table.h new file mode 100644 index 000000000000..95c895df1bf4 --- /dev/null +++ b/ext/mbstring/libmbfl/mbfl/eaw_table.h @@ -0,0 +1,36 @@ +static const struct { + int begin; + int end; +} mbfl_eaw_table[] = { + { 0x1100, 0x1159 }, + { 0x115f, 0x115f }, + { 0x2329, 0x232a }, + { 0x2e80, 0x2e99 }, + { 0x2e9b, 0x2ef3 }, + { 0x2f00, 0x2fd5 }, + { 0x2ff0, 0x2ffb }, + { 0x3000, 0x303e }, + { 0x3041, 0x3096 }, + { 0x3099, 0x30ff }, + { 0x3105, 0x312c }, + { 0x3131, 0x318e }, + { 0x3190, 0x31b7 }, + { 0x31f0, 0x321e }, + { 0x3220, 0x3243 }, + { 0x3250, 0x327d }, + { 0x327f, 0x32fe }, + { 0x3300, 0x4db5 }, + { 0x4e00, 0x9fa5 }, + { 0xa000, 0xa48c }, + { 0xa490, 0xa4c6 }, + { 0xac00, 0xd7a3 }, + { 0xf900, 0xfa2d }, + { 0xfa30, 0xfa6a }, + { 0xfe30, 0xfe52 }, + { 0xfe54, 0xfe66 }, + { 0xfe68, 0xfe6b }, + { 0xff01, 0xff60 }, + { 0xffe0, 0xffe6 }, + { 0x20000, 0x2fffd }, + { 0x30000, 0x3fffd } +}; diff --git a/ext/mbstring/libmbfl/mbfl/mbfilter.c b/ext/mbstring/libmbfl/mbfl/mbfilter.c index 7984f30931e3..b99d8df8a2b5 100644 --- a/ext/mbstring/libmbfl/mbfl/mbfilter.c +++ b/ext/mbstring/libmbfl/mbfl/mbfilter.c @@ -103,6 +103,8 @@ #include "mbfl_filter_output.h" #include "mbfilter_pass.h" +#include "eaw_table.h" + /* hex character table "0123456789ABCDEF" */ static char mbfl_hexchar_table[] = { 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44,0x45,0x46 @@ -403,16 +405,16 @@ mbfl_encoding_detector_feed(mbfl_encoding_detector *identd, mbfl_string *string) num = identd->filter_list_size; n = string->len; p = string->val; + bad = 0; while (n > 0) { - i = 0; - bad = 0; - while (i < num) { + for (i = 0; i < num; i++) { filter = identd->filter_list[i]; - (*filter->filter_function)(*p, filter); - if (filter->flag) { - bad++; + if (!filter->flag) { + (*filter->filter_function)(*p, filter); + if (filter->flag) { + bad++; + } } - i++; } if ((num - 1) <= bad) { res = 1; @@ -553,9 +555,11 @@ mbfl_identify_encoding(mbfl_string *string, enum mbfl_no_encoding *elist, int el while (n > 0) { for (i = 0; i < num; i++) { filter = &flist[i]; - (*filter->filter_function)(*p, filter); - if (filter->flag) { - bad++; + if (!filter->flag) { + (*filter->filter_function)(*p, filter); + if (filter->flag) { + bad++; + } } } if ((num - 1) <= bad && !strict) { @@ -603,7 +607,7 @@ mbfl_identify_encoding_name(mbfl_string *string, enum mbfl_no_encoding *elist, i } } -const enum mbfl_no_encoding +enum mbfl_no_encoding mbfl_identify_encoding_no(mbfl_string *string, enum mbfl_no_encoding *elist, int elistsz) { const mbfl_encoding *encoding; @@ -1346,17 +1350,27 @@ mbfl_strcut( /* * strwidth */ -static int -filter_count_width(int c, void* data) +static int is_fullwidth(int c) { - if (c >= 0x20) { - if (c < 0x2000 || (c > 0xff60 && c < 0xffa0)) { - (*(int *)data)++; - } else { - (*(int *)data) += 2; + int i; + + if (c < mbfl_eaw_table[0].begin) { + return 0; + } + + for (i = 0; i < sizeof(mbfl_eaw_table) / sizeof(mbfl_eaw_table[0]); i++) { + if (mbfl_eaw_table[i].begin <= c && c <= mbfl_eaw_table[i].end) { + return 1; } } + return 0; +} + +static int +filter_count_width(int c, void* data) +{ + (*(int *)data) += (is_fullwidth(c) ? 2: 1); return c; } @@ -1421,13 +1435,8 @@ collector_strimwidth(int c, void* data) break; default: if (pc->outchar >= pc->from) { - if (c >= 0x20) { - if (c < 0x2000 || (c > 0xff60 && c < 0xffa0)) { - pc->outwidth++; - } else { - pc->outwidth += 2; - } - } + pc->outwidth += (is_fullwidth(c) ? 2: 1); + if (pc->outwidth > pc->width) { if (pc->status == 0) { pc->endpos = pc->device.pos; @@ -1953,6 +1962,25 @@ mime_header_encoder_block_collector(int c, void *data) static int mime_header_encoder_collector(int c, void *data) { + static int qp_table[256] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x00 */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x00 */ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */ + 0, 0, 0, 0, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 1, 0, 1, /* 0x10 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0x50 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0x70 */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x80 */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x90 */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xA0 */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xB0 */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xC0 */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xD0 */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xE0 */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /* 0xF0 */ + }; + int n; struct mime_header_encoder_data *pe = (struct mime_header_encoder_data *)data; @@ -1962,7 +1990,7 @@ mime_header_encoder_collector(int c, void *data) break; default: /* ASCII */ - if (c >= 0x21 && c < 0x7f) { /* ASCII exclude SPACE and CTLs */ + if (!qp_table[(c & 0xff)]) { /* ordinary characters */ mbfl_memory_device_output(c, &pe->tmpdev); pe->status1 = 1; } else if (pe->status1 == 0 && c == 0x20) { /* repeat SPACE */ diff --git a/ext/mbstring/libmbfl/mbfl/mbfilter.h b/ext/mbstring/libmbfl/mbfl/mbfilter.h index eadae7b3f4fd..d0965251ad88 100644 --- a/ext/mbstring/libmbfl/mbfl/mbfilter.h +++ b/ext/mbstring/libmbfl/mbfl/mbfilter.h @@ -162,7 +162,7 @@ mbfl_identify_encoding(mbfl_string *string, enum mbfl_no_encoding *elist, int el MBFLAPI extern const char * mbfl_identify_encoding_name(mbfl_string *string, enum mbfl_no_encoding *elist, int elistsz, int strict); -MBFLAPI extern const enum mbfl_no_encoding +MBFLAPI extern enum mbfl_no_encoding mbfl_identify_encoding_no(mbfl_string *string, enum mbfl_no_encoding *elist, int elistsz); /* diff --git a/ext/mbstring/libmbfl/mbfl/mbfl_consts.h b/ext/mbstring/libmbfl/mbfl/mbfl_consts.h index d907512ec201..d20b3ceea96a 100644 --- a/ext/mbstring/libmbfl/mbfl/mbfl_consts.h +++ b/ext/mbstring/libmbfl/mbfl/mbfl_consts.h @@ -74,6 +74,7 @@ #define MBFL_WCSPLANE_CP1251 0x70f70000 #define MBFL_WCSPLANE_CP866 0x70f80000 #define MBFL_WCSPLANE_KOI8R 0x70f90000 +#define MBFL_WCSPLANE_8859_16 0x70fa0000 /* 00h - FFh */ #define MBFL_WCSGROUP_MASK 0xffffff #define MBFL_WCSGROUP_UCS4MAX 0x70000000 #define MBFL_WCSGROUP_WCHARMAX 0x78000000 diff --git a/ext/mbstring/libmbfl/mbfl/mbfl_convert.h b/ext/mbstring/libmbfl/mbfl/mbfl_convert.h index 0bc06209c178..afec8f06279e 100644 --- a/ext/mbstring/libmbfl/mbfl/mbfl_convert.h +++ b/ext/mbstring/libmbfl/mbfl/mbfl_convert.h @@ -51,6 +51,7 @@ struct _mbfl_convert_filter { const mbfl_encoding *to; int illegal_mode; int illegal_substchar; + void *opaque; }; struct mbfl_convert_vtbl { diff --git a/ext/mbstring/libmbfl/mbfl/mbfl_encoding.c b/ext/mbstring/libmbfl/mbfl/mbfl_encoding.c index df279336ce2e..21fb6319db78 100644 --- a/ext/mbstring/libmbfl/mbfl/mbfl_encoding.c +++ b/ext/mbstring/libmbfl/mbfl/mbfl_encoding.c @@ -80,6 +80,7 @@ #include "filters/mbfilter_iso8859_13.h" #include "filters/mbfilter_iso8859_14.h" #include "filters/mbfilter_iso8859_15.h" +#include "filters/mbfilter_iso8859_16.h" #include "filters/mbfilter_base64.h" #include "filters/mbfilter_qprint.h" #include "filters/mbfilter_uuencode.h" @@ -163,6 +164,7 @@ static const mbfl_encoding *mbfl_encoding_ptr_list[] = { &mbfl_encoding_8859_13, &mbfl_encoding_8859_14, &mbfl_encoding_8859_15, + &mbfl_encoding_8859_16, &mbfl_encoding_euc_cn, &mbfl_encoding_cp936, &mbfl_encoding_hz, @@ -295,7 +297,3 @@ mbfl_is_support_encoding(const char *name) return 1; } } - - - - diff --git a/ext/mbstring/libmbfl/mbfl/mbfl_encoding.h b/ext/mbstring/libmbfl/mbfl/mbfl_encoding.h index c99af89a0204..c9b51dd3608d 100644 --- a/ext/mbstring/libmbfl/mbfl/mbfl_encoding.h +++ b/ext/mbstring/libmbfl/mbfl/mbfl_encoding.h @@ -97,6 +97,7 @@ enum mbfl_no_encoding { mbfl_no_encoding_cp1251, mbfl_no_encoding_cp866, mbfl_no_encoding_koi8r, + mbfl_no_encoding_8859_16, mbfl_no_encoding_charset_max }; diff --git a/ext/mbstring/libmbfl/mbfl/mk_eaw_tbl.awk b/ext/mbstring/libmbfl/mbfl/mk_eaw_tbl.awk new file mode 100644 index 000000000000..c7deb4cdf5af --- /dev/null +++ b/ext/mbstring/libmbfl/mbfl/mk_eaw_tbl.awk @@ -0,0 +1,80 @@ +#!/usr/bin/awk -f +# +# $Id$ +# +# Description: a script to generate east asian width table. +# + +BEGIN { + prev = -1 + comma = 0 + ORS = "" + FS = "[;.|# ]" + print "static const struct {\n\tint begin;\n\tint end;\n} " TABLE_NAME "[] = {\n\t" +} + +/^#/ { +} + +/^[0-9a-fA-F]+;/ { + if ($2 == "W" || $2 == "F") { + v = ( "0x" $1 ) + 0 + if (prev < 0) { + first = v + } else if (v - prev > 1) { + if (comma) { + print ",\n\t" + } + printf("{ 0x%04x, 0x%04x }", first, prev) + first = v + comma = 1 + } + prev = v + } else { + if (prev >= 0) { + if (comma) { + print ",\n\t" + } + printf("{ 0x%04x, 0x%04x }", first, prev) + prev = -1 + comma = 1 + } + } +} + +/^[0-9a-fA-F]+\.\./ { + if ($4 == "W" || $4 == "F") { + vs = ( "0x" $1 ) + 0 + ve = ( "0x" $3 ) + 0 + if (prev < 0) { + first = vs + } else if (vs - prev > 1) { + if (comma) { + print ",\n\t" + } + printf("{ 0x%04x, 0x%04x }", first, prev) + first = vs + comma = 1 + } + prev = ve + } else { + if (prev >= 0) { + if (comma) { + print ",\n\t" + } + printf("{ 0x%04x, 0x%04x }", first, prev) + prev = -1 + comma = 1 + } + } +} + +END { + if (prev >= 0) { + if (comma) { + print ",\n\t" + } + printf("{ 0x%04x, 0x%04x }", first, prev) + } + print "\n};\n" +} diff --git a/ext/mbstring/mb_gpc.c b/ext/mbstring/mb_gpc.c index a58c63ac56b0..ef859c84e40c 100644 --- a/ext/mbstring/mb_gpc.c +++ b/ext/mbstring/mb_gpc.c @@ -88,6 +88,8 @@ MBSTRING_API SAPI_TREAT_DATA_FUNC(mbstr_treat_data) const char *c_var; pval *array_ptr; int free_buffer=0; + enum mbfl_no_encoding detected; + php_mb_encoding_handler_info_t info; switch (arg) { case PARSE_POST: @@ -169,21 +171,32 @@ MBSTRING_API SAPI_TREAT_DATA_FUNC(mbstr_treat_data) break; } - _php_mb_encoding_handler_ex(arg, array_ptr, res, separator, 0, 0 TSRMLS_CC); + info.data_type = arg; + info.separator = separator; + info.force_register_globals = 0; + info.report_errors = 0; + info.to_encoding = MBSTRG(internal_encoding); + info.to_language = MBSTRG(language); + info.from_encodings = MBSTRG(http_input_list); + info.num_from_encodings = MBSTRG(http_input_list_size); + info.from_language = MBSTRG(language); - if (MBSTRG(http_input_identify) != mbfl_no_encoding_invalid) { + detected = _php_mb_encoding_handler_ex(&info, array_ptr, res TSRMLS_CC); + MBSTRG(http_input_identify) = detected; + + if (detected != mbfl_no_encoding_invalid) { switch(arg){ case PARSE_POST: - MBSTRG(http_input_identify_post) = MBSTRG(http_input_identify); + MBSTRG(http_input_identify_post) = detected; break; case PARSE_GET: - MBSTRG(http_input_identify_get) = MBSTRG(http_input_identify); + MBSTRG(http_input_identify_get) = detected; break; case PARSE_COOKIE: - MBSTRG(http_input_identify_cookie) = MBSTRG(http_input_identify); + MBSTRG(http_input_identify_cookie) = detected; break; case PARSE_STRING: - MBSTRG(http_input_identify_string) = MBSTRG(http_input_identify); + MBSTRG(http_input_identify_string) = detected; break; } } @@ -198,29 +211,29 @@ MBSTRING_API SAPI_TREAT_DATA_FUNC(mbstr_treat_data) } /* }}} */ -/* {{{ int _php_mb_encoding_handler_ex() */ -int _php_mb_encoding_handler_ex(int data_type, zval *arg, char *res, char *separator, int force_register_globals, int report_errors TSRMLS_DC) +/* {{{ enum mbfl_no_encoding _php_mb_encoding_handler_ex() */ +enum mbfl_no_encoding _php_mb_encoding_handler_ex(const php_mb_encoding_handler_info_t *info, zval *arg, char *res TSRMLS_DC) { - char *var, *val, *s1, *s2; + char *var, *val; + const char *s1, *s2; char *strtok_buf = NULL, **val_list = NULL; zval *array_ptr = (zval *) arg; - int n, num, *len_list = NULL, *elist, elistsz; + int n, num, *len_list = NULL; unsigned int val_len, new_val_len; - enum mbfl_no_encoding from_encoding, to_encoding; mbfl_string string, resvar, resval; + enum mbfl_no_encoding from_encoding = mbfl_no_encoding_invalid; mbfl_encoding_detector *identd = NULL; mbfl_buffer_converter *convd = NULL; int prev_rg_state = 0; - int retval = 0; - mbfl_string_init_set(&string, MBSTRG(current_language), MBSTRG(current_internal_encoding)); - mbfl_string_init_set(&resvar, MBSTRG(current_language), MBSTRG(current_internal_encoding)); - mbfl_string_init_set(&resval, MBSTRG(current_language), MBSTRG(current_internal_encoding)); + mbfl_string_init_set(&string, info->to_language, info->to_encoding); + mbfl_string_init_set(&resvar, info->to_language, info->to_encoding); + mbfl_string_init_set(&resval, info->to_language, info->to_encoding); /* register_globals stuff * XXX: this feature is going to be deprecated? */ - if (force_register_globals) { + if (info->force_register_globals) { prev_rg_state = PG(register_globals); PG(register_globals) = 1; } @@ -231,11 +244,10 @@ int _php_mb_encoding_handler_ex(int data_type, zval *arg, char *res, char *separ /* count the variables(separators) contained in the "res". * separator may contain multiple separator chars. - * separaror chars are set in php.ini (arg_separator.input) */ num = 1; for (s1=res; *s1 != '\0'; s1++) { - for (s2=separator; *s2 != '\0'; s2++) { + for (s2=info->separator; *s2 != '\0'; s2++) { if (*s1 == *s2) { num++; } @@ -249,7 +261,7 @@ int _php_mb_encoding_handler_ex(int data_type, zval *arg, char *res, char *separ /* split and decode the query */ n = 0; strtok_buf = NULL; - var = php_strtok_r(res, separator, &strtok_buf); + var = php_strtok_r(res, info->separator, &strtok_buf); while (var) { val = strchr(var, '='); if (val) { /* have a value */ @@ -269,22 +281,19 @@ int _php_mb_encoding_handler_ex(int data_type, zval *arg, char *res, char *separ len_list[n] = 0; } n++; - var = php_strtok_r(NULL, separator, &strtok_buf); + var = php_strtok_r(NULL, info->separator, &strtok_buf); } num = n; /* make sure to process initilized vars only */ /* initialize converter */ - to_encoding = MBSTRG(current_internal_encoding); - elist = MBSTRG(http_input_list); - elistsz = MBSTRG(http_input_list_size); - if (elistsz <= 0) { + if (info->num_from_encodings <= 0) { from_encoding = mbfl_no_encoding_pass; - } else if (elistsz == 1) { - from_encoding = *elist; + } else if (info->num_from_encodings == 1) { + from_encoding = info->from_encodings[0]; } else { /* auto detect */ from_encoding = mbfl_no_encoding_invalid; - identd = mbfl_encoding_detector_new(elist, elistsz); + identd = mbfl_encoding_detector_new((enum mbfl_no_encoding *)info->from_encodings, info->num_from_encodings); if (identd) { n = 0; while (n < num) { @@ -299,7 +308,7 @@ int _php_mb_encoding_handler_ex(int data_type, zval *arg, char *res, char *separ mbfl_encoding_detector_delete(identd); } if (from_encoding == mbfl_no_encoding_invalid) { - if (report_errors) { + if (info->report_errors) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to detect encoding"); } from_encoding = mbfl_no_encoding_pass; @@ -308,12 +317,12 @@ int _php_mb_encoding_handler_ex(int data_type, zval *arg, char *res, char *separ convd = NULL; if (from_encoding != mbfl_no_encoding_pass) { - convd = mbfl_buffer_converter_new(from_encoding, to_encoding, 0); + convd = mbfl_buffer_converter_new(from_encoding, info->to_encoding, 0); if (convd != NULL) { mbfl_buffer_converter_illegal_mode(convd, MBSTRG(current_filter_illegal_mode)); mbfl_buffer_converter_illegal_substchar(convd, MBSTRG(current_filter_illegal_substchar)); } else { - if (report_errors) { + if (info->report_errors) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create converter"); } goto out; @@ -345,7 +354,7 @@ int _php_mb_encoding_handler_ex(int data_type, zval *arg, char *res, char *separ n++; /* we need val to be emalloc()ed */ val = estrndup(val, val_len); - if (sapi_module.input_filter(data_type, var, &val, val_len, &new_val_len TSRMLS_CC)) { + if (sapi_module.input_filter(info->data_type, var, &val, val_len, &new_val_len TSRMLS_CC)) { /* add variable to symbol table */ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC); } @@ -357,12 +366,9 @@ int _php_mb_encoding_handler_ex(int data_type, zval *arg, char *res, char *separ } } - MBSTRG(http_input_identify) = from_encoding; - retval = 1; - out: /* register_global stuff */ - if (force_register_globals) { + if (info->force_register_globals) { PG(register_globals) = prev_rg_state; } @@ -376,19 +382,33 @@ int _php_mb_encoding_handler_ex(int data_type, zval *arg, char *res, char *separ efree((void *)len_list); } - return retval; + return from_encoding; } /* }}} */ /* {{{ SAPI_POST_HANDLER_FUNC(php_mb_post_handler) */ SAPI_POST_HANDLER_FUNC(php_mb_post_handler) { - MBSTRG(http_input_identify_post) = mbfl_no_encoding_invalid; + enum mbfl_no_encoding detected; + php_mb_encoding_handler_info_t info; - _php_mb_encoding_handler_ex(PARSE_POST, arg, SG(request_info).post_data, "&", 0, 0 TSRMLS_CC); + MBSTRG(http_input_identify_post) = mbfl_no_encoding_invalid; - if (MBSTRG(http_input_identify) != mbfl_no_encoding_invalid) { - MBSTRG(http_input_identify_post) = MBSTRG(http_input_identify); + info.data_type = PARSE_POST; + info.separator = "&"; + info.force_register_globals = 0; + info.report_errors = 0; + info.to_encoding = MBSTRG(internal_encoding); + info.to_language = MBSTRG(language); + info.from_encodings = MBSTRG(http_input_list); + info.num_from_encodings = MBSTRG(http_input_list_size); + info.from_language = MBSTRG(language); + + detected = _php_mb_encoding_handler_ex(&info, arg, SG(request_info).post_data TSRMLS_CC); + + MBSTRG(http_input_identify) = detected; + if (detected != mbfl_no_encoding_invalid) { + MBSTRG(http_input_identify_post) = detected; } } /* }}} */ diff --git a/ext/mbstring/mb_gpc.h b/ext/mbstring/mb_gpc.h index 9eed896a1c63..7cba2c3c0789 100644 --- a/ext/mbstring/mb_gpc.h +++ b/ext/mbstring/mb_gpc.h @@ -28,12 +28,27 @@ /* }}} */ #if HAVE_MBSTRING +/* {{{ typedefs */ +typedef struct _php_mb_encoding_handler_info_t { + int data_type; + const char *separator; + unsigned int force_register_globals: 1; + unsigned int report_errors: 1; + enum mbfl_no_language to_language; + enum mbfl_no_encoding to_encoding; + enum mbfl_no_language from_language; + int num_from_encodings; + const enum mbfl_no_encoding *from_encodings; +} php_mb_encoding_handler_info_t; + +/* }}}*/ + /* {{{ prototypes */ SAPI_POST_HANDLER_FUNC(php_mb_post_handler); MBSTRING_API SAPI_TREAT_DATA_FUNC(mbstr_treat_data); int _php_mb_enable_encoding_translation(int flag); -int _php_mb_encoding_handler_ex(int data_type, zval *arg, char *res, char *separator, int force_register_globals, int report_errors TSRMLS_DC); +enum mbfl_no_encoding _php_mb_encoding_handler_ex(const php_mb_encoding_handler_info_t *info, zval *arg, char *res TSRMLS_DC); /* }}} */ #endif /* HAVE_MBSTRING */ diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 310f7b6112f8..9fdf075c2e08 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -134,7 +134,7 @@ static const enum mbfl_no_encoding php_mb_default_identify_list_neut[] = { }; -php_mb_nls_ident_list php_mb_default_identify_list[] = { +static const php_mb_nls_ident_list php_mb_default_identify_list[] = { { mbfl_no_language_japanese, php_mb_default_identify_list_ja, sizeof(php_mb_default_identify_list_ja) / sizeof(php_mb_default_identify_list_ja[0]) }, { mbfl_no_language_korean, php_mb_default_identify_list_kr, sizeof(php_mb_default_identify_list_kr) / sizeof(php_mb_default_identify_list_kr[0]) }, { mbfl_no_language_traditional_chinese, php_mb_default_identify_list_tw_hk, sizeof(php_mb_default_identify_list_tw_hk) / sizeof(php_mb_default_identify_list_tw_hk[0]) }, @@ -1339,16 +1339,16 @@ PHP_FUNCTION(mb_preferred_mime_name) PHP_FUNCTION(mb_parse_str) { zval *track_vars_array; - char *encstr = NULL, *separator = NULL; + char *encstr = NULL; int encstr_len; + php_mb_encoding_handler_info_t info; + enum mbfl_no_encoding detected; track_vars_array = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &encstr, &encstr_len, &track_vars_array) == FAILURE) { return; } - separator = (char *)estrdup(PG(arg_separator).input); - /* Clear out the array */ if (track_vars_array != NULL) { zval_dtor(track_vars_array); @@ -1357,10 +1357,23 @@ PHP_FUNCTION(mb_parse_str) encstr = estrndup(encstr, encstr_len); - RETVAL_BOOL(_php_mb_encoding_handler_ex(PARSE_STRING, track_vars_array, encstr, separator, (track_vars_array == NULL), 1 TSRMLS_CC)); + info.data_type = PARSE_STRING; + info.separator = PG(arg_separator).input; + info.force_register_globals = (track_vars_array == NULL); + info.report_errors = 1; + info.to_encoding = MBSTRG(current_internal_encoding); + info.to_language = MBSTRG(current_language); + info.from_encodings = MBSTRG(http_input_list); + info.num_from_encodings = MBSTRG(http_input_list_size); + info.from_language = MBSTRG(current_language); + + detected = _php_mb_encoding_handler_ex(&info, track_vars_array, encstr TSRMLS_CC); + + MBSTRG(http_input_identify) = detected; + + RETVAL_BOOL(detected != mbfl_no_encoding_invalid); if (encstr != NULL) efree(encstr); - if (separator != NULL) efree(separator); } /* }}} */ @@ -2254,7 +2267,6 @@ PHP_FUNCTION(mb_list_encodings) } /* }}} */ - /* {{{ proto string mb_encode_mimeheader(string str [, string charset [, string transfer-encoding [, string linefeed]]]) Converts the string to MIME "encoded-word" in the format of =?charset?(B|Q)?encoded_string?= */ PHP_FUNCTION(mb_encode_mimeheader) @@ -3216,7 +3228,7 @@ PHP_FUNCTION(mb_get_info) RETURN_FALSE; } - if (!strcasecmp("all", typ)) { + if (!typ || !strcasecmp("all", typ)) { array_init(return_value); if ((name = (char *)mbfl_no_encoding2name(MBSTRG(current_internal_encoding))) != NULL) { add_assoc_string(return_value, "internal_encoding", name, 1); diff --git a/ext/mbstring/oniguruma/COPYING b/ext/mbstring/oniguruma/COPYING index 7913cbf23f88..ed3fa53b2537 100644 --- a/ext/mbstring/oniguruma/COPYING +++ b/ext/mbstring/oniguruma/COPYING @@ -6,7 +6,7 @@ this of Ruby follows the license of Ruby. It follows the BSD license in the case of the one except for it. /*- - * Copyright (c) 2002 K.Kosako + * Copyright (c) 2002-2004 K.Kosako * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/ext/mbstring/oniguruma/HISTORY b/ext/mbstring/oniguruma/HISTORY index a7a817dd2de5..65ef03f50fad 100644 --- a/ext/mbstring/oniguruma/HISTORY +++ b/ext/mbstring/oniguruma/HISTORY @@ -1,18 +1,479 @@ History +2005/02/19: Version 3.7.0 + +2005/02/19: [test] success in ruby 1.9.0 (2005-02-19) [i386-cygwin]. +2005/02/19: [new] (thanks Minero Aoki) + add onig_region_set(). +2005/02/19: [API] change onig_region_init() to extern. +2005/02/19: [dist] remove reggnu.c from MANIFEST-RUBY. + remove reggnu.c from make 19. +2005/02/19: [dist] update doc/API and doc/API.ja. +2005/02/19: [test] success in ruby 1.9.0 (2005-02-19) [i386-cygwin]. +2005/02/19: [impl] (thanks Alexey Zakhlestin) + change UChar* to const UChar* in oniguruma.h, + regenc.h and regparse.h. +2005/02/13: [impl] change UChar* to const UChar* in oniguruma.h and + onigposix.h and st.h. +2005/02/12: [test] success in ruby 1.9.0 (2005-02-11) [i386-cygwin]. +2005/02/12: [bug] (thanks nobu) [ruby-dev:25676] + type_cclass_hash() fix overrun. +2005/02/09: [test] success in ruby 1.9.0 (2005-02-09) [i686-linux]. +2005/02/09: [spec] add RE_OPTION_FIND_NOT_EMPTY etc.. to oniggnu.h. +2005/02/09: [dist] remove hash.c.patch. +2005/02/07: [impl] remove re_mbctab, mbctab_ascii etc... + (USE_COMPATIBILITY_FOR_RUBY_EXTENSION_LIBRARY) + +2005/02/04: Version 3.6.0 + +2005/02/04: [test] success in ruby 1.9.0 (2005-02-04) [i686-linux]. +2005/02/01: [bug] add key_free() call to st_free_table(). +2005/02/01: [new] add onig_get_default_ambig_flag() and + onig_set_default_ambig_flag(). +2005/02/01: [dist] update MANIFEST-RUBY. +2005/01/31: [test] success in ruby 1.9.0 (2005-01-29) [i686-linux]. +2005/01/31: [spec] remove ONIGENC_AMBIGUOUS_MATCH_COMPOUND + from ONIGENC_AMBIGUOUS_MATCH_DEFAULT. +2005/01/31: [dist] update Makefile.in (make 19). +2005/01/29: [memo] (thanks Kazuo Saito) + Oniguruma 3.5.4 was merged to Ruby 1.9.0. +2005/01/28: [impl] (thanks UK-taniyama) + add extern "C" { } directive to oniguruma.h, oniggnu.h + and onigposix.h for C++. +2005/01/25: [impl] remove nested function call for xxx_code_to_mbclen(). + (euc_kr.c, euc_tw.c, big5.c) + +2005/01/19: Version 3.5.4 + +2005/01/19: [test] success in ruby 1.9.0 (2005-01-05) [i686-linux]. +2005/01/19: [bug] (thanks Isao Sonobe) + callback function argument name_end of onig_foreach_name() + was wrong. + name key of name table should be null terminated for + character encoding length. + add strdup_with_null(), rename onig_strdup() to k_strdup(). + use e->name_len in i_names(). +2005/01/17: [impl] (thanks UK-taniyama) + add HAVE_SYS_TYPES_H to config.h.in. + +2005/01/13: Version 3.5.3 + +2005/01/13: [test] success in ruby 1.9.0 (2005-01-05) [i686-linux]. +2005/01/13: [bug] ignore case match bug. + ex. /s+/iu.match("SSSSS") ==> [4..5] + fix OP_EXACT1_IC, OP_EXACTN_IC process. +2005/01/13: [bug] (thanks Isao Sonobe) + ignore case match bug. + ex. /is/iu.match("ss") fail. + fix str_lower_case_match() etc. + +2005/01/05: Version 3.5.2 + +2005/01/05: [test] success in ruby 1.9.0 (2005-01-05) [i686-linux]. +2005/01/05: [test] success in ruby 1.9.0 (2004-12-16) [i686-linux]. +2005/01/05: [bug] (thanks Isao Sonobe) + ignore case match bug. + ex. /s+/iu.match("sssss") ==> [4..5] + fix OP_EXACT1_IC, OP_EXACTN_IC process. +2005/01/05: [bug] (thanks Isao Sonobe) + group name table should be renumbered. + add onig_renumber_name_table(). +2004/12/24: [dist] remove file onigcmpt200.h. + +2004/12/17: Version 3.5.1 + +2004/12/17: [dist] add INSTALL-RUBY to archive. +2004/12/16: [test] success in ruby 1.9.0 (2004-12-16) [i686-linux]. +2004/12/16: [dist] update hash.c.patch. +2004/12/15: [bug] (thanks matz) + char > 127 should be casted to unsigned char. (utf8.c) +2004/12/13: [impl] add HAVE_PROTOTYPES and HAVE_STDARG_PROTOTYPES definition + to oniguruma.h in the case __cplusplus. +2004/12/06: [dist] update doc/RE and doc/RE.ja. +2004/12/03: [impl] (thanks nobu) + st.h fix prototype for C++. + +2004/12/03: Version 3.5.0 + +2004/12/02: [test] success in ruby 1.9.0 (2004-12-02) [i686-linux]. +2004/12/01: [test] success in ruby 1.9.0 (2004-12-01) [i386-mswin32]. +2004/12/01: [dist] add make targets 19 and 19up to win32/Makefile. +2004/12/01: [test] success in ruby 1.9.0 (2004-12-01) [i386-cygwin]. +2004/12/01: [test] success in ruby 1.9.0 (2004-12-01) [i686-linux]. +2004/12/01: [impl] double cast for escape warning in Cygwin. + (HashDataType* )((void* )(&e)) in regparse.c +2004/12/01: [test] success in ruby 1.9.0 (2004-11-30) [i686-linux]. +2004/12/01: [tune] change implementation of clear_opt_map_info(). + (which was 10-16% cost in gprof result for my test program) +2004/12/01: [dist] remove regex.c from distribution files. +2004/11/30: [memo] remove targets 16 and 18 from Makefile.in. +2004/11/30: [test] success in ruby 1.9.0 (2004-11-30) [i686-linux]. +2004/11/30: [inst] add "cp -p st.[ch] st.[ch].ruby_orig" to "make 19". +2004/11/30: [tune] map_position_value() return 20 if code is 0 + and minimum enclen > 1. +2004/11/30: [test] success in ruby 1.9.0 (2004-11-29) [i686-linux]. +2004/11/30: [impl] minor changes for multi-thread in regexec.c and regcomp.c. +2004/11/30: [impl] change THREAD_PASS_LIMIT_COUNT value from 10 to 8. +2004/11/30: [impl] add THREAD_ATOMIC_XXX to FreeNodeList access in regparse.c +2004/11/29: [impl] add USE_MULTI_THREAD_SYSTEM. +2004/11/29: [memo] add hash.c.patch to CVS. +2004/11/29: [dist] change mail address to 'sndgk393 AT ...' +2004/11/29: [dist] add -s option (silent mode) to test.rb. +2004/11/29: [tune] change THRESHOLD_RANGE_NUM_FOR_SHARE_CCLASS value + from 20 to 8. +2004/11/29: [inst] add make target "19up". +2004/11/29: [dist] change Oniguruma Home Page URL. +2004/11/29: [impl] remove onig_is_in_code_range_array(). +2004/11/29: [dist] fix doc/RE and RE.ja (character types). +2004/11/26: [dist] fix win32/Makefile. +2004/11/26: [dist] fix doc/RE and RE.ja (multibyte character types). +2004/11/26: [impl] add onig_free_shared_cclass_table(). +2004/11/26: [impl] move definition USE_UNICODE_FULL_RANGE_CTYPE to regenc.h. +2004/11/26: [impl] add opcode OP_CCLASS_NODE. +2004/11/26: [impl] move definition of CClassNode to regint.h. +2004/11/26: [impl] add type PointerType in regint.h. +2004/11/25: [impl] remove ONIGENC_CTYPE_MOD_NOT. +2004/11/25: [impl] rename onig_node_new_cclass_by_codepoint_range to + node_new_cclass_by_codepoint_range. +2004/11/25: [impl] remove get_type_cc_node method from OnigEncodingType. +2004/11/25: [impl] move implementation of shared char-class from enc/*.c + to regparse.c. +2004/11/25: [dist] add hash.c.patch for Ruby 1.9 hash.c change. +2004/11/22: [impl] change utf8_get_type_node(). +2004/11/22: [impl] add ONIGENC_CTYPE_MOD_NOT. +2004/11/22: [bug] (thanks MIYAMUKO Katsuyuki) + ruby make test fail in HP-UX B.11.23 ia64. + should use tok->u.code instead of tok->u.c in + the case of TK_CODE_POINT. +2004/11/19: [bug] (thanks Yoshida Masato) + invalid multibyte code causes segmentation fault. + ex. /[\xFF-\xFF]/u +2004/11/19: [bug] (thanks Yoshida Masato) + illegal check in char-class range in UTF-8. + ex. s = "[\xC2\xA0-\xC3\xBE]" + p(Regexp.new(s, nil, "u") =~ "\xC3\xBE") +2004/11/18: [impl] add onig_node_new_cclass_by_codepoint_range(). +2004/11/18: [impl] remove OnigCodePointRange type. (use OnigCodePoint[].) +2004/11/17: [bug] (thanks nobu) + abort in "a".gsub(/a\Z/, "") + fix ONIGENC_STEP_BACK() argument in onig_search(). +2004/11/16: [impl] add key2 member to st_table_entry in st.[ch]. + change API of st for non-null terminated string key. +2004/11/16: [impl] add get_type_cc_node method to OnigEncodingType. +2004/11/15: [impl] add st.h and st.c from Ruby 1.9. + use st-hash always. +2004/11/12: [impl] change menber 'not' of CClassNode to 'flags'. + add flags FLAG_CCLASS_NOT and FLAG_CCLASS_SHARE. +2004/11/12: [impl] add onig_is_in_code_range_array() to enc/unicode.c. +2004/11/12: [impl] fix CRWord in enc/unicode.c and MBWord in enc/utf8.c. +2004/11/11: [bug] fix enc/utf8.c. + size 0 array initializer was compile error in VC++. +2004/11/09: [inst] (thanks Hiroki YAGITA) + change installed file mode to 0644. +2004/11/09: [bug] (thanks UK-taniyama) + wrong definitions GET_RELADDR_INC(), GET_ABSADDR_INC() + etc... (NOT PLATFORM_UNALIGNED_WORD_ACCESS) +2004/11/09: [impl] type cast in regexec() for remove compile time warning. + (WIN32, regposix.c) +2004/11/08: [spec] fix Unicode character types. + 0x00ad (soft hyphen) should be [:cntrl:] and [:space:] type. + [0x0009..0x000d], 0x0085 should be [:print:] type. + 0x00ad should not be [:punct:] type. +2004/11/08: [inst] fix Makefile.in. (for make ctest/ptest/testcu) +2004/11/06: [impl] (thanks Kazuo Saito) + too many alternatives pattern causes core dump. + change implementation of onig_node_free(). +2004/11/05: [spec] rename ONIGERR_END_PATTERN_AT_BACKSLASH to + ONIGERR_END_PATTERN_AT_ESCAPE. +2004/11/05: [impl] (thanks matz) + escape compile time warnings for x86-64 Linux. + StackIndex type int -> long +2004/11/05: [memo] (thanks Kazuo Saito) + Oniguruma 3.4.0 was merged to Ruby 1.9.0. + +2004/10/30: Version 3.4.0 + +2004/10/30: [test] success in ruby 1.9.0 (2004-09-24) [i686-linux]. +2004/10/30: [new] add hexadecimal digit char type. (\h, \H) + syntax: ONIG_SYN_OP2_ESC_H_XDIGIT +2004/10/30: [bug] (thanks Guy Decoux) + reluctant infinite repeat bug. + ex. /^[a-z]{2,}?$/.match("aaa") fail. + fix OP_REPEAT_INC_NG process in match_at(). + +2004/10/18: Version 3.3.1 + +2004/10/18: [test] success in ruby 1.9.0 (2004-09-24) [i686-linux]. +2004/10/18: [impl] (thanks Imai Yasumasa) + enclose #include by #ifndef __BORLANDC__. +2004/10/18: [bug] (thanks Imai Yasumasa) + memory acess violation in select_opt_exact_info(). +2004/09/25: [dist] fix doc/API and doc/API.ja. +2004/09/25: [bug] fix OP_SEMI_END_BUF process in match_at() for + the case USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE + is not defined. + +2004/09/17: Version 3.3.0 + +2004/09/17: [dist] add COPYING to program source files. +2004/09/17: [test] success in ruby 1.9.0 (2004-07-23) [i686-linux]. +2004/09/17: [bug] (thanks Isao Sonobe) + memory access violations in xxx_mbc_enc_len(), + and xxx_mbc_to_normalize() and + xxx_left_adjust_char_head(). + add string range check in match_at() and onig_search(). +2004/09/08: [dist] change mail address format.(kosako AT sofnec ...) + +2004/09/04: Version 3.2.9 + +2004/09/04: [test] success in ruby 1.9.0 (2004-07-23) [i686-linux]. +2004/09/04: [bug] (thanks Bob Kerstetter and Richard Koch) + search fail in ignore case mode. + fix str_lower_case_match(). +2004/09/04: [inst] (thanks Isao Sonobe) + clear sample directory in 'make clean'. +2004/09/04: [bug] fix ONIGENC_AMBIGUOUS_MATCH_COMPOUND/ASCII/NONASCII + meanings in XXXXX_mbc_to_normalize() and + XXXXX_is_mbc_ambiguous(). +2004/08/28: [bug] fix ONIGENC_AMBIGUOUS_MATCH_COMPOUND/ASCII/NONASCII + meanings in iso_8859_XX_mbc_to_normalize() and + iso_8859_XX_is_mbc_ambiguous(). + +2004/08/24: Version 3.2.8 + +2004/08/24: [test] success in ruby 1.9.0 (2004-07-23) [i686-linux]. +2004/08/24: [spec] add ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY. + /a{n}?/ == /(?:a{n})?/ +2004/08/24: [dist] fix doc/RE and doc/RE.ja. +2004/08/24: [bug] (thanks starfish) + memory leak in set_optimize_exact_info(). + +2004/08/21: Version 3.2.7 + +2004/08/21: [test] success in ruby 1.8.2 (2004-07-28) [i686-linux]. + (1.8.2 preview2) +2004/08/21: [test] success in ruby 1.9.0 (2004-07-23) [i686-linux]. +2004/08/21: [bug] (thanks Isao Sonobe) (thanks kage) + memory access violation in bm_search_notrev(). + (forgotten to merge from 2.X) + +2004/07/24: Version 3.2.6 + +2004/07/24: [test] success in ruby 1.9.0 (2004-07-23) [i686-linux]. +2004/07/24: [test] success in ruby 1.8.2 (2004-07-16) [i686-linux]. +2004/07/24: [bug] fix warnings for regexec.c. (gcc 2.91.66) +2004/07/24: [memo] change version control system from Subversion + to CVS 1.11.17. +2004/07/20: [bug] (thanks Isao Sonobe) + illegal result in negative character class in ignore case + mode. fix pair-ambig-codes process in parse_exp(). + ex. /[^a]/i.match("A") +2004/07/20: [bug] (thanks Isao Sonobe) + undefined bytecode error happens in UTF-16BE etc.. + compile_length_cclass_node() was not consistent with + compile_cclass_node(). + +2004/07/01: Version 3.2.5 + +2004/07/01: [test] success in ruby 1.8.2 (2004-06-23) [i686-linux]. +2004/07/01: [new] add onig_get_syntax_{op,op2,behavior,options}. +2004/07/01: [bug] (thanks Isao Sonobe) + invalid result in onig_capture_tree_traverse(). + fix make_capture_history_tree(). + +2004/06/29: Version 3.2.4 + +2004/06/29: [test] success in ruby 1.8.2 (2004-06-23) [i686-linux]. +2004/06/29: [new] (thanks Isao Sonobe) + add onig_number_of_captures(). + +2004/06/25: Version 3.2.3 + +2004/06/25: [test] success in ruby 1.8.2 (2004-06-23) [i686-linux]. +2004/06/25: [bug] (thanks Isao Sonobe) + invalid result in onig_capture_tree_traverse(). + fix make_capture_history_tree(). + +2004/06/24: Version 3.2.2 + +2004/06/24: [test] success in ruby 1.8.0 (2003-08-08) [i386-cygwin]. +2004/06/24: [test] success in ruby 1.8.0 (2003-08-08) [i386-mswin32]. +2004/06/24: [test] success in ruby 1.8.2 (2004-06-23) [i686-linux]. +2004/06/24: [new] (thanks Isao Sonobe) + add onig_number_of_capture_histories(). +2004/06/24: [bug] (thanks Isao Sonobe) + invalid char position match in UTF-16 and UTF-32. + add onigenc_always_false_is_allowed_reverse_match(). + +2004/06/17: Version 3.2.1 + +2004/06/17: [test] success in ruby 1.8.0 (2003-08-08) [i386-cygwin]. +2004/06/17: [test] success in ruby 1.8.0 (2003-08-08) [i386-mswin32]. +2004/06/17: [test] success in ruby 1.8.2 (2004-05-18) [i686-linux]. +2004/06/17: [impl] should not use OP_REPEAT for (...)? even if target size + is long. +2004/06/17: [bug] (thanks nobu) [ruby-dev:23703] + should use STACK_AT() instead of stkp in OP_REPEAT_INC. + add IN_VAR_REPEAT flag in setup_tree(). +2004/06/16: [impl] change select_opt_exact_info() to use ByteValTable[]. +2004/06/16: [impl] change map_position_value() table values. +2004/06/14: [impl] (thanks John Carter) + RelAddrType, AbsAddrType and LengthType change + from short int to int type for the very long string match. +2004/06/14: [bug] (thanks Greg A. Woods) + fix nmatch argument of regexec() is smaller than + reg->num_mem + 1 case. (POSIX API) +2004/06/14: [spec] (thanks Greg A. Woods) + set pmatch to NULL if nmatch is 0 in regexec(). (POSIX API) + +2004/06/10: Version 3.2.0 + +2004/06/10: [test] success in ruby 1.8.0 (2003-08-08) [i386-cygwin]. +2004/06/10: [test] success in ruby 1.9.0 (2004-05-27) [i386-mswin32]. +2004/06/10: [test] success in ruby 1.8.2 (2004-05-18) [i686-linux]. +2004/06/10: [dist] add README.ja. +2004/06/10: [new] add onig_copy_encoding(). +2004/06/10: [API] add encoding argument to onig_set_meta_char(). + add meta_char_table member to OnigEncodingType. +2004/06/08: [dist] add doc/API.ja. +2004/06/07: [API] add num_of_elements member to OnigCompileInfo. +2004/05/29: [memo] (thanks Kazuo Saito) + Oniguruma 3.1.0 was merged to Ruby 1.9.0. +2004/05/26: [impl] rename NST_SIMPLE_REPEAT to NST_STOP_BT_SIMPLE_REPEAT. +2004/05/26: [impl] doesn't need to check that target's simple repeat-ness + for EFFECT_MEMORY type node in setup_tree(). + +2004/05/25: Version 3.1.0 + +2004/05/25: [test] success in ruby 1.8.0 (2003-08-08) [i386-mswin32]. +2004/05/25: [test] success in ruby 1.8.0 (2003-08-08) [i386-cygwin]. +2004/05/25: [test] success in ruby 1.9.0 (2004-05-23) [i686-linux]. +2004/05/25: [test] success in ruby 1.8.2 (2004-05-18) [i686-linux]. +2004/05/25: [bug] (thanks Masahiro Sakai) [ruby-dev:23560] + ruby -ruri -ve 'URI::ABS_URI =~ + "http://example.org/Andr\xC3\xA9"' + nested STK_REPEAT type stack can't backtrack repeat_stk[]. + add OP_REPEAT_INC_SG and OP_REPEAT_INC_NG_SG. +2004/05/25: [new] support UTF-32LE. (ONIG_ENCODING_UTF32_LE) +2004/05/25: [new] support UTF-32BE. (ONIG_ENCODING_UTF32_BE) +2004/05/24: [impl] divide enc/utf16.c to utf16_be.c and utf16_le.c. +2004/05/24: [impl] add enc/unicode.c. +2004/05/24: [API] change calling sequences of onig_new_deluxe() and + onig_recompile_deluxe(). + define OnigCompileInfo type. +2004/05/21: [impl] perform ensure process for rb_trap_exec() in match_at(). + add onig_exec_trap() and CHECK_INTERRUPT_IN_MATCH_AT. +2004/05/21: [impl] add regex status check to onig_match(). +2004/05/21: [new] add onig_get_capture_tree() and + onig_capture_tree_traverse(). +2004/05/20: [spec] (thanks Isao Sonobe) + capture history return capture data tree. + (see sample/listcap.c) +2004/05/19: [bug] (thanks Simon Strandgaard) + Control-C does not work in matching process on Ruby. + add calling of CHECK_INTERRUPT into match_at(). + ex. /<(?:[^">]+|"[^"]*")+>/.match('') +2004/05/19: [bug] (thanks Simon Strandgaard) + define virtual codepoint values for invalid encoding + byte 0xfe and 0xff in UTF-8. + ex. /\w+/u.match("%a\xffb\xfec%") ==> "a" +2004/05/19: [spec] (thanks Simon Strandgaard) + too big backref number should be treated as a sequence of + an octal char and number digits. + ex. /b\3777\c/.match("b\3777\c") +2004/05/17: [spec] rename encoding names "UTF-16 BE" and "UTF-16 LE" + to "UTF-16BE" and "UTF-16LE". +2004/05/17: [impl] move ismbchar() and mbclen() from oniguruma.h to oniggnu.h. +2004/05/17: [impl] rename onigenc_single_byte_is_allowed_reverse_match() to + onigenc_always_true_is_allowed_reverse_match(). + +2004/05/14: Version 3.0.0 + +2004/05/14: [test] success in ruby 1.8.0 (2003-08-08) [i386-cygwin]. +2004/05/14: [test] success in ruby 1.9.0 (2004-05-14) [i686-linux]. +2004/05/14: [test] success in ruby 1.8.0 (2003-08-08) [i386-mswin32]. + (* need to edit parse.y: + register int c; ---> int c; in yylex()) +2004/05/14: [impl] add regext.c. +2004/05/14: [spec] KOI8 is not included in library archive by default setup. +2004/05/14: [impl] implementation changes are completed for all encoding files. +2004/05/12: [impl] add divide_ambig_string_node(). + ambiguous string is divided and normalized before + optimization and compilation process. +2004/05/11: [dist] remove INSTALL-RUBY from distribution. +2004/04/28: [memo] (thanks Kazuo Saito) + Oniguruma 2.2.8 was merged to Ruby 1.9.0. +2004/04/26: [spec] change value DEFAULT_MATCH_STACK_LIMIT_SIZE = 0 : unlimited +2004/04/26: [new] add onig_get_match_stack_limit_size() and + onig_set_match_stack_limit_size(). +2004/04/26: [bug] add error check to re.c.181.patch and re.c.168.patch. +2004/04/23: [impl] remove ctype_support_level from OnigEncodingType. +2004/04/22: [spec] allow the range from single byte char to multibyte char in + character class for implementation reason. + ex. /[a-\xbb\xcc]/ in EUC-JP encoding. +2004/04/21: [impl] remove max_enc_len_by_first_byte() from OnigEncodingType. +2004/04/20: [new] add onig_copyright(). +2004/04/20: [impl] add regversion.c. +2004/04/15: [new] add onig_get_ambig_flag(). +2004/04/14: [bug] (thanks Isao Sonobe) + undefined bytecode error happens if ONIG_OPTION_FIND_LONGEST + is setted. + should finish matching process if find-condition + is fail at OP_END in match_at(). +2004/04/12: [impl] add ambig_flag to regex_t. +2004/04/09: [impl] move onig_set_meta_char() to regsyntax.c. +2004/04/09: [bug] (thanks HIROSE Masaaki) fix onig_version(). +2004/04/08: [impl] add regsyntax.c. +2004/04/07: [new] support UTF-16 LE. (ONIG_ENCODING_UTF16_LE) +2004/04/05: [impl] add ONIGENC_CTYPE_NEWLINE. +2004/04/05: [memo] (thanks Kazuo Saito) + Oniguruma 2.2.6 was merged to Ruby 1.9.0. +2004/04/02: [memo] Version 2.2.6 was released. +2004/03/26: [new] support UTF-16 BE. (ONIG_ENCODING_UTF16_BE) +2004/03/25: [spec] support non 8-bit encodings. +2004/03/16: [memo] 2.X branch for 8-bit encodings only. + +2004/03/16: Version 2.2.5 + +2004/03/16: [test] success in ruby 1.8.0 (2003-08-08) [i386-mswin32]. +2004/03/16: [test] success in ruby 1.9.0 (2004-02-24) [i686-linux]. +2004/03/16: [impl] add property name to error message of + ONIGERR_INVALID_CHAR_PROPERTY_NAME. +2004/03/16: [spec] allow prefix 'Is' for \p{...} in ONIG_SYNTAX_PERL. + add syntax op. ONIG_SYN_OP2_CHAR_PROPERTY_PREFIX_IS. +2004/03/15: [dist] add sample/syntax.c. +2004/03/15: [spec] support NOT op. in char property. \p{^...}, \P{^...}. + add syntax op. ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT. +2004/03/15: [spec] rename ONIG_SYN_OP2_ESC_P_CHAR_PROPERTY to + ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY. +2004/03/10: [impl] move ONIGERR_XXX from regenc.h to oniguruma.h, + rename ONIGERR_XXX to ONIGENCERR_XXX in regenc.h. +2004/03/08: [impl] (thanks eban) + replace defined(__CYGWIN__) to defined(__GNUC__). +2004/03/08: [bug] (thanks eban) [ruby-dev:23172] + need to separate initialization for bcc32. +2004/03/06: [memo] (thanks Kazuo Saito) + Oniguruma 2.2.4 was merged to Ruby 1.9.0. +2004/03/05: [API] change second argument type of onig_set_meta_char() + from unsigned int to OnigCodePoint. +2004/03/05: [dist] (thanks Kazuo Saito) + add MANIFEST-RUBY. + 2004/03/04: Version 2.2.4 2004/03/04: [impl] (thanks Moriyoshi Koizumi) - fix many warning in Win32 VC++ with /W3 option. + fix many warnings in Win32 VC++ with /W3 option. 2004/03/02: Version 2.2.3 2004/03/02: [bug] (thanks Isao Sonobe) return invalid capture region value if capture history is used. (OP_MEMORY_END_PUSH_REC bug) - ex. /\\g

(?@

\\(\\g\\)){0}(?(?:\\g

)*|){0}/ + ex. /\g

(?@

\(\g\)){0}(?(?:\g

)*|){0}/ .match("((())())") -2004/03/02: [impl] add :nodoc: to onig_stat_print() for RDoc. +2004/03/02: [impl] (thanks Kazuo Saito) + add :nodoc: to onig_stat_print() for RDoc. 2004/03/02: [impl] don't use ONIG_SOURCE_IS_WRAPPED. 2004/02/27: Version 2.2.2 @@ -91,14 +552,14 @@ History (0x80 - 0xff is not ASCII) 2004/01/23: [new] support ISO-8859-2. (ONIG_ENCODING_ISO_8859_2) 2004/01/23: [dist] add enc/isotable.c. -2004/01/22; [new] support EUC-TW. (ONIG_ENCODING_EUC_TW) +2004/01/22: [new] support EUC-TW. (ONIG_ENCODING_EUC_TW) 2004/01/22: [bug] definition of GET_ALIGNMENT_PAD_SIZE() and ALIGNMENT_RIGHT() was wrong. type casting should be unsigned int, not int. 2004/01/22: [impl] add defined(__x86_64) || defined(__x86_64__) to unaligned word access condition. (AMD64 ?) 2004/01/21: [dist] rename enc/eucjp.c to enc/euc_jp.c. -2004/01/21; [new] support EUC-KR. (ONIG_ENCODING_EUC_KR) +2004/01/21: [new] support EUC-KR. (ONIG_ENCODING_EUC_KR) 2004/01/20: [test] success in ruby 1.8.0 (2003-08-08) [i386-cygwin]. 2004/01/20: [dist] change Makefile.in. 2004/01/20: [spec] add \p{...}, \P{...} in char class. @@ -883,5 +1344,16 @@ History [test: test] [memo: memo] -- + +svn mkdir http://localhost/repos/branches -m "" +svn mkdir http://localhost/repos/branches/oniguruma -m "" +svn copy http://localhost/repos/trunk/oniguruma http://localhost/repos/branches/oniguruma/2.X -m "branch for 8-bit encodings only" + svn copy http://localhost/repos/trunk/oniguruma http://localhost/repos/tags/oniguruma/X.X.X -m "onigdXXXXXXXX" + + +cvs history -T + + +cvs rtag "VERSION_X_X_X" oniguruma diff --git a/ext/mbstring/oniguruma/README b/ext/mbstring/oniguruma/README index 3880423f03ba..dc4fb3b64b83 100644 --- a/ext/mbstring/oniguruma/README +++ b/ext/mbstring/oniguruma/README @@ -1,7 +1,8 @@ -README 2004/02/25 +README 2005/02/04 -Oniguruma ---- (C) K.Kosako +Oniguruma ---- (C) K.Kosako +http://www.geocities.jp/kosako3/oniguruma/ http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/oniguruma/ http://www.freebsd.org/cgi/cvsweb.cgi/ports/devel/oniguruma/ @@ -11,45 +12,38 @@ for every regular expression object can be specified. Supported character encodings: - ASCII, UTF-8, + ASCII, UTF-8, UTF-16BE, UTF-16LE, UTF-32BE, UTF-32LE, EUC-JP, EUC-TW, EUC-KR, EUC-CN, - Shift_JIS, Big5, KOI8, KOI8-R, + Shift_JIS, Big5, KOI8-R, KOI8 (*), ISO-8859-1, ISO-8859-2, ISO-8859-3, ISO-8859-4, ISO-8859-5, ISO-8859-6, ISO-8859-7, ISO-8859-8, ISO-8859-9, ISO-8859-10, ISO-8859-11, ISO-8859-13, ISO-8859-14, ISO-8859-15, ISO-8859-16 - -There are two ways of using of it in this program. - - * Built-in regular expression engine of Ruby - * C library (supported APIs: GNU regex, POSIX, Oniguruma native) - +* KOI8 is not included in library archive by default setup. + (need to edit Makefile if you want to use it.) ------------------------------------------------------------ Install -(A) Install into Ruby + Case 1: Unix and Cygwin platform - See INSTALL-RUBY. - - (character encodings: ASCII, UTF-8, EUC-JP, Shift_JIS) + 1. ./configure + 2. make + 3. make install + library file: libonig.a -(B) Install C library + test (ASCII/EUC-JP) - (B-1) Unix and Cygwin platform + make ctest - 1. ./configure - 2. make - 3. make install + uninstall - (* uninstall: make uninstall) + make uninstall - * test (ASCII/EUC-JP) - 4. make ctest - (B-2) Win32 platform (VC++) + Case 2: Win32 platform (VC++) 1. copy win32\Makefile Makefile 2. copy win32\config.h config.h @@ -77,6 +71,16 @@ Regular Expressions See doc/RE (or doc/RE.ja for Japanese). +Usage + + Include oniguruma.h in your program. (native API) + See doc/API for native API. + + If you want to use static link library(onig_s.lib) in Win32, + add option -DONIG_EXTERN=extern to C compiler. + + + Sample Programs sample/simple.c example of the minimum (native API) @@ -86,14 +90,12 @@ Sample Programs sample/posix.c POSIX API sample. sample/sql.c example of the variable meta characters. (SQL-like pattern matching) + sample/syntax.c Perl and Java syntax test. Source Files oniguruma.h Oniguruma API header file. (public) - oniggnu.h GNU regex API header file. (public) - onigcmpt200.h Oniguruma API backward compatibility header file. (public) - (for 2.0.0 or more older version) regenc.h character encodings framework header file. regint.h internal definitions @@ -101,17 +103,31 @@ Source Files regcomp.c compiling and optimization functions regenc.c character encodings framework. regerror.c error message function - regex.c source files wrapper for Ruby + regext.c extended API functions. (deluxe version API) regexec.c search and match functions regparse.c parsing functions. + regsyntax.c pattern syntax functions and built-in syntax definitions. + regtrav.c capture history tree data traverse functions. + regversion.c version info function. + st.h hash table functions header file + st.c hash table functions + + oniggnu.h GNU regex API header file. (public) reggnu.c GNU regex API functions onigposix.h POSIX API header file. (public) regposerr.c POSIX error message function. - regposix.c POSIX functions. + regposix.c POSIX API functions. enc/mktable.c character type table generator. enc/ascii.c ASCII encoding. + enc/euc_jp.c EUC-JP encoding. + enc/euc_tw.c EUC-TW encoding. + enc/euc_kr.c EUC-KR, EUC-CN encoding. + enc/sjis.c Shift_JIS encoding. + enc/big5.c Big5 encoding. + enc/koi8.c KOI8 encoding. + enc/koi8_r.c KOI8-R encoding. enc/iso8859_1.c ISO-8859-1 encoding. (Latin-1) enc/iso8859_2.c ISO-8859-2 encoding. (Latin-2) enc/iso8859_3.c ISO-8859-3 encoding. (Latin-3) @@ -128,18 +144,19 @@ Source Files enc/iso8859_15.c ISO-8859-15 encoding. (Latin-9 or West European with Euro) enc/iso8859_16.c ISO-8859-16 encoding. (Latin-10 or South-Eastern European with Euro) - enc/utf8.c UTF-8 encoding. - enc/euc_jp.c EUC-JP encoding. - enc/euc_tw.c EUC-TW encoding. - enc/euc_kr.c EUC-KR, EUC-CN encoding. - enc/sjis.c Shift_JIS encoding. - enc/koi8.c KOI8 encoding. - enc/koi8_r.c KOI8-R encoding. - enc/big5.c Big5 encoding. + enc/utf8.c UTF-8 encoding. + enc/utf16_be.c UTF-16BE encoding. + enc/utf16_le.c UTF-16LE encoding. + enc/utf32_be.c UTF-32BE encoding. + enc/utf32_le.c UTF-32LE encoding. + enc/unicode.c Unicode information data. + win32/Makefile Makefile for Win32 (VC++) + win32/config.h config.h for Win32 -API differences with Japanized GNU regex(version 0.12) of Ruby + +API differences with Japanized GNU regex(version 0.12) of Ruby 1.8/1.6 + re_compile_fastmap() is removed. + re_recompile_pattern() is added. @@ -148,18 +165,17 @@ API differences with Japanized GNU regex(version 0.12) of Ruby ToDo - 1 support 16-bit encodings. (UTF-16) - 2 different encoding pattern with target. - (ex. ASCII/UTF-16, UTF-16 BE and UTF-16 LE) - 3 add enc/name.c (onigenc_get_enc_by_name(name)) - - ? transmission stopper. (return ONIG_STOP from match_at()) - ? implement syntax behavior ONIG_SYN_CONTEXT_INDEP_ANCHORS. - ? better acess to hash table (st.c). - non null-terminated key version st_lookup(). - ? grep-like tool 'onigrep'. - ? return parse tree of regexp pattern to application. - ?? /a{n}?/ should be interpreted as /(?:a{n})?/. - ?? \h hexadecimal digit char ([0-9a-fA-F]), \H not \h. + ? ignore case in full code point range of Unicode. + ? Unicode Property. + ? ambig-flag Katakana <-> Hiragana. + ? add ONIG_OPTION_NOTBOS/NOTEOS. (\A, \z, \Z) + ? add ONIG_SYNTAX_ASIS. + ?? \X (== \PM\pM*) + ?? implement syntax behavior ONIG_SYN_CONTEXT_INDEP_ANCHORS. + ?? variable line separator. + ?? transmission stopper. (return ONIG_STOP from match_at()) and I'm thankful to Akinori MUSHA. + + +Mail Address: K.Kosako diff --git a/ext/mbstring/oniguruma/README.ja b/ext/mbstring/oniguruma/README.ja new file mode 100644 index 000000000000..44553abfefd6 --- /dev/null +++ b/ext/mbstring/oniguruma/README.ja @@ -0,0 +1,177 @@ +README.ja 2005/02/04 + +µ´¼Ö ---- (C) K.Kosako + +http://www.geocities.jp/kosako3/oniguruma/ +http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/oniguruma/ +http://www.freebsd.org/cgi/cvsweb.cgi/ports/devel/oniguruma/ + +µ´¼Ö¤ÏÀµµ¬É½¸½¥é¥¤¥Ö¥é¥ê¤Ç¤¢¤ë¡£ +¤³¤Î¥é¥¤¥Ö¥é¥ê¤ÎÆÃĹ¤Ï¡¢¤½¤ì¤¾¤ì¤ÎÀµµ¬É½¸½¥ª¥Ö¥¸¥§¥¯¥È¤´¤È¤Ë +ʸ»ú¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¤ò»ØÄê¤Ç¤­¤ë¤³¤È¤Ç¤¢¤ë¡£ + +¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤ëʸ»ú¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°: + + ASCII, UTF-8, UTF-16BE, UTF-16LE, UTF-32BE, UTF-32LE, + EUC-JP, EUC-TW, EUC-KR, EUC-CN, + Shift_JIS, Big5, KOI8-R, KOI8 (*), + ISO-8859-1, ISO-8859-2, ISO-8859-3, ISO-8859-4, ISO-8859-5, + ISO-8859-6, ISO-8859-7, ISO-8859-8, ISO-8859-9, ISO-8859-10, + ISO-8859-11, ISO-8859-13, ISO-8859-14, ISO-8859-15, ISO-8859-16 + +* KOI8¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥»¥Ã¥È¥¢¥Ã¥×¤Ç¤Ï¥é¥¤¥Ö¥é¥ê¤ÎÃæ¤Ë´Þ¤Þ¤ì¤Ê¤¤¡£ + (ɬÍפǤ¢¤ì¤ÐMakefile¤òÊÔ½¸¤¹¤ë¤³¤È) +------------------------------------------------------------ + +¥¤¥ó¥¹¥È¡¼¥ë + + ¥±¡¼¥¹£±: Unix¤ÈCygwin´Ä¶­ + + 1. ./configure + 2. make + 3. make install + + ¥é¥¤¥Ö¥é¥ê¥Õ¥¡¥¤¥ë: libonig.a + + ưºî¥Æ¥¹¥È (ASCII/EUC-JP) + + make ctest + + ¥¢¥ó¥¤¥ó¥¹¥È¡¼¥ë + + make uninstall + + + + ¥±¡¼¥¹£²: Win32(VC++)´Ä¶­ + + 1. copy win32\Makefile Makefile + 2. copy win32\config.h config.h + 3. nmake + + onig_s.lib: static link library + onig.dll: dynamic link library + + * ưºî¥Æ¥¹¥È (ASCII/Shift_JIS) + 4. copy win32\testc.c testc.c + 5. nmake ctest + + +¥é¥¤¥»¥ó¥¹ + + ¤³¤Î¥½¥Õ¥È¥¦¥§¥¢¤¬Ruby¤È°ì½ï¤Ë»ÈÍѤޤ¿¤ÏÇÛÉÛ¤µ¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ + Ruby¤Î¥é¥¤¥»¥ó¥¹¤Ë½¾¤¦¡£ + ¤½¤ì°Ê³°¤Î¾ì¹ç¤Ë¤Ï¡¢BSD¥é¥¤¥»¥ó¥¹¤Ë½¾¤¦¡£ + + +Àµµ¬É½¸½ + + doc/RE.ja¤ò»²¾È + + +»ÈÍÑÊýË¡ + + »ÈÍѤ¹¤ë¥×¥í¥°¥é¥à¤Ç¡¢oniguruma.h¤ò¥¤¥ó¥¯¥ë¡¼¥É¤¹¤ë(Native API¤Î¾ì¹ç)¡£ + Native API¤Ë¤Ä¤¤¤Æ¤Ï¡¢doc/API.ja¤ò»²¾È¡£ + + Win32¤Ç¥¹¥¿¥Æ¥£¥Ã¥¯¥ê¥ó¥¯¥é¥¤¥Ö¥é¥ê(onig_s.lib)¤ò¥ê¥ó¥¯¤¹¤ë¾ì¹ç¤Ë¤Ï¡¢ + ¥³¥ó¥Ñ¥¤¥ë¤¹¤ë¤È¤­¤Ë -DONIG_EXTERN=extern ¤ò¥³¥ó¥Ñ¥¤¥ë°ú¿ô¤ËÄɲ乤뤳¤È¡£ + + +»ÈÍÑÎã¥×¥í¥°¥é¥à + + sample/simple.c ºÇ¾®Îã (native API) + sample/names.c ̾Á°ÉÕ¤­¥°¥ë¡¼¥×¥³¡¼¥ë¥Ð¥Ã¥¯»ÈÍÑÎã + sample/encode.c ´ö¤Ä¤«¤Îʸ»ú¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°»ÈÍÑÎã + sample/listcap.c Êá³ÍÍúÎòµ¡Ç½¤Î»ÈÍÑÎã + sample/posix.c POSIX API»ÈÍÑÎã + sample/sql.c ²ÄÊѥ᥿ʸ»úµ¡Ç½»ÈÍÑÎã (SQL-like ¥Ñ¥¿¡¼¥ó) + sample/syntax.c Perl¤ÈJavaʸˡ¤Î¥Æ¥¹¥È + + +¥½¡¼¥¹¥Õ¥¡¥¤¥ë + + oniguruma.h µ´¼ÖAPI¥Ø¥Ã¥À (¸ø³«) + + regenc.h ʸ»ú¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°ÏÈÁȤߥإåÀ + regint.h ÆâÉôÀë¸À + regparse.h regparse.c¤Èregcomp.c¤Î¤¿¤á¤ÎÆâÉôÀë¸À + regcomp.c ¥³¥ó¥Ñ¥¤¥ë¡¢ºÇŬ²½´Ø¿ô + regenc.c ʸ»ú¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°ÏÈÁÈ¤ß + regerror.c ¥¨¥é¡¼¥á¥Ã¥»¡¼¥¸´Ø¿ô + regext.c ³ÈÄ¥API´Ø¿ô + regexec.c ¸¡º÷¡¢¾È¹ç´Ø¿ô + regparse.c Àµµ¬É½¸½¥Ñ¥¿¡¼¥ó²òÀÏ´Ø¿ô + regsyntax.c Àµµ¬É½¸½¥Ñ¥¿¡¼¥óʸˡ´Ø¿ô¡¢Áȹþ¤ßʸˡÄêµÁ + regtrav.c Êá³ÍÍúÎòÌÚ½ä²ó´Ø¿ô + regversion.c ÈǾðÊó´Ø¿ô + st.h ¥Ï¥Ã¥·¥å¥Æ¡¼¥Ö¥ë´Ø¿ôÀë¸À + st.c ¥Ï¥Ã¥·¥å¥Æ¡¼¥Ö¥ë´Ø¿ô + + oniggnu.h GNU regex API¥Ø¥Ã¥À (¸ø³«) + reggnu.c GNU regex API´Ø¿ô + + onigposix.h POSIX API¥Ø¥Ã¥À (¸ø³«) + regposerr.c POSIX API¥¨¥é¡¼¥á¥Ã¥»¡¼¥¸´Ø¿ô + regposix.c POSIX API´Ø¿ô + + enc/mktable.c ʸ»ú¥¿¥¤¥×¥Æ¡¼¥Ö¥ëÀ¸À®¥×¥í¥°¥é¥à + enc/ascii.c ASCII ¥¨¥ó¥³¡¼¥Ç¥£¥ó¥° + enc/euc_jp.c EUC-JP ¥¨¥ó¥³¡¼¥Ç¥£¥ó¥° + enc/euc_tw.c EUC-TW ¥¨¥ó¥³¡¼¥Ç¥£¥ó¥° + enc/euc_kr.c EUC-KR, EUC-CN ¥¨¥ó¥³¡¼¥Ç¥£¥ó¥° + enc/sjis.c Shift_JIS ¥¨¥ó¥³¡¼¥Ç¥£¥ó¥° + enc/big5.c Big5 ¥¨¥ó¥³¡¼¥Ç¥£¥ó¥° + enc/koi8.c KOI8 ¥¨¥ó¥³¡¼¥Ç¥£¥ó¥° + enc/koi8_r.c KOI8-R ¥¨¥ó¥³¡¼¥Ç¥£¥ó¥° + enc/iso8859_1.c ISO-8859-1 (Latin-1) + enc/iso8859_2.c ISO-8859-2 (Latin-2) + enc/iso8859_3.c ISO-8859-3 (Latin-3) + enc/iso8859_4.c ISO-8859-4 (Latin-4) + enc/iso8859_5.c ISO-8859-5 (Cyrillic) + enc/iso8859_6.c ISO-8859-6 (Arabic) + enc/iso8859_7.c ISO-8859-7 (Greek) + enc/iso8859_8.c ISO-8859-8 (Hebrew) + enc/iso8859_9.c ISO-8859-9 (Latin-5 ¤Þ¤¿¤Ï Turkish) + enc/iso8859_10.c ISO-8859-10 (Latin-6 ¤Þ¤¿¤Ï Nordic) + enc/iso8859_11.c ISO-8859-11 (Thai) + enc/iso8859_13.c ISO-8859-13 (Latin-7 ¤Þ¤¿¤Ï Baltic Rim) + enc/iso8859_14.c ISO-8859-14 (Latin-8 ¤Þ¤¿¤Ï Celtic) + enc/iso8859_15.c ISO-8859-15 (Latin-9 ¤Þ¤¿¤Ï West European with Euro) + enc/iso8859_16.c ISO-8859-16 + (Latin-10 ¤Þ¤¿¤Ï South-Eastern European with Euro) + enc/utf8.c UTF-8 ¥¨¥ó¥³¡¼¥Ç¥£¥ó¥° + enc/utf16_be.c UTF-16BE ¥¨¥ó¥³¡¼¥Ç¥£¥ó¥° + enc/utf16_le.c UTF-16LE ¥¨¥ó¥³¡¼¥Ç¥£¥ó¥° + enc/utf32_be.c UTF-32BE ¥¨¥ó¥³¡¼¥Ç¥£¥ó¥° + enc/utf32_le.c UTF-32LE ¥¨¥ó¥³¡¼¥Ç¥£¥ó¥° + enc/unicode.c Unicode¾ðÊó + + win32/Makefile Win32ÍÑ Makefile (for VC++) + win32/config.h Win32ÍÑ config.h + + + +Ruby 1.8/1.6¤ÎÆüËܸ첽GNU regex¤È¤ÎAPI¤Î°ã¤¤ + + + re_compile_fastmap() ¤Ïºï½ü¤µ¤ì¤¿¡£ + + re_recompile_pattern() ¤¬Äɲ䵤줿¡£ + + re_alloc_pattern() ¤¬Äɲ䵤줿¡£ + + +»Ä·ï + + ? UnicodeÁ´¥³¡¼¥É¥Ý¥¤¥ó¥ÈÎΰè¤Ç¤ÎÂçʸ»ú¾®Ê¸»ú¾È¹ç + ? Unicode¥×¥í¥Ñ¥Æ¥£ + ? ambig-flag Katakana <-> Hiragana + ? ONIG_OPTION_NOTBOS/NOTEOSÄɲà (\A, \z, \Z) + ? ONIG_SYNTAX_ASISÄɲà + ?? \X (== \PM\pM*) + ?? ʸˡÍ×ÁÇ ONIG_SYN_CONTEXT_INDEP_ANCHORS¤Î¼ÂÁõ + ?? ²þ¹Ôʸ»ú(ʸ»úÎó)¤òÊѹ¹¤Ç¤­¤ë + ?? ¸¡º÷°ÌÃÖ°ÜÆ°Ää»ß±é»»»Ò (match_at()¤«¤éONIG_STOP¤òÊÖ¤¹) + +and I'm thankful to Akinori MUSHA. + + +Mail Address: K.Kosako diff --git a/ext/mbstring/oniguruma/config.h.in b/ext/mbstring/oniguruma/config.h.in index 1a59a45dc074..5ca2056fb396 100644 --- a/ext/mbstring/oniguruma/config.h.in +++ b/ext/mbstring/oniguruma/config.h.in @@ -49,6 +49,9 @@ /* Define if you have the header file. */ #undef HAVE_STRINGS_H +/* Define if you have the header file. */ +#undef HAVE_SYS_TYPES_H + /* Define if you have the header file. */ #undef HAVE_SYS_TIME_H diff --git a/ext/mbstring/oniguruma/enc/ascii.c b/ext/mbstring/oniguruma/enc/ascii.c index 44cc78f77c3d..64be21d7fff9 100644 --- a/ext/mbstring/oniguruma/enc/ascii.c +++ b/ext/mbstring/oniguruma/enc/ascii.c @@ -1,14 +1,36 @@ /********************************************************************** - ascii.c - Oniguruma (regular expression library) - - Copyright (C) 2003-2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2004 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regenc.h" static int -ascii_code_is_ctype(OnigCodePoint code, unsigned int ctype) +ascii_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 128) return ONIGENC_IS_ASCII_CODE_CTYPE(code, ctype); @@ -17,38 +39,29 @@ ascii_code_is_ctype(OnigCodePoint code, unsigned int ctype) } OnigEncodingType OnigEncodingASCII = { - { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 - }, + onigenc_single_byte_mbc_enc_len, "US-ASCII", /* name */ 1, /* max byte length */ - FALSE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_SB, /* ctype_support_level */ - TRUE, /* is continuous sb mb codepoint */ + 1, /* min byte length */ + ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE, + { + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ + }, + onigenc_is_mbc_newline_0x0a, onigenc_single_byte_mbc_to_code, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, - onigenc_ascii_mbc_to_lower, - onigenc_ascii_mbc_is_case_ambig, - ascii_code_is_ctype, - onigenc_nothing_get_ctype_code_range, + onigenc_ascii_mbc_to_normalize, + onigenc_ascii_is_mbc_ambiguous, + onigenc_ascii_get_all_pair_ambig_codes, + onigenc_nothing_get_all_comp_ambig_codes, + ascii_is_code_ctype, + onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, - onigenc_single_byte_is_allowed_reverse_match, - onigenc_nothing_get_all_fold_match_code, - onigenc_nothing_get_fold_match_info + onigenc_always_true_is_allowed_reverse_match }; diff --git a/ext/mbstring/oniguruma/enc/big5.c b/ext/mbstring/oniguruma/enc/big5.c index 8aad7f53547e..763872e963a0 100644 --- a/ext/mbstring/oniguruma/enc/big5.c +++ b/ext/mbstring/oniguruma/enc/big5.c @@ -1,14 +1,61 @@ /********************************************************************** - big5.c - Oniguruma (regular expression library) - - Copyright (C) 2003-2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regenc.h" +static int EncLen_BIG5[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 +}; + +static int +big5_mbc_enc_len(const UChar* p) +{ + return EncLen_BIG5[*p]; +} + static OnigCodePoint -big5_mbc_to_code(UChar* p, UChar* end) +big5_mbc_to_code(const UChar* p, const UChar* end) { return onigenc_mbn_mbc_to_code(ONIG_ENCODING_BIG5, p, end); } @@ -20,15 +67,23 @@ big5_code_to_mbc(OnigCodePoint code, UChar *buf) } static int -big5_mbc_to_lower(UChar* p, UChar* lower) +big5_mbc_to_normalize(OnigAmbigType flag, const UChar** pp, const UChar* end, + UChar* lower) +{ + return onigenc_mbn_mbc_to_normalize(ONIG_ENCODING_BIG5, flag, + pp, end, lower); +} + +static int +big5_is_mbc_ambiguous(OnigAmbigType flag, const UChar** pp, const UChar* end) { - return onigenc_mbn_mbc_to_lower(ONIG_ENCODING_BIG5, p, lower); + return onigenc_mbn_is_mbc_ambiguous(ONIG_ENCODING_BIG5, flag, pp, end); } static int -big5_code_is_ctype(OnigCodePoint code, unsigned int ctype) +big5_is_code_ctype(OnigCodePoint code, unsigned int ctype) { - return onigenc_mb2_code_is_ctype(ONIG_ENCODING_BIG5, code, ctype); + return onigenc_mb2_is_code_ctype(ONIG_ENCODING_BIG5, code, ctype); } static const char BIG5_CAN_BE_TRAIL_TABLE[256] = { @@ -50,16 +105,16 @@ static const char BIG5_CAN_BE_TRAIL_TABLE[256] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 }; -#define BIG5_ISMB_FIRST(byte) (OnigEncodingBIG5.len_table[byte] > 1) +#define BIG5_ISMB_FIRST(byte) (EncLen_BIG5[byte] > 1) #define BIG5_ISMB_TRAIL(byte) BIG5_CAN_BE_TRAIL_TABLE[(byte)] static UChar* -big5_left_adjust_char_head(UChar* start, UChar* s) +big5_left_adjust_char_head(const UChar* start, const UChar* s) { - UChar *p; + const UChar *p; int len; - if (s <= start) return s; + if (s <= start) return (UChar* )s; p = s; if (BIG5_ISMB_TRAIL(*p)) { @@ -70,53 +125,44 @@ big5_left_adjust_char_head(UChar* start, UChar* s) } } } - len = enc_len(ONIG_ENCODING_BIG5, *p); - if (p + len > s) return p; + len = enc_len(ONIG_ENCODING_BIG5, p); + if (p + len > s) return (UChar* )p; p += len; - return p + ((s - p) & ~1); + return (UChar* )(p + ((s - p) & ~1)); } static int -big5_is_allowed_reverse_match(UChar* s, UChar* end) +big5_is_allowed_reverse_match(const UChar* s, const UChar* end) { - UChar c = *s; + const UChar c = *s; return (BIG5_ISMB_TRAIL(c) ? FALSE : TRUE); } OnigEncodingType OnigEncodingBIG5 = { + big5_mbc_enc_len, + "Big5", /* name */ + 2, /* max enc length */ + 1, /* min enc length */ + ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE, { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ }, - "Big5", /* name */ - 2, /* max byte length */ - FALSE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_SB, /* ctype_support_level */ - FALSE, /* is continuous sb mb codepoint */ + onigenc_is_mbc_newline_0x0a, big5_mbc_to_code, onigenc_mb2_code_to_mbclen, big5_code_to_mbc, - big5_mbc_to_lower, - onigenc_mbn_mbc_is_case_ambig, - big5_code_is_ctype, - onigenc_nothing_get_ctype_code_range, + big5_mbc_to_normalize, + big5_is_mbc_ambiguous, + onigenc_ascii_get_all_pair_ambig_codes, + onigenc_nothing_get_all_comp_ambig_codes, + big5_is_code_ctype, + onigenc_not_support_get_ctype_code_range, big5_left_adjust_char_head, - big5_is_allowed_reverse_match, - onigenc_nothing_get_all_fold_match_code, - onigenc_nothing_get_fold_match_info + big5_is_allowed_reverse_match }; diff --git a/ext/mbstring/oniguruma/enc/euc_jp.c b/ext/mbstring/oniguruma/enc/euc_jp.c index 848016ba5a01..5f13e33eb4c0 100644 --- a/ext/mbstring/oniguruma/enc/euc_jp.c +++ b/ext/mbstring/oniguruma/enc/euc_jp.c @@ -1,23 +1,69 @@ /********************************************************************** - euc_jp.c - Oniguruma (regular expression library) - - Copyright (C) 2003-2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regenc.h" #define eucjp_islead(c) ((UChar )((c) - 0xa1) > 0xfe - 0xa1) +static int EncLen_EUCJP[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 +}; + +static int +eucjp_mbc_enc_len(const UChar* p) +{ + return EncLen_EUCJP[*p]; +} + static OnigCodePoint -eucjp_mbc_to_code(UChar* p, UChar* end) +eucjp_mbc_to_code(const UChar* p, const UChar* end) { int c, i, len; OnigCodePoint n; - c = *p++; - len = enc_len(ONIG_ENCODING_EUC_JP, c); - n = c; + len = enc_len(ONIG_ENCODING_EUC_JP, p); + n = (OnigCodePoint )*p++; if (len == 1) return n; for (i = 1; i < len; i++) { @@ -31,11 +77,13 @@ eucjp_mbc_to_code(UChar* p, UChar* end) static int eucjp_code_to_mbclen(OnigCodePoint code) { - if ((code & 0xff0000) != 0) return 3; + if (ONIGENC_IS_CODE_ASCII(code)) return 1; + else if ((code & 0xff0000) != 0) return 3; else if ((code & 0xff00) != 0) return 2; - else return 1; + else return 0; } +#if 0 static int eucjp_code_to_mbc_first(OnigCodePoint code) { @@ -43,27 +91,16 @@ eucjp_code_to_mbc_first(OnigCodePoint code) if ((code & 0xff0000) != 0) { first = (code >> 16) & 0xff; - /* - if (enc_len(ONIG_ENCODING_EUC_JP, first) != 3) - return ONIGERR_INVALID_WIDE_CHAR_VALUE; - */ } else if ((code & 0xff00) != 0) { first = (code >> 8) & 0xff; - /* - if (enc_len(ONIG_ENCODING_EUC_JP, first) != 2) - return ONIGERR_INVALID_WIDE_CHAR_VALUE; - */ } else { - /* - if (enc_len(ONIG_ENCODING_EUC_JP, code) != 1) - return ONIGERR_INVALID_WIDE_CHAR_VALUE; - */ return (int )code; } return first; } +#endif static int eucjp_code_to_mbc(OnigCodePoint code, UChar *buf) @@ -75,44 +112,57 @@ eucjp_code_to_mbc(OnigCodePoint code, UChar *buf) *p++ = (UChar )(code & 0xff); #if 1 - if (enc_len(ONIG_ENCODING_EUC_JP, buf[0]) != (p - buf)) - return ONIGERR_INVALID_WIDE_CHAR_VALUE; + if (enc_len(ONIG_ENCODING_EUC_JP, buf) != (p - buf)) + return ONIGENCERR_INVALID_WIDE_CHAR_VALUE; #endif return p - buf; } static int -eucjp_mbc_to_lower(UChar* p, UChar* lower) +eucjp_mbc_to_normalize(OnigAmbigType flag, + const UChar** pp, const UChar* end, UChar* lower) { int len; + const UChar* p = *pp; if (ONIGENC_IS_MBC_ASCII(p)) { - *lower = ONIGENC_ASCII_CODE_TO_LOWER_CASE(*p); + if ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0) { + *lower = ONIGENC_ASCII_CODE_TO_LOWER_CASE(*p); + } + else { + *lower = *p; + } + + (*pp)++; return 1; } else { - len = enc_len(ONIG_ENCODING_EUC_JP, *p); + len = enc_len(ONIG_ENCODING_EUC_JP, p); if (lower != p) { - /* memcpy(lower, p, len); */ int i; for (i = 0; i < len; i++) { *lower++ = *p++; } } + (*pp) += len; return len; /* return byte length of converted char to lower */ } } static int -eucjp_code_is_ctype(OnigCodePoint code, unsigned int ctype) +eucjp_is_mbc_ambiguous(OnigAmbigType flag, const UChar** pp, const UChar* end) +{ + return onigenc_mbn_is_mbc_ambiguous(ONIG_ENCODING_EUC_JP, flag, pp, end); +} + +static int +eucjp_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if ((ctype & ONIGENC_CTYPE_WORD) != 0) { if (code < 128) return ONIGENC_IS_ASCII_CODE_CTYPE(code, ctype); - else { - int first = eucjp_code_to_mbc_first(code); - return (enc_len(ONIG_ENCODING_EUC_JP, first) > 1 ? TRUE : FALSE); - } + else + return (eucjp_code_to_mbclen(code) > 1 ? TRUE : FALSE); ctype &= ~ONIGENC_CTYPE_WORD; if (ctype == 0) return FALSE; @@ -125,28 +175,28 @@ eucjp_code_is_ctype(OnigCodePoint code, unsigned int ctype) } static UChar* -eucjp_left_adjust_char_head(UChar* start, UChar* s) +eucjp_left_adjust_char_head(const UChar* start, const UChar* s) { - /* Assumed in this encoding, - mb-trail bytes don't mix with single bytes. + /* In this encoding + mb-trail bytes doesn't mix with single bytes. */ - UChar *p; + const UChar *p; int len; - if (s <= start) return s; + if (s <= start) return (UChar* )s; p = s; while (!eucjp_islead(*p) && p > start) p--; - len = enc_len(ONIG_ENCODING_EUC_JP, *p); - if (p + len > s) return p; + len = enc_len(ONIG_ENCODING_EUC_JP, p); + if (p + len > s) return (UChar* )p; p += len; - return p + ((s - p) & ~1); + return (UChar* )(p + ((s - p) & ~1)); } static int -eucjp_is_allowed_reverse_match(UChar* s, UChar* end) +eucjp_is_allowed_reverse_match(const UChar* s, const UChar* end) { - UChar c = *s; + const UChar c = *s; if (c <= 0x7e || c == 0x8e || c == 0x8f) return TRUE; else @@ -154,38 +204,29 @@ eucjp_is_allowed_reverse_match(UChar* s, UChar* end) } OnigEncodingType OnigEncodingEUC_JP = { + eucjp_mbc_enc_len, + "EUC-JP", /* name */ + 3, /* max enc length */ + 1, /* min enc length */ + ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE, { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ }, - "EUC-JP", /* name */ - 3, /* max byte length */ - FALSE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_SB, /* ctype_support_level */ - FALSE, /* is continuous sb mb codepoint */ + onigenc_is_mbc_newline_0x0a, eucjp_mbc_to_code, eucjp_code_to_mbclen, eucjp_code_to_mbc, - eucjp_mbc_to_lower, - onigenc_mbn_mbc_is_case_ambig, - eucjp_code_is_ctype, - onigenc_nothing_get_ctype_code_range, + eucjp_mbc_to_normalize, + eucjp_is_mbc_ambiguous, + onigenc_ascii_get_all_pair_ambig_codes, + onigenc_nothing_get_all_comp_ambig_codes, + eucjp_is_code_ctype, + onigenc_not_support_get_ctype_code_range, eucjp_left_adjust_char_head, - eucjp_is_allowed_reverse_match, - onigenc_nothing_get_all_fold_match_code, - onigenc_nothing_get_fold_match_info + eucjp_is_allowed_reverse_match }; diff --git a/ext/mbstring/oniguruma/enc/euc_kr.c b/ext/mbstring/oniguruma/enc/euc_kr.c index 1a0fc996dcdf..c1e83b7e6602 100644 --- a/ext/mbstring/oniguruma/enc/euc_kr.c +++ b/ext/mbstring/oniguruma/enc/euc_kr.c @@ -1,14 +1,61 @@ /********************************************************************** - euc_kr.c - Oniguruma (regular expression library) - - Copyright (C) 2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regenc.h" +static int EncLen_EUCKR[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 +}; + +static int +euckr_mbc_enc_len(const UChar* p) +{ + return EncLen_EUCKR[*p]; +} + static OnigCodePoint -euckr_mbc_to_code(UChar* p, UChar* end) +euckr_mbc_to_code(const UChar* p, const UChar* end) { return onigenc_mbn_mbc_to_code(ONIG_ENCODING_EUC_KR, p, end); } @@ -20,117 +67,107 @@ euckr_code_to_mbc(OnigCodePoint code, UChar *buf) } static int -euckr_mbc_to_lower(UChar* p, UChar* lower) +euckr_mbc_to_normalize(OnigAmbigType flag, const UChar** pp, const UChar* end, + UChar* lower) +{ + return onigenc_mbn_mbc_to_normalize(ONIG_ENCODING_EUC_KR, flag, + pp, end, lower); +} + +static int +euckr_is_mbc_ambiguous(OnigAmbigType flag, const UChar** pp, const UChar* end) { - return onigenc_mbn_mbc_to_lower(ONIG_ENCODING_EUC_KR, p, lower); + return onigenc_mbn_is_mbc_ambiguous(ONIG_ENCODING_EUC_KR, flag, pp, end); } static int -euckr_code_is_ctype(OnigCodePoint code, unsigned int ctype) +euckr_is_code_ctype(OnigCodePoint code, unsigned int ctype) { - return onigenc_mb2_code_is_ctype(ONIG_ENCODING_EUC_KR, code, ctype); + return onigenc_mb2_is_code_ctype(ONIG_ENCODING_EUC_KR, code, ctype); } #define euckr_islead(c) ((c) < 0xa1 || (c) == 0xff) static UChar* -euckr_left_adjust_char_head(UChar* start, UChar* s) +euckr_left_adjust_char_head(const UChar* start, const UChar* s) { /* Assumed in this encoding, mb-trail bytes don't mix with single bytes. */ - UChar *p; + const UChar *p; int len; - if (s <= start) return s; + if (s <= start) return (UChar* )s; p = s; while (!euckr_islead(*p) && p > start) p--; - len = enc_len(ONIG_ENCODING_EUC_KR, *p); - if (p + len > s) return p; + len = enc_len(ONIG_ENCODING_EUC_KR, p); + if (p + len > s) return (UChar* )p; p += len; - return p + ((s - p) & ~1); + return (UChar* )(p + ((s - p) & ~1)); } static int -euckr_is_allowed_reverse_match(UChar* s, UChar* end) +euckr_is_allowed_reverse_match(const UChar* s, const UChar* end) { - UChar c = *s; + const UChar c = *s; if (c <= 0x7e) return TRUE; else return FALSE; } OnigEncodingType OnigEncodingEUC_KR = { + euckr_mbc_enc_len, + "EUC-KR", /* name */ + 2, /* max enc length */ + 1, /* min enc length */ + ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE, { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ }, - "EUC-KR", /* name */ - 2, /* max byte length */ - FALSE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_SB, /* ctype_support_level */ - FALSE, /* is continuous sb mb codepoint */ + onigenc_is_mbc_newline_0x0a, euckr_mbc_to_code, onigenc_mb2_code_to_mbclen, euckr_code_to_mbc, - euckr_mbc_to_lower, - onigenc_mbn_mbc_is_case_ambig, - euckr_code_is_ctype, - onigenc_nothing_get_ctype_code_range, + euckr_mbc_to_normalize, + euckr_is_mbc_ambiguous, + onigenc_ascii_get_all_pair_ambig_codes, + onigenc_nothing_get_all_comp_ambig_codes, + euckr_is_code_ctype, + onigenc_not_support_get_ctype_code_range, euckr_left_adjust_char_head, - euckr_is_allowed_reverse_match, - onigenc_nothing_get_all_fold_match_code, - onigenc_nothing_get_fold_match_info + euckr_is_allowed_reverse_match }; /* Same with OnigEncodingEUC_KR except the name */ OnigEncodingType OnigEncodingEUC_CN = { + euckr_mbc_enc_len, + "EUC-CN", /* name */ + 2, /* max enc length */ + 1, /* min enc length */ + ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE, { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ }, - "EUC-CN", /* name */ - 2, /* max byte length */ - FALSE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_SB, /* ctype_support_level */ - FALSE, /* is continuous sb mb codepoint */ + onigenc_is_mbc_newline_0x0a, euckr_mbc_to_code, onigenc_mb2_code_to_mbclen, euckr_code_to_mbc, - euckr_mbc_to_lower, - onigenc_mbn_mbc_is_case_ambig, - euckr_code_is_ctype, - onigenc_nothing_get_ctype_code_range, + euckr_mbc_to_normalize, + euckr_is_mbc_ambiguous, + onigenc_ascii_get_all_pair_ambig_codes, + onigenc_nothing_get_all_comp_ambig_codes, + euckr_is_code_ctype, + onigenc_not_support_get_ctype_code_range, euckr_left_adjust_char_head, - euckr_is_allowed_reverse_match, - onigenc_nothing_get_all_fold_match_code, - onigenc_nothing_get_fold_match_info + euckr_is_allowed_reverse_match }; diff --git a/ext/mbstring/oniguruma/enc/euc_tw.c b/ext/mbstring/oniguruma/enc/euc_tw.c index b39a9a5b7ac6..4e5851a45158 100644 --- a/ext/mbstring/oniguruma/enc/euc_tw.c +++ b/ext/mbstring/oniguruma/enc/euc_tw.c @@ -1,14 +1,61 @@ /********************************************************************** - euc_tw.c - Oniguruma (regular expression library) - - Copyright (C) 2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regenc.h" +static int EncLen_EUCTW[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 +}; + +static int +euctw_mbc_enc_len(const UChar* p) +{ + return EncLen_EUCTW[*p]; +} + static OnigCodePoint -euctw_mbc_to_code(UChar* p, UChar* end) +euctw_mbc_to_code(const UChar* p, const UChar* end) { return onigenc_mbn_mbc_to_code(ONIG_ENCODING_EUC_TW, p, end); } @@ -20,79 +67,78 @@ euctw_code_to_mbc(OnigCodePoint code, UChar *buf) } static int -euctw_mbc_to_lower(UChar* p, UChar* lower) +euctw_mbc_to_normalize(OnigAmbigType flag, const UChar** pp, const UChar* end, + UChar* lower) +{ + return onigenc_mbn_mbc_to_normalize(ONIG_ENCODING_EUC_TW, flag, + pp, end, lower); +} + +static int +euctw_is_mbc_ambiguous(OnigAmbigType flag, const UChar** pp, const UChar* end) { - return onigenc_mbn_mbc_to_lower(ONIG_ENCODING_EUC_TW, p, lower); + return onigenc_mbn_is_mbc_ambiguous(ONIG_ENCODING_EUC_TW, flag, pp, end); } static int -euctw_code_is_ctype(OnigCodePoint code, unsigned int ctype) +euctw_is_code_ctype(OnigCodePoint code, unsigned int ctype) { - return onigenc_mb4_code_is_ctype(ONIG_ENCODING_EUC_TW, code, ctype); + return onigenc_mb4_is_code_ctype(ONIG_ENCODING_EUC_TW, code, ctype); } #define euctw_islead(c) (((c) < 0xa1 && (c) != 0x8e) || (c) == 0xff) static UChar* -euctw_left_adjust_char_head(UChar* start, UChar* s) +euctw_left_adjust_char_head(const UChar* start, const UChar* s) { /* Assumed in this encoding, mb-trail bytes don't mix with single bytes. */ - UChar *p; + const UChar *p; int len; - if (s <= start) return s; + if (s <= start) return (UChar* )s; p = s; while (!euctw_islead(*p) && p > start) p--; - len = enc_len(ONIG_ENCODING_EUC_TW, *p); - if (p + len > s) return p; + len = enc_len(ONIG_ENCODING_EUC_TW, p); + if (p + len > s) return (UChar* )p; p += len; - return p + ((s - p) & ~1); + return (UChar* )(p + ((s - p) & ~1)); } static int -euctw_is_allowed_reverse_match(UChar* s, UChar* end) +euctw_is_allowed_reverse_match(const UChar* s, const UChar* end) { - UChar c = *s; + const UChar c = *s; if (c <= 0x7e) return TRUE; else return FALSE; } OnigEncodingType OnigEncodingEUC_TW = { + euctw_mbc_enc_len, + "EUC-TW", /* name */ + 4, /* max enc length */ + 1, /* min enc length */ + ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE, { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ }, - "EUC-TW", /* name */ - 4, /* max byte length */ - FALSE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_SB, /* ctype_support_level */ - FALSE, /* is continuous sb mb codepoint */ + onigenc_is_mbc_newline_0x0a, euctw_mbc_to_code, onigenc_mb4_code_to_mbclen, euctw_code_to_mbc, - euctw_mbc_to_lower, - onigenc_mbn_mbc_is_case_ambig, - euctw_code_is_ctype, - onigenc_nothing_get_ctype_code_range, + euctw_mbc_to_normalize, + euctw_is_mbc_ambiguous, + onigenc_ascii_get_all_pair_ambig_codes, + onigenc_nothing_get_all_comp_ambig_codes, + euctw_is_code_ctype, + onigenc_not_support_get_ctype_code_range, euctw_left_adjust_char_head, - euctw_is_allowed_reverse_match, - onigenc_nothing_get_all_fold_match_code, - onigenc_nothing_get_fold_match_info + euctw_is_allowed_reverse_match }; diff --git a/ext/mbstring/oniguruma/enc/iso8859_1.c b/ext/mbstring/oniguruma/enc/iso8859_1.c index 662f0e2c0794..53ad52ee13d6 100644 --- a/ext/mbstring/oniguruma/enc/iso8859_1.c +++ b/ext/mbstring/oniguruma/enc/iso8859_1.c @@ -1,112 +1,145 @@ /********************************************************************** - iso8859_1.c - Oniguruma (regular expression library) - - Copyright (C) 2003-2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regenc.h" -#define ENC_ISO_8859_1_TO_LOWER_CASE(c) EncISO_8859_1_ToLowerCaseTable[c] #define ENC_IS_ISO_8859_1_CTYPE(code,ctype) \ ((EncISO_8859_1_CtypeTable[code] & ctype) != 0) -static UChar EncISO_8859_1_ToLowerCaseTable[256] = { - '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', - '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', - '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', - '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', - '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', - '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', - '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', - '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', - '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', - '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', - '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', - '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', - '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', - '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', - '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', - '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', - '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', - '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', - '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', - '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', - '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', - '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', - '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', - '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', - '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', - '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', - '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\327', - '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\337', - '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', - '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', - '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', - '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377' -}; - static unsigned short EncISO_8859_1_CtypeTable[256] = { - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1106, 0x1104, 0x1104, 0x1104, 0x1104, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1142, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, - 0x1c58, 0x1c58, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x18d0, - 0x10d0, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x1004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0142, 0x00d0, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, - 0x0050, 0x0050, 0x0871, 0x00d0, 0x0050, 0x00d0, 0x0050, 0x0050, - 0x0050, 0x0050, 0x0850, 0x0850, 0x0050, 0x0871, 0x0050, 0x00d0, - 0x0050, 0x0850, 0x0871, 0x00d0, 0x0850, 0x0850, 0x0850, 0x00d0, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0050, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0050, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871 + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x220c, 0x2209, 0x2208, 0x2208, 0x2208, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2284, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, + 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, + 0x38b0, 0x38b0, 0x21a0, 0x21a0, 0x20a0, 0x20a0, 0x20a0, 0x21a0, + 0x21a0, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x31a0, + 0x20a0, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x21a0, 0x20a0, 0x21a0, 0x20a0, 0x2008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0284, 0x01a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, + 0x00a0, 0x00a0, 0x10e2, 0x01a0, 0x00a0, 0x01a0, 0x00a0, 0x00a0, + 0x00a0, 0x00a0, 0x10a0, 0x10a0, 0x00a0, 0x10e2, 0x00a0, 0x01a0, + 0x00a0, 0x10a0, 0x10e2, 0x01a0, 0x10a0, 0x10a0, 0x10a0, 0x01a0, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x00a0, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x00a0, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2 }; static int -iso_8859_1_mbc_to_lower(UChar* p, UChar* lower) +iso_8859_1_mbc_to_normalize(OnigAmbigType flag, const UChar** pp, const UChar* end, UChar* lower) { - *lower = ENC_ISO_8859_1_TO_LOWER_CASE(*p); + const UChar* p = *pp; + + if (end > p + 1 && (flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + if ((*p == 's' && *(p+1) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+1) == 'S'))) { + *lower = 0xdf; + (*pp) += 2; + return 1; + } + } + + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + *lower = ONIGENC_ISO_8859_1_TO_LOWER_CASE(*p); + } + else { + *lower = *p; + } + (*pp)++; return 1; /* return byte length of converted char to lower */ } static int -iso_8859_1_mbc_is_case_ambig(UChar* p) +iso_8859_1_is_mbc_ambiguous(OnigAmbigType flag, + const UChar** pp, const UChar* end) { - int v = (EncISO_8859_1_CtypeTable[*p] & - (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); + const UChar* p = *pp; - if ((v | ONIGENC_CTYPE_LOWER) != 0) { - /* 0xdf, 0xaa, 0xb5, 0xba are lower case letter, but can't convert. */ - if (*p == 0xdf || (*p >= 0xaa && *p <= 0xba)) - return FALSE; - else + if ((flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + if (end > p + 1) { + if ((*p == 's' && *(p+1) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+1) == 'S'))) { + (*pp) += 2; + return TRUE; + } + } + + if (*p == 0xdf) { + (*pp)++; return TRUE; + } } - return (v != 0 ? TRUE : FALSE); + (*pp)++; + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + int v = (EncISO_8859_1_CtypeTable[*p] & + (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); + + if ((v | ONIGENC_CTYPE_LOWER) != 0) { + /* 0xdf, 0xaa, 0xb5, 0xba are lower case letter, but can't convert. */ + if (*p == 0xdf || (*p >= 0xaa && *p <= 0xba)) + return FALSE; + else + return TRUE; + } + + return (v != 0 ? TRUE : FALSE); + } + return FALSE; } static int -iso_8859_1_code_is_ctype(OnigCodePoint code, unsigned int ctype) +iso_8859_1_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_1_CTYPE(code, ctype); @@ -115,38 +148,31 @@ iso_8859_1_code_is_ctype(OnigCodePoint code, unsigned int ctype) } OnigEncodingType OnigEncodingISO_8859_1 = { + onigenc_single_byte_mbc_enc_len, + "ISO-8859-1", /* name */ + 1, /* max enc length */ + 1, /* min enc length */ + (ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_COMPOUND), { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ }, - "ISO-8859-1", /* name */ - 1, /* max byte length */ - TRUE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_SB, /* ctype_support_level */ - TRUE, /* is continuous sb mb codepoint */ + onigenc_is_mbc_newline_0x0a, onigenc_single_byte_mbc_to_code, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, - iso_8859_1_mbc_to_lower, - iso_8859_1_mbc_is_case_ambig, - iso_8859_1_code_is_ctype, - onigenc_nothing_get_ctype_code_range, + iso_8859_1_mbc_to_normalize, + iso_8859_1_is_mbc_ambiguous, + onigenc_iso_8859_1_get_all_pair_ambig_codes, + onigenc_ess_tsett_get_all_comp_ambig_codes, + iso_8859_1_is_code_ctype, + onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, - onigenc_single_byte_is_allowed_reverse_match, - onigenc_get_all_fold_match_code_ss_0xdf, - onigenc_get_fold_match_info_ss_0xdf + onigenc_always_true_is_allowed_reverse_match }; diff --git a/ext/mbstring/oniguruma/enc/iso8859_10.c b/ext/mbstring/oniguruma/enc/iso8859_10.c index ac493037144b..a9331cebf35e 100644 --- a/ext/mbstring/oniguruma/enc/iso8859_10.c +++ b/ext/mbstring/oniguruma/enc/iso8859_10.c @@ -1,10 +1,32 @@ /********************************************************************** - iso8859_10.c - Oniguruma (regular expression library) - - Copyright (C) 2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regenc.h" #define ENC_ISO_8859_10_TO_LOWER_CASE(c) EncISO_8859_10_ToLowerCaseTable[c] @@ -47,69 +69,114 @@ static UChar EncISO_8859_10_ToLowerCaseTable[256] = { }; static unsigned short EncISO_8859_10_CtypeTable[256] = { - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1106, 0x1104, 0x1104, 0x1104, 0x1104, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1142, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, - 0x1c58, 0x1c58, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x18d0, - 0x10d0, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x1004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0142, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0050, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x00d0, 0x0a51, 0x0a51, - 0x0050, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x00d0, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x00d0, 0x0871, 0x0871, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871 + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x220c, 0x2209, 0x2208, 0x2208, 0x2208, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2284, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, + 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, + 0x38b0, 0x38b0, 0x21a0, 0x21a0, 0x20a0, 0x20a0, 0x20a0, 0x21a0, + 0x21a0, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x31a0, + 0x20a0, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x21a0, 0x20a0, 0x21a0, 0x20a0, 0x2008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0284, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x00a0, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x01a0, 0x14a2, 0x14a2, + 0x00a0, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x01a0, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x01a0, 0x10e2, 0x10e2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2 }; static int -iso_8859_10_mbc_to_lower(UChar* p, UChar* lower) +iso_8859_10_mbc_to_normalize(OnigAmbigType flag, + const UChar** pp, const UChar* end, UChar* lower) { - *lower = ENC_ISO_8859_10_TO_LOWER_CASE(*p); + const UChar* p = *pp; + + if (end > p + 1 && (flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + if ((*p == 's' && *(p+1) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+1) == 'S'))) { + *lower = 0xdf; + (*pp) += 2; + return 1; + } + } + + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + *lower = ENC_ISO_8859_10_TO_LOWER_CASE(*p); + } + else { + *lower = *p; + } + (*pp)++; return 1; /* return byte length of converted char to lower */ } static int -iso_8859_10_mbc_is_case_ambig(UChar* p) +iso_8859_10_is_mbc_ambiguous(OnigAmbigType flag, + const UChar** pp, const UChar* end) { - int v = (EncISO_8859_10_CtypeTable[*p] & - (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); - - if ((v | ONIGENC_CTYPE_LOWER) != 0) { - /* 0xdf is lower case letter, but can't convert. */ - if (*p == 0xdf) - return FALSE; - else + const UChar* p = *pp; + + if ((flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + if (end > p + 1) { + if ((*p == 's' && *(p+1) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+1) == 'S'))) { + (*pp) += 2; + return TRUE; + } + } + + if (*p == 0xdf) { + (*pp)++; return TRUE; - } - else if (v != 0) { - return TRUE; + } } + (*pp)++; + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + int v = (EncISO_8859_10_CtypeTable[*p] & + (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); + + if ((v | ONIGENC_CTYPE_LOWER) != 0) { + /* 0xdf is lower case letter, but can't convert. */ + if (*p == 0xdf) + return FALSE; + else + return TRUE; + } + + return (v != 0 ? TRUE : FALSE); + } return FALSE; } static int -iso_8859_10_code_is_ctype(OnigCodePoint code, unsigned int ctype) +iso_8859_10_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_10_CTYPE(code, ctype); @@ -117,39 +184,144 @@ iso_8859_10_code_is_ctype(OnigCodePoint code, unsigned int ctype) return FALSE; } +static int +iso_8859_10_get_all_pair_ambig_codes(OnigAmbigType flag, + OnigPairAmbigCodes** ccs) +{ + static OnigPairAmbigCodes cc[] = { + { 0xa1, 0xb1 }, + { 0xa2, 0xb2 }, + { 0xa3, 0xb3 }, + { 0xa4, 0xb4 }, + { 0xa5, 0xb5 }, + { 0xa6, 0xb6 }, + { 0xa8, 0xb8 }, + { 0xa9, 0xb9 }, + { 0xaa, 0xba }, + { 0xab, 0xbb }, + { 0xac, 0xbc }, + { 0xae, 0xbe }, + { 0xaf, 0xbf }, + + { 0xb1, 0xa1 }, + { 0xb2, 0xa2 }, + { 0xb3, 0xa3 }, + { 0xb4, 0xa4 }, + { 0xb5, 0xa5 }, + { 0xb6, 0xa6 }, + { 0xb8, 0xa8 }, + { 0xb9, 0xa9 }, + { 0xba, 0xaa }, + { 0xbb, 0xab }, + { 0xbc, 0xac }, + { 0xbe, 0xae }, + { 0xbf, 0xaf }, + + { 0xc0, 0xe0 }, + { 0xc1, 0xe1 }, + { 0xc2, 0xe2 }, + { 0xc3, 0xe3 }, + { 0xc4, 0xe4 }, + { 0xc5, 0xe5 }, + { 0xc6, 0xe6 }, + { 0xc7, 0xe7 }, + { 0xc8, 0xe8 }, + { 0xc9, 0xe9 }, + { 0xca, 0xea }, + { 0xcb, 0xeb }, + { 0xcc, 0xec }, + { 0xcd, 0xed }, + { 0xce, 0xee }, + { 0xcf, 0xef }, + + { 0xd0, 0xf0 }, + { 0xd1, 0xf1 }, + { 0xd2, 0xf2 }, + { 0xd3, 0xf3 }, + { 0xd4, 0xf4 }, + { 0xd5, 0xf5 }, + { 0xd6, 0xf6 }, + { 0xd7, 0xf7 }, + { 0xd8, 0xf8 }, + { 0xd9, 0xf9 }, + { 0xda, 0xfa }, + { 0xdb, 0xfb }, + { 0xdc, 0xfc }, + { 0xdd, 0xfd }, + { 0xde, 0xfe }, + + { 0xe0, 0xc0 }, + { 0xe1, 0xc1 }, + { 0xe2, 0xc2 }, + { 0xe3, 0xc3 }, + { 0xe4, 0xc4 }, + { 0xe5, 0xc5 }, + { 0xe6, 0xc6 }, + { 0xe7, 0xc7 }, + { 0xe8, 0xc8 }, + { 0xe9, 0xc9 }, + { 0xea, 0xca }, + { 0xeb, 0xcb }, + { 0xec, 0xcc }, + { 0xed, 0xcd }, + { 0xee, 0xce }, + { 0xef, 0xcf }, + + { 0xf0, 0xd0 }, + { 0xf1, 0xd1 }, + { 0xf2, 0xd2 }, + { 0xf3, 0xd3 }, + { 0xf4, 0xd4 }, + { 0xf5, 0xd5 }, + { 0xf6, 0xd6 }, + { 0xf7, 0xd7 }, + { 0xf8, 0xd8 }, + { 0xf9, 0xd9 }, + { 0xfa, 0xda }, + { 0xfb, 0xdb }, + { 0xfc, 0xdc }, + { 0xfd, 0xdd }, + { 0xfe, 0xde } + }; + + if (flag == ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) { + *ccs = OnigAsciiPairAmbigCodes; + return 52; + } + if (flag == ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) { + *ccs = cc; + return sizeof(cc) / sizeof(OnigPairAmbigCodes); + } + else + return 0; +} + OnigEncodingType OnigEncodingISO_8859_10 = { + onigenc_single_byte_mbc_enc_len, + "ISO-8859-10", /* name */ + 1, /* max enc length */ + 1, /* min enc length */ + (ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_COMPOUND), { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ }, - "ISO-8859-10", /* name */ - 1, /* max byte length */ - TRUE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_SB, /* ctype_support_level */ - TRUE, /* is continuous sb mb codepoint */ + onigenc_is_mbc_newline_0x0a, onigenc_single_byte_mbc_to_code, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, - iso_8859_10_mbc_to_lower, - iso_8859_10_mbc_is_case_ambig, - iso_8859_10_code_is_ctype, - onigenc_nothing_get_ctype_code_range, + iso_8859_10_mbc_to_normalize, + iso_8859_10_is_mbc_ambiguous, + iso_8859_10_get_all_pair_ambig_codes, + onigenc_ess_tsett_get_all_comp_ambig_codes, + iso_8859_10_is_code_ctype, + onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, - onigenc_single_byte_is_allowed_reverse_match, - onigenc_get_all_fold_match_code_ss_0xdf, - onigenc_get_fold_match_info_ss_0xdf + onigenc_always_true_is_allowed_reverse_match }; diff --git a/ext/mbstring/oniguruma/enc/iso8859_11.c b/ext/mbstring/oniguruma/enc/iso8859_11.c index ebe81d325fcc..bb1098807ac2 100644 --- a/ext/mbstring/oniguruma/enc/iso8859_11.c +++ b/ext/mbstring/oniguruma/enc/iso8859_11.c @@ -1,52 +1,74 @@ /********************************************************************** - iso8859_11.c - Oniguruma (regular expression library) - - Copyright (C) 2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2004 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regenc.h" #define ENC_IS_ISO_8859_11_CTYPE(code,ctype) \ ((EncISO_8859_11_CtypeTable[code] & ctype) != 0) static unsigned short EncISO_8859_11_CtypeTable[256] = { - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1106, 0x1104, 0x1104, 0x1104, 0x1104, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1142, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, - 0x1c58, 0x1c58, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x18d0, - 0x10d0, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x1004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0142, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, - 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, - 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, - 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, - 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, - 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, - 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, - 0x0851, 0x0851, 0x0851, 0x0000, 0x0000, 0x0000, 0x0000, 0x0851, - 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, - 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, - 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, - 0x0851, 0x0851, 0x0851, 0x0851, 0x0000, 0x0000, 0x0000, 0x0000 + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x220c, 0x2209, 0x2208, 0x2208, 0x2208, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2284, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, + 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, + 0x38b0, 0x38b0, 0x21a0, 0x21a0, 0x20a0, 0x20a0, 0x20a0, 0x21a0, + 0x21a0, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x31a0, + 0x20a0, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x21a0, 0x20a0, 0x21a0, 0x20a0, 0x2008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0284, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, + 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, + 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, + 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, + 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, + 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, + 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, + 0x10a2, 0x10a2, 0x10a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x10a2, + 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, + 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, + 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, + 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x0000, 0x0000, 0x0000, 0x0000 }; static int -iso_8859_11_code_is_ctype(OnigCodePoint code, unsigned int ctype) +iso_8859_11_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_11_CTYPE(code, ctype); @@ -55,38 +77,29 @@ iso_8859_11_code_is_ctype(OnigCodePoint code, unsigned int ctype) } OnigEncodingType OnigEncodingISO_8859_11 = { + onigenc_single_byte_mbc_enc_len, + "ISO-8859-11", /* name */ + 1, /* max enc length */ + 1, /* min enc length */ + ( ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE ), { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ }, - "ISO-8859-11", /* name */ - 1, /* max byte length */ - FALSE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_SB, /* ctype_support_level */ - TRUE, /* is continuous sb mb codepoint */ + onigenc_is_mbc_newline_0x0a, onigenc_single_byte_mbc_to_code, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, - onigenc_ascii_mbc_to_lower, - onigenc_ascii_mbc_is_case_ambig, - iso_8859_11_code_is_ctype, - onigenc_nothing_get_ctype_code_range, + onigenc_ascii_mbc_to_normalize, + onigenc_ascii_is_mbc_ambiguous, + onigenc_ascii_get_all_pair_ambig_codes, + onigenc_nothing_get_all_comp_ambig_codes, + iso_8859_11_is_code_ctype, + onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, - onigenc_single_byte_is_allowed_reverse_match, - onigenc_nothing_get_all_fold_match_code, - onigenc_nothing_get_fold_match_info + onigenc_always_true_is_allowed_reverse_match }; diff --git a/ext/mbstring/oniguruma/enc/iso8859_13.c b/ext/mbstring/oniguruma/enc/iso8859_13.c index 8de7251d2f0b..827ca508e8b9 100644 --- a/ext/mbstring/oniguruma/enc/iso8859_13.c +++ b/ext/mbstring/oniguruma/enc/iso8859_13.c @@ -1,10 +1,32 @@ /********************************************************************** - iso8859_13.c - Oniguruma (regular expression library) - - Copyright (C) 2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regenc.h" #define ENC_ISO_8859_13_TO_LOWER_CASE(c) EncISO_8859_13_ToLowerCaseTable[c] @@ -47,69 +69,114 @@ static UChar EncISO_8859_13_ToLowerCaseTable[256] = { }; static unsigned short EncISO_8859_13_CtypeTable[256] = { - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1106, 0x1104, 0x1104, 0x1104, 0x1104, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1142, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, - 0x1c58, 0x1c58, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x18d0, - 0x10d0, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x1004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0142, 0x00d0, 0x0050, 0x0050, 0x0050, 0x00d0, 0x0050, 0x0050, - 0x0a51, 0x0050, 0x0a51, 0x00d0, 0x0050, 0x00d0, 0x0050, 0x0a51, - 0x0050, 0x0050, 0x0850, 0x0850, 0x00d0, 0x0871, 0x0050, 0x00d0, - 0x0871, 0x0850, 0x0871, 0x00d0, 0x0850, 0x0850, 0x0850, 0x0871, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0050, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0050, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x00d0 + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x220c, 0x2209, 0x2208, 0x2208, 0x2208, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2284, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, + 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, + 0x38b0, 0x38b0, 0x21a0, 0x21a0, 0x20a0, 0x20a0, 0x20a0, 0x21a0, + 0x21a0, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x31a0, + 0x20a0, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x21a0, 0x20a0, 0x21a0, 0x20a0, 0x2008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0284, 0x01a0, 0x00a0, 0x00a0, 0x00a0, 0x01a0, 0x00a0, 0x00a0, + 0x14a2, 0x00a0, 0x14a2, 0x01a0, 0x00a0, 0x01a0, 0x00a0, 0x14a2, + 0x00a0, 0x00a0, 0x10a0, 0x10a0, 0x01a0, 0x10e2, 0x00a0, 0x01a0, + 0x10e2, 0x10a0, 0x10e2, 0x01a0, 0x10a0, 0x10a0, 0x10a0, 0x10e2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x00a0, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x00a0, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x01a0 }; static int -iso_8859_13_mbc_to_lower(UChar* p, UChar* lower) +iso_8859_13_mbc_to_normalize(OnigAmbigType flag, + const UChar** pp, const UChar* end, UChar* lower) { - *lower = ENC_ISO_8859_13_TO_LOWER_CASE(*p); + const UChar* p = *pp; + + if (end > p + 1 && (flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + if ((*p == 's' && *(p+1) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+1) == 'S'))) { + *lower = 0xdf; + (*pp) += 2; + return 1; + } + } + + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + *lower = ENC_ISO_8859_13_TO_LOWER_CASE(*p); + } + else { + *lower = *p; + } + (*pp)++; return 1; /* return byte length of converted char to lower */ } static int -iso_8859_13_mbc_is_case_ambig(UChar* p) +iso_8859_13_is_mbc_ambiguous(OnigAmbigType flag, + const UChar** pp, const UChar* end) { - int v = (EncISO_8859_13_CtypeTable[*p] & - (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); - - if ((v | ONIGENC_CTYPE_LOWER) != 0) { - /* 0xdf is lower case letter, but can't convert. */ - if (*p == 0xdf || *p == 0xb5) - return FALSE; - else + const UChar* p = *pp; + + if ((flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + if (end > p + 1) { + if ((*p == 's' && *(p+1) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+1) == 'S'))) { + (*pp) += 2; + return TRUE; + } + } + + if (*p == 0xdf) { + (*pp)++; return TRUE; + } } - else if (v != 0) { - return TRUE; - } + (*pp)++; + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + int v = (EncISO_8859_13_CtypeTable[*p] & + (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); + + if ((v | ONIGENC_CTYPE_LOWER) != 0) { + /* 0xdf, 0xb5 are lower case letter, but can't convert. */ + if (*p == 0xdf || *p == 0xb5) + return FALSE; + else + return TRUE; + } + + return (v != 0 ? TRUE : FALSE); + } return FALSE; } static int -iso_8859_13_code_is_ctype(OnigCodePoint code, unsigned int ctype) +iso_8859_13_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_13_CTYPE(code, ctype); @@ -117,39 +184,114 @@ iso_8859_13_code_is_ctype(OnigCodePoint code, unsigned int ctype) return FALSE; } +static int +iso_8859_13_get_all_pair_ambig_codes(OnigAmbigType flag, + OnigPairAmbigCodes** ccs) +{ + static OnigPairAmbigCodes cc[] = { + { 0xc0, 0xe0 }, + { 0xc1, 0xe1 }, + { 0xc2, 0xe2 }, + { 0xc3, 0xe3 }, + { 0xc4, 0xe4 }, + { 0xc5, 0xe5 }, + { 0xc6, 0xe6 }, + { 0xc7, 0xe7 }, + { 0xc8, 0xe8 }, + { 0xc9, 0xe9 }, + { 0xca, 0xea }, + { 0xcb, 0xeb }, + { 0xcc, 0xec }, + { 0xcd, 0xed }, + { 0xce, 0xee }, + { 0xcf, 0xef }, + + { 0xd0, 0xf0 }, + { 0xd1, 0xf1 }, + { 0xd2, 0xf2 }, + { 0xd3, 0xf3 }, + { 0xd4, 0xf4 }, + { 0xd5, 0xf5 }, + { 0xd6, 0xf6 }, + { 0xd8, 0xf8 }, + { 0xd9, 0xf9 }, + { 0xda, 0xfa }, + { 0xdb, 0xfb }, + { 0xdc, 0xfc }, + { 0xdd, 0xfd }, + { 0xde, 0xfe }, + + { 0xe0, 0xc0 }, + { 0xe1, 0xc1 }, + { 0xe2, 0xc2 }, + { 0xe3, 0xc3 }, + { 0xe4, 0xc4 }, + { 0xe5, 0xc5 }, + { 0xe6, 0xc6 }, + { 0xe7, 0xc7 }, + { 0xe8, 0xc8 }, + { 0xe9, 0xc9 }, + { 0xea, 0xca }, + { 0xeb, 0xcb }, + { 0xec, 0xcc }, + { 0xed, 0xcd }, + { 0xee, 0xce }, + { 0xef, 0xcf }, + + { 0xf0, 0xd0 }, + { 0xf1, 0xd1 }, + { 0xf2, 0xd2 }, + { 0xf3, 0xd3 }, + { 0xf4, 0xd4 }, + { 0xf5, 0xd5 }, + { 0xf6, 0xd6 }, + { 0xf8, 0xd8 }, + { 0xf9, 0xd9 }, + { 0xfa, 0xda }, + { 0xfb, 0xdb }, + { 0xfc, 0xdc }, + { 0xfd, 0xdd }, + { 0xfe, 0xde } + }; + + if (flag == ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) { + *ccs = OnigAsciiPairAmbigCodes; + return 52; + } + if (flag == ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) { + *ccs = cc; + return sizeof(cc) / sizeof(OnigPairAmbigCodes); + } + else + return 0; +} + OnigEncodingType OnigEncodingISO_8859_13 = { + onigenc_single_byte_mbc_enc_len, + "ISO-8859-13", /* name */ + 1, /* max enc length */ + 1, /* min enc length */ + (ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_COMPOUND), { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ }, - "ISO-8859-13", /* name */ - 1, /* max byte length */ - TRUE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_SB, /* ctype_support_level */ - TRUE, /* is continuous sb mb codepoint */ + onigenc_is_mbc_newline_0x0a, onigenc_single_byte_mbc_to_code, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, - iso_8859_13_mbc_to_lower, - iso_8859_13_mbc_is_case_ambig, - iso_8859_13_code_is_ctype, - onigenc_nothing_get_ctype_code_range, + iso_8859_13_mbc_to_normalize, + iso_8859_13_is_mbc_ambiguous, + iso_8859_13_get_all_pair_ambig_codes, + onigenc_ess_tsett_get_all_comp_ambig_codes, + iso_8859_13_is_code_ctype, + onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, - onigenc_single_byte_is_allowed_reverse_match, - onigenc_get_all_fold_match_code_ss_0xdf, - onigenc_get_fold_match_info_ss_0xdf + onigenc_always_true_is_allowed_reverse_match }; diff --git a/ext/mbstring/oniguruma/enc/iso8859_14.c b/ext/mbstring/oniguruma/enc/iso8859_14.c index 333deeba3200..4fe5ab29d1ef 100644 --- a/ext/mbstring/oniguruma/enc/iso8859_14.c +++ b/ext/mbstring/oniguruma/enc/iso8859_14.c @@ -1,10 +1,32 @@ /********************************************************************** - iso8859_14.c - Oniguruma (regular expression library) - - Copyright (C) 2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regenc.h" #define ENC_ISO_8859_14_TO_LOWER_CASE(c) EncISO_8859_14_ToLowerCaseTable[c] @@ -47,69 +69,114 @@ static UChar EncISO_8859_14_ToLowerCaseTable[256] = { }; static unsigned short EncISO_8859_14_CtypeTable[256] = { - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1106, 0x1104, 0x1104, 0x1104, 0x1104, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1142, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, - 0x1c58, 0x1c58, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x18d0, - 0x10d0, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x1004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0142, 0x0a51, 0x0871, 0x0050, 0x0a51, 0x0871, 0x0a51, 0x0050, - 0x0a51, 0x0050, 0x0a51, 0x0871, 0x0a51, 0x00d0, 0x0050, 0x0a51, - 0x0a51, 0x0871, 0x0a51, 0x0871, 0x0a51, 0x0871, 0x0050, 0x0a51, - 0x0871, 0x0871, 0x0871, 0x0a51, 0x0871, 0x0a51, 0x0871, 0x0871, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871 + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x220c, 0x2209, 0x2208, 0x2208, 0x2208, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2284, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, + 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, + 0x38b0, 0x38b0, 0x21a0, 0x21a0, 0x20a0, 0x20a0, 0x20a0, 0x21a0, + 0x21a0, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x31a0, + 0x20a0, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x21a0, 0x20a0, 0x21a0, 0x20a0, 0x2008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0284, 0x14a2, 0x10e2, 0x00a0, 0x14a2, 0x10e2, 0x14a2, 0x00a0, + 0x14a2, 0x00a0, 0x14a2, 0x10e2, 0x14a2, 0x01a0, 0x00a0, 0x14a2, + 0x14a2, 0x10e2, 0x14a2, 0x10e2, 0x14a2, 0x10e2, 0x00a0, 0x14a2, + 0x10e2, 0x10e2, 0x10e2, 0x14a2, 0x10e2, 0x14a2, 0x10e2, 0x10e2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2 }; static int -iso_8859_14_mbc_to_lower(UChar* p, UChar* lower) +iso_8859_14_mbc_to_normalize(OnigAmbigType flag, + const UChar** pp, const UChar* end, UChar* lower) { - *lower = ENC_ISO_8859_14_TO_LOWER_CASE(*p); + const UChar* p = *pp; + + if (end > p + 1 && (flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + if ((*p == 's' && *(p+1) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+1) == 'S'))) { + *lower = 0xdf; + (*pp) += 2; + return 1; + } + } + + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + *lower = ENC_ISO_8859_14_TO_LOWER_CASE(*p); + } + else { + *lower = *p; + } + (*pp)++; return 1; /* return byte length of converted char to lower */ } static int -iso_8859_14_mbc_is_case_ambig(UChar* p) +iso_8859_14_is_mbc_ambiguous(OnigAmbigType flag, + const UChar** pp, const UChar* end) { - int v = (EncISO_8859_14_CtypeTable[*p] & - (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); - - if ((v | ONIGENC_CTYPE_LOWER) != 0) { - /* 0xdf is lower case letter, but can't convert. */ - if (*p == 0xdf) - return FALSE; - else + const UChar* p = *pp; + + if ((flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + if (end > p + 1) { + if ((*p == 's' && *(p+1) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+1) == 'S'))) { + (*pp) += 2; + return TRUE; + } + } + + if (*p == 0xdf) { + (*pp)++; return TRUE; + } } - else if (v != 0) { - return TRUE; - } + (*pp)++; + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + int v = (EncISO_8859_14_CtypeTable[*p] & + (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); + + if ((v | ONIGENC_CTYPE_LOWER) != 0) { + /* 0xdf is lower case letter, but can't convert. */ + if (*p == 0xdf) + return FALSE; + else + return TRUE; + } + + return (v != 0 ? TRUE : FALSE); + } return FALSE; } static int -iso_8859_14_code_is_ctype(OnigCodePoint code, unsigned int ctype) +iso_8859_14_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_14_CTYPE(code, ctype); @@ -117,39 +184,144 @@ iso_8859_14_code_is_ctype(OnigCodePoint code, unsigned int ctype) return FALSE; } +static int +iso_8859_14_get_all_pair_ambig_codes(OnigAmbigType flag, + OnigPairAmbigCodes** ccs) +{ + static OnigPairAmbigCodes cc[] = { + { 0xa1, 0xa2 }, + { 0xa2, 0xa1 }, + { 0xa4, 0xa5 }, + { 0xa5, 0xa4 }, + { 0xa6, 0xab }, + { 0xa8, 0xb8 }, + { 0xaa, 0xba }, + { 0xab, 0xa6 }, + { 0xac, 0xbc }, + { 0xaf, 0xff }, + + { 0xb0, 0xb1 }, + { 0xb1, 0xb0 }, + { 0xb2, 0xb3 }, + { 0xb3, 0xb2 }, + { 0xb4, 0xb5 }, + { 0xb5, 0xb4 }, + { 0xb7, 0xb9 }, + { 0xb8, 0xa8 }, + { 0xb9, 0xb7 }, + { 0xba, 0xaa }, + { 0xbb, 0xbf }, + { 0xbc, 0xac }, + { 0xbd, 0xbe }, + { 0xbe, 0xbd }, + { 0xbf, 0xbb }, + + { 0xc0, 0xe0 }, + { 0xc1, 0xe1 }, + { 0xc2, 0xe2 }, + { 0xc3, 0xe3 }, + { 0xc4, 0xe4 }, + { 0xc5, 0xe5 }, + { 0xc6, 0xe6 }, + { 0xc7, 0xe7 }, + { 0xc8, 0xe8 }, + { 0xc9, 0xe9 }, + { 0xca, 0xea }, + { 0xcb, 0xeb }, + { 0xcc, 0xec }, + { 0xcd, 0xed }, + { 0xce, 0xee }, + { 0xcf, 0xef }, + + { 0xd0, 0xf0 }, + { 0xd1, 0xf1 }, + { 0xd2, 0xf2 }, + { 0xd3, 0xf3 }, + { 0xd4, 0xf4 }, + { 0xd5, 0xf5 }, + { 0xd6, 0xf6 }, + { 0xd7, 0xf7 }, + { 0xd8, 0xf8 }, + { 0xd9, 0xf9 }, + { 0xda, 0xfa }, + { 0xdb, 0xfb }, + { 0xdc, 0xfc }, + { 0xdd, 0xfd }, + { 0xde, 0xfe }, + + { 0xe0, 0xc0 }, + { 0xe1, 0xc1 }, + { 0xe2, 0xc2 }, + { 0xe3, 0xc3 }, + { 0xe4, 0xc4 }, + { 0xe5, 0xc5 }, + { 0xe6, 0xc6 }, + { 0xe7, 0xc7 }, + { 0xe8, 0xc8 }, + { 0xe9, 0xc9 }, + { 0xea, 0xca }, + { 0xeb, 0xcb }, + { 0xec, 0xcc }, + { 0xed, 0xcd }, + { 0xee, 0xce }, + { 0xef, 0xcf }, + + { 0xf0, 0xd0 }, + { 0xf1, 0xd1 }, + { 0xf2, 0xd2 }, + { 0xf3, 0xd3 }, + { 0xf4, 0xd4 }, + { 0xf5, 0xd5 }, + { 0xf6, 0xd6 }, + { 0xf7, 0xd7 }, + { 0xf8, 0xd8 }, + { 0xf9, 0xd9 }, + { 0xfa, 0xda }, + { 0xfb, 0xdb }, + { 0xfc, 0xdc }, + { 0xfd, 0xdd }, + { 0xfe, 0xde }, + { 0xff, 0xaf } + }; + + if (flag == ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) { + *ccs = OnigAsciiPairAmbigCodes; + return 52; + } + if (flag == ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) { + *ccs = cc; + return sizeof(cc) / sizeof(OnigPairAmbigCodes); + } + else + return 0; +} + OnigEncodingType OnigEncodingISO_8859_14 = { + onigenc_single_byte_mbc_enc_len, + "ISO-8859-14", /* name */ + 1, /* max enc length */ + 1, /* min enc length */ + (ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_COMPOUND), { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ }, - "ISO-8859-14", /* name */ - 1, /* max byte length */ - TRUE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_SB, /* ctype_support_level */ - TRUE, /* is continuous sb mb codepoint */ + onigenc_is_mbc_newline_0x0a, onigenc_single_byte_mbc_to_code, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, - iso_8859_14_mbc_to_lower, - iso_8859_14_mbc_is_case_ambig, - iso_8859_14_code_is_ctype, - onigenc_nothing_get_ctype_code_range, + iso_8859_14_mbc_to_normalize, + iso_8859_14_is_mbc_ambiguous, + iso_8859_14_get_all_pair_ambig_codes, + onigenc_ess_tsett_get_all_comp_ambig_codes, + iso_8859_14_is_code_ctype, + onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, - onigenc_single_byte_is_allowed_reverse_match, - onigenc_get_all_fold_match_code_ss_0xdf, - onigenc_get_fold_match_info_ss_0xdf + onigenc_always_true_is_allowed_reverse_match }; diff --git a/ext/mbstring/oniguruma/enc/iso8859_15.c b/ext/mbstring/oniguruma/enc/iso8859_15.c index 49cb266058b5..1a8bd7b4c5bc 100644 --- a/ext/mbstring/oniguruma/enc/iso8859_15.c +++ b/ext/mbstring/oniguruma/enc/iso8859_15.c @@ -1,15 +1,33 @@ /********************************************************************** - iso8859_15.c - Oniguruma (regular expression library) - - Copyright (C) 2003-2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ -#include "regenc.h" +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ -/* reference - http://en.wikipedia.org/wiki/ISO_8859-15 -*/ +#include "regenc.h" #define ENC_ISO_8859_15_TO_LOWER_CASE(c) EncISO_8859_15_ToLowerCaseTable[c] #define ENC_IS_ISO_8859_15_CTYPE(code,ctype) \ @@ -51,65 +69,114 @@ static UChar EncISO_8859_15_ToLowerCaseTable[256] = { }; static unsigned short EncISO_8859_15_CtypeTable[256] = { - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1106, 0x1104, 0x1104, 0x1104, 0x1104, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1142, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, - 0x1c58, 0x1c58, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x18d0, - 0x10d0, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x1004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0142, 0x00d0, 0x0050, 0x0050, 0x0050, 0x0050, 0x0a51, 0x0050, - 0x0871, 0x0050, 0x0871, 0x00d0, 0x0050, 0x00d0, 0x0050, 0x0050, - 0x0050, 0x0050, 0x0850, 0x0850, 0x0a51, 0x0871, 0x0050, 0x00d0, - 0x0871, 0x0850, 0x0871, 0x00d0, 0x0a51, 0x0871, 0x0a51, 0x00d0, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0050, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0050, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871 + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x220c, 0x2209, 0x2208, 0x2208, 0x2208, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2284, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, + 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, + 0x38b0, 0x38b0, 0x21a0, 0x21a0, 0x20a0, 0x20a0, 0x20a0, 0x21a0, + 0x21a0, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x31a0, + 0x20a0, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x21a0, 0x20a0, 0x21a0, 0x20a0, 0x2008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0284, 0x01a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x14a2, 0x00a0, + 0x10e2, 0x00a0, 0x10e2, 0x01a0, 0x00a0, 0x01a0, 0x00a0, 0x00a0, + 0x00a0, 0x00a0, 0x10a0, 0x10a0, 0x14a2, 0x10e2, 0x00a0, 0x01a0, + 0x10e2, 0x10a0, 0x10e2, 0x01a0, 0x14a2, 0x10e2, 0x14a2, 0x01a0, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x00a0, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x00a0, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2 }; static int -iso_8859_15_mbc_to_lower(UChar* p, UChar* lower) +iso_8859_15_mbc_to_normalize(OnigAmbigType flag, + const UChar** pp, const UChar* end, UChar* lower) { - *lower = ENC_ISO_8859_15_TO_LOWER_CASE(*p); + const UChar* p = *pp; + + if (end > p + 1 && (flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + if ((*p == 's' && *(p+1) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+1) == 'S'))) { + *lower = 0xdf; + (*pp) += 2; + return 1; + } + } + + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + *lower = ENC_ISO_8859_15_TO_LOWER_CASE(*p); + } + else { + *lower = *p; + } + (*pp)++; return 1; /* return byte length of converted char to lower */ } static int -iso_8859_15_mbc_is_case_ambig(UChar* p) +iso_8859_15_is_mbc_ambiguous(OnigAmbigType flag, + const UChar** pp, const UChar* end) { - int v = (EncISO_8859_15_CtypeTable[*p] - & (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); - - if ((v | ONIGENC_CTYPE_LOWER) != 0) { - /* 0xdf, 0xaa, 0xb5, 0xba are lower case letter, but can't convert. */ - if (*p == 0xdf || *p == 0xaa || *p == 0xb5 || *p == 0xba) - return FALSE; - else + const UChar* p = *pp; + + if ((flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + if (end > p + 1) { + if ((*p == 's' && *(p+1) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+1) == 'S'))) { + (*pp) += 2; + return TRUE; + } + } + + if (*p == 0xdf) { + (*pp)++; return TRUE; + } + } + + (*pp)++; + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + int v = (EncISO_8859_15_CtypeTable[*p] & + (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); + + if ((v | ONIGENC_CTYPE_LOWER) != 0) { + /* 0xdf etc.. are lower case letter, but can't convert. */ + if (*p == 0xdf || *p == 0xaa || *p == 0xb5 || *p == 0xba) + return FALSE; + else + return TRUE; + } + + return (v != 0 ? TRUE : FALSE); } - return (v != 0 ? TRUE : FALSE); + return FALSE; } static int -iso_8859_15_code_is_ctype(OnigCodePoint code, unsigned int ctype) +iso_8859_15_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_15_CTYPE(code, ctype); @@ -117,39 +184,124 @@ iso_8859_15_code_is_ctype(OnigCodePoint code, unsigned int ctype) return FALSE; } +static int +iso_8859_15_get_all_pair_ambig_codes(OnigAmbigType flag, + OnigPairAmbigCodes** ccs) +{ + static OnigPairAmbigCodes cc[] = { + { 0xa6, 0xa8 }, + { 0xa8, 0xa6 }, + + { 0xb4, 0xb8 }, + { 0xb8, 0xb4 }, + { 0xbc, 0xbd }, + { 0xbd, 0xbc }, + { 0xbe, 0xff }, + + { 0xc0, 0xe0 }, + { 0xc1, 0xe1 }, + { 0xc2, 0xe2 }, + { 0xc3, 0xe3 }, + { 0xc4, 0xe4 }, + { 0xc5, 0xe5 }, + { 0xc6, 0xe6 }, + { 0xc7, 0xe7 }, + { 0xc8, 0xe8 }, + { 0xc9, 0xe9 }, + { 0xca, 0xea }, + { 0xcb, 0xeb }, + { 0xcc, 0xec }, + { 0xcd, 0xed }, + { 0xce, 0xee }, + { 0xcf, 0xef }, + + { 0xd0, 0xf0 }, + { 0xd1, 0xf1 }, + { 0xd2, 0xf2 }, + { 0xd3, 0xf3 }, + { 0xd4, 0xf4 }, + { 0xd5, 0xf5 }, + { 0xd6, 0xf6 }, + { 0xd8, 0xf8 }, + { 0xd9, 0xf9 }, + { 0xda, 0xfa }, + { 0xdb, 0xfb }, + { 0xdc, 0xfc }, + { 0xdd, 0xfd }, + { 0xde, 0xfe }, + + { 0xe0, 0xc0 }, + { 0xe1, 0xc1 }, + { 0xe2, 0xc2 }, + { 0xe3, 0xc3 }, + { 0xe4, 0xc4 }, + { 0xe5, 0xc5 }, + { 0xe6, 0xc6 }, + { 0xe7, 0xc7 }, + { 0xe8, 0xc8 }, + { 0xe9, 0xc9 }, + { 0xea, 0xca }, + { 0xeb, 0xcb }, + { 0xec, 0xcc }, + { 0xed, 0xcd }, + { 0xee, 0xce }, + { 0xef, 0xcf }, + + { 0xf0, 0xd0 }, + { 0xf1, 0xd1 }, + { 0xf2, 0xd2 }, + { 0xf3, 0xd3 }, + { 0xf4, 0xd4 }, + { 0xf5, 0xd5 }, + { 0xf6, 0xd6 }, + { 0xf8, 0xd8 }, + { 0xf9, 0xd9 }, + { 0xfa, 0xda }, + { 0xfb, 0xdb }, + { 0xfc, 0xdc }, + { 0xfd, 0xdd }, + { 0xfe, 0xde }, + { 0xff, 0xbe } + }; + + if (flag == ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) { + *ccs = OnigAsciiPairAmbigCodes; + return 52; + } + if (flag == ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) { + *ccs = cc; + return sizeof(cc) / sizeof(OnigPairAmbigCodes); + } + else + return 0; +} + OnigEncodingType OnigEncodingISO_8859_15 = { + onigenc_single_byte_mbc_enc_len, + "ISO-8859-15", /* name */ + 1, /* max enc length */ + 1, /* min enc length */ + (ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_COMPOUND), { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ }, - "ISO-8859-15", /* name */ - 1, /* max byte length */ - TRUE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_SB, /* ctype_support_level */ - TRUE, /* is continuous sb mb codepoint */ + onigenc_is_mbc_newline_0x0a, onigenc_single_byte_mbc_to_code, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, - iso_8859_15_mbc_to_lower, - iso_8859_15_mbc_is_case_ambig, - iso_8859_15_code_is_ctype, - onigenc_nothing_get_ctype_code_range, + iso_8859_15_mbc_to_normalize, + iso_8859_15_is_mbc_ambiguous, + iso_8859_15_get_all_pair_ambig_codes, + onigenc_ess_tsett_get_all_comp_ambig_codes, + iso_8859_15_is_code_ctype, + onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, - onigenc_single_byte_is_allowed_reverse_match, - onigenc_get_all_fold_match_code_ss_0xdf, - onigenc_get_fold_match_info_ss_0xdf + onigenc_always_true_is_allowed_reverse_match }; diff --git a/ext/mbstring/oniguruma/enc/iso8859_16.c b/ext/mbstring/oniguruma/enc/iso8859_16.c index e59ea0f42c4c..e283db17ccf6 100644 --- a/ext/mbstring/oniguruma/enc/iso8859_16.c +++ b/ext/mbstring/oniguruma/enc/iso8859_16.c @@ -1,10 +1,32 @@ /********************************************************************** - iso8859_16.c - Oniguruma (regular expression library) - - Copyright (C) 2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regenc.h" #define ENC_ISO_8859_16_TO_LOWER_CASE(c) EncISO_8859_16_ToLowerCaseTable[c] @@ -47,69 +69,114 @@ static UChar EncISO_8859_16_ToLowerCaseTable[256] = { }; static unsigned short EncISO_8859_16_CtypeTable[256] = { - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1106, 0x1104, 0x1104, 0x1104, 0x1104, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1142, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, - 0x1c58, 0x1c58, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x18d0, - 0x10d0, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x1004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0142, 0x0a51, 0x0871, 0x0a51, 0x0050, 0x00d0, 0x0a51, 0x0050, - 0x0871, 0x0050, 0x0a51, 0x00d0, 0x0a51, 0x00d0, 0x0871, 0x0a51, - 0x0050, 0x0050, 0x0a51, 0x0871, 0x0a51, 0x00d0, 0x0050, 0x00d0, - 0x0871, 0x0871, 0x0871, 0x00d0, 0x0a51, 0x0871, 0x0a51, 0x0871, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871 + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x220c, 0x2209, 0x2208, 0x2208, 0x2208, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2284, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, + 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, + 0x38b0, 0x38b0, 0x21a0, 0x21a0, 0x20a0, 0x20a0, 0x20a0, 0x21a0, + 0x21a0, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x31a0, + 0x20a0, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x21a0, 0x20a0, 0x21a0, 0x20a0, 0x2008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0284, 0x14a2, 0x10e2, 0x14a2, 0x00a0, 0x01a0, 0x14a2, 0x00a0, + 0x10e2, 0x00a0, 0x14a2, 0x01a0, 0x14a2, 0x01a0, 0x10e2, 0x14a2, + 0x00a0, 0x00a0, 0x14a2, 0x10e2, 0x14a2, 0x01a0, 0x00a0, 0x01a0, + 0x10e2, 0x10e2, 0x10e2, 0x01a0, 0x14a2, 0x10e2, 0x14a2, 0x10e2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2 }; static int -iso_8859_16_mbc_to_lower(UChar* p, UChar* lower) +iso_8859_16_mbc_to_normalize(OnigAmbigType flag, + const UChar** pp, const UChar* end, UChar* lower) { - *lower = ENC_ISO_8859_16_TO_LOWER_CASE(*p); + const UChar* p = *pp; + + if (end > p + 1 && (flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + if ((*p == 's' && *(p+1) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+1) == 'S'))) { + *lower = 0xdf; + (*pp) += 2; + return 1; + } + } + + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + *lower = ENC_ISO_8859_16_TO_LOWER_CASE(*p); + } + else { + *lower = *p; + } + (*pp)++; return 1; /* return byte length of converted char to lower */ } static int -iso_8859_16_mbc_is_case_ambig(UChar* p) +iso_8859_16_is_mbc_ambiguous(OnigAmbigType flag, + const UChar** pp, const UChar* end) { - int v = (EncISO_8859_16_CtypeTable[*p] & - (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); - - if ((v | ONIGENC_CTYPE_LOWER) != 0) { - /* 0xdf is lower case letter, but can't convert. */ - if (*p == 0xdf) - return FALSE; - else + const UChar* p = *pp; + + if ((flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + if (end > p + 1) { + if ((*p == 's' && *(p+1) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+1) == 'S'))) { + (*pp) += 2; + return TRUE; + } + } + + if (*p == 0xdf) { + (*pp)++; return TRUE; + } } - else if (v != 0) { - return TRUE; - } + (*pp)++; + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + int v = (EncISO_8859_16_CtypeTable[*p] & + (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); + + if ((v | ONIGENC_CTYPE_LOWER) != 0) { + /* 0xdf is lower case letter, but can't convert. */ + if (*p == 0xdf) + return FALSE; + else + return TRUE; + } + + return (v != 0 ? TRUE : FALSE); + } return FALSE; } static int -iso_8859_16_code_is_ctype(OnigCodePoint code, unsigned int ctype) +iso_8859_16_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_16_CTYPE(code, ctype); @@ -117,39 +184,138 @@ iso_8859_16_code_is_ctype(OnigCodePoint code, unsigned int ctype) return FALSE; } +static int +iso_8859_16_get_all_pair_ambig_codes(OnigAmbigType flag, + OnigPairAmbigCodes** ccs) +{ + static OnigPairAmbigCodes cc[] = { + { 0xa1, 0xa2 }, + { 0xa2, 0xa1 }, + { 0xa3, 0xb3 }, + { 0xa6, 0xa8 }, + { 0xa8, 0xa6 }, + { 0xaa, 0xba }, + { 0xac, 0xae }, + { 0xae, 0xac }, + { 0xaf, 0xbf }, + + { 0xb2, 0xb9 }, + { 0xb3, 0xa3 }, + { 0xb4, 0xb8 }, + { 0xb8, 0xb4 }, + { 0xb9, 0xb2 }, + { 0xba, 0xaa }, + { 0xbc, 0xbd }, + { 0xbd, 0xbc }, + { 0xbe, 0xff }, + { 0xbf, 0xaf }, + + { 0xc0, 0xe0 }, + { 0xc1, 0xe1 }, + { 0xc2, 0xe2 }, + { 0xc3, 0xe3 }, + { 0xc4, 0xe4 }, + { 0xc5, 0xe5 }, + { 0xc6, 0xe6 }, + { 0xc7, 0xe7 }, + { 0xc8, 0xe8 }, + { 0xc9, 0xe9 }, + { 0xca, 0xea }, + { 0xcb, 0xeb }, + { 0xcc, 0xec }, + { 0xcd, 0xed }, + { 0xce, 0xee }, + { 0xcf, 0xef }, + + { 0xd0, 0xf0 }, + { 0xd1, 0xf1 }, + { 0xd2, 0xf2 }, + { 0xd3, 0xf3 }, + { 0xd4, 0xf4 }, + { 0xd5, 0xf5 }, + { 0xd6, 0xf6 }, + { 0xd7, 0xf7 }, + { 0xd8, 0xf8 }, + { 0xd9, 0xf9 }, + { 0xda, 0xfa }, + { 0xdb, 0xfb }, + { 0xdc, 0xfc }, + { 0xdd, 0xfd }, + { 0xde, 0xfe }, + + { 0xe0, 0xc0 }, + { 0xe1, 0xc1 }, + { 0xe2, 0xc2 }, + { 0xe3, 0xc3 }, + { 0xe4, 0xc4 }, + { 0xe5, 0xc5 }, + { 0xe6, 0xc6 }, + { 0xe7, 0xc7 }, + { 0xe8, 0xc8 }, + { 0xe9, 0xc9 }, + { 0xea, 0xca }, + { 0xeb, 0xcb }, + { 0xec, 0xcc }, + { 0xed, 0xcd }, + { 0xee, 0xce }, + { 0xef, 0xcf }, + + { 0xf0, 0xd0 }, + { 0xf1, 0xd1 }, + { 0xf2, 0xd2 }, + { 0xf3, 0xd3 }, + { 0xf4, 0xd4 }, + { 0xf5, 0xd5 }, + { 0xf6, 0xd6 }, + { 0xf7, 0xd7 }, + { 0xf8, 0xd8 }, + { 0xf9, 0xd9 }, + { 0xfa, 0xda }, + { 0xfb, 0xdb }, + { 0xfc, 0xdc }, + { 0xfd, 0xdd }, + { 0xfe, 0xde }, + { 0xff, 0xbe } + }; + + if (flag == ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) { + *ccs = OnigAsciiPairAmbigCodes; + return 52; + } + if (flag == ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) { + *ccs = cc; + return sizeof(cc) / sizeof(OnigPairAmbigCodes); + } + else + return 0; +} + OnigEncodingType OnigEncodingISO_8859_16 = { + onigenc_single_byte_mbc_enc_len, + "ISO-8859-16", /* name */ + 1, /* max enc length */ + 1, /* min enc length */ + (ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_COMPOUND), { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ }, - "ISO-8859-16", /* name */ - 1, /* max byte length */ - TRUE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_SB, /* ctype_support_level */ - TRUE, /* is continuous sb mb codepoint */ + onigenc_is_mbc_newline_0x0a, onigenc_single_byte_mbc_to_code, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, - iso_8859_16_mbc_to_lower, - iso_8859_16_mbc_is_case_ambig, - iso_8859_16_code_is_ctype, - onigenc_nothing_get_ctype_code_range, + iso_8859_16_mbc_to_normalize, + iso_8859_16_is_mbc_ambiguous, + iso_8859_16_get_all_pair_ambig_codes, + onigenc_ess_tsett_get_all_comp_ambig_codes, + iso_8859_16_is_code_ctype, + onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, - onigenc_single_byte_is_allowed_reverse_match, - onigenc_get_all_fold_match_code_ss_0xdf, - onigenc_get_fold_match_info_ss_0xdf + onigenc_always_true_is_allowed_reverse_match }; diff --git a/ext/mbstring/oniguruma/enc/iso8859_2.c b/ext/mbstring/oniguruma/enc/iso8859_2.c index 3d6b0a6573d8..e86415b9c963 100644 --- a/ext/mbstring/oniguruma/enc/iso8859_2.c +++ b/ext/mbstring/oniguruma/enc/iso8859_2.c @@ -1,10 +1,32 @@ /********************************************************************** - iso8859_2.c - Oniguruma (regular expression library) - - Copyright (C) 2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regenc.h" #define ENC_ISO_8859_2_TO_LOWER_CASE(c) EncISO_8859_2_ToLowerCaseTable[c] @@ -47,66 +69,218 @@ static UChar EncISO_8859_2_ToLowerCaseTable[256] = { }; static unsigned short EncISO_8859_2_CtypeTable[256] = { - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1106, 0x1104, 0x1104, 0x1104, 0x1104, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1142, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, - 0x1c58, 0x1c58, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x18d0, - 0x10d0, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x1004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0142, 0x0a51, 0x0050, 0x0a51, 0x0050, 0x0a51, 0x0a51, 0x0050, - 0x0050, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x00d0, 0x0a51, 0x0a51, - 0x0050, 0x0871, 0x0050, 0x0871, 0x0050, 0x0871, 0x0871, 0x0050, - 0x0050, 0x0871, 0x0871, 0x0871, 0x0871, 0x0050, 0x0871, 0x0871, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0050, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0050, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0050 + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x220c, 0x2209, 0x2208, 0x2208, 0x2208, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2284, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, + 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, + 0x38b0, 0x38b0, 0x21a0, 0x21a0, 0x20a0, 0x20a0, 0x20a0, 0x21a0, + 0x21a0, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x31a0, + 0x20a0, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x21a0, 0x20a0, 0x21a0, 0x20a0, 0x2008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0284, 0x14a2, 0x00a0, 0x14a2, 0x00a0, 0x14a2, 0x14a2, 0x00a0, + 0x00a0, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x01a0, 0x14a2, 0x14a2, + 0x00a0, 0x10e2, 0x00a0, 0x10e2, 0x00a0, 0x10e2, 0x10e2, 0x00a0, + 0x00a0, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x00a0, 0x10e2, 0x10e2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x00a0, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x00a0, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x00a0 }; static int -iso_8859_2_mbc_to_lower(UChar* p, UChar* lower) +iso_8859_2_mbc_to_normalize(OnigAmbigType flag, + const UChar** pp, const UChar* end, UChar* lower) { - *lower = ENC_ISO_8859_2_TO_LOWER_CASE(*p); + const UChar* p = *pp; + + if (end > p + 1 && (flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + if ((*p == 's' && *(p+1) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+1) == 'S'))) { + *lower = 0xdf; + (*pp) += 2; + return 1; + } + } + + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + *lower = ENC_ISO_8859_2_TO_LOWER_CASE(*p); + } + else { + *lower = *p; + } + (*pp)++; return 1; /* return byte length of converted char to lower */ } static int -iso_8859_2_mbc_is_case_ambig(UChar* p) +iso_8859_2_is_mbc_ambiguous(OnigAmbigType flag, + const UChar** pp, const UChar* end) { - int v = (EncISO_8859_2_CtypeTable[*p] & - (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); - - if ((v | ONIGENC_CTYPE_LOWER) != 0) { - /* 0xdf is lower case letter, but can't convert. */ - if (*p == 0xdf) - return FALSE; - else + const UChar* p = *pp; + + if ((flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + if (end > p + 1) { + if ((*p == 's' && *(p+1) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+1) == 'S'))) { + (*pp) += 2; + return TRUE; + } + } + + if (*p == 0xdf) { + (*pp)++; return TRUE; + } } - return (v != 0 ? TRUE : FALSE); + (*pp)++; + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + int v = (EncISO_8859_2_CtypeTable[*p] & + (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); + + if ((v | ONIGENC_CTYPE_LOWER) != 0) { + /* 0xdf is lower case letter, but can't convert. */ + if (*p == 0xdf) + return FALSE; + else + return TRUE; + } + + return (v != 0 ? TRUE : FALSE); + } + return FALSE; } static int -iso_8859_2_code_is_ctype(OnigCodePoint code, unsigned int ctype) +iso_8859_2_get_all_pair_ambig_codes(OnigAmbigType flag, + OnigPairAmbigCodes** ccs) +{ + static OnigPairAmbigCodes cc[] = { + { 0xa1, 0xb1 }, + { 0xa3, 0xb3 }, + { 0xa5, 0xb5 }, + { 0xa6, 0xb6 }, + { 0xa9, 0xb9 }, + { 0xaa, 0xba }, + { 0xab, 0xbb }, + { 0xac, 0xbc }, + { 0xae, 0xbe }, + { 0xaf, 0xbf }, + + { 0xb1, 0xa1 }, + { 0xb3, 0xa3 }, + { 0xb5, 0xa5 }, + { 0xb6, 0xa6 }, + { 0xb9, 0xa9 }, + { 0xba, 0xaa }, + { 0xbb, 0xab }, + { 0xbc, 0xac }, + { 0xbe, 0xae }, + { 0xbf, 0xaf }, + + { 0xc0, 0xe0 }, + { 0xc1, 0xe1 }, + { 0xc2, 0xe2 }, + { 0xc3, 0xe3 }, + { 0xc4, 0xe4 }, + { 0xc5, 0xe5 }, + { 0xc6, 0xe6 }, + { 0xc7, 0xe7 }, + { 0xc8, 0xe8 }, + { 0xc9, 0xe9 }, + { 0xca, 0xea }, + { 0xcb, 0xeb }, + { 0xcc, 0xec }, + { 0xcd, 0xed }, + { 0xce, 0xee }, + { 0xcf, 0xef }, + + { 0xd0, 0xf0 }, + { 0xd1, 0xf1 }, + { 0xd2, 0xf2 }, + { 0xd3, 0xf3 }, + { 0xd4, 0xf4 }, + { 0xd5, 0xf5 }, + { 0xd6, 0xf6 }, + { 0xd8, 0xf8 }, + { 0xd9, 0xf9 }, + { 0xda, 0xfa }, + { 0xdb, 0xfb }, + { 0xdc, 0xfc }, + { 0xdd, 0xfd }, + { 0xde, 0xfe }, + + { 0xe0, 0xc0 }, + { 0xe1, 0xc1 }, + { 0xe2, 0xc2 }, + { 0xe3, 0xc3 }, + { 0xe4, 0xc4 }, + { 0xe5, 0xc5 }, + { 0xe6, 0xc6 }, + { 0xe7, 0xc7 }, + { 0xe8, 0xc8 }, + { 0xe9, 0xc9 }, + { 0xea, 0xca }, + { 0xeb, 0xcb }, + { 0xec, 0xcc }, + { 0xed, 0xcd }, + { 0xee, 0xce }, + { 0xef, 0xcf }, + + { 0xf0, 0xd0 }, + { 0xf1, 0xd1 }, + { 0xf2, 0xd2 }, + { 0xf3, 0xd3 }, + { 0xf4, 0xd4 }, + { 0xf5, 0xd5 }, + { 0xf6, 0xd6 }, + { 0xf8, 0xd8 }, + { 0xf9, 0xd9 }, + { 0xfa, 0xda }, + { 0xfb, 0xdb }, + { 0xfc, 0xdc }, + { 0xfd, 0xdd }, + { 0xfe, 0xde } + }; + + if (flag == ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) { + *ccs = OnigAsciiPairAmbigCodes; + return 52; + } + if (flag == ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) { + *ccs = cc; + return sizeof(cc) / sizeof(OnigPairAmbigCodes); + } + else + return 0; +} + +static int +iso_8859_2_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_2_CTYPE(code, ctype); @@ -115,38 +289,31 @@ iso_8859_2_code_is_ctype(OnigCodePoint code, unsigned int ctype) } OnigEncodingType OnigEncodingISO_8859_2 = { + onigenc_single_byte_mbc_enc_len, + "ISO-8859-2", /* name */ + 1, /* max enc length */ + 1, /* min enc length */ + (ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_COMPOUND), { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ }, - "ISO-8859-2", /* name */ - 1, /* max byte length */ - TRUE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_SB, /* ctype_support_level */ - TRUE, /* is continuous sb mb codepoint */ + onigenc_is_mbc_newline_0x0a, onigenc_single_byte_mbc_to_code, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, - iso_8859_2_mbc_to_lower, - iso_8859_2_mbc_is_case_ambig, - iso_8859_2_code_is_ctype, - onigenc_nothing_get_ctype_code_range, + iso_8859_2_mbc_to_normalize, + iso_8859_2_is_mbc_ambiguous, + iso_8859_2_get_all_pair_ambig_codes, + onigenc_ess_tsett_get_all_comp_ambig_codes, + iso_8859_2_is_code_ctype, + onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, - onigenc_single_byte_is_allowed_reverse_match, - onigenc_get_all_fold_match_code_ss_0xdf, - onigenc_get_fold_match_info_ss_0xdf + onigenc_always_true_is_allowed_reverse_match }; diff --git a/ext/mbstring/oniguruma/enc/iso8859_3.c b/ext/mbstring/oniguruma/enc/iso8859_3.c index 37a3089aabd8..76d2bec8a876 100644 --- a/ext/mbstring/oniguruma/enc/iso8859_3.c +++ b/ext/mbstring/oniguruma/enc/iso8859_3.c @@ -1,10 +1,32 @@ /********************************************************************** - iso8859_3.c - Oniguruma (regular expression library) - - Copyright (C) 2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regenc.h" #define ENC_ISO_8859_3_TO_LOWER_CASE(c) EncISO_8859_3_ToLowerCaseTable[c] @@ -47,66 +69,114 @@ static UChar EncISO_8859_3_ToLowerCaseTable[256] = { }; static unsigned short EncISO_8859_3_CtypeTable[256] = { - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1106, 0x1104, 0x1104, 0x1104, 0x1104, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1142, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, - 0x1c58, 0x1c58, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x18d0, - 0x10d0, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x1004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0142, 0x0a51, 0x0050, 0x0050, 0x0050, 0x0000, 0x0a51, 0x0050, - 0x0050, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x00d0, 0x0000, 0x0a51, - 0x0050, 0x0871, 0x0850, 0x0850, 0x0050, 0x0871, 0x0871, 0x00d0, - 0x0050, 0x0871, 0x0871, 0x0871, 0x0871, 0x0850, 0x0000, 0x0871, - 0x0a51, 0x0a51, 0x0a51, 0x0000, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0000, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0050, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0000, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0000, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0050, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0050 + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x220c, 0x2209, 0x2208, 0x2208, 0x2208, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2284, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, + 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, + 0x38b0, 0x38b0, 0x21a0, 0x21a0, 0x20a0, 0x20a0, 0x20a0, 0x21a0, + 0x21a0, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x31a0, + 0x20a0, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x21a0, 0x20a0, 0x21a0, 0x20a0, 0x2008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0284, 0x14a2, 0x00a0, 0x00a0, 0x00a0, 0x0000, 0x14a2, 0x00a0, + 0x00a0, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x01a0, 0x0000, 0x14a2, + 0x00a0, 0x10e2, 0x10a0, 0x10a0, 0x00a0, 0x10e2, 0x10e2, 0x01a0, + 0x00a0, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x11a0, 0x0000, 0x10e2, + 0x14a2, 0x14a2, 0x14a2, 0x0000, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x0000, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x00a0, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x0000, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x0000, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x00a0, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x00a0 }; static int -iso_8859_3_mbc_to_lower(UChar* p, UChar* lower) +iso_8859_3_mbc_to_normalize(OnigAmbigType flag, + const UChar** pp, const UChar* end, UChar* lower) { - *lower = ENC_ISO_8859_3_TO_LOWER_CASE(*p); + const UChar* p = *pp; + + if (end > p + 1 && (flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + if ((*p == 's' && *(p+1) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+1) == 'S'))) { + *lower = 0xdf; + (*pp) += 2; + return 1; + } + } + + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + *lower = ENC_ISO_8859_3_TO_LOWER_CASE(*p); + } + else { + *lower = *p; + } + (*pp)++; return 1; /* return byte length of converted char to lower */ } static int -iso_8859_3_mbc_is_case_ambig(UChar* p) +iso_8859_3_is_mbc_ambiguous(OnigAmbigType flag, + const UChar** pp, const UChar* end) { - int v = (EncISO_8859_3_CtypeTable[*p] & - (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); - - if ((v | ONIGENC_CTYPE_LOWER) != 0) { - /* 0xdf is lower case letter, but can't convert. */ - if (*p == 0xdf || *p == 0xb5) - return FALSE; - else + const UChar* p = *pp; + + if ((flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + if (end > p + 1) { + if ((*p == 's' && *(p+1) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+1) == 'S'))) { + (*pp) += 2; + return TRUE; + } + } + + if (*p == 0xdf) { + (*pp)++; return TRUE; + } } - return (v != 0 ? TRUE : FALSE); + (*pp)++; + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + int v = (EncISO_8859_3_CtypeTable[*p] & + (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); + + if ((v | ONIGENC_CTYPE_LOWER) != 0) { + /* 0xdf, 0xaa, 0xb5, 0xba are lower case letter, but can't convert. */ + if (*p == 0xdf || *p == 0xb5) + return FALSE; + else + return TRUE; + } + + return (v != 0 ? TRUE : FALSE); + } + return FALSE; } static int -iso_8859_3_code_is_ctype(OnigCodePoint code, unsigned int ctype) +iso_8859_3_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_3_CTYPE(code, ctype); @@ -114,39 +184,125 @@ iso_8859_3_code_is_ctype(OnigCodePoint code, unsigned int ctype) return FALSE; } +static int +iso_8859_3_get_all_pair_ambig_codes(OnigAmbigType flag, + OnigPairAmbigCodes** ccs) +{ + static OnigPairAmbigCodes cc[] = { + { 0xa1, 0xb1 }, + { 0xa6, 0xb6 }, + { 0xa9, 0xb9 }, + { 0xaa, 0xba }, + { 0xab, 0xbb }, + { 0xac, 0xbc }, + { 0xaf, 0xbf }, + { 0xb1, 0xa1 }, + { 0xb6, 0xa6 }, + { 0xb9, 0xa9 }, + { 0xba, 0xaa }, + { 0xbb, 0xab }, + { 0xbc, 0xac }, + { 0xbf, 0xaf }, + + { 0xc0, 0xe0 }, + { 0xc1, 0xe1 }, + { 0xc2, 0xe2 }, + { 0xc4, 0xe4 }, + { 0xc5, 0xe5 }, + { 0xc6, 0xe6 }, + { 0xc7, 0xe7 }, + { 0xc8, 0xe8 }, + { 0xc9, 0xe9 }, + { 0xca, 0xea }, + { 0xcb, 0xeb }, + { 0xcc, 0xec }, + { 0xcd, 0xed }, + { 0xce, 0xee }, + { 0xcf, 0xef }, + + { 0xd1, 0xf1 }, + { 0xd2, 0xf2 }, + { 0xd3, 0xf3 }, + { 0xd4, 0xf4 }, + { 0xd5, 0xf5 }, + { 0xd6, 0xf6 }, + { 0xd8, 0xf8 }, + { 0xd9, 0xf9 }, + { 0xda, 0xfa }, + { 0xdb, 0xfb }, + { 0xdc, 0xfc }, + { 0xdd, 0xfd }, + { 0xde, 0xfe }, + + { 0xe0, 0xc0 }, + { 0xe1, 0xc1 }, + { 0xe2, 0xc2 }, + { 0xe4, 0xc4 }, + { 0xe5, 0xc5 }, + { 0xe6, 0xc6 }, + { 0xe7, 0xc7 }, + { 0xe8, 0xc8 }, + { 0xe9, 0xc9 }, + { 0xea, 0xca }, + { 0xeb, 0xcb }, + { 0xec, 0xcc }, + { 0xed, 0xcd }, + { 0xee, 0xce }, + { 0xef, 0xcf }, + + { 0xf1, 0xd1 }, + { 0xf2, 0xd2 }, + { 0xf3, 0xd3 }, + { 0xf4, 0xd4 }, + { 0xf5, 0xd5 }, + { 0xf6, 0xd6 }, + { 0xf8, 0xd8 }, + { 0xf9, 0xd9 }, + { 0xfa, 0xda }, + { 0xfb, 0xdb }, + { 0xfc, 0xdc }, + { 0xfd, 0xdd }, + { 0xfe, 0xde } + }; + + if (flag == ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) { + *ccs = OnigAsciiPairAmbigCodes; + return 52; + } + if (flag == ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) { + *ccs = cc; + return sizeof(cc) / sizeof(OnigPairAmbigCodes); + } + else + return 0; +} + OnigEncodingType OnigEncodingISO_8859_3 = { + onigenc_single_byte_mbc_enc_len, + "ISO-8859-3", /* name */ + 1, /* max enc length */ + 1, /* min enc length */ + (ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_COMPOUND), { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ }, - "ISO-8859-3", /* name */ - 1, /* max byte length */ - TRUE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_SB, /* ctype_support_level */ - TRUE, /* is continuous sb mb codepoint */ + onigenc_is_mbc_newline_0x0a, onigenc_single_byte_mbc_to_code, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, - iso_8859_3_mbc_to_lower, - iso_8859_3_mbc_is_case_ambig, - iso_8859_3_code_is_ctype, - onigenc_nothing_get_ctype_code_range, + iso_8859_3_mbc_to_normalize, + iso_8859_3_is_mbc_ambiguous, + iso_8859_3_get_all_pair_ambig_codes, + onigenc_ess_tsett_get_all_comp_ambig_codes, + iso_8859_3_is_code_ctype, + onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, - onigenc_single_byte_is_allowed_reverse_match, - onigenc_get_all_fold_match_code_ss_0xdf, - onigenc_get_fold_match_info_ss_0xdf + onigenc_always_true_is_allowed_reverse_match }; diff --git a/ext/mbstring/oniguruma/enc/iso8859_4.c b/ext/mbstring/oniguruma/enc/iso8859_4.c index 897eec957fdd..7569006725c7 100644 --- a/ext/mbstring/oniguruma/enc/iso8859_4.c +++ b/ext/mbstring/oniguruma/enc/iso8859_4.c @@ -1,10 +1,32 @@ /********************************************************************** - iso8859_4.c - Oniguruma (regular expression library) - - Copyright (C) 2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regenc.h" #define ENC_ISO_8859_4_TO_LOWER_CASE(c) EncISO_8859_4_ToLowerCaseTable[c] @@ -47,69 +69,114 @@ static UChar EncISO_8859_4_ToLowerCaseTable[256] = { }; static unsigned short EncISO_8859_4_CtypeTable[256] = { - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1106, 0x1104, 0x1104, 0x1104, 0x1104, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1142, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, - 0x1c58, 0x1c58, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x18d0, - 0x10d0, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x1004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0142, 0x0a51, 0x0871, 0x0a51, 0x0050, 0x0a51, 0x0a51, 0x0050, - 0x0050, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x00d0, 0x0a51, 0x0050, - 0x0050, 0x0871, 0x0050, 0x0871, 0x0050, 0x0871, 0x0871, 0x0050, - 0x0050, 0x0871, 0x0871, 0x0871, 0x0871, 0x0a51, 0x0871, 0x0871, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0050, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0050, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0050 + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x220c, 0x2209, 0x2208, 0x2208, 0x2208, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2284, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, + 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, + 0x38b0, 0x38b0, 0x21a0, 0x21a0, 0x20a0, 0x20a0, 0x20a0, 0x21a0, + 0x21a0, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x31a0, + 0x20a0, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x21a0, 0x20a0, 0x21a0, 0x20a0, 0x2008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0284, 0x14a2, 0x10e2, 0x14a2, 0x00a0, 0x14a2, 0x14a2, 0x00a0, + 0x00a0, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x01a0, 0x14a2, 0x00a0, + 0x00a0, 0x10e2, 0x00a0, 0x10e2, 0x00a0, 0x10e2, 0x10e2, 0x00a0, + 0x00a0, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x14a2, 0x10e2, 0x10e2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x00a0, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x00a0, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x00a0 }; static int -iso_8859_4_mbc_to_lower(UChar* p, UChar* lower) +iso_8859_4_mbc_to_normalize(OnigAmbigType flag, + const UChar** pp, const UChar* end, UChar* lower) { - *lower = ENC_ISO_8859_4_TO_LOWER_CASE(*p); + const UChar* p = *pp; + + if (end > p + 1 && (flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + if ((*p == 's' && *(p+1) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+1) == 'S'))) { + *lower = 0xdf; + (*pp) += 2; + return 1; + } + } + + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + *lower = ENC_ISO_8859_4_TO_LOWER_CASE(*p); + } + else { + *lower = *p; + } + (*pp)++; return 1; /* return byte length of converted char to lower */ } static int -iso_8859_4_mbc_is_case_ambig(UChar* p) +iso_8859_4_is_mbc_ambiguous(OnigAmbigType flag, + const UChar** pp, const UChar* end) { - int v = (EncISO_8859_4_CtypeTable[*p] & - (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); - - if ((v | ONIGENC_CTYPE_LOWER) != 0) { - /* 0xdf is lower case letter, but can't convert. */ - if (*p == 0xdf || *p == 0xa2) - return FALSE; - else + const UChar* p = *pp; + + if ((flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + if (end > p + 1) { + if ((*p == 's' && *(p+1) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+1) == 'S'))) { + (*pp) += 2; + return TRUE; + } + } + + if (*p == 0xdf) { + (*pp)++; return TRUE; - } - else if (v != 0) { - return TRUE; + } } + (*pp)++; + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + int v = (EncISO_8859_4_CtypeTable[*p] & + (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); + + if ((v | ONIGENC_CTYPE_LOWER) != 0) { + /* 0xdf, 0xaa, 0xb5, 0xba are lower case letter, but can't convert. */ + if (*p == 0xdf || *p == 0xa2) + return FALSE; + else + return TRUE; + } + + return (v != 0 ? TRUE : FALSE); + } return FALSE; } static int -iso_8859_4_code_is_ctype(OnigCodePoint code, unsigned int ctype) +iso_8859_4_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_4_CTYPE(code, ctype); @@ -117,39 +184,134 @@ iso_8859_4_code_is_ctype(OnigCodePoint code, unsigned int ctype) return FALSE; } +static int +iso_8859_4_get_all_pair_ambig_codes(OnigAmbigType flag, + OnigPairAmbigCodes** ccs) +{ + static OnigPairAmbigCodes cc[] = { + { 0xa1, 0xb1 }, + { 0xa3, 0xb3 }, + { 0xa5, 0xb5 }, + { 0xa6, 0xb6 }, + { 0xa9, 0xb9 }, + { 0xaa, 0xba }, + { 0xab, 0xbb }, + { 0xac, 0xbc }, + { 0xae, 0xbe }, + + { 0xb1, 0xa1 }, + { 0xb3, 0xa3 }, + { 0xb5, 0xa5 }, + { 0xb6, 0xa6 }, + { 0xb9, 0xa9 }, + { 0xba, 0xaa }, + { 0xbb, 0xab }, + { 0xbc, 0xac }, + { 0xbe, 0xae }, + + { 0xc0, 0xe0 }, + { 0xc1, 0xe1 }, + { 0xc2, 0xe2 }, + { 0xc3, 0xe3 }, + { 0xc4, 0xe4 }, + { 0xc5, 0xe5 }, + { 0xc6, 0xe6 }, + { 0xc7, 0xe7 }, + { 0xc8, 0xe8 }, + { 0xc9, 0xe9 }, + { 0xca, 0xea }, + { 0xcb, 0xeb }, + { 0xcc, 0xec }, + { 0xcd, 0xed }, + { 0xce, 0xee }, + { 0xcf, 0xef }, + + { 0xd0, 0xf0 }, + { 0xd1, 0xf1 }, + { 0xd2, 0xf2 }, + { 0xd3, 0xf3 }, + { 0xd4, 0xf4 }, + { 0xd5, 0xf5 }, + { 0xd6, 0xf6 }, + { 0xd8, 0xf8 }, + { 0xd9, 0xf9 }, + { 0xda, 0xfa }, + { 0xdb, 0xfb }, + { 0xdc, 0xfc }, + { 0xdd, 0xfd }, + { 0xde, 0xfe }, + + { 0xe0, 0xc0 }, + { 0xe1, 0xc1 }, + { 0xe2, 0xc2 }, + { 0xe3, 0xc3 }, + { 0xe4, 0xc4 }, + { 0xe5, 0xc5 }, + { 0xe6, 0xc6 }, + { 0xe7, 0xc7 }, + { 0xe8, 0xc8 }, + { 0xe9, 0xc9 }, + { 0xea, 0xca }, + { 0xeb, 0xcb }, + { 0xec, 0xcc }, + { 0xed, 0xcd }, + { 0xee, 0xce }, + { 0xef, 0xcf }, + + { 0xf0, 0xd0 }, + { 0xf1, 0xd1 }, + { 0xf2, 0xd2 }, + { 0xf3, 0xd3 }, + { 0xf4, 0xd4 }, + { 0xf5, 0xd5 }, + { 0xf6, 0xd6 }, + { 0xf8, 0xd8 }, + { 0xf9, 0xd9 }, + { 0xfa, 0xda }, + { 0xfb, 0xdb }, + { 0xfc, 0xdc }, + { 0xfd, 0xdd }, + { 0xfe, 0xde } + }; + + if (flag == ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) { + *ccs = OnigAsciiPairAmbigCodes; + return 52; + } + if (flag == ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) { + *ccs = cc; + return sizeof(cc) / sizeof(OnigPairAmbigCodes); + } + else + return 0; +} + OnigEncodingType OnigEncodingISO_8859_4 = { + onigenc_single_byte_mbc_enc_len, + "ISO-8859-4", /* name */ + 1, /* max enc length */ + 1, /* min enc length */ + (ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_COMPOUND), { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ }, - "ISO-8859-4", /* name */ - 1, /* max byte length */ - TRUE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_SB, /* ctype_support_level */ - TRUE, /* is continuous sb mb codepoint */ + onigenc_is_mbc_newline_0x0a, onigenc_single_byte_mbc_to_code, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, - iso_8859_4_mbc_to_lower, - iso_8859_4_mbc_is_case_ambig, - iso_8859_4_code_is_ctype, - onigenc_nothing_get_ctype_code_range, + iso_8859_4_mbc_to_normalize, + iso_8859_4_is_mbc_ambiguous, + iso_8859_4_get_all_pair_ambig_codes, + onigenc_ess_tsett_get_all_comp_ambig_codes, + iso_8859_4_is_code_ctype, + onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, - onigenc_single_byte_is_allowed_reverse_match, - onigenc_get_all_fold_match_code_ss_0xdf, - onigenc_get_fold_match_info_ss_0xdf + onigenc_always_true_is_allowed_reverse_match }; diff --git a/ext/mbstring/oniguruma/enc/iso8859_5.c b/ext/mbstring/oniguruma/enc/iso8859_5.c index 34e0f9db3ee3..2f7677b3e7a9 100644 --- a/ext/mbstring/oniguruma/enc/iso8859_5.c +++ b/ext/mbstring/oniguruma/enc/iso8859_5.c @@ -1,10 +1,32 @@ /********************************************************************** - iso8859_5.c - Oniguruma (regular expression library) - - Copyright (C) 2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regenc.h" #define ENC_ISO_8859_5_TO_LOWER_CASE(c) EncISO_8859_5_ToLowerCaseTable[c] @@ -47,58 +69,80 @@ static UChar EncISO_8859_5_ToLowerCaseTable[256] = { }; static unsigned short EncISO_8859_5_CtypeTable[256] = { - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1106, 0x1104, 0x1104, 0x1104, 0x1104, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1142, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, - 0x1c58, 0x1c58, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x18d0, - 0x10d0, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x1004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0142, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x00d0, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0050, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0050, 0x0871, 0x0871 + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x220c, 0x2209, 0x2208, 0x2208, 0x2208, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2284, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, + 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, + 0x38b0, 0x38b0, 0x21a0, 0x21a0, 0x20a0, 0x20a0, 0x20a0, 0x21a0, + 0x21a0, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x31a0, + 0x20a0, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x21a0, 0x20a0, 0x21a0, 0x20a0, 0x2008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0284, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x01a0, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x00a0, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x00a0, 0x10e2, 0x10e2 }; static int -iso_8859_5_mbc_to_lower(UChar* p, UChar* lower) +iso_8859_5_mbc_to_normalize(OnigAmbigType flag, + const UChar** pp, const UChar* end, UChar* lower) { - *lower = ENC_ISO_8859_5_TO_LOWER_CASE(*p); + const UChar* p = *pp; + + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + *lower = ENC_ISO_8859_5_TO_LOWER_CASE(*p); + } + else { + *lower = *p; + } + + (*pp)++; return 1; /* return byte length of converted char to lower */ } static int -iso_8859_5_mbc_is_case_ambig(UChar* p) +iso_8859_5_is_mbc_ambiguous(OnigAmbigType flag, + const UChar** pp, const UChar* end) { - int v = (EncISO_8859_5_CtypeTable[*p] & - (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); + const UChar* p = *pp; - return (v != 0 ? TRUE : FALSE); + (*pp)++; + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + int v = (EncISO_8859_5_CtypeTable[*p] & + (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); + return (v != 0 ? TRUE : FALSE); + } + return FALSE; } static int -iso_8859_5_code_is_ctype(OnigCodePoint code, unsigned int ctype) +iso_8859_5_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_5_CTYPE(code, ctype); @@ -106,39 +150,147 @@ iso_8859_5_code_is_ctype(OnigCodePoint code, unsigned int ctype) return FALSE; } +static int +iso_8859_5_get_all_pair_ambig_codes(OnigAmbigType flag, + OnigPairAmbigCodes** ccs) +{ + static OnigPairAmbigCodes cc[] = { + { 0xa1, 0xf1 }, + { 0xa2, 0xf2 }, + { 0xa3, 0xf3 }, + { 0xa4, 0xf4 }, + { 0xa5, 0xf5 }, + { 0xa6, 0xf6 }, + { 0xa7, 0xf7 }, + { 0xa8, 0xf8 }, + { 0xa9, 0xf9 }, + { 0xaa, 0xfa }, + { 0xab, 0xfb }, + { 0xac, 0xfc }, + { 0xae, 0xfe }, + { 0xaf, 0xff }, + + { 0xb0, 0xd0 }, + { 0xb1, 0xd1 }, + { 0xb2, 0xd2 }, + { 0xb3, 0xd3 }, + { 0xb4, 0xd4 }, + { 0xb5, 0xd5 }, + { 0xb6, 0xd6 }, + { 0xb7, 0xd7 }, + { 0xb8, 0xd8 }, + { 0xb9, 0xd9 }, + { 0xba, 0xda }, + { 0xbb, 0xdb }, + { 0xbc, 0xdc }, + { 0xbd, 0xdd }, + { 0xbe, 0xdf }, + { 0xbf, 0xdf }, + + { 0xc0, 0xe0 }, + { 0xc1, 0xe1 }, + { 0xc2, 0xe2 }, + { 0xc3, 0xe3 }, + { 0xc4, 0xe4 }, + { 0xc5, 0xe5 }, + { 0xc6, 0xe6 }, + { 0xc7, 0xe7 }, + { 0xc8, 0xe8 }, + { 0xc9, 0xe9 }, + { 0xca, 0xea }, + { 0xcb, 0xeb }, + { 0xcc, 0xec }, + { 0xcd, 0xed }, + { 0xce, 0xee }, + { 0xcf, 0xef }, + + { 0xd0, 0xb0 }, + { 0xd1, 0xb1 }, + { 0xd2, 0xb2 }, + { 0xd3, 0xb3 }, + { 0xd4, 0xb4 }, + { 0xd5, 0xb5 }, + { 0xd6, 0xb6 }, + { 0xd7, 0xb7 }, + { 0xd8, 0xb8 }, + { 0xd9, 0xb9 }, + { 0xda, 0xba }, + { 0xdb, 0xbb }, + { 0xdc, 0xbc }, + { 0xdd, 0xbd }, + { 0xde, 0xbe }, + { 0xdf, 0xbf }, + + { 0xe0, 0xc0 }, + { 0xe1, 0xc1 }, + { 0xe2, 0xc2 }, + { 0xe3, 0xc3 }, + { 0xe4, 0xc4 }, + { 0xe5, 0xc5 }, + { 0xe6, 0xc6 }, + { 0xe7, 0xc7 }, + { 0xe8, 0xc8 }, + { 0xe9, 0xc9 }, + { 0xea, 0xca }, + { 0xeb, 0xcb }, + { 0xec, 0xcc }, + { 0xed, 0xcd }, + { 0xee, 0xce }, + { 0xef, 0xcf }, + + { 0xf1, 0xa1 }, + { 0xf2, 0xa2 }, + { 0xf3, 0xa3 }, + { 0xf4, 0xa4 }, + { 0xf5, 0xa5 }, + { 0xf6, 0xa6 }, + { 0xf7, 0xa7 }, + { 0xf8, 0xa8 }, + { 0xf9, 0xa9 }, + { 0xfa, 0xaa }, + { 0xfb, 0xab }, + { 0xfc, 0xac }, + { 0xfe, 0xae }, + { 0xff, 0xaf } + }; + + if (flag == ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) { + *ccs = OnigAsciiPairAmbigCodes; + return 52; + } + if (flag == ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) { + *ccs = cc; + return sizeof(cc) / sizeof(OnigPairAmbigCodes); + } + else + return 0; +} + OnigEncodingType OnigEncodingISO_8859_5 = { + onigenc_single_byte_mbc_enc_len, + "ISO-8859-5", /* name */ + 1, /* max enc length */ + 1, /* min enc length */ + (ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE ), { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ }, - "ISO-8859-5", /* name */ - 1, /* max byte length */ - FALSE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_SB, /* ctype_support_level */ - TRUE, /* is continuous sb mb codepoint */ + onigenc_is_mbc_newline_0x0a, onigenc_single_byte_mbc_to_code, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, - iso_8859_5_mbc_to_lower, - iso_8859_5_mbc_is_case_ambig, - iso_8859_5_code_is_ctype, - onigenc_nothing_get_ctype_code_range, + iso_8859_5_mbc_to_normalize, + iso_8859_5_is_mbc_ambiguous, + iso_8859_5_get_all_pair_ambig_codes, + onigenc_nothing_get_all_comp_ambig_codes, + iso_8859_5_is_code_ctype, + onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, - onigenc_single_byte_is_allowed_reverse_match, - onigenc_nothing_get_all_fold_match_code, - onigenc_nothing_get_fold_match_info + onigenc_always_true_is_allowed_reverse_match }; diff --git a/ext/mbstring/oniguruma/enc/iso8859_6.c b/ext/mbstring/oniguruma/enc/iso8859_6.c index 956e982878aa..0fcb9e8b8363 100644 --- a/ext/mbstring/oniguruma/enc/iso8859_6.c +++ b/ext/mbstring/oniguruma/enc/iso8859_6.c @@ -1,52 +1,74 @@ /********************************************************************** - iso8859_6.c - Oniguruma (regular expression library) - - Copyright (C) 2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regenc.h" #define ENC_IS_ISO_8859_6_CTYPE(code,ctype) \ ((EncISO_8859_6_CtypeTable[code] & ctype) != 0) static unsigned short EncISO_8859_6_CtypeTable[256] = { - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1106, 0x1104, 0x1104, 0x1104, 0x1104, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1142, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, - 0x1c58, 0x1c58, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x18d0, - 0x10d0, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x1004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0142, 0x0000, 0x0000, 0x0000, 0x0050, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x00d0, 0x00d0, 0x0000, 0x0000, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x220c, 0x2209, 0x2208, 0x2208, 0x2208, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2284, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, + 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, + 0x38b0, 0x38b0, 0x21a0, 0x21a0, 0x20a0, 0x20a0, 0x20a0, 0x21a0, + 0x21a0, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x31a0, + 0x20a0, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x21a0, 0x20a0, 0x21a0, 0x20a0, 0x2008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0284, 0x0000, 0x0000, 0x0000, 0x00a0, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x01a0, 0x01a0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x00d0, 0x0000, 0x0000, 0x0000, 0x00d0, - 0x0000, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, - 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, - 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, - 0x0851, 0x0851, 0x0851, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, - 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, - 0x0851, 0x0851, 0x0851, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x01a0, 0x0000, 0x0000, 0x0000, 0x01a0, + 0x0000, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, + 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, + 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, + 0x10a2, 0x10a2, 0x10a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, + 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, + 0x10a2, 0x10a2, 0x10a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; static int -iso_8859_6_code_is_ctype(OnigCodePoint code, unsigned int ctype) +iso_8859_6_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_6_CTYPE(code, ctype); @@ -55,38 +77,29 @@ iso_8859_6_code_is_ctype(OnigCodePoint code, unsigned int ctype) } OnigEncodingType OnigEncodingISO_8859_6 = { + onigenc_single_byte_mbc_enc_len, + "ISO-8859-6", /* name */ + 1, /* max enc length */ + 1, /* min enc length */ + ( ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE ), { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ }, - "ISO-8859-6", /* name */ - 1, /* max byte length */ - FALSE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_SB, /* ctype_support_level */ - TRUE, /* is continuous sb mb codepoint */ + onigenc_is_mbc_newline_0x0a, onigenc_single_byte_mbc_to_code, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, - onigenc_ascii_mbc_to_lower, - onigenc_ascii_mbc_is_case_ambig, - iso_8859_6_code_is_ctype, - onigenc_nothing_get_ctype_code_range, + onigenc_ascii_mbc_to_normalize, + onigenc_ascii_is_mbc_ambiguous, + onigenc_ascii_get_all_pair_ambig_codes, + onigenc_nothing_get_all_comp_ambig_codes, + iso_8859_6_is_code_ctype, + onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, - onigenc_single_byte_is_allowed_reverse_match, - onigenc_nothing_get_all_fold_match_code, - onigenc_nothing_get_fold_match_info + onigenc_always_true_is_allowed_reverse_match }; diff --git a/ext/mbstring/oniguruma/enc/iso8859_7.c b/ext/mbstring/oniguruma/enc/iso8859_7.c index 1ea225007fe5..8b2cb9ec5921 100644 --- a/ext/mbstring/oniguruma/enc/iso8859_7.c +++ b/ext/mbstring/oniguruma/enc/iso8859_7.c @@ -1,10 +1,32 @@ /********************************************************************** - iso8859_7.c - Oniguruma (regular expression library) - - Copyright (C) 2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regenc.h" #define ENC_ISO_8859_7_TO_LOWER_CASE(c) EncISO_8859_7_ToLowerCaseTable[c] @@ -47,65 +69,87 @@ static UChar EncISO_8859_7_ToLowerCaseTable[256] = { }; static unsigned short EncISO_8859_7_CtypeTable[256] = { - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1106, 0x1104, 0x1104, 0x1104, 0x1104, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1142, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, - 0x1c58, 0x1c58, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x18d0, - 0x10d0, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x1004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0142, 0x00d0, 0x00d0, 0x0050, 0x0000, 0x0000, 0x0050, 0x0050, - 0x0050, 0x0050, 0x0000, 0x00d0, 0x0050, 0x00d0, 0x0000, 0x00d0, - 0x0050, 0x0050, 0x0850, 0x0850, 0x0050, 0x0050, 0x0a51, 0x00d0, - 0x0a51, 0x0a51, 0x0a51, 0x00d0, 0x0a51, 0x0850, 0x0a51, 0x0a51, - 0x0871, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0000, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0000 + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x220c, 0x2209, 0x2208, 0x2208, 0x2208, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2284, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, + 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, + 0x38b0, 0x38b0, 0x21a0, 0x21a0, 0x20a0, 0x20a0, 0x20a0, 0x21a0, + 0x21a0, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x31a0, + 0x20a0, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x21a0, 0x20a0, 0x21a0, 0x20a0, 0x2008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0284, 0x01a0, 0x01a0, 0x00a0, 0x0000, 0x0000, 0x00a0, 0x00a0, + 0x00a0, 0x00a0, 0x0000, 0x01a0, 0x00a0, 0x01a0, 0x0000, 0x01a0, + 0x00a0, 0x00a0, 0x10a0, 0x10a0, 0x00a0, 0x00a0, 0x14a2, 0x01a0, + 0x14a2, 0x14a2, 0x14a2, 0x01a0, 0x14a2, 0x10a0, 0x14a2, 0x14a2, + 0x10e2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x0000, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x0000 }; static int -iso_8859_7_mbc_to_lower(UChar* p, UChar* lower) +iso_8859_7_mbc_to_normalize(OnigAmbigType flag, + const UChar** pp, const UChar* end, UChar* lower) { - *lower = ENC_ISO_8859_7_TO_LOWER_CASE(*p); + const UChar* p = *pp; + + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + *lower = ENC_ISO_8859_7_TO_LOWER_CASE(*p); + } + else { + *lower = *p; + } + (*pp)++; return 1; /* return byte length of converted char to lower */ } static int -iso_8859_7_mbc_is_case_ambig(UChar* p) +iso_8859_7_is_mbc_ambiguous(OnigAmbigType flag, + const UChar** pp, const UChar* end) { - int v = (EncISO_8859_7_CtypeTable[*p] & - (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); - - if ((v | ONIGENC_CTYPE_LOWER) != 0) { - if (*p == 0xc0 || *p == 0xe0) - return FALSE; - else - return TRUE; - } + const UChar* p = *pp; + + (*pp)++; + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + int v = (EncISO_8859_7_CtypeTable[*p] & + (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); + + if ((v | ONIGENC_CTYPE_LOWER) != 0) { + if (*p == 0xc0 || *p == 0xe0) + return FALSE; + else + return TRUE; + } - return (v != 0 ? TRUE : FALSE); + return (v != 0 ? TRUE : FALSE); + } + return FALSE; } static int -iso_8859_7_code_is_ctype(OnigCodePoint code, unsigned int ctype) +iso_8859_7_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_7_CTYPE(code, ctype); @@ -113,39 +157,122 @@ iso_8859_7_code_is_ctype(OnigCodePoint code, unsigned int ctype) return FALSE; } +static int +iso_8859_7_get_all_pair_ambig_codes(OnigAmbigType flag, + OnigPairAmbigCodes** ccs) +{ + static OnigPairAmbigCodes cc[] = { + { 0xb6, 0xdc }, + { 0xb8, 0xdd }, + { 0xb9, 0xde }, + { 0xba, 0xdf }, + { 0xbc, 0xfc }, + { 0xbe, 0xfd }, + { 0xbf, 0xfe }, + + { 0xc1, 0xe1 }, + { 0xc2, 0xe2 }, + { 0xc3, 0xe3 }, + { 0xc4, 0xe4 }, + { 0xc5, 0xe5 }, + { 0xc6, 0xe6 }, + { 0xc7, 0xe7 }, + { 0xc8, 0xe8 }, + { 0xc9, 0xe9 }, + { 0xca, 0xea }, + { 0xcb, 0xeb }, + { 0xcc, 0xec }, + { 0xcd, 0xed }, + { 0xce, 0xee }, + { 0xcf, 0xef }, + + { 0xd0, 0xf0 }, + { 0xd1, 0xf1 }, + { 0xd2, 0xf2 }, + { 0xd3, 0xf3 }, + { 0xd4, 0xf4 }, + { 0xd5, 0xf5 }, + { 0xd6, 0xf6 }, + { 0xd7, 0xf7 }, + { 0xd8, 0xf8 }, + { 0xd9, 0xf9 }, + { 0xda, 0xfa }, + { 0xdb, 0xfb }, + { 0xdc, 0xb6 }, + { 0xdd, 0xb8 }, + { 0xde, 0xb9 }, + { 0xdf, 0xba }, + + { 0xe1, 0xc1 }, + { 0xe2, 0xc2 }, + { 0xe3, 0xc3 }, + { 0xe4, 0xc4 }, + { 0xe5, 0xc5 }, + { 0xe6, 0xc6 }, + { 0xe7, 0xc7 }, + { 0xe8, 0xc8 }, + { 0xe9, 0xc9 }, + { 0xea, 0xca }, + { 0xeb, 0xcb }, + { 0xec, 0xcc }, + { 0xed, 0xcd }, + { 0xee, 0xce }, + { 0xef, 0xcf }, + + { 0xf0, 0xd0 }, + { 0xf1, 0xd1 }, + { 0xf2, 0xd2 }, + { 0xf3, 0xd3 }, + { 0xf4, 0xd4 }, + { 0xf5, 0xd5 }, + { 0xf6, 0xd6 }, + { 0xf7, 0xd7 }, + { 0xf8, 0xd8 }, + { 0xf9, 0xd9 }, + { 0xfa, 0xda }, + { 0xfb, 0xdb }, + { 0xfc, 0xbc }, + { 0xfd, 0xbe }, + { 0xfe, 0xbf } + }; + + if (flag == ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) { + *ccs = OnigAsciiPairAmbigCodes; + return 52; + } + if (flag == ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) { + *ccs = cc; + return sizeof(cc) / sizeof(OnigPairAmbigCodes); + } + else + return 0; +} + OnigEncodingType OnigEncodingISO_8859_7 = { + onigenc_single_byte_mbc_enc_len, + "ISO-8859-7", /* name */ + 1, /* max enc length */ + 1, /* min enc length */ + (ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE ), { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ }, - "ISO-8859-7", /* name */ - 1, /* max byte length */ - FALSE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_SB, /* ctype_support_level */ - TRUE, /* is continuous sb mb codepoint */ + onigenc_is_mbc_newline_0x0a, onigenc_single_byte_mbc_to_code, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, - iso_8859_7_mbc_to_lower, - iso_8859_7_mbc_is_case_ambig, - iso_8859_7_code_is_ctype, - onigenc_nothing_get_ctype_code_range, + iso_8859_7_mbc_to_normalize, + iso_8859_7_is_mbc_ambiguous, + iso_8859_7_get_all_pair_ambig_codes, + onigenc_nothing_get_all_comp_ambig_codes, + iso_8859_7_is_code_ctype, + onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, - onigenc_single_byte_is_allowed_reverse_match, - onigenc_nothing_get_all_fold_match_code, - onigenc_nothing_get_fold_match_info + onigenc_always_true_is_allowed_reverse_match }; diff --git a/ext/mbstring/oniguruma/enc/iso8859_8.c b/ext/mbstring/oniguruma/enc/iso8859_8.c index d87774a83278..3c95b9b1375e 100644 --- a/ext/mbstring/oniguruma/enc/iso8859_8.c +++ b/ext/mbstring/oniguruma/enc/iso8859_8.c @@ -1,52 +1,74 @@ /********************************************************************** - iso8859_8.c - Oniguruma (regular expression library) - - Copyright (C) 2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2004 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regenc.h" #define ENC_IS_ISO_8859_8_CTYPE(code,ctype) \ ((EncISO_8859_8_CtypeTable[code] & ctype) != 0) static unsigned short EncISO_8859_8_CtypeTable[256] = { - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1106, 0x1104, 0x1104, 0x1104, 0x1104, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1142, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, - 0x1c58, 0x1c58, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x18d0, - 0x10d0, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x1004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0142, 0x0000, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, - 0x0050, 0x0050, 0x0050, 0x00d0, 0x0050, 0x00d0, 0x0050, 0x0050, - 0x0050, 0x0050, 0x0850, 0x0850, 0x0050, 0x0871, 0x0050, 0x00d0, - 0x0050, 0x0850, 0x0050, 0x00d0, 0x0850, 0x0850, 0x0850, 0x0000, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x220c, 0x2209, 0x2208, 0x2208, 0x2208, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2284, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, + 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, + 0x38b0, 0x38b0, 0x21a0, 0x21a0, 0x20a0, 0x20a0, 0x20a0, 0x21a0, + 0x21a0, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x31a0, + 0x20a0, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x21a0, 0x20a0, 0x21a0, 0x20a0, 0x2008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0284, 0x0000, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, + 0x00a0, 0x00a0, 0x00a0, 0x01a0, 0x00a0, 0x01a0, 0x00a0, 0x00a0, + 0x00a0, 0x00a0, 0x10a0, 0x10a0, 0x00a0, 0x10e2, 0x00a0, 0x01a0, + 0x00a0, 0x10a0, 0x00a0, 0x01a0, 0x10a0, 0x10a0, 0x10a0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00d0, - 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, - 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, - 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, 0x0851, - 0x0851, 0x0851, 0x0851, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01a0, + 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, + 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, + 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, 0x10a2, + 0x10a2, 0x10a2, 0x10a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; static int -iso_8859_8_code_is_ctype(OnigCodePoint code, unsigned int ctype) +iso_8859_8_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_8_CTYPE(code, ctype); @@ -55,38 +77,29 @@ iso_8859_8_code_is_ctype(OnigCodePoint code, unsigned int ctype) } OnigEncodingType OnigEncodingISO_8859_8 = { + onigenc_single_byte_mbc_enc_len, + "ISO-8859-8", /* name */ + 1, /* max enc length */ + 1, /* min enc length */ + ( ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE ), { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ }, - "ISO-8859-8", /* name */ - 1, /* max byte length */ - FALSE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_SB, /* ctype_support_level */ - TRUE, /* is continuous sb mb codepoint */ + onigenc_is_mbc_newline_0x0a, onigenc_single_byte_mbc_to_code, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, - onigenc_ascii_mbc_to_lower, - onigenc_ascii_mbc_is_case_ambig, - iso_8859_8_code_is_ctype, - onigenc_nothing_get_ctype_code_range, + onigenc_ascii_mbc_to_normalize, + onigenc_ascii_is_mbc_ambiguous, + onigenc_ascii_get_all_pair_ambig_codes, + onigenc_nothing_get_all_comp_ambig_codes, + iso_8859_8_is_code_ctype, + onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, - onigenc_single_byte_is_allowed_reverse_match, - onigenc_nothing_get_all_fold_match_code, - onigenc_nothing_get_fold_match_info + onigenc_always_true_is_allowed_reverse_match }; diff --git a/ext/mbstring/oniguruma/enc/iso8859_9.c b/ext/mbstring/oniguruma/enc/iso8859_9.c index 9638b9299435..1b061ff6ea79 100644 --- a/ext/mbstring/oniguruma/enc/iso8859_9.c +++ b/ext/mbstring/oniguruma/enc/iso8859_9.c @@ -1,10 +1,32 @@ /********************************************************************** - iso8859_9.c - Oniguruma (regular expression library) - - Copyright (C) 2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regenc.h" #define ENC_ISO_8859_9_TO_LOWER_CASE(c) EncISO_8859_9_ToLowerCaseTable[c] @@ -47,66 +69,114 @@ static UChar EncISO_8859_9_ToLowerCaseTable[256] = { }; static unsigned short EncISO_8859_9_CtypeTable[256] = { - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1106, 0x1104, 0x1104, 0x1104, 0x1104, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1142, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, - 0x1c58, 0x1c58, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x18d0, - 0x10d0, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x1004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0142, 0x00d0, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, - 0x0050, 0x0050, 0x0871, 0x00d0, 0x0050, 0x00d0, 0x0050, 0x0050, - 0x0050, 0x0050, 0x0850, 0x0850, 0x0050, 0x0871, 0x0050, 0x00d0, - 0x0050, 0x0850, 0x0871, 0x00d0, 0x0850, 0x0850, 0x0850, 0x00d0, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0050, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0050, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871 + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x220c, 0x2209, 0x2208, 0x2208, 0x2208, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2284, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, + 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, + 0x38b0, 0x38b0, 0x21a0, 0x21a0, 0x20a0, 0x20a0, 0x20a0, 0x21a0, + 0x21a0, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x31a0, + 0x20a0, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x21a0, 0x20a0, 0x21a0, 0x20a0, 0x2008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0284, 0x01a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, + 0x00a0, 0x00a0, 0x10e2, 0x01a0, 0x00a0, 0x01a0, 0x00a0, 0x00a0, + 0x00a0, 0x00a0, 0x10a0, 0x10a0, 0x00a0, 0x10e2, 0x00a0, 0x01a0, + 0x00a0, 0x10a0, 0x10e2, 0x01a0, 0x10a0, 0x10a0, 0x10a0, 0x01a0, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x00a0, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x00a0, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2 }; static int -iso_8859_9_mbc_to_lower(UChar* p, UChar* lower) +iso_8859_9_mbc_to_normalize(OnigAmbigType flag, + const UChar** pp, const UChar* end, UChar* lower) { - *lower = ENC_ISO_8859_9_TO_LOWER_CASE(*p); + const UChar* p = *pp; + + if (end > p + 1 && (flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + if ((*p == 's' && *(p+1) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+1) == 'S'))) { + *lower = 0xdf; + (*pp) += 2; + return 1; + } + } + + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + *lower = ENC_ISO_8859_9_TO_LOWER_CASE(*p); + } + else { + *lower = *p; + } + (*pp)++; return 1; /* return byte length of converted char to lower */ } static int -iso_8859_9_mbc_is_case_ambig(UChar* p) +iso_8859_9_is_mbc_ambiguous(OnigAmbigType flag, + const UChar** pp, const UChar* end) { - int v = (EncISO_8859_9_CtypeTable[*p] & - (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); - - if ((v | ONIGENC_CTYPE_LOWER) != 0) { - /* 0xdf, 0xaa, 0xb5, 0xba are lower case letter, but can't convert. */ - if (*p == 0xdf || (*p >= 0xaa && *p <= 0xba)) - return FALSE; - else + const UChar* p = *pp; + + if ((flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + if (end > p + 1) { + if ((*p == 's' && *(p+1) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+1) == 'S'))) { + (*pp) += 2; + return TRUE; + } + } + + if (*p == 0xdf) { + (*pp)++; return TRUE; + } } - return (v != 0 ? TRUE : FALSE); + (*pp)++; + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + int v = (EncISO_8859_9_CtypeTable[*p] & + (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); + + if ((v | ONIGENC_CTYPE_LOWER) != 0) { + /* 0xdf etc.. are lower case letter, but can't convert. */ + if (*p == 0xdf || (*p >= 0xaa && *p <= 0xba)) + return FALSE; + else + return TRUE; + } + + return (v != 0 ? TRUE : FALSE); + } + return FALSE; } static int -iso_8859_9_code_is_ctype(OnigCodePoint code, unsigned int ctype) +iso_8859_9_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_9_CTYPE(code, ctype); @@ -114,39 +184,114 @@ iso_8859_9_code_is_ctype(OnigCodePoint code, unsigned int ctype) return FALSE; } +static int +iso_8859_9_get_all_pair_ambig_codes(OnigAmbigType flag, + OnigPairAmbigCodes** ccs) +{ + static OnigPairAmbigCodes cc[] = { + { 0xc0, 0xe0 }, + { 0xc1, 0xe1 }, + { 0xc2, 0xe2 }, + { 0xc3, 0xe3 }, + { 0xc4, 0xe4 }, + { 0xc5, 0xe5 }, + { 0xc6, 0xe6 }, + { 0xc7, 0xe7 }, + { 0xc8, 0xe8 }, + { 0xc9, 0xe9 }, + { 0xca, 0xea }, + { 0xcb, 0xeb }, + { 0xcc, 0xec }, + { 0xcd, 0xed }, + { 0xce, 0xee }, + { 0xcf, 0xef }, + + { 0xd0, 0xf0 }, + { 0xd1, 0xf1 }, + { 0xd2, 0xf2 }, + { 0xd3, 0xf3 }, + { 0xd4, 0xf4 }, + { 0xd5, 0xf5 }, + { 0xd6, 0xf6 }, + { 0xd8, 0xf8 }, + { 0xd9, 0xf9 }, + { 0xda, 0xfa }, + { 0xdb, 0xfb }, + { 0xdc, 0xfc }, + { 0xdd, 0xfd }, + { 0xde, 0xfe }, + + { 0xe0, 0xc0 }, + { 0xe1, 0xc1 }, + { 0xe2, 0xc2 }, + { 0xe3, 0xc3 }, + { 0xe4, 0xc4 }, + { 0xe5, 0xc5 }, + { 0xe6, 0xc6 }, + { 0xe7, 0xc7 }, + { 0xe8, 0xc8 }, + { 0xe9, 0xc9 }, + { 0xea, 0xca }, + { 0xeb, 0xcb }, + { 0xec, 0xcc }, + { 0xed, 0xcd }, + { 0xee, 0xce }, + { 0xef, 0xcf }, + + { 0xf0, 0xd0 }, + { 0xf1, 0xd1 }, + { 0xf2, 0xd2 }, + { 0xf3, 0xd3 }, + { 0xf4, 0xd4 }, + { 0xf5, 0xd5 }, + { 0xf6, 0xd6 }, + { 0xf8, 0xd8 }, + { 0xf9, 0xd9 }, + { 0xfa, 0xda }, + { 0xfb, 0xdb }, + { 0xfc, 0xdc }, + { 0xfd, 0xdd }, + { 0xfe, 0xde } + }; + + if (flag == ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) { + *ccs = OnigAsciiPairAmbigCodes; + return 52; + } + if (flag == ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) { + *ccs = cc; + return sizeof(cc) / sizeof(OnigPairAmbigCodes); + } + else + return 0; +} + OnigEncodingType OnigEncodingISO_8859_9 = { + onigenc_single_byte_mbc_enc_len, + "ISO-8859-9", /* name */ + 1, /* max enc length */ + 1, /* min enc length */ + (ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_COMPOUND), { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ }, - "ISO-8859-9", /* name */ - 1, /* max byte length */ - TRUE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_SB, /* ctype_support_level */ - TRUE, /* is continuous sb mb codepoint */ + onigenc_is_mbc_newline_0x0a, onigenc_single_byte_mbc_to_code, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, - iso_8859_9_mbc_to_lower, - iso_8859_9_mbc_is_case_ambig, - iso_8859_9_code_is_ctype, - onigenc_nothing_get_ctype_code_range, + iso_8859_9_mbc_to_normalize, + iso_8859_9_is_mbc_ambiguous, + iso_8859_9_get_all_pair_ambig_codes, + onigenc_ess_tsett_get_all_comp_ambig_codes, + iso_8859_9_is_code_ctype, + onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, - onigenc_single_byte_is_allowed_reverse_match, - onigenc_get_all_fold_match_code_ss_0xdf, - onigenc_get_fold_match_info_ss_0xdf + onigenc_always_true_is_allowed_reverse_match }; diff --git a/ext/mbstring/oniguruma/enc/koi8.c b/ext/mbstring/oniguruma/enc/koi8.c index 9dba2641c962..f8a5a1da617f 100644 --- a/ext/mbstring/oniguruma/enc/koi8.c +++ b/ext/mbstring/oniguruma/enc/koi8.c @@ -1,10 +1,32 @@ /********************************************************************** - koi8.c - Oniguruma (regular expression library) - - Copyright (C) 2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2004 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regenc.h" #define ENC_KOI8_TO_LOWER_CASE(c) EncKOI8_ToLowerCaseTable[c] @@ -47,58 +69,79 @@ static UChar EncKOI8_ToLowerCaseTable[256] = { }; static unsigned short EncKOI8_CtypeTable[256] = { - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1106, 0x1104, 0x1104, 0x1104, 0x1104, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1142, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, - 0x1c58, 0x1c58, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x18d0, - 0x10d0, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x1004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, - 0x0142, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x220c, 0x2209, 0x2208, 0x2208, 0x2208, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2284, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, + 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, + 0x38b0, 0x38b0, 0x21a0, 0x21a0, 0x20a0, 0x20a0, 0x20a0, 0x21a0, + 0x21a0, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x31a0, + 0x20a0, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x21a0, 0x20a0, 0x21a0, 0x20a0, 0x2008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0284, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51 + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2 }; static int -koi8_mbc_to_lower(UChar* p, UChar* lower) +koi8_mbc_to_normalize(OnigAmbigType flag, + const UChar** pp, const UChar* end, UChar* lower) { - *lower = ENC_KOI8_TO_LOWER_CASE(*p); + UChar* p = (UChar *)*pp; + + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + *lower = ENC_KOI8_TO_LOWER_CASE(*p); + } + else { + *lower = *p; + } + (*pp)++; return 1; /* return byte length of converted char to lower */ } static int -koi8_mbc_is_case_ambig(UChar* p) +koi8_is_mbc_ambiguous(OnigAmbigType flag, const UChar** pp, const UChar* end) { - int v = (EncKOI8_CtypeTable[*p] & - (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); + UChar* p = (UChar *)*pp; - return ((v != 0) ? TRUE : FALSE); + (*pp)++; + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + int v = (EncKOI8_CtypeTable[*p] & + (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); + return (v != 0 ? TRUE : FALSE); + } + return FALSE; } + static int -koi8_code_is_ctype(OnigCodePoint code, unsigned int ctype) +koi8_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_KOI8_CTYPE(code, ctype); @@ -106,39 +149,116 @@ koi8_code_is_ctype(OnigCodePoint code, unsigned int ctype) return FALSE; } +static int +koi8_get_all_pair_ambig_codes(OnigAmbigType flag, + OnigPairAmbigCodes** ccs) +{ + static OnigPairAmbigCodes cc[] = { + { 0xc0, 0xe0 }, + { 0xc1, 0xe1 }, + { 0xc2, 0xe2 }, + { 0xc3, 0xe3 }, + { 0xc4, 0xe4 }, + { 0xc5, 0xe5 }, + { 0xc6, 0xe6 }, + { 0xc7, 0xe7 }, + { 0xc8, 0xe8 }, + { 0xc9, 0xe9 }, + { 0xca, 0xea }, + { 0xcb, 0xeb }, + { 0xcc, 0xec }, + { 0xcd, 0xed }, + { 0xce, 0xee }, + { 0xcf, 0xef }, + + { 0xd0, 0xf0 }, + { 0xd1, 0xf1 }, + { 0xd2, 0xf2 }, + { 0xd3, 0xf3 }, + { 0xd4, 0xf4 }, + { 0xd5, 0xf5 }, + { 0xd6, 0xf6 }, + { 0xd7, 0xf7 }, + { 0xd8, 0xf8 }, + { 0xd9, 0xf9 }, + { 0xda, 0xfa }, + { 0xdb, 0xfb }, + { 0xdc, 0xfc }, + { 0xdd, 0xfd }, + { 0xde, 0xfe }, + { 0xdf, 0xff }, + + { 0xe0, 0xc0 }, + { 0xe1, 0xc1 }, + { 0xe2, 0xc2 }, + { 0xe3, 0xc3 }, + { 0xe4, 0xc4 }, + { 0xe5, 0xc5 }, + { 0xe6, 0xc6 }, + { 0xe7, 0xc7 }, + { 0xe8, 0xc8 }, + { 0xe9, 0xc9 }, + { 0xea, 0xca }, + { 0xeb, 0xcb }, + { 0xec, 0xcc }, + { 0xed, 0xcd }, + { 0xee, 0xce }, + { 0xef, 0xcf }, + + { 0xf0, 0xd0 }, + { 0xf1, 0xd1 }, + { 0xf2, 0xd2 }, + { 0xf3, 0xd3 }, + { 0xf4, 0xd4 }, + { 0xf5, 0xd5 }, + { 0xf6, 0xd6 }, + { 0xf7, 0xd7 }, + { 0xf8, 0xd8 }, + { 0xf9, 0xd9 }, + { 0xfa, 0xda }, + { 0xfb, 0xdb }, + { 0xfc, 0xdc }, + { 0xfe, 0xde }, + { 0xff, 0xdf } + }; + + if (flag == ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) { + *ccs = OnigAsciiPairAmbigCodes; + return 52; + } + if (flag == ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) { + *ccs = cc; + return sizeof(cc) / sizeof(OnigPairAmbigCodes); + } + else + return 0; +} + OnigEncodingType OnigEncodingKOI8 = { + onigenc_single_byte_mbc_enc_len, + "KOI8", /* name */ + 1, /* max enc length */ + 1, /* min enc length */ + (ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE ), { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ }, - "KOI8", /* name */ - 1, /* max byte length */ - FALSE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_SB, /* ctype_support_level */ - TRUE, /* is continuous sb mb codepoint */ + onigenc_is_mbc_newline_0x0a, onigenc_single_byte_mbc_to_code, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, - koi8_mbc_to_lower, - koi8_mbc_is_case_ambig, - koi8_code_is_ctype, - onigenc_nothing_get_ctype_code_range, + koi8_mbc_to_normalize, + koi8_is_mbc_ambiguous, + koi8_get_all_pair_ambig_codes, + onigenc_nothing_get_all_comp_ambig_codes, + koi8_is_code_ctype, + onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, - onigenc_single_byte_is_allowed_reverse_match, - onigenc_nothing_get_all_fold_match_code, - onigenc_nothing_get_fold_match_info + onigenc_always_true_is_allowed_reverse_match }; diff --git a/ext/mbstring/oniguruma/enc/koi8_r.c b/ext/mbstring/oniguruma/enc/koi8_r.c index 20e7d73a12b4..7c626df61615 100644 --- a/ext/mbstring/oniguruma/enc/koi8_r.c +++ b/ext/mbstring/oniguruma/enc/koi8_r.c @@ -1,10 +1,32 @@ /********************************************************************** - koi8_r.c - Oniguruma (regular expression library) - - Copyright (C) 2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regenc.h" #define ENC_KOI8_R_TO_LOWER_CASE(c) EncKOI8_R_ToLowerCaseTable[c] @@ -47,58 +69,78 @@ static UChar EncKOI8_R_ToLowerCaseTable[256] = { }; static unsigned short EncKOI8_R_CtypeTable[256] = { - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1106, 0x1104, 0x1104, 0x1104, 0x1104, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1142, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, - 0x1c58, 0x1c58, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x18d0, - 0x10d0, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x1004, - 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, - 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, - 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, - 0x0050, 0x0050, 0x0142, 0x0050, 0x0050, 0x0850, 0x00d0, 0x0050, - 0x0050, 0x0050, 0x0050, 0x0871, 0x0050, 0x0050, 0x0050, 0x0050, - 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, - 0x0050, 0x0050, 0x0050, 0x0a51, 0x0050, 0x0050, 0x0050, 0x0050, - 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, 0x0871, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, - 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51, 0x0a51 + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x220c, 0x2209, 0x2208, 0x2208, 0x2208, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2284, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, + 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, + 0x38b0, 0x38b0, 0x21a0, 0x21a0, 0x20a0, 0x20a0, 0x20a0, 0x21a0, + 0x21a0, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x21a0, 0x21a0, 0x21a0, 0x20a0, 0x31a0, + 0x20a0, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x21a0, 0x20a0, 0x21a0, 0x20a0, 0x2008, + 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, + 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, + 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, + 0x00a0, 0x00a0, 0x0284, 0x00a0, 0x00a0, 0x10a0, 0x01a0, 0x00a0, + 0x00a0, 0x00a0, 0x00a0, 0x10e2, 0x00a0, 0x00a0, 0x00a0, 0x00a0, + 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, + 0x00a0, 0x00a0, 0x00a0, 0x14a2, 0x00a0, 0x00a0, 0x00a0, 0x00a0, + 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2 }; static int -koi8_r_mbc_to_lower(UChar* p, UChar* lower) +koi8_r_mbc_to_normalize(OnigAmbigType flag, + const UChar** pp, const UChar* end, UChar* lower) { - *lower = ENC_KOI8_R_TO_LOWER_CASE(*p); + const UChar* p = *pp; + + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + *lower = ENC_KOI8_R_TO_LOWER_CASE(*p); + } + else { + *lower = *p; + } + (*pp)++; return 1; /* return byte length of converted char to lower */ } static int -koi8_r_mbc_is_case_ambig(UChar* p) +koi8_r_is_mbc_ambiguous(OnigAmbigType flag, const UChar** pp, const UChar* end) { - int v = (EncKOI8_R_CtypeTable[*p] & - (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); + const UChar* p = *pp; - return ((v != 0) ? TRUE : FALSE); + (*pp)++; + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + int v = (EncKOI8_R_CtypeTable[*p] & + (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); + return (v != 0 ? TRUE : FALSE); + } + return FALSE; } static int -koi8_r_code_is_ctype(OnigCodePoint code, unsigned int ctype) +koi8_r_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_KOI8_R_CTYPE(code, ctype); @@ -106,39 +148,116 @@ koi8_r_code_is_ctype(OnigCodePoint code, unsigned int ctype) return FALSE; } +static int +koi8_r_get_all_pair_ambig_codes(OnigAmbigType flag, + OnigPairAmbigCodes** ccs) +{ + static OnigPairAmbigCodes cc[] = { + { 0xc0, 0xe0 }, + { 0xc1, 0xe1 }, + { 0xc2, 0xe2 }, + { 0xc3, 0xe3 }, + { 0xc4, 0xe4 }, + { 0xc5, 0xe5 }, + { 0xc6, 0xe6 }, + { 0xc7, 0xe7 }, + { 0xc8, 0xe8 }, + { 0xc9, 0xe9 }, + { 0xca, 0xea }, + { 0xcb, 0xeb }, + { 0xcc, 0xec }, + { 0xcd, 0xed }, + { 0xce, 0xee }, + { 0xcf, 0xef }, + + { 0xd0, 0xf0 }, + { 0xd1, 0xf1 }, + { 0xd2, 0xf2 }, + { 0xd3, 0xf3 }, + { 0xd4, 0xf4 }, + { 0xd5, 0xf5 }, + { 0xd6, 0xf6 }, + { 0xd7, 0xf7 }, + { 0xd8, 0xf8 }, + { 0xd9, 0xf9 }, + { 0xda, 0xfa }, + { 0xdb, 0xfb }, + { 0xdc, 0xfc }, + { 0xdd, 0xfd }, + { 0xde, 0xfe }, + { 0xdf, 0xff }, + + { 0xe0, 0xc0 }, + { 0xe1, 0xc1 }, + { 0xe2, 0xc2 }, + { 0xe3, 0xc3 }, + { 0xe4, 0xc4 }, + { 0xe5, 0xc5 }, + { 0xe6, 0xc6 }, + { 0xe7, 0xc7 }, + { 0xe8, 0xc8 }, + { 0xe9, 0xc9 }, + { 0xea, 0xca }, + { 0xeb, 0xcb }, + { 0xec, 0xcc }, + { 0xed, 0xcd }, + { 0xee, 0xce }, + { 0xef, 0xcf }, + + { 0xf0, 0xd0 }, + { 0xf1, 0xd1 }, + { 0xf2, 0xd2 }, + { 0xf3, 0xd3 }, + { 0xf4, 0xd4 }, + { 0xf5, 0xd5 }, + { 0xf6, 0xd6 }, + { 0xf7, 0xd7 }, + { 0xf8, 0xd8 }, + { 0xf9, 0xd9 }, + { 0xfa, 0xda }, + { 0xfb, 0xdb }, + { 0xfc, 0xdc }, + { 0xfe, 0xde }, + { 0xff, 0xdf } + }; + + if (flag == ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) { + *ccs = OnigAsciiPairAmbigCodes; + return 52; + } + if (flag == ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) { + *ccs = cc; + return sizeof(cc) / sizeof(OnigPairAmbigCodes); + } + else + return 0; +} + OnigEncodingType OnigEncodingKOI8_R = { + onigenc_single_byte_mbc_enc_len, + "KOI8-R", /* name */ + 1, /* max enc length */ + 1, /* min enc length */ + (ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE ), { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ }, - "KOI8-R", /* name */ - 1, /* max byte length */ - FALSE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_SB, /* ctype_support_level */ - TRUE, /* is continuous sb mb codepoint */ + onigenc_is_mbc_newline_0x0a, onigenc_single_byte_mbc_to_code, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, - koi8_r_mbc_to_lower, - koi8_r_mbc_is_case_ambig, - koi8_r_code_is_ctype, - onigenc_nothing_get_ctype_code_range, + koi8_r_mbc_to_normalize, + koi8_r_is_mbc_ambiguous, + koi8_r_get_all_pair_ambig_codes, + onigenc_nothing_get_all_comp_ambig_codes, + koi8_r_is_code_ctype, + onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, - onigenc_single_byte_is_allowed_reverse_match, - onigenc_nothing_get_all_fold_match_code, - onigenc_nothing_get_fold_match_info + onigenc_always_true_is_allowed_reverse_match }; diff --git a/ext/mbstring/oniguruma/enc/mktable.c b/ext/mbstring/oniguruma/enc/mktable.c index 67e9a61313b9..6b9ef4c5b5b1 100644 --- a/ext/mbstring/oniguruma/enc/mktable.c +++ b/ext/mbstring/oniguruma/enc/mktable.c @@ -1,32 +1,55 @@ /********************************************************************** - mktable.c - - Copyright (C) 2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2004 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include #define NOT_RUBY #include "regenc.h" -#define ISO_8859_1 0 -#define ISO_8859_2 1 -#define ISO_8859_3 2 -#define ISO_8859_4 3 -#define ISO_8859_5 4 -#define ISO_8859_6 5 -#define ISO_8859_7 6 -#define ISO_8859_8 7 -#define ISO_8859_9 8 -#define ISO_8859_10 9 -#define ISO_8859_11 10 -#define ISO_8859_13 11 -#define ISO_8859_14 12 -#define ISO_8859_15 13 -#define ISO_8859_16 14 -#define KOI8 15 -#define KOI8_R 16 +#define UNICODE_ISO_8859_1 0 +#define ISO_8859_1 1 +#define ISO_8859_2 2 +#define ISO_8859_3 3 +#define ISO_8859_4 4 +#define ISO_8859_5 5 +#define ISO_8859_6 6 +#define ISO_8859_7 7 +#define ISO_8859_8 8 +#define ISO_8859_9 9 +#define ISO_8859_10 10 +#define ISO_8859_11 11 +#define ISO_8859_13 12 +#define ISO_8859_14 13 +#define ISO_8859_15 14 +#define ISO_8859_16 15 +#define KOI8 16 +#define KOI8_R 17 typedef struct { int num; @@ -34,6 +57,7 @@ typedef struct { } ENC_INFO; static ENC_INFO Info[] = { + { UNICODE_ISO_8859_1, "UNICODE_ISO_8859_1" }, { ISO_8859_1, "ISO_8859_1" }, { ISO_8859_2, "ISO_8859_2" }, { ISO_8859_3, "ISO_8859_3" }, @@ -60,6 +84,7 @@ static int IsAlpha(int enc, int c) if (c >= 0x61 && c <= 0x7a) return 1; switch (enc) { + case UNICODE_ISO_8859_1: case ISO_8859_1: case ISO_8859_9: if (c == 0xaa) return 1; @@ -232,6 +257,7 @@ static int IsBlank(int enc, int c) if (c == 0x09 || c == 0x20) return 1; switch (enc) { + case UNICODE_ISO_8859_1: case ISO_8859_1: case ISO_8859_2: case ISO_8859_3: @@ -267,6 +293,9 @@ static int IsCntrl(int enc, int c) if (c >= 0x00 && c <= 0x1F) return 1; switch (enc) { + case UNICODE_ISO_8859_1: + if (c == 0xad) return 1; + /* fall */ case ISO_8859_1: case ISO_8859_2: case ISO_8859_3: @@ -286,6 +315,7 @@ static int IsCntrl(int enc, int c) if (c >= 0x7f && c <= 0x9F) return 1; break; + case KOI8_R: if (c == 0x7f) return 1; break; @@ -308,6 +338,7 @@ static int IsGraph(int enc, int c) if (c >= 0x21 && c <= 0x7e) return 1; switch (enc) { + case UNICODE_ISO_8859_1: case ISO_8859_1: case ISO_8859_2: case ISO_8859_4: @@ -376,6 +407,7 @@ static int IsLower(int enc, int c) if (c >= 0x61 && c <= 0x7a) return 1; switch (enc) { + case UNICODE_ISO_8859_1: case ISO_8859_1: case ISO_8859_9: if (c == 0xaa) return 1; @@ -504,6 +536,10 @@ static int IsPrint(int enc, int c) if (c >= 0x20 && c <= 0x7e) return 1; switch (enc) { + case UNICODE_ISO_8859_1: + if (c >= 0x09 && c <= 0x0d) return 1; + if (c == 0x85) return 1; + /* fall */ case ISO_8859_1: case ISO_8859_2: case ISO_8859_4: @@ -572,11 +608,11 @@ static int IsPrint(int enc, int c) static int IsPunct(int enc, int c) { -#ifndef BY_UNICODE_PROPERTY - if (c == 0x24 || c == 0x2b || c == 0x5e || c == 0x60 || - c == 0x7c || c == 0x7e) return 1; - if (c >= 0x3c && c <= 0x3e) return 1; -#endif + if (enc == UNICODE_ISO_8859_1) { + if (c == 0x24 || c == 0x2b || c == 0x5e || c == 0x60 || + c == 0x7c || c == 0x7e) return 1; + if (c >= 0x3c && c <= 0x3e) return 1; + } if (c >= 0x21 && c <= 0x23) return 1; if (c >= 0x25 && c <= 0x2a) return 1; @@ -592,9 +628,11 @@ static int IsPunct(int enc, int c) case ISO_8859_1: case ISO_8859_9: case ISO_8859_15: + if (c == 0xad) return 1; + /* fall */ + case UNICODE_ISO_8859_1: if (c == 0xa1) return 1; if (c == 0xab) return 1; - if (c == 0xad) return 1; if (c == 0xb7) return 1; if (c == 0xbb) return 1; if (c == 0xbf) return 1; @@ -675,6 +713,9 @@ static int IsSpace(int enc, int c) if (c == 0x20) return 1; switch (enc) { + case UNICODE_ISO_8859_1: + if (c == 0x85) return 1; + /* fall */ case ISO_8859_1: case ISO_8859_2: case ISO_8859_3: @@ -710,6 +751,7 @@ static int IsUpper(int enc, int c) if (c >= 0x41 && c <= 0x5a) return 1; switch (enc) { + case UNICODE_ISO_8859_1: case ISO_8859_1: case ISO_8859_9: if (c >= 0xc0 && c <= 0xd6) return 1; @@ -844,6 +886,7 @@ static int IsWord(int enc, int c) if (c >= 0x61 && c <= 0x7a) return 1; switch (enc) { + case UNICODE_ISO_8859_1: case ISO_8859_1: case ISO_8859_9: if (c == 0xaa) return 1; @@ -1019,6 +1062,12 @@ static int IsAscii(int enc, int c) return 0; } +static int IsNewline(int enc, int c) +{ + if (c == 0x0a) return 1; + return 0; +} + static int exec(FILE* fp, ENC_INFO* einfo) { #define NCOL 8 @@ -1032,19 +1081,20 @@ static int exec(FILE* fp, ENC_INFO* einfo) for (c = 0; c < 256; c++) { val = 0; - if (IsAlpha (enc, c)) val |= ONIGENC_CTYPE_ALPHA; - if (IsBlank (enc, c)) val |= ONIGENC_CTYPE_BLANK; - if (IsCntrl (enc, c)) val |= ONIGENC_CTYPE_CNTRL; - if (IsDigit (enc, c)) val |= ONIGENC_CTYPE_DIGIT; - if (IsGraph (enc, c)) val |= ONIGENC_CTYPE_GRAPH; - if (IsLower (enc, c)) val |= ONIGENC_CTYPE_LOWER; - if (IsPrint (enc, c)) val |= ONIGENC_CTYPE_PRINT; - if (IsPunct (enc, c)) val |= ONIGENC_CTYPE_PUNCT; - if (IsSpace (enc, c)) val |= ONIGENC_CTYPE_SPACE; - if (IsUpper (enc, c)) val |= ONIGENC_CTYPE_UPPER; - if (IsXDigit(enc, c)) val |= ONIGENC_CTYPE_XDIGIT; - if (IsWord (enc, c)) val |= ONIGENC_CTYPE_WORD; - if (IsAscii (enc, c)) val |= ONIGENC_CTYPE_ASCII; + if (IsNewline(enc, c)) val |= ONIGENC_CTYPE_NEWLINE; + if (IsAlpha (enc, c)) val |= ONIGENC_CTYPE_ALPHA; + if (IsBlank (enc, c)) val |= ONIGENC_CTYPE_BLANK; + if (IsCntrl (enc, c)) val |= ONIGENC_CTYPE_CNTRL; + if (IsDigit (enc, c)) val |= ONIGENC_CTYPE_DIGIT; + if (IsGraph (enc, c)) val |= ONIGENC_CTYPE_GRAPH; + if (IsLower (enc, c)) val |= ONIGENC_CTYPE_LOWER; + if (IsPrint (enc, c)) val |= ONIGENC_CTYPE_PRINT; + if (IsPunct (enc, c)) val |= ONIGENC_CTYPE_PUNCT; + if (IsSpace (enc, c)) val |= ONIGENC_CTYPE_SPACE; + if (IsUpper (enc, c)) val |= ONIGENC_CTYPE_UPPER; + if (IsXDigit(enc, c)) val |= ONIGENC_CTYPE_XDIGIT; + if (IsWord (enc, c)) val |= ONIGENC_CTYPE_WORD; + if (IsAscii (enc, c)) val |= ONIGENC_CTYPE_ASCII; if (c % NCOL == 0) fputs(" ", fp); fprintf(fp, "0x%04x", val); diff --git a/ext/mbstring/oniguruma/enc/sjis.c b/ext/mbstring/oniguruma/enc/sjis.c index 8485910e6964..e13407bccfd9 100644 --- a/ext/mbstring/oniguruma/enc/sjis.c +++ b/ext/mbstring/oniguruma/enc/sjis.c @@ -1,12 +1,53 @@ /********************************************************************** - sjis.c - Oniguruma (regular expression library) - - Copyright (C) 2003-2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regenc.h" +static int EncLen_SJIS[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 +}; + static const char SJIS_CAN_BE_TRAIL_TABLE[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -26,17 +67,39 @@ static const char SJIS_CAN_BE_TRAIL_TABLE[256] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 }; -#define SJIS_ISMB_FIRST(byte) (OnigEncodingSJIS.len_table[byte] > 1) +#define SJIS_ISMB_FIRST(byte) (EncLen_SJIS[byte] > 1) #define SJIS_ISMB_TRAIL(byte) SJIS_CAN_BE_TRAIL_TABLE[(byte)] +static int +sjis_mbc_enc_len(const UChar* p) +{ + return EncLen_SJIS[*p]; +} + +extern int +sjis_code_to_mbclen(OnigCodePoint code) +{ + if (code < 256) { + if (EncLen_SJIS[(int )code] == 1) + return 1; + else + return 0; + } + else if (code <= 0xffff) { + return 2; + } + else + return 0; +} + static OnigCodePoint -sjis_mbc_to_code(UChar* p, UChar* end) +sjis_mbc_to_code(const UChar* p, const UChar* end) { int c, i, len; OnigCodePoint n; + len = enc_len(ONIG_ENCODING_SJIS, p); c = *p++; - len = enc_len(ONIG_ENCODING_SJIS, c); n = c; if (len == 1) return n; @@ -57,43 +120,58 @@ sjis_code_to_mbc(OnigCodePoint code, UChar *buf) *p++ = (UChar )(code & 0xff); #if 0 - if (enc_len(ONIG_ENCODING_SJIS, buf[0]) != (p - buf)) + if (enc_len(ONIG_ENCODING_SJIS, buf) != (p - buf)) return REGERR_INVALID_WIDE_CHAR_VALUE; #endif return p - buf; } static int -sjis_mbc_to_lower(UChar* p, UChar* lower) +sjis_mbc_to_normalize(OnigAmbigType flag, + const UChar** pp, const UChar* end, UChar* lower) { - int len; + const UChar* p = *pp; if (ONIGENC_IS_MBC_ASCII(p)) { - *lower = ONIGENC_ASCII_CODE_TO_LOWER_CASE(*p); + if ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0) { + *lower = ONIGENC_ASCII_CODE_TO_LOWER_CASE(*p); + } + else { + *lower = *p; + } + + (*pp)++; return 1; } else { - len = enc_len(ONIG_ENCODING_SJIS, *p); + int len = enc_len(ONIG_ENCODING_SJIS, p); + if (lower != p) { - /* memcpy(lower, p, len); */ int i; for (i = 0; i < len; i++) { *lower++ = *p++; } } + (*pp) += len; return len; /* return byte length of converted char to lower */ } } static int -sjis_code_is_ctype(OnigCodePoint code, unsigned int ctype) +sjis_is_mbc_ambiguous(OnigAmbigType flag, const UChar** pp, const UChar* end) +{ + return onigenc_mbn_is_mbc_ambiguous(ONIG_ENCODING_SJIS, flag, pp, end); + +} + +static int +sjis_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if ((ctype & ONIGENC_CTYPE_WORD) != 0) { if (code < 128) return ONIGENC_IS_ASCII_CODE_CTYPE(code, ctype); else { - int first = onigenc_mb2_code_to_mbc_first(code); - return (enc_len(ONIG_ENCODING_SJIS, first) > 1 ? TRUE : FALSE); + return (sjis_code_to_mbclen(code) > 1 ? TRUE : FALSE); } ctype &= ~ONIGENC_CTYPE_WORD; @@ -107,12 +185,12 @@ sjis_code_is_ctype(OnigCodePoint code, unsigned int ctype) } static UChar* -sjis_left_adjust_char_head(UChar* start, UChar* s) +sjis_left_adjust_char_head(const UChar* start, const UChar* s) { - UChar *p; + const UChar *p; int len; - if (s <= start) return s; + if (s <= start) return (UChar* )s; p = s; if (SJIS_ISMB_TRAIL(*p)) { @@ -123,52 +201,43 @@ sjis_left_adjust_char_head(UChar* start, UChar* s) } } } - len = enc_len(ONIG_ENCODING_SJIS, *p); - if (p + len > s) return p; + len = enc_len(ONIG_ENCODING_SJIS, p); + if (p + len > s) return (UChar* )p; p += len; - return p + ((s - p) & ~1); + return (UChar* )(p + ((s - p) & ~1)); } static int -sjis_is_allowed_reverse_match(UChar* s, UChar* end) +sjis_is_allowed_reverse_match(const UChar* s, const UChar* end) { - UChar c = *s; + const UChar c = *s; return (SJIS_ISMB_TRAIL(c) ? FALSE : TRUE); } OnigEncodingType OnigEncodingSJIS = { - { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 - }, + sjis_mbc_enc_len, "Shift_JIS", /* name */ 2, /* max byte length */ - FALSE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_SB, /* ctype_support_level */ - FALSE, /* is continuous sb mb codepoint */ + 1, /* min byte length */ + ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE, + { + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ + }, + onigenc_is_mbc_newline_0x0a, sjis_mbc_to_code, - onigenc_mb2_code_to_mbclen, + sjis_code_to_mbclen, sjis_code_to_mbc, - sjis_mbc_to_lower, - onigenc_mbn_mbc_is_case_ambig, - sjis_code_is_ctype, - onigenc_nothing_get_ctype_code_range, + sjis_mbc_to_normalize, + sjis_is_mbc_ambiguous, + onigenc_ascii_get_all_pair_ambig_codes, + onigenc_nothing_get_all_comp_ambig_codes, + sjis_is_code_ctype, + onigenc_not_support_get_ctype_code_range, sjis_left_adjust_char_head, - sjis_is_allowed_reverse_match, - onigenc_nothing_get_all_fold_match_code, - onigenc_nothing_get_fold_match_info + sjis_is_allowed_reverse_match }; diff --git a/ext/mbstring/oniguruma/enc/unicode.c b/ext/mbstring/oniguruma/enc/unicode.c new file mode 100644 index 000000000000..e3be9450a511 --- /dev/null +++ b/ext/mbstring/oniguruma/enc/unicode.c @@ -0,0 +1,3400 @@ +/********************************************************************** + unicode.c - Oniguruma (regular expression library) +**********************************************************************/ +/*- + * Copyright (c) 2002-2004 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "regenc.h" + + +unsigned short OnigEnc_Unicode_ISO_8859_1_CtypeTable[256] = { + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x228c, 0x2289, 0x2288, 0x2288, 0x2288, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2284, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, + 0x38b0, 0x38b0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x21a0, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x31a0, + 0x21a0, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x2008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0288, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0284, 0x01a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, + 0x00a0, 0x00a0, 0x10e2, 0x01a0, 0x00a0, 0x00a8, 0x00a0, 0x00a0, + 0x00a0, 0x00a0, 0x10a0, 0x10a0, 0x00a0, 0x10e2, 0x00a0, 0x01a0, + 0x00a0, 0x10a0, 0x10e2, 0x01a0, 0x10a0, 0x10a0, 0x10a0, 0x01a0, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x00a0, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x00a0, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2 +}; + +static OnigCodePoint CRAlnum[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 414, +#else + 9, +#endif + 0x0030, 0x0039, + 0x0041, 0x005a, + 0x0061, 0x007a, + 0x00aa, 0x00aa, + 0x00b5, 0x00b5, + 0x00ba, 0x00ba, + 0x00c0, 0x00d6, + 0x00d8, 0x00f6, + 0x00f8, 0x0236 +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + , + 0x0250, 0x02c1, + 0x02c6, 0x02d1, + 0x02e0, 0x02e4, + 0x02ee, 0x02ee, + 0x0300, 0x0357, + 0x035d, 0x036f, + 0x037a, 0x037a, + 0x0386, 0x0386, + 0x0388, 0x038a, + 0x038c, 0x038c, + 0x038e, 0x03a1, + 0x03a3, 0x03ce, + 0x03d0, 0x03f5, + 0x03f7, 0x03fb, + 0x0400, 0x0481, + 0x0483, 0x0486, + 0x0488, 0x04ce, + 0x04d0, 0x04f5, + 0x04f8, 0x04f9, + 0x0500, 0x050f, + 0x0531, 0x0556, + 0x0559, 0x0559, + 0x0561, 0x0587, + 0x0591, 0x05a1, + 0x05a3, 0x05b9, + 0x05bb, 0x05bd, + 0x05bf, 0x05bf, + 0x05c1, 0x05c2, + 0x05c4, 0x05c4, + 0x05d0, 0x05ea, + 0x05f0, 0x05f2, + 0x0610, 0x0615, + 0x0621, 0x063a, + 0x0640, 0x0658, + 0x0660, 0x0669, + 0x066e, 0x06d3, + 0x06d5, 0x06dc, + 0x06de, 0x06e8, + 0x06ea, 0x06fc, + 0x06ff, 0x06ff, + 0x0710, 0x074a, + 0x074d, 0x074f, + 0x0780, 0x07b1, + 0x0901, 0x0939, + 0x093c, 0x094d, + 0x0950, 0x0954, + 0x0958, 0x0963, + 0x0966, 0x096f, + 0x0981, 0x0983, + 0x0985, 0x098c, + 0x098f, 0x0990, + 0x0993, 0x09a8, + 0x09aa, 0x09b0, + 0x09b2, 0x09b2, + 0x09b6, 0x09b9, + 0x09bc, 0x09c4, + 0x09c7, 0x09c8, + 0x09cb, 0x09cd, + 0x09d7, 0x09d7, + 0x09dc, 0x09dd, + 0x09df, 0x09e3, + 0x09e6, 0x09f1, + 0x0a01, 0x0a03, + 0x0a05, 0x0a0a, + 0x0a0f, 0x0a10, + 0x0a13, 0x0a28, + 0x0a2a, 0x0a30, + 0x0a32, 0x0a33, + 0x0a35, 0x0a36, + 0x0a38, 0x0a39, + 0x0a3c, 0x0a3c, + 0x0a3e, 0x0a42, + 0x0a47, 0x0a48, + 0x0a4b, 0x0a4d, + 0x0a59, 0x0a5c, + 0x0a5e, 0x0a5e, + 0x0a66, 0x0a74, + 0x0a81, 0x0a83, + 0x0a85, 0x0a8d, + 0x0a8f, 0x0a91, + 0x0a93, 0x0aa8, + 0x0aaa, 0x0ab0, + 0x0ab2, 0x0ab3, + 0x0ab5, 0x0ab9, + 0x0abc, 0x0ac5, + 0x0ac7, 0x0ac9, + 0x0acb, 0x0acd, + 0x0ad0, 0x0ad0, + 0x0ae0, 0x0ae3, + 0x0ae6, 0x0aef, + 0x0b01, 0x0b03, + 0x0b05, 0x0b0c, + 0x0b0f, 0x0b10, + 0x0b13, 0x0b28, + 0x0b2a, 0x0b30, + 0x0b32, 0x0b33, + 0x0b35, 0x0b39, + 0x0b3c, 0x0b43, + 0x0b47, 0x0b48, + 0x0b4b, 0x0b4d, + 0x0b56, 0x0b57, + 0x0b5c, 0x0b5d, + 0x0b5f, 0x0b61, + 0x0b66, 0x0b6f, + 0x0b71, 0x0b71, + 0x0b82, 0x0b83, + 0x0b85, 0x0b8a, + 0x0b8e, 0x0b90, + 0x0b92, 0x0b95, + 0x0b99, 0x0b9a, + 0x0b9c, 0x0b9c, + 0x0b9e, 0x0b9f, + 0x0ba3, 0x0ba4, + 0x0ba8, 0x0baa, + 0x0bae, 0x0bb5, + 0x0bb7, 0x0bb9, + 0x0bbe, 0x0bc2, + 0x0bc6, 0x0bc8, + 0x0bca, 0x0bcd, + 0x0bd7, 0x0bd7, + 0x0be7, 0x0bef, + 0x0c01, 0x0c03, + 0x0c05, 0x0c0c, + 0x0c0e, 0x0c10, + 0x0c12, 0x0c28, + 0x0c2a, 0x0c33, + 0x0c35, 0x0c39, + 0x0c3e, 0x0c44, + 0x0c46, 0x0c48, + 0x0c4a, 0x0c4d, + 0x0c55, 0x0c56, + 0x0c60, 0x0c61, + 0x0c66, 0x0c6f, + 0x0c82, 0x0c83, + 0x0c85, 0x0c8c, + 0x0c8e, 0x0c90, + 0x0c92, 0x0ca8, + 0x0caa, 0x0cb3, + 0x0cb5, 0x0cb9, + 0x0cbc, 0x0cc4, + 0x0cc6, 0x0cc8, + 0x0cca, 0x0ccd, + 0x0cd5, 0x0cd6, + 0x0cde, 0x0cde, + 0x0ce0, 0x0ce1, + 0x0ce6, 0x0cef, + 0x0d02, 0x0d03, + 0x0d05, 0x0d0c, + 0x0d0e, 0x0d10, + 0x0d12, 0x0d28, + 0x0d2a, 0x0d39, + 0x0d3e, 0x0d43, + 0x0d46, 0x0d48, + 0x0d4a, 0x0d4d, + 0x0d57, 0x0d57, + 0x0d60, 0x0d61, + 0x0d66, 0x0d6f, + 0x0d82, 0x0d83, + 0x0d85, 0x0d96, + 0x0d9a, 0x0db1, + 0x0db3, 0x0dbb, + 0x0dbd, 0x0dbd, + 0x0dc0, 0x0dc6, + 0x0dca, 0x0dca, + 0x0dcf, 0x0dd4, + 0x0dd6, 0x0dd6, + 0x0dd8, 0x0ddf, + 0x0df2, 0x0df3, + 0x0e01, 0x0e3a, + 0x0e40, 0x0e4e, + 0x0e50, 0x0e59, + 0x0e81, 0x0e82, + 0x0e84, 0x0e84, + 0x0e87, 0x0e88, + 0x0e8a, 0x0e8a, + 0x0e8d, 0x0e8d, + 0x0e94, 0x0e97, + 0x0e99, 0x0e9f, + 0x0ea1, 0x0ea3, + 0x0ea5, 0x0ea5, + 0x0ea7, 0x0ea7, + 0x0eaa, 0x0eab, + 0x0ead, 0x0eb9, + 0x0ebb, 0x0ebd, + 0x0ec0, 0x0ec4, + 0x0ec6, 0x0ec6, + 0x0ec8, 0x0ecd, + 0x0ed0, 0x0ed9, + 0x0edc, 0x0edd, + 0x0f00, 0x0f00, + 0x0f18, 0x0f19, + 0x0f20, 0x0f29, + 0x0f35, 0x0f35, + 0x0f37, 0x0f37, + 0x0f39, 0x0f39, + 0x0f3e, 0x0f47, + 0x0f49, 0x0f6a, + 0x0f71, 0x0f84, + 0x0f86, 0x0f8b, + 0x0f90, 0x0f97, + 0x0f99, 0x0fbc, + 0x0fc6, 0x0fc6, + 0x1000, 0x1021, + 0x1023, 0x1027, + 0x1029, 0x102a, + 0x102c, 0x1032, + 0x1036, 0x1039, + 0x1040, 0x1049, + 0x1050, 0x1059, + 0x10a0, 0x10c5, + 0x10d0, 0x10f8, + 0x1100, 0x1159, + 0x115f, 0x11a2, + 0x11a8, 0x11f9, + 0x1200, 0x1206, + 0x1208, 0x1246, + 0x1248, 0x1248, + 0x124a, 0x124d, + 0x1250, 0x1256, + 0x1258, 0x1258, + 0x125a, 0x125d, + 0x1260, 0x1286, + 0x1288, 0x1288, + 0x128a, 0x128d, + 0x1290, 0x12ae, + 0x12b0, 0x12b0, + 0x12b2, 0x12b5, + 0x12b8, 0x12be, + 0x12c0, 0x12c0, + 0x12c2, 0x12c5, + 0x12c8, 0x12ce, + 0x12d0, 0x12d6, + 0x12d8, 0x12ee, + 0x12f0, 0x130e, + 0x1310, 0x1310, + 0x1312, 0x1315, + 0x1318, 0x131e, + 0x1320, 0x1346, + 0x1348, 0x135a, + 0x1369, 0x1371, + 0x13a0, 0x13f4, + 0x1401, 0x166c, + 0x166f, 0x1676, + 0x1681, 0x169a, + 0x16a0, 0x16ea, + 0x1700, 0x170c, + 0x170e, 0x1714, + 0x1720, 0x1734, + 0x1740, 0x1753, + 0x1760, 0x176c, + 0x176e, 0x1770, + 0x1772, 0x1773, + 0x1780, 0x17b3, + 0x17b6, 0x17d3, + 0x17d7, 0x17d7, + 0x17dc, 0x17dd, + 0x17e0, 0x17e9, + 0x180b, 0x180d, + 0x1810, 0x1819, + 0x1820, 0x1877, + 0x1880, 0x18a9, + 0x1900, 0x191c, + 0x1920, 0x192b, + 0x1930, 0x193b, + 0x1946, 0x196d, + 0x1970, 0x1974, + 0x1d00, 0x1d6b, + 0x1e00, 0x1e9b, + 0x1ea0, 0x1ef9, + 0x1f00, 0x1f15, + 0x1f18, 0x1f1d, + 0x1f20, 0x1f45, + 0x1f48, 0x1f4d, + 0x1f50, 0x1f57, + 0x1f59, 0x1f59, + 0x1f5b, 0x1f5b, + 0x1f5d, 0x1f5d, + 0x1f5f, 0x1f7d, + 0x1f80, 0x1fb4, + 0x1fb6, 0x1fbc, + 0x1fbe, 0x1fbe, + 0x1fc2, 0x1fc4, + 0x1fc6, 0x1fcc, + 0x1fd0, 0x1fd3, + 0x1fd6, 0x1fdb, + 0x1fe0, 0x1fec, + 0x1ff2, 0x1ff4, + 0x1ff6, 0x1ffc, + 0x2071, 0x2071, + 0x207f, 0x207f, + 0x20d0, 0x20ea, + 0x2102, 0x2102, + 0x2107, 0x2107, + 0x210a, 0x2113, + 0x2115, 0x2115, + 0x2119, 0x211d, + 0x2124, 0x2124, + 0x2126, 0x2126, + 0x2128, 0x2128, + 0x212a, 0x212d, + 0x212f, 0x2131, + 0x2133, 0x2139, + 0x213d, 0x213f, + 0x2145, 0x2149, + 0x3005, 0x3006, + 0x302a, 0x302f, + 0x3031, 0x3035, + 0x303b, 0x303c, + 0x3041, 0x3096, + 0x3099, 0x309a, + 0x309d, 0x309f, + 0x30a1, 0x30fa, + 0x30fc, 0x30ff, + 0x3105, 0x312c, + 0x3131, 0x318e, + 0x31a0, 0x31b7, + 0x31f0, 0x31ff, + 0x3400, 0x4db5, + 0x4e00, 0x9fa5, + 0xa000, 0xa48c, + 0xac00, 0xd7a3, + 0xf900, 0xfa2d, + 0xfa30, 0xfa6a, + 0xfb00, 0xfb06, + 0xfb13, 0xfb17, + 0xfb1d, 0xfb28, + 0xfb2a, 0xfb36, + 0xfb38, 0xfb3c, + 0xfb3e, 0xfb3e, + 0xfb40, 0xfb41, + 0xfb43, 0xfb44, + 0xfb46, 0xfbb1, + 0xfbd3, 0xfd3d, + 0xfd50, 0xfd8f, + 0xfd92, 0xfdc7, + 0xfdf0, 0xfdfb, + 0xfe00, 0xfe0f, + 0xfe20, 0xfe23, + 0xfe70, 0xfe74, + 0xfe76, 0xfefc, + 0xff10, 0xff19, + 0xff21, 0xff3a, + 0xff41, 0xff5a, + 0xff66, 0xffbe, + 0xffc2, 0xffc7, + 0xffca, 0xffcf, + 0xffd2, 0xffd7, + 0xffda, 0xffdc, + 0x10000, 0x1000b, + 0x1000d, 0x10026, + 0x10028, 0x1003a, + 0x1003c, 0x1003d, + 0x1003f, 0x1004d, + 0x10050, 0x1005d, + 0x10080, 0x100fa, + 0x10300, 0x1031e, + 0x10330, 0x10349, + 0x10380, 0x1039d, + 0x10400, 0x1049d, + 0x104a0, 0x104a9, + 0x10800, 0x10805, + 0x10808, 0x10808, + 0x1080a, 0x10835, + 0x10837, 0x10838, + 0x1083c, 0x1083c, + 0x1083f, 0x1083f, + 0x1d165, 0x1d169, + 0x1d16d, 0x1d172, + 0x1d17b, 0x1d182, + 0x1d185, 0x1d18b, + 0x1d1aa, 0x1d1ad, + 0x1d400, 0x1d454, + 0x1d456, 0x1d49c, + 0x1d49e, 0x1d49f, + 0x1d4a2, 0x1d4a2, + 0x1d4a5, 0x1d4a6, + 0x1d4a9, 0x1d4ac, + 0x1d4ae, 0x1d4b9, + 0x1d4bb, 0x1d4bb, + 0x1d4bd, 0x1d4c3, + 0x1d4c5, 0x1d505, + 0x1d507, 0x1d50a, + 0x1d50d, 0x1d514, + 0x1d516, 0x1d51c, + 0x1d51e, 0x1d539, + 0x1d53b, 0x1d53e, + 0x1d540, 0x1d544, + 0x1d546, 0x1d546, + 0x1d54a, 0x1d550, + 0x1d552, 0x1d6a3, + 0x1d6a8, 0x1d6c0, + 0x1d6c2, 0x1d6da, + 0x1d6dc, 0x1d6fa, + 0x1d6fc, 0x1d714, + 0x1d716, 0x1d734, + 0x1d736, 0x1d74e, + 0x1d750, 0x1d76e, + 0x1d770, 0x1d788, + 0x1d78a, 0x1d7a8, + 0x1d7aa, 0x1d7c2, + 0x1d7c4, 0x1d7c9, + 0x1d7ce, 0x1d7ff, + 0x20000, 0x2a6d6, + 0x2f800, 0x2fa1d, + 0xe0100, 0xe01ef +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +}; /* end of CRAlnum */ + +static OnigCodePoint CRAlpha[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 396, +#else + 8, +#endif + 0x0041, 0x005a, + 0x0061, 0x007a, + 0x00aa, 0x00aa, + 0x00b5, 0x00b5, + 0x00ba, 0x00ba, + 0x00c0, 0x00d6, + 0x00d8, 0x00f6, + 0x00f8, 0x0236 +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + , + 0x0250, 0x02c1, + 0x02c6, 0x02d1, + 0x02e0, 0x02e4, + 0x02ee, 0x02ee, + 0x0300, 0x0357, + 0x035d, 0x036f, + 0x037a, 0x037a, + 0x0386, 0x0386, + 0x0388, 0x038a, + 0x038c, 0x038c, + 0x038e, 0x03a1, + 0x03a3, 0x03ce, + 0x03d0, 0x03f5, + 0x03f7, 0x03fb, + 0x0400, 0x0481, + 0x0483, 0x0486, + 0x0488, 0x04ce, + 0x04d0, 0x04f5, + 0x04f8, 0x04f9, + 0x0500, 0x050f, + 0x0531, 0x0556, + 0x0559, 0x0559, + 0x0561, 0x0587, + 0x0591, 0x05a1, + 0x05a3, 0x05b9, + 0x05bb, 0x05bd, + 0x05bf, 0x05bf, + 0x05c1, 0x05c2, + 0x05c4, 0x05c4, + 0x05d0, 0x05ea, + 0x05f0, 0x05f2, + 0x0610, 0x0615, + 0x0621, 0x063a, + 0x0640, 0x0658, + 0x066e, 0x06d3, + 0x06d5, 0x06dc, + 0x06de, 0x06e8, + 0x06ea, 0x06ef, + 0x06fa, 0x06fc, + 0x06ff, 0x06ff, + 0x0710, 0x074a, + 0x074d, 0x074f, + 0x0780, 0x07b1, + 0x0901, 0x0939, + 0x093c, 0x094d, + 0x0950, 0x0954, + 0x0958, 0x0963, + 0x0981, 0x0983, + 0x0985, 0x098c, + 0x098f, 0x0990, + 0x0993, 0x09a8, + 0x09aa, 0x09b0, + 0x09b2, 0x09b2, + 0x09b6, 0x09b9, + 0x09bc, 0x09c4, + 0x09c7, 0x09c8, + 0x09cb, 0x09cd, + 0x09d7, 0x09d7, + 0x09dc, 0x09dd, + 0x09df, 0x09e3, + 0x09f0, 0x09f1, + 0x0a01, 0x0a03, + 0x0a05, 0x0a0a, + 0x0a0f, 0x0a10, + 0x0a13, 0x0a28, + 0x0a2a, 0x0a30, + 0x0a32, 0x0a33, + 0x0a35, 0x0a36, + 0x0a38, 0x0a39, + 0x0a3c, 0x0a3c, + 0x0a3e, 0x0a42, + 0x0a47, 0x0a48, + 0x0a4b, 0x0a4d, + 0x0a59, 0x0a5c, + 0x0a5e, 0x0a5e, + 0x0a70, 0x0a74, + 0x0a81, 0x0a83, + 0x0a85, 0x0a8d, + 0x0a8f, 0x0a91, + 0x0a93, 0x0aa8, + 0x0aaa, 0x0ab0, + 0x0ab2, 0x0ab3, + 0x0ab5, 0x0ab9, + 0x0abc, 0x0ac5, + 0x0ac7, 0x0ac9, + 0x0acb, 0x0acd, + 0x0ad0, 0x0ad0, + 0x0ae0, 0x0ae3, + 0x0b01, 0x0b03, + 0x0b05, 0x0b0c, + 0x0b0f, 0x0b10, + 0x0b13, 0x0b28, + 0x0b2a, 0x0b30, + 0x0b32, 0x0b33, + 0x0b35, 0x0b39, + 0x0b3c, 0x0b43, + 0x0b47, 0x0b48, + 0x0b4b, 0x0b4d, + 0x0b56, 0x0b57, + 0x0b5c, 0x0b5d, + 0x0b5f, 0x0b61, + 0x0b71, 0x0b71, + 0x0b82, 0x0b83, + 0x0b85, 0x0b8a, + 0x0b8e, 0x0b90, + 0x0b92, 0x0b95, + 0x0b99, 0x0b9a, + 0x0b9c, 0x0b9c, + 0x0b9e, 0x0b9f, + 0x0ba3, 0x0ba4, + 0x0ba8, 0x0baa, + 0x0bae, 0x0bb5, + 0x0bb7, 0x0bb9, + 0x0bbe, 0x0bc2, + 0x0bc6, 0x0bc8, + 0x0bca, 0x0bcd, + 0x0bd7, 0x0bd7, + 0x0c01, 0x0c03, + 0x0c05, 0x0c0c, + 0x0c0e, 0x0c10, + 0x0c12, 0x0c28, + 0x0c2a, 0x0c33, + 0x0c35, 0x0c39, + 0x0c3e, 0x0c44, + 0x0c46, 0x0c48, + 0x0c4a, 0x0c4d, + 0x0c55, 0x0c56, + 0x0c60, 0x0c61, + 0x0c82, 0x0c83, + 0x0c85, 0x0c8c, + 0x0c8e, 0x0c90, + 0x0c92, 0x0ca8, + 0x0caa, 0x0cb3, + 0x0cb5, 0x0cb9, + 0x0cbc, 0x0cc4, + 0x0cc6, 0x0cc8, + 0x0cca, 0x0ccd, + 0x0cd5, 0x0cd6, + 0x0cde, 0x0cde, + 0x0ce0, 0x0ce1, + 0x0d02, 0x0d03, + 0x0d05, 0x0d0c, + 0x0d0e, 0x0d10, + 0x0d12, 0x0d28, + 0x0d2a, 0x0d39, + 0x0d3e, 0x0d43, + 0x0d46, 0x0d48, + 0x0d4a, 0x0d4d, + 0x0d57, 0x0d57, + 0x0d60, 0x0d61, + 0x0d82, 0x0d83, + 0x0d85, 0x0d96, + 0x0d9a, 0x0db1, + 0x0db3, 0x0dbb, + 0x0dbd, 0x0dbd, + 0x0dc0, 0x0dc6, + 0x0dca, 0x0dca, + 0x0dcf, 0x0dd4, + 0x0dd6, 0x0dd6, + 0x0dd8, 0x0ddf, + 0x0df2, 0x0df3, + 0x0e01, 0x0e3a, + 0x0e40, 0x0e4e, + 0x0e81, 0x0e82, + 0x0e84, 0x0e84, + 0x0e87, 0x0e88, + 0x0e8a, 0x0e8a, + 0x0e8d, 0x0e8d, + 0x0e94, 0x0e97, + 0x0e99, 0x0e9f, + 0x0ea1, 0x0ea3, + 0x0ea5, 0x0ea5, + 0x0ea7, 0x0ea7, + 0x0eaa, 0x0eab, + 0x0ead, 0x0eb9, + 0x0ebb, 0x0ebd, + 0x0ec0, 0x0ec4, + 0x0ec6, 0x0ec6, + 0x0ec8, 0x0ecd, + 0x0edc, 0x0edd, + 0x0f00, 0x0f00, + 0x0f18, 0x0f19, + 0x0f35, 0x0f35, + 0x0f37, 0x0f37, + 0x0f39, 0x0f39, + 0x0f3e, 0x0f47, + 0x0f49, 0x0f6a, + 0x0f71, 0x0f84, + 0x0f86, 0x0f8b, + 0x0f90, 0x0f97, + 0x0f99, 0x0fbc, + 0x0fc6, 0x0fc6, + 0x1000, 0x1021, + 0x1023, 0x1027, + 0x1029, 0x102a, + 0x102c, 0x1032, + 0x1036, 0x1039, + 0x1050, 0x1059, + 0x10a0, 0x10c5, + 0x10d0, 0x10f8, + 0x1100, 0x1159, + 0x115f, 0x11a2, + 0x11a8, 0x11f9, + 0x1200, 0x1206, + 0x1208, 0x1246, + 0x1248, 0x1248, + 0x124a, 0x124d, + 0x1250, 0x1256, + 0x1258, 0x1258, + 0x125a, 0x125d, + 0x1260, 0x1286, + 0x1288, 0x1288, + 0x128a, 0x128d, + 0x1290, 0x12ae, + 0x12b0, 0x12b0, + 0x12b2, 0x12b5, + 0x12b8, 0x12be, + 0x12c0, 0x12c0, + 0x12c2, 0x12c5, + 0x12c8, 0x12ce, + 0x12d0, 0x12d6, + 0x12d8, 0x12ee, + 0x12f0, 0x130e, + 0x1310, 0x1310, + 0x1312, 0x1315, + 0x1318, 0x131e, + 0x1320, 0x1346, + 0x1348, 0x135a, + 0x13a0, 0x13f4, + 0x1401, 0x166c, + 0x166f, 0x1676, + 0x1681, 0x169a, + 0x16a0, 0x16ea, + 0x1700, 0x170c, + 0x170e, 0x1714, + 0x1720, 0x1734, + 0x1740, 0x1753, + 0x1760, 0x176c, + 0x176e, 0x1770, + 0x1772, 0x1773, + 0x1780, 0x17b3, + 0x17b6, 0x17d3, + 0x17d7, 0x17d7, + 0x17dc, 0x17dd, + 0x180b, 0x180d, + 0x1820, 0x1877, + 0x1880, 0x18a9, + 0x1900, 0x191c, + 0x1920, 0x192b, + 0x1930, 0x193b, + 0x1950, 0x196d, + 0x1970, 0x1974, + 0x1d00, 0x1d6b, + 0x1e00, 0x1e9b, + 0x1ea0, 0x1ef9, + 0x1f00, 0x1f15, + 0x1f18, 0x1f1d, + 0x1f20, 0x1f45, + 0x1f48, 0x1f4d, + 0x1f50, 0x1f57, + 0x1f59, 0x1f59, + 0x1f5b, 0x1f5b, + 0x1f5d, 0x1f5d, + 0x1f5f, 0x1f7d, + 0x1f80, 0x1fb4, + 0x1fb6, 0x1fbc, + 0x1fbe, 0x1fbe, + 0x1fc2, 0x1fc4, + 0x1fc6, 0x1fcc, + 0x1fd0, 0x1fd3, + 0x1fd6, 0x1fdb, + 0x1fe0, 0x1fec, + 0x1ff2, 0x1ff4, + 0x1ff6, 0x1ffc, + 0x2071, 0x2071, + 0x207f, 0x207f, + 0x20d0, 0x20ea, + 0x2102, 0x2102, + 0x2107, 0x2107, + 0x210a, 0x2113, + 0x2115, 0x2115, + 0x2119, 0x211d, + 0x2124, 0x2124, + 0x2126, 0x2126, + 0x2128, 0x2128, + 0x212a, 0x212d, + 0x212f, 0x2131, + 0x2133, 0x2139, + 0x213d, 0x213f, + 0x2145, 0x2149, + 0x3005, 0x3006, + 0x302a, 0x302f, + 0x3031, 0x3035, + 0x303b, 0x303c, + 0x3041, 0x3096, + 0x3099, 0x309a, + 0x309d, 0x309f, + 0x30a1, 0x30fa, + 0x30fc, 0x30ff, + 0x3105, 0x312c, + 0x3131, 0x318e, + 0x31a0, 0x31b7, + 0x31f0, 0x31ff, + 0x3400, 0x4db5, + 0x4e00, 0x9fa5, + 0xa000, 0xa48c, + 0xac00, 0xd7a3, + 0xf900, 0xfa2d, + 0xfa30, 0xfa6a, + 0xfb00, 0xfb06, + 0xfb13, 0xfb17, + 0xfb1d, 0xfb28, + 0xfb2a, 0xfb36, + 0xfb38, 0xfb3c, + 0xfb3e, 0xfb3e, + 0xfb40, 0xfb41, + 0xfb43, 0xfb44, + 0xfb46, 0xfbb1, + 0xfbd3, 0xfd3d, + 0xfd50, 0xfd8f, + 0xfd92, 0xfdc7, + 0xfdf0, 0xfdfb, + 0xfe00, 0xfe0f, + 0xfe20, 0xfe23, + 0xfe70, 0xfe74, + 0xfe76, 0xfefc, + 0xff21, 0xff3a, + 0xff41, 0xff5a, + 0xff66, 0xffbe, + 0xffc2, 0xffc7, + 0xffca, 0xffcf, + 0xffd2, 0xffd7, + 0xffda, 0xffdc, + 0x10000, 0x1000b, + 0x1000d, 0x10026, + 0x10028, 0x1003a, + 0x1003c, 0x1003d, + 0x1003f, 0x1004d, + 0x10050, 0x1005d, + 0x10080, 0x100fa, + 0x10300, 0x1031e, + 0x10330, 0x10349, + 0x10380, 0x1039d, + 0x10400, 0x1049d, + 0x10800, 0x10805, + 0x10808, 0x10808, + 0x1080a, 0x10835, + 0x10837, 0x10838, + 0x1083c, 0x1083c, + 0x1083f, 0x1083f, + 0x1d165, 0x1d169, + 0x1d16d, 0x1d172, + 0x1d17b, 0x1d182, + 0x1d185, 0x1d18b, + 0x1d1aa, 0x1d1ad, + 0x1d400, 0x1d454, + 0x1d456, 0x1d49c, + 0x1d49e, 0x1d49f, + 0x1d4a2, 0x1d4a2, + 0x1d4a5, 0x1d4a6, + 0x1d4a9, 0x1d4ac, + 0x1d4ae, 0x1d4b9, + 0x1d4bb, 0x1d4bb, + 0x1d4bd, 0x1d4c3, + 0x1d4c5, 0x1d505, + 0x1d507, 0x1d50a, + 0x1d50d, 0x1d514, + 0x1d516, 0x1d51c, + 0x1d51e, 0x1d539, + 0x1d53b, 0x1d53e, + 0x1d540, 0x1d544, + 0x1d546, 0x1d546, + 0x1d54a, 0x1d550, + 0x1d552, 0x1d6a3, + 0x1d6a8, 0x1d6c0, + 0x1d6c2, 0x1d6da, + 0x1d6dc, 0x1d6fa, + 0x1d6fc, 0x1d714, + 0x1d716, 0x1d734, + 0x1d736, 0x1d74e, + 0x1d750, 0x1d76e, + 0x1d770, 0x1d788, + 0x1d78a, 0x1d7a8, + 0x1d7aa, 0x1d7c2, + 0x1d7c4, 0x1d7c9, + 0x20000, 0x2a6d6, + 0x2f800, 0x2fa1d, + 0xe0100, 0xe01ef +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +}; /* end of CRAlpha */ + +static OnigCodePoint CRBlank[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 9, +#else + 3, +#endif + 0x0009, 0x0009, + 0x0020, 0x0020, + 0x00a0, 0x00a0 +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + , + 0x1680, 0x1680, + 0x180e, 0x180e, + 0x2000, 0x200a, + 0x202f, 0x202f, + 0x205f, 0x205f, + 0x3000, 0x3000 +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +}; /* end of CRBlank */ + +static OnigCodePoint CRCntrl[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 19, +#else + 3, +#endif + 0x0000, 0x001f, + 0x007f, 0x009f, + 0x00ad, 0x00ad +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + , + 0x0600, 0x0603, + 0x06dd, 0x06dd, + 0x070f, 0x070f, + 0x17b4, 0x17b5, + 0x200b, 0x200f, + 0x202a, 0x202e, + 0x2060, 0x2063, + 0x206a, 0x206f, + 0xd800, 0xf8ff, + 0xfeff, 0xfeff, + 0xfff9, 0xfffb, + 0x1d173, 0x1d17a, + 0xe0001, 0xe0001, + 0xe0020, 0xe007f, + 0xf0000, 0xffffd, + 0x100000, 0x10fffd +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +}; /* end of CRCntrl */ + +static OnigCodePoint CRDigit[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 23, +#else + 1, +#endif + 0x0030, 0x0039 +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + , + 0x0660, 0x0669, + 0x06f0, 0x06f9, + 0x0966, 0x096f, + 0x09e6, 0x09ef, + 0x0a66, 0x0a6f, + 0x0ae6, 0x0aef, + 0x0b66, 0x0b6f, + 0x0be7, 0x0bef, + 0x0c66, 0x0c6f, + 0x0ce6, 0x0cef, + 0x0d66, 0x0d6f, + 0x0e50, 0x0e59, + 0x0ed0, 0x0ed9, + 0x0f20, 0x0f29, + 0x1040, 0x1049, + 0x1369, 0x1371, + 0x17e0, 0x17e9, + 0x1810, 0x1819, + 0x1946, 0x194f, + 0xff10, 0xff19, + 0x104a0, 0x104a9, + 0x1d7ce, 0x1d7ff +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +}; /* end of CRDigit */ + +static OnigCodePoint CRGraph[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 405, +#else + 2, +#endif + 0x0021, 0x007e, + 0x00a1, 0x0236 +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + , + 0x0250, 0x0357, + 0x035d, 0x036f, + 0x0374, 0x0375, + 0x037a, 0x037a, + 0x037e, 0x037e, + 0x0384, 0x038a, + 0x038c, 0x038c, + 0x038e, 0x03a1, + 0x03a3, 0x03ce, + 0x03d0, 0x03fb, + 0x0400, 0x0486, + 0x0488, 0x04ce, + 0x04d0, 0x04f5, + 0x04f8, 0x04f9, + 0x0500, 0x050f, + 0x0531, 0x0556, + 0x0559, 0x055f, + 0x0561, 0x0587, + 0x0589, 0x058a, + 0x0591, 0x05a1, + 0x05a3, 0x05b9, + 0x05bb, 0x05c4, + 0x05d0, 0x05ea, + 0x05f0, 0x05f4, + 0x0600, 0x0603, + 0x060c, 0x0615, + 0x061b, 0x061b, + 0x061f, 0x061f, + 0x0621, 0x063a, + 0x0640, 0x0658, + 0x0660, 0x070d, + 0x070f, 0x074a, + 0x074d, 0x074f, + 0x0780, 0x07b1, + 0x0901, 0x0939, + 0x093c, 0x094d, + 0x0950, 0x0954, + 0x0958, 0x0970, + 0x0981, 0x0983, + 0x0985, 0x098c, + 0x098f, 0x0990, + 0x0993, 0x09a8, + 0x09aa, 0x09b0, + 0x09b2, 0x09b2, + 0x09b6, 0x09b9, + 0x09bc, 0x09c4, + 0x09c7, 0x09c8, + 0x09cb, 0x09cd, + 0x09d7, 0x09d7, + 0x09dc, 0x09dd, + 0x09df, 0x09e3, + 0x09e6, 0x09fa, + 0x0a01, 0x0a03, + 0x0a05, 0x0a0a, + 0x0a0f, 0x0a10, + 0x0a13, 0x0a28, + 0x0a2a, 0x0a30, + 0x0a32, 0x0a33, + 0x0a35, 0x0a36, + 0x0a38, 0x0a39, + 0x0a3c, 0x0a3c, + 0x0a3e, 0x0a42, + 0x0a47, 0x0a48, + 0x0a4b, 0x0a4d, + 0x0a59, 0x0a5c, + 0x0a5e, 0x0a5e, + 0x0a66, 0x0a74, + 0x0a81, 0x0a83, + 0x0a85, 0x0a8d, + 0x0a8f, 0x0a91, + 0x0a93, 0x0aa8, + 0x0aaa, 0x0ab0, + 0x0ab2, 0x0ab3, + 0x0ab5, 0x0ab9, + 0x0abc, 0x0ac5, + 0x0ac7, 0x0ac9, + 0x0acb, 0x0acd, + 0x0ad0, 0x0ad0, + 0x0ae0, 0x0ae3, + 0x0ae6, 0x0aef, + 0x0af1, 0x0af1, + 0x0b01, 0x0b03, + 0x0b05, 0x0b0c, + 0x0b0f, 0x0b10, + 0x0b13, 0x0b28, + 0x0b2a, 0x0b30, + 0x0b32, 0x0b33, + 0x0b35, 0x0b39, + 0x0b3c, 0x0b43, + 0x0b47, 0x0b48, + 0x0b4b, 0x0b4d, + 0x0b56, 0x0b57, + 0x0b5c, 0x0b5d, + 0x0b5f, 0x0b61, + 0x0b66, 0x0b71, + 0x0b82, 0x0b83, + 0x0b85, 0x0b8a, + 0x0b8e, 0x0b90, + 0x0b92, 0x0b95, + 0x0b99, 0x0b9a, + 0x0b9c, 0x0b9c, + 0x0b9e, 0x0b9f, + 0x0ba3, 0x0ba4, + 0x0ba8, 0x0baa, + 0x0bae, 0x0bb5, + 0x0bb7, 0x0bb9, + 0x0bbe, 0x0bc2, + 0x0bc6, 0x0bc8, + 0x0bca, 0x0bcd, + 0x0bd7, 0x0bd7, + 0x0be7, 0x0bfa, + 0x0c01, 0x0c03, + 0x0c05, 0x0c0c, + 0x0c0e, 0x0c10, + 0x0c12, 0x0c28, + 0x0c2a, 0x0c33, + 0x0c35, 0x0c39, + 0x0c3e, 0x0c44, + 0x0c46, 0x0c48, + 0x0c4a, 0x0c4d, + 0x0c55, 0x0c56, + 0x0c60, 0x0c61, + 0x0c66, 0x0c6f, + 0x0c82, 0x0c83, + 0x0c85, 0x0c8c, + 0x0c8e, 0x0c90, + 0x0c92, 0x0ca8, + 0x0caa, 0x0cb3, + 0x0cb5, 0x0cb9, + 0x0cbc, 0x0cc4, + 0x0cc6, 0x0cc8, + 0x0cca, 0x0ccd, + 0x0cd5, 0x0cd6, + 0x0cde, 0x0cde, + 0x0ce0, 0x0ce1, + 0x0ce6, 0x0cef, + 0x0d02, 0x0d03, + 0x0d05, 0x0d0c, + 0x0d0e, 0x0d10, + 0x0d12, 0x0d28, + 0x0d2a, 0x0d39, + 0x0d3e, 0x0d43, + 0x0d46, 0x0d48, + 0x0d4a, 0x0d4d, + 0x0d57, 0x0d57, + 0x0d60, 0x0d61, + 0x0d66, 0x0d6f, + 0x0d82, 0x0d83, + 0x0d85, 0x0d96, + 0x0d9a, 0x0db1, + 0x0db3, 0x0dbb, + 0x0dbd, 0x0dbd, + 0x0dc0, 0x0dc6, + 0x0dca, 0x0dca, + 0x0dcf, 0x0dd4, + 0x0dd6, 0x0dd6, + 0x0dd8, 0x0ddf, + 0x0df2, 0x0df4, + 0x0e01, 0x0e3a, + 0x0e3f, 0x0e5b, + 0x0e81, 0x0e82, + 0x0e84, 0x0e84, + 0x0e87, 0x0e88, + 0x0e8a, 0x0e8a, + 0x0e8d, 0x0e8d, + 0x0e94, 0x0e97, + 0x0e99, 0x0e9f, + 0x0ea1, 0x0ea3, + 0x0ea5, 0x0ea5, + 0x0ea7, 0x0ea7, + 0x0eaa, 0x0eab, + 0x0ead, 0x0eb9, + 0x0ebb, 0x0ebd, + 0x0ec0, 0x0ec4, + 0x0ec6, 0x0ec6, + 0x0ec8, 0x0ecd, + 0x0ed0, 0x0ed9, + 0x0edc, 0x0edd, + 0x0f00, 0x0f47, + 0x0f49, 0x0f6a, + 0x0f71, 0x0f8b, + 0x0f90, 0x0f97, + 0x0f99, 0x0fbc, + 0x0fbe, 0x0fcc, + 0x0fcf, 0x0fcf, + 0x1000, 0x1021, + 0x1023, 0x1027, + 0x1029, 0x102a, + 0x102c, 0x1032, + 0x1036, 0x1039, + 0x1040, 0x1059, + 0x10a0, 0x10c5, + 0x10d0, 0x10f8, + 0x10fb, 0x10fb, + 0x1100, 0x1159, + 0x115f, 0x11a2, + 0x11a8, 0x11f9, + 0x1200, 0x1206, + 0x1208, 0x1246, + 0x1248, 0x1248, + 0x124a, 0x124d, + 0x1250, 0x1256, + 0x1258, 0x1258, + 0x125a, 0x125d, + 0x1260, 0x1286, + 0x1288, 0x1288, + 0x128a, 0x128d, + 0x1290, 0x12ae, + 0x12b0, 0x12b0, + 0x12b2, 0x12b5, + 0x12b8, 0x12be, + 0x12c0, 0x12c0, + 0x12c2, 0x12c5, + 0x12c8, 0x12ce, + 0x12d0, 0x12d6, + 0x12d8, 0x12ee, + 0x12f0, 0x130e, + 0x1310, 0x1310, + 0x1312, 0x1315, + 0x1318, 0x131e, + 0x1320, 0x1346, + 0x1348, 0x135a, + 0x1361, 0x137c, + 0x13a0, 0x13f4, + 0x1401, 0x1676, + 0x1681, 0x169c, + 0x16a0, 0x16f0, + 0x1700, 0x170c, + 0x170e, 0x1714, + 0x1720, 0x1736, + 0x1740, 0x1753, + 0x1760, 0x176c, + 0x176e, 0x1770, + 0x1772, 0x1773, + 0x1780, 0x17dd, + 0x17e0, 0x17e9, + 0x17f0, 0x17f9, + 0x1800, 0x180d, + 0x1810, 0x1819, + 0x1820, 0x1877, + 0x1880, 0x18a9, + 0x1900, 0x191c, + 0x1920, 0x192b, + 0x1930, 0x193b, + 0x1940, 0x1940, + 0x1944, 0x196d, + 0x1970, 0x1974, + 0x19e0, 0x19ff, + 0x1d00, 0x1d6b, + 0x1e00, 0x1e9b, + 0x1ea0, 0x1ef9, + 0x1f00, 0x1f15, + 0x1f18, 0x1f1d, + 0x1f20, 0x1f45, + 0x1f48, 0x1f4d, + 0x1f50, 0x1f57, + 0x1f59, 0x1f59, + 0x1f5b, 0x1f5b, + 0x1f5d, 0x1f5d, + 0x1f5f, 0x1f7d, + 0x1f80, 0x1fb4, + 0x1fb6, 0x1fc4, + 0x1fc6, 0x1fd3, + 0x1fd6, 0x1fdb, + 0x1fdd, 0x1fef, + 0x1ff2, 0x1ff4, + 0x1ff6, 0x1ffe, + 0x200b, 0x2027, + 0x202a, 0x202e, + 0x2030, 0x2054, + 0x2057, 0x2057, + 0x2060, 0x2063, + 0x206a, 0x2071, + 0x2074, 0x208e, + 0x20a0, 0x20b1, + 0x20d0, 0x20ea, + 0x2100, 0x213b, + 0x213d, 0x214b, + 0x2153, 0x2183, + 0x2190, 0x23d0, + 0x2400, 0x2426, + 0x2440, 0x244a, + 0x2460, 0x2617, + 0x2619, 0x267d, + 0x2680, 0x2691, + 0x26a0, 0x26a1, + 0x2701, 0x2704, + 0x2706, 0x2709, + 0x270c, 0x2727, + 0x2729, 0x274b, + 0x274d, 0x274d, + 0x274f, 0x2752, + 0x2756, 0x2756, + 0x2758, 0x275e, + 0x2761, 0x2794, + 0x2798, 0x27af, + 0x27b1, 0x27be, + 0x27d0, 0x27eb, + 0x27f0, 0x2b0d, + 0x2e80, 0x2e99, + 0x2e9b, 0x2ef3, + 0x2f00, 0x2fd5, + 0x2ff0, 0x2ffb, + 0x3001, 0x303f, + 0x3041, 0x3096, + 0x3099, 0x30ff, + 0x3105, 0x312c, + 0x3131, 0x318e, + 0x3190, 0x31b7, + 0x31f0, 0x321e, + 0x3220, 0x3243, + 0x3250, 0x327d, + 0x327f, 0x32fe, + 0x3300, 0x4db5, + 0x4dc0, 0x9fa5, + 0xa000, 0xa48c, + 0xa490, 0xa4c6, + 0xac00, 0xd7a3, + 0xe000, 0xfa2d, + 0xfa30, 0xfa6a, + 0xfb00, 0xfb06, + 0xfb13, 0xfb17, + 0xfb1d, 0xfb36, + 0xfb38, 0xfb3c, + 0xfb3e, 0xfb3e, + 0xfb40, 0xfb41, + 0xfb43, 0xfb44, + 0xfb46, 0xfbb1, + 0xfbd3, 0xfd3f, + 0xfd50, 0xfd8f, + 0xfd92, 0xfdc7, + 0xfdf0, 0xfdfd, + 0xfe00, 0xfe0f, + 0xfe20, 0xfe23, + 0xfe30, 0xfe52, + 0xfe54, 0xfe66, + 0xfe68, 0xfe6b, + 0xfe70, 0xfe74, + 0xfe76, 0xfefc, + 0xfeff, 0xfeff, + 0xff01, 0xffbe, + 0xffc2, 0xffc7, + 0xffca, 0xffcf, + 0xffd2, 0xffd7, + 0xffda, 0xffdc, + 0xffe0, 0xffe6, + 0xffe8, 0xffee, + 0xfff9, 0xfffd, + 0x10000, 0x1000b, + 0x1000d, 0x10026, + 0x10028, 0x1003a, + 0x1003c, 0x1003d, + 0x1003f, 0x1004d, + 0x10050, 0x1005d, + 0x10080, 0x100fa, + 0x10100, 0x10102, + 0x10107, 0x10133, + 0x10137, 0x1013f, + 0x10300, 0x1031e, + 0x10320, 0x10323, + 0x10330, 0x1034a, + 0x10380, 0x1039d, + 0x1039f, 0x1039f, + 0x10400, 0x1049d, + 0x104a0, 0x104a9, + 0x10800, 0x10805, + 0x10808, 0x10808, + 0x1080a, 0x10835, + 0x10837, 0x10838, + 0x1083c, 0x1083c, + 0x1083f, 0x1083f, + 0x1d000, 0x1d0f5, + 0x1d100, 0x1d126, + 0x1d12a, 0x1d1dd, + 0x1d300, 0x1d356, + 0x1d400, 0x1d454, + 0x1d456, 0x1d49c, + 0x1d49e, 0x1d49f, + 0x1d4a2, 0x1d4a2, + 0x1d4a5, 0x1d4a6, + 0x1d4a9, 0x1d4ac, + 0x1d4ae, 0x1d4b9, + 0x1d4bb, 0x1d4bb, + 0x1d4bd, 0x1d4c3, + 0x1d4c5, 0x1d505, + 0x1d507, 0x1d50a, + 0x1d50d, 0x1d514, + 0x1d516, 0x1d51c, + 0x1d51e, 0x1d539, + 0x1d53b, 0x1d53e, + 0x1d540, 0x1d544, + 0x1d546, 0x1d546, + 0x1d54a, 0x1d550, + 0x1d552, 0x1d6a3, + 0x1d6a8, 0x1d7c9, + 0x1d7ce, 0x1d7ff, + 0x20000, 0x2a6d6, + 0x2f800, 0x2fa1d, + 0xe0001, 0xe0001, + 0xe0020, 0xe007f, + 0xe0100, 0xe01ef, + 0xf0000, 0xffffd, + 0x100000, 0x10fffd +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +}; /* end of CRGraph */ + +static OnigCodePoint CRLower[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 424, +#else + 6, +#endif + 0x0061, 0x007a, + 0x00aa, 0x00aa, + 0x00b5, 0x00b5, + 0x00ba, 0x00ba, + 0x00df, 0x00f6, + 0x00f8, 0x00ff +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + , + 0x0101, 0x0101, + 0x0103, 0x0103, + 0x0105, 0x0105, + 0x0107, 0x0107, + 0x0109, 0x0109, + 0x010b, 0x010b, + 0x010d, 0x010d, + 0x010f, 0x010f, + 0x0111, 0x0111, + 0x0113, 0x0113, + 0x0115, 0x0115, + 0x0117, 0x0117, + 0x0119, 0x0119, + 0x011b, 0x011b, + 0x011d, 0x011d, + 0x011f, 0x011f, + 0x0121, 0x0121, + 0x0123, 0x0123, + 0x0125, 0x0125, + 0x0127, 0x0127, + 0x0129, 0x0129, + 0x012b, 0x012b, + 0x012d, 0x012d, + 0x012f, 0x012f, + 0x0131, 0x0131, + 0x0133, 0x0133, + 0x0135, 0x0135, + 0x0137, 0x0138, + 0x013a, 0x013a, + 0x013c, 0x013c, + 0x013e, 0x013e, + 0x0140, 0x0140, + 0x0142, 0x0142, + 0x0144, 0x0144, + 0x0146, 0x0146, + 0x0148, 0x0149, + 0x014b, 0x014b, + 0x014d, 0x014d, + 0x014f, 0x014f, + 0x0151, 0x0151, + 0x0153, 0x0153, + 0x0155, 0x0155, + 0x0157, 0x0157, + 0x0159, 0x0159, + 0x015b, 0x015b, + 0x015d, 0x015d, + 0x015f, 0x015f, + 0x0161, 0x0161, + 0x0163, 0x0163, + 0x0165, 0x0165, + 0x0167, 0x0167, + 0x0169, 0x0169, + 0x016b, 0x016b, + 0x016d, 0x016d, + 0x016f, 0x016f, + 0x0171, 0x0171, + 0x0173, 0x0173, + 0x0175, 0x0175, + 0x0177, 0x0177, + 0x017a, 0x017a, + 0x017c, 0x017c, + 0x017e, 0x0180, + 0x0183, 0x0183, + 0x0185, 0x0185, + 0x0188, 0x0188, + 0x018c, 0x018d, + 0x0192, 0x0192, + 0x0195, 0x0195, + 0x0199, 0x019b, + 0x019e, 0x019e, + 0x01a1, 0x01a1, + 0x01a3, 0x01a3, + 0x01a5, 0x01a5, + 0x01a8, 0x01a8, + 0x01aa, 0x01ab, + 0x01ad, 0x01ad, + 0x01b0, 0x01b0, + 0x01b4, 0x01b4, + 0x01b6, 0x01b6, + 0x01b9, 0x01ba, + 0x01bd, 0x01bf, + 0x01c6, 0x01c6, + 0x01c9, 0x01c9, + 0x01cc, 0x01cc, + 0x01ce, 0x01ce, + 0x01d0, 0x01d0, + 0x01d2, 0x01d2, + 0x01d4, 0x01d4, + 0x01d6, 0x01d6, + 0x01d8, 0x01d8, + 0x01da, 0x01da, + 0x01dc, 0x01dd, + 0x01df, 0x01df, + 0x01e1, 0x01e1, + 0x01e3, 0x01e3, + 0x01e5, 0x01e5, + 0x01e7, 0x01e7, + 0x01e9, 0x01e9, + 0x01eb, 0x01eb, + 0x01ed, 0x01ed, + 0x01ef, 0x01f0, + 0x01f3, 0x01f3, + 0x01f5, 0x01f5, + 0x01f9, 0x01f9, + 0x01fb, 0x01fb, + 0x01fd, 0x01fd, + 0x01ff, 0x01ff, + 0x0201, 0x0201, + 0x0203, 0x0203, + 0x0205, 0x0205, + 0x0207, 0x0207, + 0x0209, 0x0209, + 0x020b, 0x020b, + 0x020d, 0x020d, + 0x020f, 0x020f, + 0x0211, 0x0211, + 0x0213, 0x0213, + 0x0215, 0x0215, + 0x0217, 0x0217, + 0x0219, 0x0219, + 0x021b, 0x021b, + 0x021d, 0x021d, + 0x021f, 0x021f, + 0x0221, 0x0221, + 0x0223, 0x0223, + 0x0225, 0x0225, + 0x0227, 0x0227, + 0x0229, 0x0229, + 0x022b, 0x022b, + 0x022d, 0x022d, + 0x022f, 0x022f, + 0x0231, 0x0231, + 0x0233, 0x0236, + 0x0250, 0x02af, + 0x0390, 0x0390, + 0x03ac, 0x03ce, + 0x03d0, 0x03d1, + 0x03d5, 0x03d7, + 0x03d9, 0x03d9, + 0x03db, 0x03db, + 0x03dd, 0x03dd, + 0x03df, 0x03df, + 0x03e1, 0x03e1, + 0x03e3, 0x03e3, + 0x03e5, 0x03e5, + 0x03e7, 0x03e7, + 0x03e9, 0x03e9, + 0x03eb, 0x03eb, + 0x03ed, 0x03ed, + 0x03ef, 0x03f3, + 0x03f5, 0x03f5, + 0x03f8, 0x03f8, + 0x03fb, 0x03fb, + 0x0430, 0x045f, + 0x0461, 0x0461, + 0x0463, 0x0463, + 0x0465, 0x0465, + 0x0467, 0x0467, + 0x0469, 0x0469, + 0x046b, 0x046b, + 0x046d, 0x046d, + 0x046f, 0x046f, + 0x0471, 0x0471, + 0x0473, 0x0473, + 0x0475, 0x0475, + 0x0477, 0x0477, + 0x0479, 0x0479, + 0x047b, 0x047b, + 0x047d, 0x047d, + 0x047f, 0x047f, + 0x0481, 0x0481, + 0x048b, 0x048b, + 0x048d, 0x048d, + 0x048f, 0x048f, + 0x0491, 0x0491, + 0x0493, 0x0493, + 0x0495, 0x0495, + 0x0497, 0x0497, + 0x0499, 0x0499, + 0x049b, 0x049b, + 0x049d, 0x049d, + 0x049f, 0x049f, + 0x04a1, 0x04a1, + 0x04a3, 0x04a3, + 0x04a5, 0x04a5, + 0x04a7, 0x04a7, + 0x04a9, 0x04a9, + 0x04ab, 0x04ab, + 0x04ad, 0x04ad, + 0x04af, 0x04af, + 0x04b1, 0x04b1, + 0x04b3, 0x04b3, + 0x04b5, 0x04b5, + 0x04b7, 0x04b7, + 0x04b9, 0x04b9, + 0x04bb, 0x04bb, + 0x04bd, 0x04bd, + 0x04bf, 0x04bf, + 0x04c2, 0x04c2, + 0x04c4, 0x04c4, + 0x04c6, 0x04c6, + 0x04c8, 0x04c8, + 0x04ca, 0x04ca, + 0x04cc, 0x04cc, + 0x04ce, 0x04ce, + 0x04d1, 0x04d1, + 0x04d3, 0x04d3, + 0x04d5, 0x04d5, + 0x04d7, 0x04d7, + 0x04d9, 0x04d9, + 0x04db, 0x04db, + 0x04dd, 0x04dd, + 0x04df, 0x04df, + 0x04e1, 0x04e1, + 0x04e3, 0x04e3, + 0x04e5, 0x04e5, + 0x04e7, 0x04e7, + 0x04e9, 0x04e9, + 0x04eb, 0x04eb, + 0x04ed, 0x04ed, + 0x04ef, 0x04ef, + 0x04f1, 0x04f1, + 0x04f3, 0x04f3, + 0x04f5, 0x04f5, + 0x04f9, 0x04f9, + 0x0501, 0x0501, + 0x0503, 0x0503, + 0x0505, 0x0505, + 0x0507, 0x0507, + 0x0509, 0x0509, + 0x050b, 0x050b, + 0x050d, 0x050d, + 0x050f, 0x050f, + 0x0561, 0x0587, + 0x1d00, 0x1d2b, + 0x1d62, 0x1d6b, + 0x1e01, 0x1e01, + 0x1e03, 0x1e03, + 0x1e05, 0x1e05, + 0x1e07, 0x1e07, + 0x1e09, 0x1e09, + 0x1e0b, 0x1e0b, + 0x1e0d, 0x1e0d, + 0x1e0f, 0x1e0f, + 0x1e11, 0x1e11, + 0x1e13, 0x1e13, + 0x1e15, 0x1e15, + 0x1e17, 0x1e17, + 0x1e19, 0x1e19, + 0x1e1b, 0x1e1b, + 0x1e1d, 0x1e1d, + 0x1e1f, 0x1e1f, + 0x1e21, 0x1e21, + 0x1e23, 0x1e23, + 0x1e25, 0x1e25, + 0x1e27, 0x1e27, + 0x1e29, 0x1e29, + 0x1e2b, 0x1e2b, + 0x1e2d, 0x1e2d, + 0x1e2f, 0x1e2f, + 0x1e31, 0x1e31, + 0x1e33, 0x1e33, + 0x1e35, 0x1e35, + 0x1e37, 0x1e37, + 0x1e39, 0x1e39, + 0x1e3b, 0x1e3b, + 0x1e3d, 0x1e3d, + 0x1e3f, 0x1e3f, + 0x1e41, 0x1e41, + 0x1e43, 0x1e43, + 0x1e45, 0x1e45, + 0x1e47, 0x1e47, + 0x1e49, 0x1e49, + 0x1e4b, 0x1e4b, + 0x1e4d, 0x1e4d, + 0x1e4f, 0x1e4f, + 0x1e51, 0x1e51, + 0x1e53, 0x1e53, + 0x1e55, 0x1e55, + 0x1e57, 0x1e57, + 0x1e59, 0x1e59, + 0x1e5b, 0x1e5b, + 0x1e5d, 0x1e5d, + 0x1e5f, 0x1e5f, + 0x1e61, 0x1e61, + 0x1e63, 0x1e63, + 0x1e65, 0x1e65, + 0x1e67, 0x1e67, + 0x1e69, 0x1e69, + 0x1e6b, 0x1e6b, + 0x1e6d, 0x1e6d, + 0x1e6f, 0x1e6f, + 0x1e71, 0x1e71, + 0x1e73, 0x1e73, + 0x1e75, 0x1e75, + 0x1e77, 0x1e77, + 0x1e79, 0x1e79, + 0x1e7b, 0x1e7b, + 0x1e7d, 0x1e7d, + 0x1e7f, 0x1e7f, + 0x1e81, 0x1e81, + 0x1e83, 0x1e83, + 0x1e85, 0x1e85, + 0x1e87, 0x1e87, + 0x1e89, 0x1e89, + 0x1e8b, 0x1e8b, + 0x1e8d, 0x1e8d, + 0x1e8f, 0x1e8f, + 0x1e91, 0x1e91, + 0x1e93, 0x1e93, + 0x1e95, 0x1e9b, + 0x1ea1, 0x1ea1, + 0x1ea3, 0x1ea3, + 0x1ea5, 0x1ea5, + 0x1ea7, 0x1ea7, + 0x1ea9, 0x1ea9, + 0x1eab, 0x1eab, + 0x1ead, 0x1ead, + 0x1eaf, 0x1eaf, + 0x1eb1, 0x1eb1, + 0x1eb3, 0x1eb3, + 0x1eb5, 0x1eb5, + 0x1eb7, 0x1eb7, + 0x1eb9, 0x1eb9, + 0x1ebb, 0x1ebb, + 0x1ebd, 0x1ebd, + 0x1ebf, 0x1ebf, + 0x1ec1, 0x1ec1, + 0x1ec3, 0x1ec3, + 0x1ec5, 0x1ec5, + 0x1ec7, 0x1ec7, + 0x1ec9, 0x1ec9, + 0x1ecb, 0x1ecb, + 0x1ecd, 0x1ecd, + 0x1ecf, 0x1ecf, + 0x1ed1, 0x1ed1, + 0x1ed3, 0x1ed3, + 0x1ed5, 0x1ed5, + 0x1ed7, 0x1ed7, + 0x1ed9, 0x1ed9, + 0x1edb, 0x1edb, + 0x1edd, 0x1edd, + 0x1edf, 0x1edf, + 0x1ee1, 0x1ee1, + 0x1ee3, 0x1ee3, + 0x1ee5, 0x1ee5, + 0x1ee7, 0x1ee7, + 0x1ee9, 0x1ee9, + 0x1eeb, 0x1eeb, + 0x1eed, 0x1eed, + 0x1eef, 0x1eef, + 0x1ef1, 0x1ef1, + 0x1ef3, 0x1ef3, + 0x1ef5, 0x1ef5, + 0x1ef7, 0x1ef7, + 0x1ef9, 0x1ef9, + 0x1f00, 0x1f07, + 0x1f10, 0x1f15, + 0x1f20, 0x1f27, + 0x1f30, 0x1f37, + 0x1f40, 0x1f45, + 0x1f50, 0x1f57, + 0x1f60, 0x1f67, + 0x1f70, 0x1f7d, + 0x1f80, 0x1f87, + 0x1f90, 0x1f97, + 0x1fa0, 0x1fa7, + 0x1fb0, 0x1fb4, + 0x1fb6, 0x1fb7, + 0x1fbe, 0x1fbe, + 0x1fc2, 0x1fc4, + 0x1fc6, 0x1fc7, + 0x1fd0, 0x1fd3, + 0x1fd6, 0x1fd7, + 0x1fe0, 0x1fe7, + 0x1ff2, 0x1ff4, + 0x1ff6, 0x1ff7, + 0x2071, 0x2071, + 0x207f, 0x207f, + 0x210a, 0x210a, + 0x210e, 0x210f, + 0x2113, 0x2113, + 0x212f, 0x212f, + 0x2134, 0x2134, + 0x2139, 0x2139, + 0x213d, 0x213d, + 0x2146, 0x2149, + 0xfb00, 0xfb06, + 0xfb13, 0xfb17, + 0xff41, 0xff5a, + 0x10428, 0x1044f, + 0x1d41a, 0x1d433, + 0x1d44e, 0x1d454, + 0x1d456, 0x1d467, + 0x1d482, 0x1d49b, + 0x1d4b6, 0x1d4b9, + 0x1d4bb, 0x1d4bb, + 0x1d4bd, 0x1d4c3, + 0x1d4c5, 0x1d4cf, + 0x1d4ea, 0x1d503, + 0x1d51e, 0x1d537, + 0x1d552, 0x1d56b, + 0x1d586, 0x1d59f, + 0x1d5ba, 0x1d5d3, + 0x1d5ee, 0x1d607, + 0x1d622, 0x1d63b, + 0x1d656, 0x1d66f, + 0x1d68a, 0x1d6a3, + 0x1d6c2, 0x1d6da, + 0x1d6dc, 0x1d6e1, + 0x1d6fc, 0x1d714, + 0x1d716, 0x1d71b, + 0x1d736, 0x1d74e, + 0x1d750, 0x1d755, + 0x1d770, 0x1d788, + 0x1d78a, 0x1d78f, + 0x1d7aa, 0x1d7c2, + 0x1d7c4, 0x1d7c9 +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +}; /* end of CRLower */ + +static OnigCodePoint CRPrint[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 405, +#else + 4, +#endif + 0x0009, 0x000d, + 0x0020, 0x007e, + 0x0085, 0x0085, + 0x00a0, 0x0236 +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + , + 0x0250, 0x0357, + 0x035d, 0x036f, + 0x0374, 0x0375, + 0x037a, 0x037a, + 0x037e, 0x037e, + 0x0384, 0x038a, + 0x038c, 0x038c, + 0x038e, 0x03a1, + 0x03a3, 0x03ce, + 0x03d0, 0x03fb, + 0x0400, 0x0486, + 0x0488, 0x04ce, + 0x04d0, 0x04f5, + 0x04f8, 0x04f9, + 0x0500, 0x050f, + 0x0531, 0x0556, + 0x0559, 0x055f, + 0x0561, 0x0587, + 0x0589, 0x058a, + 0x0591, 0x05a1, + 0x05a3, 0x05b9, + 0x05bb, 0x05c4, + 0x05d0, 0x05ea, + 0x05f0, 0x05f4, + 0x0600, 0x0603, + 0x060c, 0x0615, + 0x061b, 0x061b, + 0x061f, 0x061f, + 0x0621, 0x063a, + 0x0640, 0x0658, + 0x0660, 0x070d, + 0x070f, 0x074a, + 0x074d, 0x074f, + 0x0780, 0x07b1, + 0x0901, 0x0939, + 0x093c, 0x094d, + 0x0950, 0x0954, + 0x0958, 0x0970, + 0x0981, 0x0983, + 0x0985, 0x098c, + 0x098f, 0x0990, + 0x0993, 0x09a8, + 0x09aa, 0x09b0, + 0x09b2, 0x09b2, + 0x09b6, 0x09b9, + 0x09bc, 0x09c4, + 0x09c7, 0x09c8, + 0x09cb, 0x09cd, + 0x09d7, 0x09d7, + 0x09dc, 0x09dd, + 0x09df, 0x09e3, + 0x09e6, 0x09fa, + 0x0a01, 0x0a03, + 0x0a05, 0x0a0a, + 0x0a0f, 0x0a10, + 0x0a13, 0x0a28, + 0x0a2a, 0x0a30, + 0x0a32, 0x0a33, + 0x0a35, 0x0a36, + 0x0a38, 0x0a39, + 0x0a3c, 0x0a3c, + 0x0a3e, 0x0a42, + 0x0a47, 0x0a48, + 0x0a4b, 0x0a4d, + 0x0a59, 0x0a5c, + 0x0a5e, 0x0a5e, + 0x0a66, 0x0a74, + 0x0a81, 0x0a83, + 0x0a85, 0x0a8d, + 0x0a8f, 0x0a91, + 0x0a93, 0x0aa8, + 0x0aaa, 0x0ab0, + 0x0ab2, 0x0ab3, + 0x0ab5, 0x0ab9, + 0x0abc, 0x0ac5, + 0x0ac7, 0x0ac9, + 0x0acb, 0x0acd, + 0x0ad0, 0x0ad0, + 0x0ae0, 0x0ae3, + 0x0ae6, 0x0aef, + 0x0af1, 0x0af1, + 0x0b01, 0x0b03, + 0x0b05, 0x0b0c, + 0x0b0f, 0x0b10, + 0x0b13, 0x0b28, + 0x0b2a, 0x0b30, + 0x0b32, 0x0b33, + 0x0b35, 0x0b39, + 0x0b3c, 0x0b43, + 0x0b47, 0x0b48, + 0x0b4b, 0x0b4d, + 0x0b56, 0x0b57, + 0x0b5c, 0x0b5d, + 0x0b5f, 0x0b61, + 0x0b66, 0x0b71, + 0x0b82, 0x0b83, + 0x0b85, 0x0b8a, + 0x0b8e, 0x0b90, + 0x0b92, 0x0b95, + 0x0b99, 0x0b9a, + 0x0b9c, 0x0b9c, + 0x0b9e, 0x0b9f, + 0x0ba3, 0x0ba4, + 0x0ba8, 0x0baa, + 0x0bae, 0x0bb5, + 0x0bb7, 0x0bb9, + 0x0bbe, 0x0bc2, + 0x0bc6, 0x0bc8, + 0x0bca, 0x0bcd, + 0x0bd7, 0x0bd7, + 0x0be7, 0x0bfa, + 0x0c01, 0x0c03, + 0x0c05, 0x0c0c, + 0x0c0e, 0x0c10, + 0x0c12, 0x0c28, + 0x0c2a, 0x0c33, + 0x0c35, 0x0c39, + 0x0c3e, 0x0c44, + 0x0c46, 0x0c48, + 0x0c4a, 0x0c4d, + 0x0c55, 0x0c56, + 0x0c60, 0x0c61, + 0x0c66, 0x0c6f, + 0x0c82, 0x0c83, + 0x0c85, 0x0c8c, + 0x0c8e, 0x0c90, + 0x0c92, 0x0ca8, + 0x0caa, 0x0cb3, + 0x0cb5, 0x0cb9, + 0x0cbc, 0x0cc4, + 0x0cc6, 0x0cc8, + 0x0cca, 0x0ccd, + 0x0cd5, 0x0cd6, + 0x0cde, 0x0cde, + 0x0ce0, 0x0ce1, + 0x0ce6, 0x0cef, + 0x0d02, 0x0d03, + 0x0d05, 0x0d0c, + 0x0d0e, 0x0d10, + 0x0d12, 0x0d28, + 0x0d2a, 0x0d39, + 0x0d3e, 0x0d43, + 0x0d46, 0x0d48, + 0x0d4a, 0x0d4d, + 0x0d57, 0x0d57, + 0x0d60, 0x0d61, + 0x0d66, 0x0d6f, + 0x0d82, 0x0d83, + 0x0d85, 0x0d96, + 0x0d9a, 0x0db1, + 0x0db3, 0x0dbb, + 0x0dbd, 0x0dbd, + 0x0dc0, 0x0dc6, + 0x0dca, 0x0dca, + 0x0dcf, 0x0dd4, + 0x0dd6, 0x0dd6, + 0x0dd8, 0x0ddf, + 0x0df2, 0x0df4, + 0x0e01, 0x0e3a, + 0x0e3f, 0x0e5b, + 0x0e81, 0x0e82, + 0x0e84, 0x0e84, + 0x0e87, 0x0e88, + 0x0e8a, 0x0e8a, + 0x0e8d, 0x0e8d, + 0x0e94, 0x0e97, + 0x0e99, 0x0e9f, + 0x0ea1, 0x0ea3, + 0x0ea5, 0x0ea5, + 0x0ea7, 0x0ea7, + 0x0eaa, 0x0eab, + 0x0ead, 0x0eb9, + 0x0ebb, 0x0ebd, + 0x0ec0, 0x0ec4, + 0x0ec6, 0x0ec6, + 0x0ec8, 0x0ecd, + 0x0ed0, 0x0ed9, + 0x0edc, 0x0edd, + 0x0f00, 0x0f47, + 0x0f49, 0x0f6a, + 0x0f71, 0x0f8b, + 0x0f90, 0x0f97, + 0x0f99, 0x0fbc, + 0x0fbe, 0x0fcc, + 0x0fcf, 0x0fcf, + 0x1000, 0x1021, + 0x1023, 0x1027, + 0x1029, 0x102a, + 0x102c, 0x1032, + 0x1036, 0x1039, + 0x1040, 0x1059, + 0x10a0, 0x10c5, + 0x10d0, 0x10f8, + 0x10fb, 0x10fb, + 0x1100, 0x1159, + 0x115f, 0x11a2, + 0x11a8, 0x11f9, + 0x1200, 0x1206, + 0x1208, 0x1246, + 0x1248, 0x1248, + 0x124a, 0x124d, + 0x1250, 0x1256, + 0x1258, 0x1258, + 0x125a, 0x125d, + 0x1260, 0x1286, + 0x1288, 0x1288, + 0x128a, 0x128d, + 0x1290, 0x12ae, + 0x12b0, 0x12b0, + 0x12b2, 0x12b5, + 0x12b8, 0x12be, + 0x12c0, 0x12c0, + 0x12c2, 0x12c5, + 0x12c8, 0x12ce, + 0x12d0, 0x12d6, + 0x12d8, 0x12ee, + 0x12f0, 0x130e, + 0x1310, 0x1310, + 0x1312, 0x1315, + 0x1318, 0x131e, + 0x1320, 0x1346, + 0x1348, 0x135a, + 0x1361, 0x137c, + 0x13a0, 0x13f4, + 0x1401, 0x1676, + 0x1680, 0x169c, + 0x16a0, 0x16f0, + 0x1700, 0x170c, + 0x170e, 0x1714, + 0x1720, 0x1736, + 0x1740, 0x1753, + 0x1760, 0x176c, + 0x176e, 0x1770, + 0x1772, 0x1773, + 0x1780, 0x17dd, + 0x17e0, 0x17e9, + 0x17f0, 0x17f9, + 0x1800, 0x180e, + 0x1810, 0x1819, + 0x1820, 0x1877, + 0x1880, 0x18a9, + 0x1900, 0x191c, + 0x1920, 0x192b, + 0x1930, 0x193b, + 0x1940, 0x1940, + 0x1944, 0x196d, + 0x1970, 0x1974, + 0x19e0, 0x19ff, + 0x1d00, 0x1d6b, + 0x1e00, 0x1e9b, + 0x1ea0, 0x1ef9, + 0x1f00, 0x1f15, + 0x1f18, 0x1f1d, + 0x1f20, 0x1f45, + 0x1f48, 0x1f4d, + 0x1f50, 0x1f57, + 0x1f59, 0x1f59, + 0x1f5b, 0x1f5b, + 0x1f5d, 0x1f5d, + 0x1f5f, 0x1f7d, + 0x1f80, 0x1fb4, + 0x1fb6, 0x1fc4, + 0x1fc6, 0x1fd3, + 0x1fd6, 0x1fdb, + 0x1fdd, 0x1fef, + 0x1ff2, 0x1ff4, + 0x1ff6, 0x1ffe, + 0x2000, 0x2054, + 0x2057, 0x2057, + 0x205f, 0x2063, + 0x206a, 0x2071, + 0x2074, 0x208e, + 0x20a0, 0x20b1, + 0x20d0, 0x20ea, + 0x2100, 0x213b, + 0x213d, 0x214b, + 0x2153, 0x2183, + 0x2190, 0x23d0, + 0x2400, 0x2426, + 0x2440, 0x244a, + 0x2460, 0x2617, + 0x2619, 0x267d, + 0x2680, 0x2691, + 0x26a0, 0x26a1, + 0x2701, 0x2704, + 0x2706, 0x2709, + 0x270c, 0x2727, + 0x2729, 0x274b, + 0x274d, 0x274d, + 0x274f, 0x2752, + 0x2756, 0x2756, + 0x2758, 0x275e, + 0x2761, 0x2794, + 0x2798, 0x27af, + 0x27b1, 0x27be, + 0x27d0, 0x27eb, + 0x27f0, 0x2b0d, + 0x2e80, 0x2e99, + 0x2e9b, 0x2ef3, + 0x2f00, 0x2fd5, + 0x2ff0, 0x2ffb, + 0x3000, 0x303f, + 0x3041, 0x3096, + 0x3099, 0x30ff, + 0x3105, 0x312c, + 0x3131, 0x318e, + 0x3190, 0x31b7, + 0x31f0, 0x321e, + 0x3220, 0x3243, + 0x3250, 0x327d, + 0x327f, 0x32fe, + 0x3300, 0x4db5, + 0x4dc0, 0x9fa5, + 0xa000, 0xa48c, + 0xa490, 0xa4c6, + 0xac00, 0xd7a3, + 0xe000, 0xfa2d, + 0xfa30, 0xfa6a, + 0xfb00, 0xfb06, + 0xfb13, 0xfb17, + 0xfb1d, 0xfb36, + 0xfb38, 0xfb3c, + 0xfb3e, 0xfb3e, + 0xfb40, 0xfb41, + 0xfb43, 0xfb44, + 0xfb46, 0xfbb1, + 0xfbd3, 0xfd3f, + 0xfd50, 0xfd8f, + 0xfd92, 0xfdc7, + 0xfdf0, 0xfdfd, + 0xfe00, 0xfe0f, + 0xfe20, 0xfe23, + 0xfe30, 0xfe52, + 0xfe54, 0xfe66, + 0xfe68, 0xfe6b, + 0xfe70, 0xfe74, + 0xfe76, 0xfefc, + 0xfeff, 0xfeff, + 0xff01, 0xffbe, + 0xffc2, 0xffc7, + 0xffca, 0xffcf, + 0xffd2, 0xffd7, + 0xffda, 0xffdc, + 0xffe0, 0xffe6, + 0xffe8, 0xffee, + 0xfff9, 0xfffd, + 0x10000, 0x1000b, + 0x1000d, 0x10026, + 0x10028, 0x1003a, + 0x1003c, 0x1003d, + 0x1003f, 0x1004d, + 0x10050, 0x1005d, + 0x10080, 0x100fa, + 0x10100, 0x10102, + 0x10107, 0x10133, + 0x10137, 0x1013f, + 0x10300, 0x1031e, + 0x10320, 0x10323, + 0x10330, 0x1034a, + 0x10380, 0x1039d, + 0x1039f, 0x1039f, + 0x10400, 0x1049d, + 0x104a0, 0x104a9, + 0x10800, 0x10805, + 0x10808, 0x10808, + 0x1080a, 0x10835, + 0x10837, 0x10838, + 0x1083c, 0x1083c, + 0x1083f, 0x1083f, + 0x1d000, 0x1d0f5, + 0x1d100, 0x1d126, + 0x1d12a, 0x1d1dd, + 0x1d300, 0x1d356, + 0x1d400, 0x1d454, + 0x1d456, 0x1d49c, + 0x1d49e, 0x1d49f, + 0x1d4a2, 0x1d4a2, + 0x1d4a5, 0x1d4a6, + 0x1d4a9, 0x1d4ac, + 0x1d4ae, 0x1d4b9, + 0x1d4bb, 0x1d4bb, + 0x1d4bd, 0x1d4c3, + 0x1d4c5, 0x1d505, + 0x1d507, 0x1d50a, + 0x1d50d, 0x1d514, + 0x1d516, 0x1d51c, + 0x1d51e, 0x1d539, + 0x1d53b, 0x1d53e, + 0x1d540, 0x1d544, + 0x1d546, 0x1d546, + 0x1d54a, 0x1d550, + 0x1d552, 0x1d6a3, + 0x1d6a8, 0x1d7c9, + 0x1d7ce, 0x1d7ff, + 0x20000, 0x2a6d6, + 0x2f800, 0x2fa1d, + 0xe0001, 0xe0001, + 0xe0020, 0xe007f, + 0xe0100, 0xe01ef, + 0xf0000, 0xffffd, + 0x100000, 0x10fffd +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +}; /* end of CRPrint */ + +static OnigCodePoint CRPunct[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 86, +#else + 14, +#endif + 0x0021, 0x0023, + 0x0025, 0x002a, + 0x002c, 0x002f, + 0x003a, 0x003b, + 0x003f, 0x0040, + 0x005b, 0x005d, + 0x005f, 0x005f, + 0x007b, 0x007b, + 0x007d, 0x007d, + 0x00a1, 0x00a1, + 0x00ab, 0x00ab, + 0x00b7, 0x00b7, + 0x00bb, 0x00bb, + 0x00bf, 0x00bf +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + , + 0x037e, 0x037e, + 0x0387, 0x0387, + 0x055a, 0x055f, + 0x0589, 0x058a, + 0x05be, 0x05be, + 0x05c0, 0x05c0, + 0x05c3, 0x05c3, + 0x05f3, 0x05f4, + 0x060c, 0x060d, + 0x061b, 0x061b, + 0x061f, 0x061f, + 0x066a, 0x066d, + 0x06d4, 0x06d4, + 0x0700, 0x070d, + 0x0964, 0x0965, + 0x0970, 0x0970, + 0x0df4, 0x0df4, + 0x0e4f, 0x0e4f, + 0x0e5a, 0x0e5b, + 0x0f04, 0x0f12, + 0x0f3a, 0x0f3d, + 0x0f85, 0x0f85, + 0x104a, 0x104f, + 0x10fb, 0x10fb, + 0x1361, 0x1368, + 0x166d, 0x166e, + 0x169b, 0x169c, + 0x16eb, 0x16ed, + 0x1735, 0x1736, + 0x17d4, 0x17d6, + 0x17d8, 0x17da, + 0x1800, 0x180a, + 0x1944, 0x1945, + 0x2010, 0x2027, + 0x2030, 0x2043, + 0x2045, 0x2051, + 0x2053, 0x2054, + 0x2057, 0x2057, + 0x207d, 0x207e, + 0x208d, 0x208e, + 0x2329, 0x232a, + 0x23b4, 0x23b6, + 0x2768, 0x2775, + 0x27e6, 0x27eb, + 0x2983, 0x2998, + 0x29d8, 0x29db, + 0x29fc, 0x29fd, + 0x3001, 0x3003, + 0x3008, 0x3011, + 0x3014, 0x301f, + 0x3030, 0x3030, + 0x303d, 0x303d, + 0x30a0, 0x30a0, + 0x30fb, 0x30fb, + 0xfd3e, 0xfd3f, + 0xfe30, 0xfe52, + 0xfe54, 0xfe61, + 0xfe63, 0xfe63, + 0xfe68, 0xfe68, + 0xfe6a, 0xfe6b, + 0xff01, 0xff03, + 0xff05, 0xff0a, + 0xff0c, 0xff0f, + 0xff1a, 0xff1b, + 0xff1f, 0xff20, + 0xff3b, 0xff3d, + 0xff3f, 0xff3f, + 0xff5b, 0xff5b, + 0xff5d, 0xff5d, + 0xff5f, 0xff65, + 0x10100, 0x10101, + 0x1039f, 0x1039f +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +}; /* end of CRPunct */ + +static OnigCodePoint CRSpace[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 11, +#else + 4, +#endif + 0x0009, 0x000d, + 0x0020, 0x0020, + 0x0085, 0x0085, + 0x00a0, 0x00a0 +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + , + 0x1680, 0x1680, + 0x180e, 0x180e, + 0x2000, 0x200a, + 0x2028, 0x2029, + 0x202f, 0x202f, + 0x205f, 0x205f, + 0x3000, 0x3000 +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +}; /* end of CRSpace */ + +static OnigCodePoint CRUpper[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 421, +#else + 3, +#endif + 0x0041, 0x005a, + 0x00c0, 0x00d6, + 0x00d8, 0x00de +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + , + 0x0100, 0x0100, + 0x0102, 0x0102, + 0x0104, 0x0104, + 0x0106, 0x0106, + 0x0108, 0x0108, + 0x010a, 0x010a, + 0x010c, 0x010c, + 0x010e, 0x010e, + 0x0110, 0x0110, + 0x0112, 0x0112, + 0x0114, 0x0114, + 0x0116, 0x0116, + 0x0118, 0x0118, + 0x011a, 0x011a, + 0x011c, 0x011c, + 0x011e, 0x011e, + 0x0120, 0x0120, + 0x0122, 0x0122, + 0x0124, 0x0124, + 0x0126, 0x0126, + 0x0128, 0x0128, + 0x012a, 0x012a, + 0x012c, 0x012c, + 0x012e, 0x012e, + 0x0130, 0x0130, + 0x0132, 0x0132, + 0x0134, 0x0134, + 0x0136, 0x0136, + 0x0139, 0x0139, + 0x013b, 0x013b, + 0x013d, 0x013d, + 0x013f, 0x013f, + 0x0141, 0x0141, + 0x0143, 0x0143, + 0x0145, 0x0145, + 0x0147, 0x0147, + 0x014a, 0x014a, + 0x014c, 0x014c, + 0x014e, 0x014e, + 0x0150, 0x0150, + 0x0152, 0x0152, + 0x0154, 0x0154, + 0x0156, 0x0156, + 0x0158, 0x0158, + 0x015a, 0x015a, + 0x015c, 0x015c, + 0x015e, 0x015e, + 0x0160, 0x0160, + 0x0162, 0x0162, + 0x0164, 0x0164, + 0x0166, 0x0166, + 0x0168, 0x0168, + 0x016a, 0x016a, + 0x016c, 0x016c, + 0x016e, 0x016e, + 0x0170, 0x0170, + 0x0172, 0x0172, + 0x0174, 0x0174, + 0x0176, 0x0176, + 0x0178, 0x0179, + 0x017b, 0x017b, + 0x017d, 0x017d, + 0x0181, 0x0182, + 0x0184, 0x0184, + 0x0186, 0x0187, + 0x0189, 0x018b, + 0x018e, 0x0191, + 0x0193, 0x0194, + 0x0196, 0x0198, + 0x019c, 0x019d, + 0x019f, 0x01a0, + 0x01a2, 0x01a2, + 0x01a4, 0x01a4, + 0x01a6, 0x01a7, + 0x01a9, 0x01a9, + 0x01ac, 0x01ac, + 0x01ae, 0x01af, + 0x01b1, 0x01b3, + 0x01b5, 0x01b5, + 0x01b7, 0x01b8, + 0x01bc, 0x01bc, + 0x01c4, 0x01c4, + 0x01c7, 0x01c7, + 0x01ca, 0x01ca, + 0x01cd, 0x01cd, + 0x01cf, 0x01cf, + 0x01d1, 0x01d1, + 0x01d3, 0x01d3, + 0x01d5, 0x01d5, + 0x01d7, 0x01d7, + 0x01d9, 0x01d9, + 0x01db, 0x01db, + 0x01de, 0x01de, + 0x01e0, 0x01e0, + 0x01e2, 0x01e2, + 0x01e4, 0x01e4, + 0x01e6, 0x01e6, + 0x01e8, 0x01e8, + 0x01ea, 0x01ea, + 0x01ec, 0x01ec, + 0x01ee, 0x01ee, + 0x01f1, 0x01f1, + 0x01f4, 0x01f4, + 0x01f6, 0x01f8, + 0x01fa, 0x01fa, + 0x01fc, 0x01fc, + 0x01fe, 0x01fe, + 0x0200, 0x0200, + 0x0202, 0x0202, + 0x0204, 0x0204, + 0x0206, 0x0206, + 0x0208, 0x0208, + 0x020a, 0x020a, + 0x020c, 0x020c, + 0x020e, 0x020e, + 0x0210, 0x0210, + 0x0212, 0x0212, + 0x0214, 0x0214, + 0x0216, 0x0216, + 0x0218, 0x0218, + 0x021a, 0x021a, + 0x021c, 0x021c, + 0x021e, 0x021e, + 0x0220, 0x0220, + 0x0222, 0x0222, + 0x0224, 0x0224, + 0x0226, 0x0226, + 0x0228, 0x0228, + 0x022a, 0x022a, + 0x022c, 0x022c, + 0x022e, 0x022e, + 0x0230, 0x0230, + 0x0232, 0x0232, + 0x0386, 0x0386, + 0x0388, 0x038a, + 0x038c, 0x038c, + 0x038e, 0x038f, + 0x0391, 0x03a1, + 0x03a3, 0x03ab, + 0x03d2, 0x03d4, + 0x03d8, 0x03d8, + 0x03da, 0x03da, + 0x03dc, 0x03dc, + 0x03de, 0x03de, + 0x03e0, 0x03e0, + 0x03e2, 0x03e2, + 0x03e4, 0x03e4, + 0x03e6, 0x03e6, + 0x03e8, 0x03e8, + 0x03ea, 0x03ea, + 0x03ec, 0x03ec, + 0x03ee, 0x03ee, + 0x03f4, 0x03f4, + 0x03f7, 0x03f7, + 0x03f9, 0x03fa, + 0x0400, 0x042f, + 0x0460, 0x0460, + 0x0462, 0x0462, + 0x0464, 0x0464, + 0x0466, 0x0466, + 0x0468, 0x0468, + 0x046a, 0x046a, + 0x046c, 0x046c, + 0x046e, 0x046e, + 0x0470, 0x0470, + 0x0472, 0x0472, + 0x0474, 0x0474, + 0x0476, 0x0476, + 0x0478, 0x0478, + 0x047a, 0x047a, + 0x047c, 0x047c, + 0x047e, 0x047e, + 0x0480, 0x0480, + 0x048a, 0x048a, + 0x048c, 0x048c, + 0x048e, 0x048e, + 0x0490, 0x0490, + 0x0492, 0x0492, + 0x0494, 0x0494, + 0x0496, 0x0496, + 0x0498, 0x0498, + 0x049a, 0x049a, + 0x049c, 0x049c, + 0x049e, 0x049e, + 0x04a0, 0x04a0, + 0x04a2, 0x04a2, + 0x04a4, 0x04a4, + 0x04a6, 0x04a6, + 0x04a8, 0x04a8, + 0x04aa, 0x04aa, + 0x04ac, 0x04ac, + 0x04ae, 0x04ae, + 0x04b0, 0x04b0, + 0x04b2, 0x04b2, + 0x04b4, 0x04b4, + 0x04b6, 0x04b6, + 0x04b8, 0x04b8, + 0x04ba, 0x04ba, + 0x04bc, 0x04bc, + 0x04be, 0x04be, + 0x04c0, 0x04c1, + 0x04c3, 0x04c3, + 0x04c5, 0x04c5, + 0x04c7, 0x04c7, + 0x04c9, 0x04c9, + 0x04cb, 0x04cb, + 0x04cd, 0x04cd, + 0x04d0, 0x04d0, + 0x04d2, 0x04d2, + 0x04d4, 0x04d4, + 0x04d6, 0x04d6, + 0x04d8, 0x04d8, + 0x04da, 0x04da, + 0x04dc, 0x04dc, + 0x04de, 0x04de, + 0x04e0, 0x04e0, + 0x04e2, 0x04e2, + 0x04e4, 0x04e4, + 0x04e6, 0x04e6, + 0x04e8, 0x04e8, + 0x04ea, 0x04ea, + 0x04ec, 0x04ec, + 0x04ee, 0x04ee, + 0x04f0, 0x04f0, + 0x04f2, 0x04f2, + 0x04f4, 0x04f4, + 0x04f8, 0x04f8, + 0x0500, 0x0500, + 0x0502, 0x0502, + 0x0504, 0x0504, + 0x0506, 0x0506, + 0x0508, 0x0508, + 0x050a, 0x050a, + 0x050c, 0x050c, + 0x050e, 0x050e, + 0x0531, 0x0556, + 0x10a0, 0x10c5, + 0x1e00, 0x1e00, + 0x1e02, 0x1e02, + 0x1e04, 0x1e04, + 0x1e06, 0x1e06, + 0x1e08, 0x1e08, + 0x1e0a, 0x1e0a, + 0x1e0c, 0x1e0c, + 0x1e0e, 0x1e0e, + 0x1e10, 0x1e10, + 0x1e12, 0x1e12, + 0x1e14, 0x1e14, + 0x1e16, 0x1e16, + 0x1e18, 0x1e18, + 0x1e1a, 0x1e1a, + 0x1e1c, 0x1e1c, + 0x1e1e, 0x1e1e, + 0x1e20, 0x1e20, + 0x1e22, 0x1e22, + 0x1e24, 0x1e24, + 0x1e26, 0x1e26, + 0x1e28, 0x1e28, + 0x1e2a, 0x1e2a, + 0x1e2c, 0x1e2c, + 0x1e2e, 0x1e2e, + 0x1e30, 0x1e30, + 0x1e32, 0x1e32, + 0x1e34, 0x1e34, + 0x1e36, 0x1e36, + 0x1e38, 0x1e38, + 0x1e3a, 0x1e3a, + 0x1e3c, 0x1e3c, + 0x1e3e, 0x1e3e, + 0x1e40, 0x1e40, + 0x1e42, 0x1e42, + 0x1e44, 0x1e44, + 0x1e46, 0x1e46, + 0x1e48, 0x1e48, + 0x1e4a, 0x1e4a, + 0x1e4c, 0x1e4c, + 0x1e4e, 0x1e4e, + 0x1e50, 0x1e50, + 0x1e52, 0x1e52, + 0x1e54, 0x1e54, + 0x1e56, 0x1e56, + 0x1e58, 0x1e58, + 0x1e5a, 0x1e5a, + 0x1e5c, 0x1e5c, + 0x1e5e, 0x1e5e, + 0x1e60, 0x1e60, + 0x1e62, 0x1e62, + 0x1e64, 0x1e64, + 0x1e66, 0x1e66, + 0x1e68, 0x1e68, + 0x1e6a, 0x1e6a, + 0x1e6c, 0x1e6c, + 0x1e6e, 0x1e6e, + 0x1e70, 0x1e70, + 0x1e72, 0x1e72, + 0x1e74, 0x1e74, + 0x1e76, 0x1e76, + 0x1e78, 0x1e78, + 0x1e7a, 0x1e7a, + 0x1e7c, 0x1e7c, + 0x1e7e, 0x1e7e, + 0x1e80, 0x1e80, + 0x1e82, 0x1e82, + 0x1e84, 0x1e84, + 0x1e86, 0x1e86, + 0x1e88, 0x1e88, + 0x1e8a, 0x1e8a, + 0x1e8c, 0x1e8c, + 0x1e8e, 0x1e8e, + 0x1e90, 0x1e90, + 0x1e92, 0x1e92, + 0x1e94, 0x1e94, + 0x1ea0, 0x1ea0, + 0x1ea2, 0x1ea2, + 0x1ea4, 0x1ea4, + 0x1ea6, 0x1ea6, + 0x1ea8, 0x1ea8, + 0x1eaa, 0x1eaa, + 0x1eac, 0x1eac, + 0x1eae, 0x1eae, + 0x1eb0, 0x1eb0, + 0x1eb2, 0x1eb2, + 0x1eb4, 0x1eb4, + 0x1eb6, 0x1eb6, + 0x1eb8, 0x1eb8, + 0x1eba, 0x1eba, + 0x1ebc, 0x1ebc, + 0x1ebe, 0x1ebe, + 0x1ec0, 0x1ec0, + 0x1ec2, 0x1ec2, + 0x1ec4, 0x1ec4, + 0x1ec6, 0x1ec6, + 0x1ec8, 0x1ec8, + 0x1eca, 0x1eca, + 0x1ecc, 0x1ecc, + 0x1ece, 0x1ece, + 0x1ed0, 0x1ed0, + 0x1ed2, 0x1ed2, + 0x1ed4, 0x1ed4, + 0x1ed6, 0x1ed6, + 0x1ed8, 0x1ed8, + 0x1eda, 0x1eda, + 0x1edc, 0x1edc, + 0x1ede, 0x1ede, + 0x1ee0, 0x1ee0, + 0x1ee2, 0x1ee2, + 0x1ee4, 0x1ee4, + 0x1ee6, 0x1ee6, + 0x1ee8, 0x1ee8, + 0x1eea, 0x1eea, + 0x1eec, 0x1eec, + 0x1eee, 0x1eee, + 0x1ef0, 0x1ef0, + 0x1ef2, 0x1ef2, + 0x1ef4, 0x1ef4, + 0x1ef6, 0x1ef6, + 0x1ef8, 0x1ef8, + 0x1f08, 0x1f0f, + 0x1f18, 0x1f1d, + 0x1f28, 0x1f2f, + 0x1f38, 0x1f3f, + 0x1f48, 0x1f4d, + 0x1f59, 0x1f59, + 0x1f5b, 0x1f5b, + 0x1f5d, 0x1f5d, + 0x1f5f, 0x1f5f, + 0x1f68, 0x1f6f, + 0x1fb8, 0x1fbb, + 0x1fc8, 0x1fcb, + 0x1fd8, 0x1fdb, + 0x1fe8, 0x1fec, + 0x1ff8, 0x1ffb, + 0x2102, 0x2102, + 0x2107, 0x2107, + 0x210b, 0x210d, + 0x2110, 0x2112, + 0x2115, 0x2115, + 0x2119, 0x211d, + 0x2124, 0x2124, + 0x2126, 0x2126, + 0x2128, 0x2128, + 0x212a, 0x212d, + 0x2130, 0x2131, + 0x2133, 0x2133, + 0x213e, 0x213f, + 0x2145, 0x2145, + 0xff21, 0xff3a, + 0x10400, 0x10427, + 0x1d400, 0x1d419, + 0x1d434, 0x1d44d, + 0x1d468, 0x1d481, + 0x1d49c, 0x1d49c, + 0x1d49e, 0x1d49f, + 0x1d4a2, 0x1d4a2, + 0x1d4a5, 0x1d4a6, + 0x1d4a9, 0x1d4ac, + 0x1d4ae, 0x1d4b5, + 0x1d4d0, 0x1d4e9, + 0x1d504, 0x1d505, + 0x1d507, 0x1d50a, + 0x1d50d, 0x1d514, + 0x1d516, 0x1d51c, + 0x1d538, 0x1d539, + 0x1d53b, 0x1d53e, + 0x1d540, 0x1d544, + 0x1d546, 0x1d546, + 0x1d54a, 0x1d550, + 0x1d56c, 0x1d585, + 0x1d5a0, 0x1d5b9, + 0x1d5d4, 0x1d5ed, + 0x1d608, 0x1d621, + 0x1d63c, 0x1d655, + 0x1d670, 0x1d689, + 0x1d6a8, 0x1d6c0, + 0x1d6e2, 0x1d6fa, + 0x1d71c, 0x1d734, + 0x1d756, 0x1d76e, + 0x1d790, 0x1d7a8 +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +}; /* end of CRUpper */ + +static OnigCodePoint CRXDigit[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 3, +#else + 3, +#endif + 0x0030, 0x0039, + 0x0041, 0x0046, + 0x0061, 0x0066 +}; + +static OnigCodePoint CRASCII[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 1, +#else + 1, +#endif + 0x0000, 0x007f +}; + +static OnigCodePoint CRWord[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 436, +#else + 12, +#endif + 0x0030, 0x0039, + 0x0041, 0x005a, + 0x005f, 0x005f, + 0x0061, 0x007a, + 0x00aa, 0x00aa, + 0x00b2, 0x00b3, + 0x00b5, 0x00b5, + 0x00b9, 0x00ba, + 0x00bc, 0x00be, + 0x00c0, 0x00d6, + 0x00d8, 0x00f6, +#ifndef USE_UNICODE_FULL_RANGE_CTYPE + 0x00f8, 0x7fffffff +#else /* not USE_UNICODE_FULL_RANGE_CTYPE */ + 0x00f8, 0x0236, + 0x0250, 0x02c1, + 0x02c6, 0x02d1, + 0x02e0, 0x02e4, + 0x02ee, 0x02ee, + 0x0300, 0x0357, + 0x035d, 0x036f, + 0x037a, 0x037a, + 0x0386, 0x0386, + 0x0388, 0x038a, + 0x038c, 0x038c, + 0x038e, 0x03a1, + 0x03a3, 0x03ce, + 0x03d0, 0x03f5, + 0x03f7, 0x03fb, + 0x0400, 0x0481, + 0x0483, 0x0486, + 0x0488, 0x04ce, + 0x04d0, 0x04f5, + 0x04f8, 0x04f9, + 0x0500, 0x050f, + 0x0531, 0x0556, + 0x0559, 0x0559, + 0x0561, 0x0587, + 0x0591, 0x05a1, + 0x05a3, 0x05b9, + 0x05bb, 0x05bd, + 0x05bf, 0x05bf, + 0x05c1, 0x05c2, + 0x05c4, 0x05c4, + 0x05d0, 0x05ea, + 0x05f0, 0x05f2, + 0x0610, 0x0615, + 0x0621, 0x063a, + 0x0640, 0x0658, + 0x0660, 0x0669, + 0x066e, 0x06d3, + 0x06d5, 0x06dc, + 0x06de, 0x06e8, + 0x06ea, 0x06fc, + 0x06ff, 0x06ff, + 0x0710, 0x074a, + 0x074d, 0x074f, + 0x0780, 0x07b1, + 0x0901, 0x0939, + 0x093c, 0x094d, + 0x0950, 0x0954, + 0x0958, 0x0963, + 0x0966, 0x096f, + 0x0981, 0x0983, + 0x0985, 0x098c, + 0x098f, 0x0990, + 0x0993, 0x09a8, + 0x09aa, 0x09b0, + 0x09b2, 0x09b2, + 0x09b6, 0x09b9, + 0x09bc, 0x09c4, + 0x09c7, 0x09c8, + 0x09cb, 0x09cd, + 0x09d7, 0x09d7, + 0x09dc, 0x09dd, + 0x09df, 0x09e3, + 0x09e6, 0x09f1, + 0x09f4, 0x09f9, + 0x0a01, 0x0a03, + 0x0a05, 0x0a0a, + 0x0a0f, 0x0a10, + 0x0a13, 0x0a28, + 0x0a2a, 0x0a30, + 0x0a32, 0x0a33, + 0x0a35, 0x0a36, + 0x0a38, 0x0a39, + 0x0a3c, 0x0a3c, + 0x0a3e, 0x0a42, + 0x0a47, 0x0a48, + 0x0a4b, 0x0a4d, + 0x0a59, 0x0a5c, + 0x0a5e, 0x0a5e, + 0x0a66, 0x0a74, + 0x0a81, 0x0a83, + 0x0a85, 0x0a8d, + 0x0a8f, 0x0a91, + 0x0a93, 0x0aa8, + 0x0aaa, 0x0ab0, + 0x0ab2, 0x0ab3, + 0x0ab5, 0x0ab9, + 0x0abc, 0x0ac5, + 0x0ac7, 0x0ac9, + 0x0acb, 0x0acd, + 0x0ad0, 0x0ad0, + 0x0ae0, 0x0ae3, + 0x0ae6, 0x0aef, + 0x0b01, 0x0b03, + 0x0b05, 0x0b0c, + 0x0b0f, 0x0b10, + 0x0b13, 0x0b28, + 0x0b2a, 0x0b30, + 0x0b32, 0x0b33, + 0x0b35, 0x0b39, + 0x0b3c, 0x0b43, + 0x0b47, 0x0b48, + 0x0b4b, 0x0b4d, + 0x0b56, 0x0b57, + 0x0b5c, 0x0b5d, + 0x0b5f, 0x0b61, + 0x0b66, 0x0b6f, + 0x0b71, 0x0b71, + 0x0b82, 0x0b83, + 0x0b85, 0x0b8a, + 0x0b8e, 0x0b90, + 0x0b92, 0x0b95, + 0x0b99, 0x0b9a, + 0x0b9c, 0x0b9c, + 0x0b9e, 0x0b9f, + 0x0ba3, 0x0ba4, + 0x0ba8, 0x0baa, + 0x0bae, 0x0bb5, + 0x0bb7, 0x0bb9, + 0x0bbe, 0x0bc2, + 0x0bc6, 0x0bc8, + 0x0bca, 0x0bcd, + 0x0bd7, 0x0bd7, + 0x0be7, 0x0bf2, + 0x0c01, 0x0c03, + 0x0c05, 0x0c0c, + 0x0c0e, 0x0c10, + 0x0c12, 0x0c28, + 0x0c2a, 0x0c33, + 0x0c35, 0x0c39, + 0x0c3e, 0x0c44, + 0x0c46, 0x0c48, + 0x0c4a, 0x0c4d, + 0x0c55, 0x0c56, + 0x0c60, 0x0c61, + 0x0c66, 0x0c6f, + 0x0c82, 0x0c83, + 0x0c85, 0x0c8c, + 0x0c8e, 0x0c90, + 0x0c92, 0x0ca8, + 0x0caa, 0x0cb3, + 0x0cb5, 0x0cb9, + 0x0cbc, 0x0cc4, + 0x0cc6, 0x0cc8, + 0x0cca, 0x0ccd, + 0x0cd5, 0x0cd6, + 0x0cde, 0x0cde, + 0x0ce0, 0x0ce1, + 0x0ce6, 0x0cef, + 0x0d02, 0x0d03, + 0x0d05, 0x0d0c, + 0x0d0e, 0x0d10, + 0x0d12, 0x0d28, + 0x0d2a, 0x0d39, + 0x0d3e, 0x0d43, + 0x0d46, 0x0d48, + 0x0d4a, 0x0d4d, + 0x0d57, 0x0d57, + 0x0d60, 0x0d61, + 0x0d66, 0x0d6f, + 0x0d82, 0x0d83, + 0x0d85, 0x0d96, + 0x0d9a, 0x0db1, + 0x0db3, 0x0dbb, + 0x0dbd, 0x0dbd, + 0x0dc0, 0x0dc6, + 0x0dca, 0x0dca, + 0x0dcf, 0x0dd4, + 0x0dd6, 0x0dd6, + 0x0dd8, 0x0ddf, + 0x0df2, 0x0df3, + 0x0e01, 0x0e3a, + 0x0e40, 0x0e4e, + 0x0e50, 0x0e59, + 0x0e81, 0x0e82, + 0x0e84, 0x0e84, + 0x0e87, 0x0e88, + 0x0e8a, 0x0e8a, + 0x0e8d, 0x0e8d, + 0x0e94, 0x0e97, + 0x0e99, 0x0e9f, + 0x0ea1, 0x0ea3, + 0x0ea5, 0x0ea5, + 0x0ea7, 0x0ea7, + 0x0eaa, 0x0eab, + 0x0ead, 0x0eb9, + 0x0ebb, 0x0ebd, + 0x0ec0, 0x0ec4, + 0x0ec6, 0x0ec6, + 0x0ec8, 0x0ecd, + 0x0ed0, 0x0ed9, + 0x0edc, 0x0edd, + 0x0f00, 0x0f00, + 0x0f18, 0x0f19, + 0x0f20, 0x0f33, + 0x0f35, 0x0f35, + 0x0f37, 0x0f37, + 0x0f39, 0x0f39, + 0x0f3e, 0x0f47, + 0x0f49, 0x0f6a, + 0x0f71, 0x0f84, + 0x0f86, 0x0f8b, + 0x0f90, 0x0f97, + 0x0f99, 0x0fbc, + 0x0fc6, 0x0fc6, + 0x1000, 0x1021, + 0x1023, 0x1027, + 0x1029, 0x102a, + 0x102c, 0x1032, + 0x1036, 0x1039, + 0x1040, 0x1049, + 0x1050, 0x1059, + 0x10a0, 0x10c5, + 0x10d0, 0x10f8, + 0x1100, 0x1159, + 0x115f, 0x11a2, + 0x11a8, 0x11f9, + 0x1200, 0x1206, + 0x1208, 0x1246, + 0x1248, 0x1248, + 0x124a, 0x124d, + 0x1250, 0x1256, + 0x1258, 0x1258, + 0x125a, 0x125d, + 0x1260, 0x1286, + 0x1288, 0x1288, + 0x128a, 0x128d, + 0x1290, 0x12ae, + 0x12b0, 0x12b0, + 0x12b2, 0x12b5, + 0x12b8, 0x12be, + 0x12c0, 0x12c0, + 0x12c2, 0x12c5, + 0x12c8, 0x12ce, + 0x12d0, 0x12d6, + 0x12d8, 0x12ee, + 0x12f0, 0x130e, + 0x1310, 0x1310, + 0x1312, 0x1315, + 0x1318, 0x131e, + 0x1320, 0x1346, + 0x1348, 0x135a, + 0x1369, 0x137c, + 0x13a0, 0x13f4, + 0x1401, 0x166c, + 0x166f, 0x1676, + 0x1681, 0x169a, + 0x16a0, 0x16ea, + 0x16ee, 0x16f0, + 0x1700, 0x170c, + 0x170e, 0x1714, + 0x1720, 0x1734, + 0x1740, 0x1753, + 0x1760, 0x176c, + 0x176e, 0x1770, + 0x1772, 0x1773, + 0x1780, 0x17b3, + 0x17b6, 0x17d3, + 0x17d7, 0x17d7, + 0x17dc, 0x17dd, + 0x17e0, 0x17e9, + 0x17f0, 0x17f9, + 0x180b, 0x180d, + 0x1810, 0x1819, + 0x1820, 0x1877, + 0x1880, 0x18a9, + 0x1900, 0x191c, + 0x1920, 0x192b, + 0x1930, 0x193b, + 0x1946, 0x196d, + 0x1970, 0x1974, + 0x1d00, 0x1d6b, + 0x1e00, 0x1e9b, + 0x1ea0, 0x1ef9, + 0x1f00, 0x1f15, + 0x1f18, 0x1f1d, + 0x1f20, 0x1f45, + 0x1f48, 0x1f4d, + 0x1f50, 0x1f57, + 0x1f59, 0x1f59, + 0x1f5b, 0x1f5b, + 0x1f5d, 0x1f5d, + 0x1f5f, 0x1f7d, + 0x1f80, 0x1fb4, + 0x1fb6, 0x1fbc, + 0x1fbe, 0x1fbe, + 0x1fc2, 0x1fc4, + 0x1fc6, 0x1fcc, + 0x1fd0, 0x1fd3, + 0x1fd6, 0x1fdb, + 0x1fe0, 0x1fec, + 0x1ff2, 0x1ff4, + 0x1ff6, 0x1ffc, + 0x203f, 0x2040, + 0x2054, 0x2054, + 0x2070, 0x2071, + 0x2074, 0x2079, + 0x207f, 0x2089, + 0x20d0, 0x20ea, + 0x2102, 0x2102, + 0x2107, 0x2107, + 0x210a, 0x2113, + 0x2115, 0x2115, + 0x2119, 0x211d, + 0x2124, 0x2124, + 0x2126, 0x2126, + 0x2128, 0x2128, + 0x212a, 0x212d, + 0x212f, 0x2131, + 0x2133, 0x2139, + 0x213d, 0x213f, + 0x2145, 0x2149, + 0x2153, 0x2183, + 0x2460, 0x249b, + 0x24ea, 0x24ff, + 0x2776, 0x2793, + 0x3005, 0x3007, + 0x3021, 0x302f, + 0x3031, 0x3035, + 0x3038, 0x303c, + 0x3041, 0x3096, + 0x3099, 0x309a, + 0x309d, 0x309f, + 0x30a1, 0x30ff, + 0x3105, 0x312c, + 0x3131, 0x318e, + 0x3192, 0x3195, + 0x31a0, 0x31b7, + 0x31f0, 0x31ff, + 0x3220, 0x3229, + 0x3251, 0x325f, + 0x3280, 0x3289, + 0x32b1, 0x32bf, + 0x3400, 0x4db5, + 0x4e00, 0x9fa5, + 0xa000, 0xa48c, + 0xac00, 0xd7a3, + 0xf900, 0xfa2d, + 0xfa30, 0xfa6a, + 0xfb00, 0xfb06, + 0xfb13, 0xfb17, + 0xfb1d, 0xfb28, + 0xfb2a, 0xfb36, + 0xfb38, 0xfb3c, + 0xfb3e, 0xfb3e, + 0xfb40, 0xfb41, + 0xfb43, 0xfb44, + 0xfb46, 0xfbb1, + 0xfbd3, 0xfd3d, + 0xfd50, 0xfd8f, + 0xfd92, 0xfdc7, + 0xfdf0, 0xfdfb, + 0xfe00, 0xfe0f, + 0xfe20, 0xfe23, + 0xfe33, 0xfe34, + 0xfe4d, 0xfe4f, + 0xfe70, 0xfe74, + 0xfe76, 0xfefc, + 0xff10, 0xff19, + 0xff21, 0xff3a, + 0xff3f, 0xff3f, + 0xff41, 0xff5a, + 0xff65, 0xffbe, + 0xffc2, 0xffc7, + 0xffca, 0xffcf, + 0xffd2, 0xffd7, + 0xffda, 0xffdc, + 0x10000, 0x1000b, + 0x1000d, 0x10026, + 0x10028, 0x1003a, + 0x1003c, 0x1003d, + 0x1003f, 0x1004d, + 0x10050, 0x1005d, + 0x10080, 0x100fa, + 0x10107, 0x10133, + 0x10300, 0x1031e, + 0x10320, 0x10323, + 0x10330, 0x1034a, + 0x10380, 0x1039d, + 0x10400, 0x1049d, + 0x104a0, 0x104a9, + 0x10800, 0x10805, + 0x10808, 0x10808, + 0x1080a, 0x10835, + 0x10837, 0x10838, + 0x1083c, 0x1083c, + 0x1083f, 0x1083f, + 0x1d165, 0x1d169, + 0x1d16d, 0x1d172, + 0x1d17b, 0x1d182, + 0x1d185, 0x1d18b, + 0x1d1aa, 0x1d1ad, + 0x1d400, 0x1d454, + 0x1d456, 0x1d49c, + 0x1d49e, 0x1d49f, + 0x1d4a2, 0x1d4a2, + 0x1d4a5, 0x1d4a6, + 0x1d4a9, 0x1d4ac, + 0x1d4ae, 0x1d4b9, + 0x1d4bb, 0x1d4bb, + 0x1d4bd, 0x1d4c3, + 0x1d4c5, 0x1d505, + 0x1d507, 0x1d50a, + 0x1d50d, 0x1d514, + 0x1d516, 0x1d51c, + 0x1d51e, 0x1d539, + 0x1d53b, 0x1d53e, + 0x1d540, 0x1d544, + 0x1d546, 0x1d546, + 0x1d54a, 0x1d550, + 0x1d552, 0x1d6a3, + 0x1d6a8, 0x1d6c0, + 0x1d6c2, 0x1d6da, + 0x1d6dc, 0x1d6fa, + 0x1d6fc, 0x1d714, + 0x1d716, 0x1d734, + 0x1d736, 0x1d74e, + 0x1d750, 0x1d76e, + 0x1d770, 0x1d788, + 0x1d78a, 0x1d7a8, + 0x1d7aa, 0x1d7c2, + 0x1d7c4, 0x1d7c9, + 0x1d7ce, 0x1d7ff, + 0x20000, 0x2a6d6, + 0x2f800, 0x2fa1d, + 0xe0100, 0xe01ef +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +}; /* end of CRWord */ + + +extern int +onigenc_unicode_is_code_ctype(OnigCodePoint code, unsigned int ctype) +{ + if (code < 256) { + return ONIGENC_IS_UNICODE_ISO_8859_1_CTYPE(code, ctype); + } + +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + + switch (ctype) { + case ONIGENC_CTYPE_ALPHA: + return onig_is_in_code_range((UChar* )CRAlpha, code); + break; + case ONIGENC_CTYPE_BLANK: + return onig_is_in_code_range((UChar* )CRBlank, code); + break; + case ONIGENC_CTYPE_CNTRL: + return onig_is_in_code_range((UChar* )CRCntrl, code); + break; + case ONIGENC_CTYPE_DIGIT: + return onig_is_in_code_range((UChar* )CRDigit, code); + break; + case ONIGENC_CTYPE_GRAPH: + return onig_is_in_code_range((UChar* )CRGraph, code); + break; + case ONIGENC_CTYPE_LOWER: + return onig_is_in_code_range((UChar* )CRLower, code); + break; + case ONIGENC_CTYPE_PRINT: + return onig_is_in_code_range((UChar* )CRPrint, code); + break; + case ONIGENC_CTYPE_PUNCT: + return onig_is_in_code_range((UChar* )CRPunct, code); + break; + case ONIGENC_CTYPE_SPACE: + return onig_is_in_code_range((UChar* )CRSpace, code); + break; + case ONIGENC_CTYPE_UPPER: + return onig_is_in_code_range((UChar* )CRUpper, code); + break; + case ONIGENC_CTYPE_XDIGIT: + return FALSE; + break; + case ONIGENC_CTYPE_WORD: + return onig_is_in_code_range((UChar* )CRWord, code); + break; + case ONIGENC_CTYPE_ASCII: + return FALSE; + break; + case ONIGENC_CTYPE_ALNUM: + return onig_is_in_code_range((UChar* )CRAlnum, code); + break; + + default: + return ONIGENCERR_TYPE_BUG; + break; + } + +#else + + if ((ctype & ONIGENC_CTYPE_WORD) != 0) { + return TRUE; + } + return FALSE; +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +} + +extern int +onigenc_unicode_get_ctype_code_range(int ctype, + OnigCodePoint* sbr[], OnigCodePoint* mbr[]) +{ + static OnigCodePoint EmptyRange[] = { 0 }; + +#define CR_SET(list) do { \ + *mbr = list; \ +} while (0) + + *sbr = EmptyRange; + + switch (ctype) { + case ONIGENC_CTYPE_ALPHA: + CR_SET(CRAlpha); + break; + case ONIGENC_CTYPE_BLANK: + CR_SET(CRBlank); + break; + case ONIGENC_CTYPE_CNTRL: + CR_SET(CRCntrl); + break; + case ONIGENC_CTYPE_DIGIT: + CR_SET(CRDigit); + break; + case ONIGENC_CTYPE_GRAPH: + CR_SET(CRGraph); + break; + case ONIGENC_CTYPE_LOWER: + CR_SET(CRLower); + break; + case ONIGENC_CTYPE_PRINT: + CR_SET(CRPrint); + break; + case ONIGENC_CTYPE_PUNCT: + CR_SET(CRPunct); + break; + case ONIGENC_CTYPE_SPACE: + CR_SET(CRSpace); + break; + case ONIGENC_CTYPE_UPPER: + CR_SET(CRUpper); + break; + case ONIGENC_CTYPE_XDIGIT: + CR_SET(CRXDigit); + break; + case ONIGENC_CTYPE_WORD: + CR_SET(CRWord); + break; + case ONIGENC_CTYPE_ASCII: + CR_SET(CRASCII); + break; + case ONIGENC_CTYPE_ALNUM: + CR_SET(CRAlnum); + break; + + default: + return ONIGENCERR_TYPE_BUG; + break; + } + + return 0; +} diff --git a/ext/mbstring/oniguruma/enc/utf16_be.c b/ext/mbstring/oniguruma/enc/utf16_be.c new file mode 100755 index 000000000000..ad33ddbeeb3b --- /dev/null +++ b/ext/mbstring/oniguruma/enc/utf16_be.c @@ -0,0 +1,253 @@ +/********************************************************************** + utf16_be.c - Oniguruma (regular expression library) +**********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "regenc.h" + +#define UTF16_IS_SURROGATE_FIRST(c) (c >= 0xd8 && c <= 0xdb) +#define UTF16_IS_SURROGATE_SECOND(c) (c >= 0xdc && c <= 0xdf) + +static int EncLen_UTF16[] = { + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static int +utf16be_mbc_enc_len(const UChar* p) +{ + return EncLen_UTF16[*p]; +} + +static int +utf16be_is_mbc_newline(const UChar* p, const UChar* end) +{ + if (p + 1 < end) { + if (*(p+1) == 0x0a && *p == 0x00) + return 1; + } + return 0; +} + +static OnigCodePoint +utf16be_mbc_to_code(const UChar* p, const UChar* end) +{ + OnigCodePoint code; + + if (UTF16_IS_SURROGATE_FIRST(*p)) { + code = ((((p[0] - 0xd8) << 2) + ((p[1] & 0xc0) >> 6) + 1) << 16) + + ((((p[1] & 0x3f) << 2) + (p[2] - 0xdc)) << 8) + + p[3]; + } + else { + code = p[0] * 256 + p[1]; + } + return code; +} + +static int +utf16be_code_to_mbclen(OnigCodePoint code) +{ + return (code > 0xffff ? 4 : 2); +} + +static int +utf16be_code_to_mbc(OnigCodePoint code, UChar *buf) +{ + UChar* p = buf; + + if (code > 0xffff) { + unsigned int plane, high; + + plane = code >> 16; + *p++ = (plane >> 2) + 0xd8; + high = (code & 0xff00) >> 8; + *p++ = ((plane & 0x03) << 6) + (high >> 2); + *p++ = (high & 0x02) + 0xdc; + *p = (UChar )(code & 0xff); + return 4; + } + else { + *p++ = (UChar )((code & 0xff00) >> 8); + *p++ = (UChar )(code & 0xff); + return 2; + } +} + +static int +utf16be_mbc_to_normalize(OnigAmbigType flag, const UChar** pp, const UChar* end, + UChar* lower) +{ + const UChar* p = *pp; + + if (*p == 0) { + p++; + if (end > p + 2 && + (flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0 && + ((*p == 's' && *(p+2) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+2) == 'S'))) && + *(p+1) == 0) { + *lower++ = '\0'; + *lower = 0xdf; + (*pp) += 4; + return 2; + } + + *lower++ = '\0'; + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + *lower = ONIGENC_ISO_8859_1_TO_LOWER_CASE(*p); + } + else { + *lower = *p; + } + + (*pp) += 2; + return 2; /* return byte length of converted char to lower */ + } + else { + int len; + len = EncLen_UTF16[*p]; + if (lower != p) { + int i; + for (i = 0; i < len; i++) { + *lower++ = *p++; + } + } + (*pp) += len; + return len; /* return byte length of converted char to lower */ + } +} + +static int +utf16be_is_mbc_ambiguous(OnigAmbigType flag, const UChar** pp, const UChar* end) +{ + const UChar* p = *pp; + + (*pp) += EncLen_UTF16[*p]; + + if (*p == 0) { + int c, v; + + p++; + if ((flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + if (end > p + 2 && + ((*p == 's' && *(p+2) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+2) == 'S'))) && + *(p+1) == 0) { + (*pp) += 2; + return TRUE; + } + else if (*p == 0xdf) { + return TRUE; + } + } + + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + c = *p; + v = ONIGENC_IS_UNICODE_ISO_8859_1_CTYPE(c, + (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); + + if ((v | ONIGENC_CTYPE_LOWER) != 0) { + /* 0xaa, 0xb5, 0xba are lower case letter, but can't convert. */ + if (c >= 0xaa && c <= 0xba) + return FALSE; + else + return TRUE; + } + return (v != 0 ? TRUE : FALSE); + } + } + + return FALSE; +} + +static UChar* +utf16be_left_adjust_char_head(const UChar* start, const UChar* s) +{ + if (s <= start) return (UChar* )s; + + if ((s - start) % 2 == 1) { + s--; + } + + if (UTF16_IS_SURROGATE_SECOND(*s) && s > start + 1) + s -= 2; + + return (UChar* )s; +} + +OnigEncodingType OnigEncodingUTF16_BE = { + utf16be_mbc_enc_len, + "UTF-16BE", /* name */ + 4, /* max byte length */ + 2, /* min byte length */ + (ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_COMPOUND), + { + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ + }, + utf16be_is_mbc_newline, + utf16be_mbc_to_code, + utf16be_code_to_mbclen, + utf16be_code_to_mbc, + utf16be_mbc_to_normalize, + utf16be_is_mbc_ambiguous, + onigenc_iso_8859_1_get_all_pair_ambig_codes, + onigenc_ess_tsett_get_all_comp_ambig_codes, + onigenc_unicode_is_code_ctype, + onigenc_unicode_get_ctype_code_range, + utf16be_left_adjust_char_head, + onigenc_always_false_is_allowed_reverse_match +}; diff --git a/ext/mbstring/oniguruma/enc/utf16_le.c b/ext/mbstring/oniguruma/enc/utf16_le.c new file mode 100755 index 000000000000..db892dcd14d9 --- /dev/null +++ b/ext/mbstring/oniguruma/enc/utf16_le.c @@ -0,0 +1,248 @@ +/********************************************************************** + utf16_le.c - Oniguruma (regular expression library) +**********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "regenc.h" + +#define UTF16_IS_SURROGATE_FIRST(c) (c >= 0xd8 && c <= 0xdb) +#define UTF16_IS_SURROGATE_SECOND(c) (c >= 0xdc && c <= 0xdf) + +static int EncLen_UTF16[] = { + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static int +utf16le_code_to_mbclen(OnigCodePoint code) +{ + return (code > 0xffff ? 4 : 2); +} + +static int +utf16le_mbc_enc_len(const UChar* p) +{ + return EncLen_UTF16[*(p+1)]; +} + +static int +utf16le_is_mbc_newline(const UChar* p, const UChar* end) +{ + if (p + 1 < end) { + if (*p == 0x0a && *(p+1) == 0x00) + return 1; + } + return 0; +} + +static OnigCodePoint +utf16le_mbc_to_code(const UChar* p, const UChar* end) +{ + OnigCodePoint code; + UChar c0 = *p; + UChar c1 = *(p+1); + + if (UTF16_IS_SURROGATE_FIRST(c1)) { + code = ((((c1 - 0xd8) << 2) + ((c0 & 0xc0) >> 6) + 1) << 16) + + ((((c0 & 0x3f) << 2) + (p[3] - 0xdc)) << 8) + + p[2]; + } + else { + code = c1 * 256 + p[0]; + } + return code; +} + +static int +utf16le_code_to_mbc(OnigCodePoint code, UChar *buf) +{ + UChar* p = buf; + + if (code > 0xffff) { + unsigned int plane, high; + + plane = code >> 16; + high = (code & 0xff00) >> 8; + + *p++ = ((plane & 0x03) << 6) + (high >> 2); + *p++ = (plane >> 2) + 0xd8; + *p++ = (UChar )(code & 0xff); + *p = (high & 0x02) + 0xdc; + return 4; + } + else { + *p++ = (UChar )(code & 0xff); + *p++ = (UChar )((code & 0xff00) >> 8); + return 2; + } +} + +static int +utf16le_mbc_to_normalize(OnigAmbigType flag, const UChar** pp, const UChar* end, + UChar* lower) +{ + const UChar* p = *pp; + + if (*(p+1) == 0) { + if (end > p + 3 && + (flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0 && + ((*p == 's' && *(p+2) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+2) == 'S'))) && + *(p+3) == 0) { + *lower++ = 0xdf; + *lower = '\0'; + (*pp) += 4; + return 2; + } + + *(lower+1) = '\0'; + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + *lower = ONIGENC_ISO_8859_1_TO_LOWER_CASE(*p); + } + else { + *lower = *p; + } + (*pp) += 2; + return 2; /* return byte length of converted char to lower */ + } + else { + int len = EncLen_UTF16[*(p+1)]; + if (lower != p) { + int i; + for (i = 0; i < len; i++) { + *lower++ = *p++; + } + } + (*pp) += len; + return len; /* return byte length of converted char to lower */ + } +} + +static int +utf16le_is_mbc_ambiguous(OnigAmbigType flag, const UChar** pp, const UChar* end) +{ + const UChar* p = *pp; + + (*pp) += EncLen_UTF16[*(p+1)]; + + if (*(p+1) == 0) { + int c, v; + + if ((flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + if (end > p + 3 && + ((*p == 's' && *(p+2) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+2) == 'S'))) && + *(p+3) == 0) { + (*pp) += 2; + return TRUE; + } + } + + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + c = *p; + v = ONIGENC_IS_UNICODE_ISO_8859_1_CTYPE(c, + (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); + if ((v | ONIGENC_CTYPE_LOWER) != 0) { + /* 0xaa, 0xb5, 0xba are lower case letter, but can't convert. */ + if (c >= 0xaa && c <= 0xba) + return FALSE; + else + return TRUE; + } + return (v != 0 ? TRUE : FALSE); + } + } + + return FALSE; +} + +static UChar* +utf16le_left_adjust_char_head(const UChar* start, const UChar* s) +{ + if (s <= start) return (UChar* )s; + + if ((s - start) % 2 == 1) { + s--; + } + + if (UTF16_IS_SURROGATE_SECOND(*(s+1)) && s > start + 1) + s -= 2; + + return (UChar* )s; +} + +OnigEncodingType OnigEncodingUTF16_LE = { + utf16le_mbc_enc_len, + "UTF-16LE", /* name */ + 4, /* max byte length */ + 2, /* min byte length */ + (ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_COMPOUND), + { + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ + }, + utf16le_is_mbc_newline, + utf16le_mbc_to_code, + utf16le_code_to_mbclen, + utf16le_code_to_mbc, + utf16le_mbc_to_normalize, + utf16le_is_mbc_ambiguous, + onigenc_iso_8859_1_get_all_pair_ambig_codes, + onigenc_ess_tsett_get_all_comp_ambig_codes, + onigenc_unicode_is_code_ctype, + onigenc_unicode_get_ctype_code_range, + utf16le_left_adjust_char_head, + onigenc_always_false_is_allowed_reverse_match +}; diff --git a/ext/mbstring/oniguruma/enc/utf32_be.c b/ext/mbstring/oniguruma/enc/utf32_be.c new file mode 100755 index 000000000000..60feb040b821 --- /dev/null +++ b/ext/mbstring/oniguruma/enc/utf32_be.c @@ -0,0 +1,208 @@ +/********************************************************************** + utf32_be.c - Oniguruma (regular expression library) +**********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "regenc.h" + +static int +utf32be_mbc_enc_len(const UChar* p) +{ + return 4; +} + +static int +utf32be_is_mbc_newline(const UChar* p, const UChar* end) +{ + if (p + 3 < end) { + if (*(p+3) == 0x0a && *(p+2) == 0 && *(p+1) == 0 && *p == 0) + return 1; + } + return 0; +} + +static OnigCodePoint +utf32be_mbc_to_code(const UChar* p, const UChar* end) +{ + return (OnigCodePoint )(((p[0] * 256 + p[1]) * 256 + p[2]) * 256 + p[3]); +} + +static int +utf32be_code_to_mbclen(OnigCodePoint code) +{ + return 4; +} + +static int +utf32be_code_to_mbc(OnigCodePoint code, UChar *buf) +{ + UChar* p = buf; + + *p++ = (UChar )((code & 0xff000000) >>24); + *p++ = (UChar )((code & 0xff0000) >>16); + *p++ = (UChar )((code & 0xff00) >> 8); + *p++ = (UChar ) (code & 0xff); + return 4; +} + +static int +utf32be_mbc_to_normalize(OnigAmbigType flag, const UChar** pp, const UChar* end, + UChar* lower) +{ + const UChar* p = *pp; + + if (*(p+2) == 0 && *(p+1) == 0 && *p == 0) { + p += 3; + if (end > p + 4 && + (flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0 && + ((*p == 's' && *(p+4) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+4) == 'S'))) && + *(p+3) == 0 && *(p+2) == 0 && *(p+1) == 0) { + *lower++ = '\0'; + *lower++ = '\0'; + *lower++ = '\0'; + *lower = 0xdf; + (*pp) += 8; + return 4; + } + + *lower++ = '\0'; + *lower++ = '\0'; + *lower++ = '\0'; + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + *lower = ONIGENC_ISO_8859_1_TO_LOWER_CASE(*p); + } + else { + *lower = *p; + } + + (*pp) += 4; + return 4; /* return byte length of converted char to lower */ + } + else { + int len = 4; + if (lower != p) { + int i; + for (i = 0; i < len; i++) { + *lower++ = *p++; + } + } + (*pp) += len; + return len; /* return byte length of converted char to lower */ + } +} + +static int +utf32be_is_mbc_ambiguous(OnigAmbigType flag, const UChar** pp, const UChar* end) +{ + const UChar* p = *pp; + + (*pp) += 4; + + if (*(p+2) == 0 && *(p+1) == 0 && *p == 0) { + int c, v; + + p += 3; + if ((flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + if (end > p + 4 && + ((*p == 's' && *(p+4) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+4) == 'S'))) && + *(p+3) == 0 && *(p+2) == 0 && *(p+1) == 0) { + (*pp) += 4; + return TRUE; + } + else if (*p == 0xdf) { + return TRUE; + } + } + + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + c = *p; + v = ONIGENC_IS_UNICODE_ISO_8859_1_CTYPE(c, + (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); + if ((v | ONIGENC_CTYPE_LOWER) != 0) { + /* 0xaa, 0xb5, 0xba are lower case letter, but can't convert. */ + if (c >= 0xaa && c <= 0xba) + return FALSE; + else + return TRUE; + } + return (v != 0 ? TRUE : FALSE); + } + } + + return FALSE; +} + +static UChar* +utf32be_left_adjust_char_head(const UChar* start, const UChar* s) +{ + int rem; + + if (s <= start) return (UChar* )s; + + rem = (s - start) % 4; + return (UChar* )(s - rem); +} + +OnigEncodingType OnigEncodingUTF32_BE = { + utf32be_mbc_enc_len, + "UTF-32BE", /* name */ + 4, /* max byte length */ + 4, /* min byte length */ + (ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_COMPOUND), + { + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ + }, + utf32be_is_mbc_newline, + utf32be_mbc_to_code, + utf32be_code_to_mbclen, + utf32be_code_to_mbc, + utf32be_mbc_to_normalize, + utf32be_is_mbc_ambiguous, + onigenc_iso_8859_1_get_all_pair_ambig_codes, + onigenc_ess_tsett_get_all_comp_ambig_codes, + onigenc_unicode_is_code_ctype, + onigenc_unicode_get_ctype_code_range, + utf32be_left_adjust_char_head, + onigenc_always_false_is_allowed_reverse_match +}; diff --git a/ext/mbstring/oniguruma/enc/utf32_le.c b/ext/mbstring/oniguruma/enc/utf32_le.c new file mode 100755 index 000000000000..bba9689f7617 --- /dev/null +++ b/ext/mbstring/oniguruma/enc/utf32_le.c @@ -0,0 +1,206 @@ +/********************************************************************** + utf32_le.c - Oniguruma (regular expression library) +**********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "regenc.h" + +static int +utf32le_mbc_enc_len(const UChar* p) +{ + return 4; +} + +static int +utf32le_is_mbc_newline(const UChar* p, const UChar* end) +{ + if (p + 3 < end) { + if (*p == 0x0a && *(p+1) == 0 && *(p+2) == 0 && *(p+3) == 0) + return 1; + } + return 0; +} + +static OnigCodePoint +utf32le_mbc_to_code(const UChar* p, const UChar* end) +{ + return (OnigCodePoint )(((p[3] * 256 + p[2]) * 256 + p[1]) * 256 + p[0]); +} + +static int +utf32le_code_to_mbclen(OnigCodePoint code) +{ + return 4; +} + +static int +utf32le_code_to_mbc(OnigCodePoint code, UChar *buf) +{ + UChar* p = buf; + + *p++ = (UChar ) (code & 0xff); + *p++ = (UChar )((code & 0xff00) >> 8); + *p++ = (UChar )((code & 0xff0000) >>16); + *p++ = (UChar )((code & 0xff000000) >>24); + return 4; +} + +static int +utf32le_mbc_to_normalize(OnigAmbigType flag, const UChar** pp, const UChar* end, + UChar* lower) +{ + const UChar* p = *pp; + + if (*(p+1) == 0 && *(p+2) == 0 && *(p+3) == 0) { + if (end > p + 7 && + (flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0 && + ((*p == 's' && *(p+4) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+4) == 'S'))) && + *(p+5) == 0 && *(p+6) == 0 && *(p+7) == 0) { + *lower++ = 0xdf; + *lower++ = '\0'; + *lower++ = '\0'; + *lower = '\0'; + (*pp) += 8; + return 4; + } + + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + *lower++ = ONIGENC_ISO_8859_1_TO_LOWER_CASE(*p); + } + else { + *lower++ = *p; + } + *lower++ = '\0'; + *lower++ = '\0'; + *lower = '\0'; + + (*pp) += 4; + return 4; /* return byte length of converted char to lower */ + } + else { + int len = 4; + if (lower != p) { + int i; + for (i = 0; i < len; i++) { + *lower++ = *p++; + } + } + (*pp) += len; + return len; /* return byte length of converted char to lower */ + } +} + +static int +utf32le_is_mbc_ambiguous(OnigAmbigType flag, const UChar** pp, const UChar* end) +{ + const UChar* p = *pp; + + (*pp) += 4; + + if (*(p+1) == 0 && *(p+2) == 0 && *(p+3) == 0) { + int c, v; + + if ((flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + if (end > p + 7 && + ((*p == 's' && *(p+4) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+4) == 'S'))) && + *(p+5) == 0 && *(p+6) == 0 && *(p+7) == 0) { + (*pp) += 4; + return TRUE; + } + else if (*p == 0xdf) { + return TRUE; + } + } + + if (((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + ONIGENC_IS_MBC_ASCII(p)) || + ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0 && + !ONIGENC_IS_MBC_ASCII(p))) { + c = *p; + v = ONIGENC_IS_UNICODE_ISO_8859_1_CTYPE(c, + (ONIGENC_CTYPE_UPPER | ONIGENC_CTYPE_LOWER)); + if ((v | ONIGENC_CTYPE_LOWER) != 0) { + /* 0xaa, 0xb5, 0xba are lower case letter, but can't convert. */ + if (c >= 0xaa && c <= 0xba) + return FALSE; + else + return TRUE; + } + return (v != 0 ? TRUE : FALSE); + } + } + + return FALSE; +} + +static UChar* +utf32le_left_adjust_char_head(const UChar* start, const UChar* s) +{ + int rem; + + if (s <= start) return (UChar* )s; + + rem = (s - start) % 4; + return (UChar* )(s - rem); +} + +OnigEncodingType OnigEncodingUTF32_LE = { + utf32le_mbc_enc_len, + "UTF-32LE", /* name */ + 4, /* max byte length */ + 4, /* min byte length */ + (ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_COMPOUND), + { + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ + }, + utf32le_is_mbc_newline, + utf32le_mbc_to_code, + utf32le_code_to_mbclen, + utf32le_code_to_mbc, + utf32le_mbc_to_normalize, + utf32le_is_mbc_ambiguous, + onigenc_iso_8859_1_get_all_pair_ambig_codes, + onigenc_ess_tsett_get_all_comp_ambig_codes, + onigenc_unicode_is_code_ctype, + onigenc_unicode_get_ctype_code_range, + utf32le_left_adjust_char_head, + onigenc_always_false_is_allowed_reverse_match +}; diff --git a/ext/mbstring/oniguruma/enc/utf8.c b/ext/mbstring/oniguruma/enc/utf8.c index 604cfac2ef94..592bebfe8f26 100644 --- a/ext/mbstring/oniguruma/enc/utf8.c +++ b/ext/mbstring/oniguruma/enc/utf8.c @@ -1,60 +1,78 @@ /********************************************************************** - utf8.c - Oniguruma (regular expression library) - - Copyright (C) 2003-2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regenc.h" +#define USE_INVALID_CODE_SCHEME + +#ifdef USE_INVALID_CODE_SCHEME +/* virtual codepoint values for invalid encoding byte 0xfe and 0xff */ +#define INVALID_CODE_FE 0xfffffffe +#define INVALID_CODE_FF 0xffffffff +#define VALID_CODE_LIMIT 0x7fffffff +#endif + #define utf8_islead(c) ((UChar )((c) & 0xc0) != 0x80) -#define ENC_IS_ISO_8859_1_CTYPE(code,ctype) \ - ((EncUnicode_ISO_8859_1_CtypeTable[code] & ctype) != 0) - -static unsigned short EncUnicode_ISO_8859_1_CtypeTable[256] = { - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1106, 0x1104, 0x1104, 0x1104, 0x1104, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1142, 0x10d0, 0x10d0, 0x10d0, 0x1050, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x10d0, 0x10d0, 0x1050, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, - 0x1c58, 0x1c58, 0x10d0, 0x10d0, 0x1050, 0x1050, 0x1050, 0x10d0, - 0x10d0, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x10d0, 0x10d0, 0x10d0, 0x1050, 0x18d0, - 0x1050, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x10d0, 0x1050, 0x10d0, 0x1050, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1142, 0x10d0, 0x1050, 0x1050, 0x1050, 0x1050, 0x1050, 0x1050, - 0x1050, 0x1050, 0x1871, 0x10d0, 0x1050, 0x10d0, 0x1050, 0x1050, - 0x1050, 0x1050, 0x1850, 0x1850, 0x1050, 0x1871, 0x1050, 0x10d0, - 0x1050, 0x1850, 0x1871, 0x10d0, 0x1850, 0x1850, 0x1850, 0x10d0, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1050, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1050, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871 +static int EncLen_UTF8[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1 }; +static int +utf8_mbc_enc_len(const UChar* p) +{ + return EncLen_UTF8[*p]; +} + static OnigCodePoint -utf8_mbc_to_code(UChar* p, UChar* end) +utf8_mbc_to_code(const UChar* p, const UChar* end) { int c, len; OnigCodePoint n; + len = enc_len(ONIG_ENCODING_UTF8, p); c = *p++; - len = enc_len(ONIG_ENCODING_UTF8, c); if (len > 1) { len--; n = c & ((1 << (6 - len)) - 1); @@ -64,8 +82,14 @@ utf8_mbc_to_code(UChar* p, UChar* end) } return n; } - else + else { +#ifdef USE_INVALID_CODE_SCHEME + if (c > 0xfd) { + return ((c == 0xfe) ? INVALID_CODE_FE : INVALID_CODE_FF); + } +#endif return (OnigCodePoint )c; + } } static int @@ -81,8 +105,12 @@ utf8_code_to_mbclen(OnigCodePoint code) else if ((code & 0xffe00000) == 0) return 4; else if ((code & 0xfc000000) == 0) return 5; else if ((code & 0x80000000) == 0) return 6; +#ifdef USE_INVALID_CODE_SCHEME + else if (code == INVALID_CODE_FE) return 1; + else if (code == INVALID_CODE_FF) return 1; +#endif else - return ONIGERR_TOO_BIG_WIDE_CHAR_VALUE; + return ONIGENCERR_TOO_BIG_WIDE_CHAR_VALUE; } #if 0 @@ -103,7 +131,7 @@ utf8_code_to_mbc_first(OnigCodePoint code) else if ((code & 0x80000000) == 0) return ((code>>30) & 0x01) | 0xfc; else { - return ONIGERR_TOO_BIG_WIDE_CHAR_VALUE; + return ONIGENCERR_TOO_BIG_WIDE_CHAR_VALUE; } } } @@ -147,8 +175,18 @@ utf8_code_to_mbc(OnigCodePoint code, UChar *buf) *p++ = UTF8_TRAILS(code, 12); *p++ = UTF8_TRAILS(code, 6); } +#ifdef USE_INVALID_CODE_SCHEME + else if (code == INVALID_CODE_FE) { + *p = 0xfe; + return 1; + } + else if (code == INVALID_CODE_FF) { + *p = 0xff; + return 1; + } +#endif else { - return ONIGERR_TOO_BIG_WIDE_CHAR_VALUE; + return ONIGENCERR_TOO_BIG_WIDE_CHAR_VALUE; } *p++ = UTF8_TRAIL0(code); @@ -157,221 +195,3377 @@ utf8_code_to_mbc(OnigCodePoint code, UChar *buf) } static int -utf8_mbc_to_lower(UChar* p, UChar* lower) +utf8_mbc_to_normalize(OnigAmbigType flag, const UChar** pp, const UChar* end, UChar* lower) { - int len; + const UChar* p = *pp; - /* !!! U+0080 - U+00ff is treated by fold match. !!! */ if (ONIGENC_IS_MBC_ASCII(p)) { - *lower = ONIGENC_ASCII_CODE_TO_LOWER_CASE(*p); + if (end > p + 1 && + (flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0 && + ((*p == 's' && *(p+1) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+1) == 'S')))) { + *lower++ = '\303'; + *lower = '\237'; + (*pp) += 2; + return 2; + } + + if ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0) { + *lower = ONIGENC_ASCII_CODE_TO_LOWER_CASE(*p); + } + else { + *lower = *p; + } + (*pp)++; return 1; /* return byte length of converted char to lower */ } else { - len = enc_len(ONIG_ENCODING_UTF8, *p); + int len; + + if (*p == 195) { /* 195 == '\303' */ + int c = *(p + 1); + if (c >= 128) { + if (c <= (UChar )'\236' && /* upper */ + (flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0) { + if (c != (UChar )'\227') { + *lower++ = *p; + *lower = (UChar )(c + 32); + (*pp) += 2; + return 2; + } + } +#if 0 + else if (c == (UChar )'\237' && + (flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + *lower++ = '\303'; + *lower = '\237'; + (*pp) += 2; + return 2; + } +#endif + } + } + + len = enc_len(ONIG_ENCODING_UTF8, p); if (lower != p) { - /* memcpy(lower, p, len); */ int i; for (i = 0; i < len; i++) { *lower++ = *p++; } } + (*pp) += len; return len; /* return byte length of converted char to lower */ } } static int -utf8_mbc_is_case_ambig(UChar* p) +utf8_is_mbc_ambiguous(OnigAmbigType flag, const UChar** pp, const UChar* end) { - /* !!! U+0080 - U+00ff ( 0x80[0xc2,0x80] - 0xff[0xc3,0xbf] ) - is treated by fold match. !!! */ - - if (ONIGENC_IS_MBC_ASCII(p)) - return ONIGENC_IS_ASCII_CODE_CASE_AMBIG(*p); + const UChar* p = *pp; - return FALSE; -} + if (ONIGENC_IS_MBC_ASCII(p)) { + if (end > p + 1 && + (flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0 && + ((*p == 's' && *(p+1) == 's') || + ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0 && + (*p == 'S' && *(p+1) == 'S')))) { + (*pp) += 2; + return TRUE; + } -static int -utf8_code_is_ctype(OnigCodePoint code, unsigned int ctype) -{ - if (code < 256) { - return ENC_IS_ISO_8859_1_CTYPE(code, ctype); + (*pp)++; + if ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0) { + return ONIGENC_IS_ASCII_CODE_CASE_AMBIG(*p); + } } - - if ((ctype & ONIGENC_CTYPE_WORD) != 0) { - return TRUE; + else { + (*pp) += enc_len(ONIG_ENCODING_UTF8, p); + + if (*p == 195) { /* 195 == '\303' */ + int c = *(p + 1); + if (c >= 128) { + if ((flag & ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) != 0) { + if (c <= (UChar )'\236') { /* upper */ + if (c == (UChar )'\227') return FALSE; + return TRUE; + } + else if (c >= (UChar )'\240' && c <= (UChar )'\276') { /* lower */ + if (c == (UChar )'\267') return FALSE; + return TRUE; + } + } + else if (c == (UChar )'\237' && + (flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + return TRUE; + } + } + } } return FALSE; } + +static OnigCodePoint EmptyRange[] = { 0 }; + +static OnigCodePoint SBAlnum[] = { + 3, + 0x0030, 0x0039, + 0x0041, 0x005a, + 0x0061, 0x007a +}; + +static OnigCodePoint MBAlnum[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 411, +#else + 6, +#endif + 0x00aa, 0x00aa, + 0x00b5, 0x00b5, + 0x00ba, 0x00ba, + 0x00c0, 0x00d6, + 0x00d8, 0x00f6, + 0x00f8, 0x0236 +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + , + 0x0250, 0x02c1, + 0x02c6, 0x02d1, + 0x02e0, 0x02e4, + 0x02ee, 0x02ee, + 0x0300, 0x0357, + 0x035d, 0x036f, + 0x037a, 0x037a, + 0x0386, 0x0386, + 0x0388, 0x038a, + 0x038c, 0x038c, + 0x038e, 0x03a1, + 0x03a3, 0x03ce, + 0x03d0, 0x03f5, + 0x03f7, 0x03fb, + 0x0400, 0x0481, + 0x0483, 0x0486, + 0x0488, 0x04ce, + 0x04d0, 0x04f5, + 0x04f8, 0x04f9, + 0x0500, 0x050f, + 0x0531, 0x0556, + 0x0559, 0x0559, + 0x0561, 0x0587, + 0x0591, 0x05a1, + 0x05a3, 0x05b9, + 0x05bb, 0x05bd, + 0x05bf, 0x05bf, + 0x05c1, 0x05c2, + 0x05c4, 0x05c4, + 0x05d0, 0x05ea, + 0x05f0, 0x05f2, + 0x0610, 0x0615, + 0x0621, 0x063a, + 0x0640, 0x0658, + 0x0660, 0x0669, + 0x066e, 0x06d3, + 0x06d5, 0x06dc, + 0x06de, 0x06e8, + 0x06ea, 0x06fc, + 0x06ff, 0x06ff, + 0x0710, 0x074a, + 0x074d, 0x074f, + 0x0780, 0x07b1, + 0x0901, 0x0939, + 0x093c, 0x094d, + 0x0950, 0x0954, + 0x0958, 0x0963, + 0x0966, 0x096f, + 0x0981, 0x0983, + 0x0985, 0x098c, + 0x098f, 0x0990, + 0x0993, 0x09a8, + 0x09aa, 0x09b0, + 0x09b2, 0x09b2, + 0x09b6, 0x09b9, + 0x09bc, 0x09c4, + 0x09c7, 0x09c8, + 0x09cb, 0x09cd, + 0x09d7, 0x09d7, + 0x09dc, 0x09dd, + 0x09df, 0x09e3, + 0x09e6, 0x09f1, + 0x0a01, 0x0a03, + 0x0a05, 0x0a0a, + 0x0a0f, 0x0a10, + 0x0a13, 0x0a28, + 0x0a2a, 0x0a30, + 0x0a32, 0x0a33, + 0x0a35, 0x0a36, + 0x0a38, 0x0a39, + 0x0a3c, 0x0a3c, + 0x0a3e, 0x0a42, + 0x0a47, 0x0a48, + 0x0a4b, 0x0a4d, + 0x0a59, 0x0a5c, + 0x0a5e, 0x0a5e, + 0x0a66, 0x0a74, + 0x0a81, 0x0a83, + 0x0a85, 0x0a8d, + 0x0a8f, 0x0a91, + 0x0a93, 0x0aa8, + 0x0aaa, 0x0ab0, + 0x0ab2, 0x0ab3, + 0x0ab5, 0x0ab9, + 0x0abc, 0x0ac5, + 0x0ac7, 0x0ac9, + 0x0acb, 0x0acd, + 0x0ad0, 0x0ad0, + 0x0ae0, 0x0ae3, + 0x0ae6, 0x0aef, + 0x0b01, 0x0b03, + 0x0b05, 0x0b0c, + 0x0b0f, 0x0b10, + 0x0b13, 0x0b28, + 0x0b2a, 0x0b30, + 0x0b32, 0x0b33, + 0x0b35, 0x0b39, + 0x0b3c, 0x0b43, + 0x0b47, 0x0b48, + 0x0b4b, 0x0b4d, + 0x0b56, 0x0b57, + 0x0b5c, 0x0b5d, + 0x0b5f, 0x0b61, + 0x0b66, 0x0b6f, + 0x0b71, 0x0b71, + 0x0b82, 0x0b83, + 0x0b85, 0x0b8a, + 0x0b8e, 0x0b90, + 0x0b92, 0x0b95, + 0x0b99, 0x0b9a, + 0x0b9c, 0x0b9c, + 0x0b9e, 0x0b9f, + 0x0ba3, 0x0ba4, + 0x0ba8, 0x0baa, + 0x0bae, 0x0bb5, + 0x0bb7, 0x0bb9, + 0x0bbe, 0x0bc2, + 0x0bc6, 0x0bc8, + 0x0bca, 0x0bcd, + 0x0bd7, 0x0bd7, + 0x0be7, 0x0bef, + 0x0c01, 0x0c03, + 0x0c05, 0x0c0c, + 0x0c0e, 0x0c10, + 0x0c12, 0x0c28, + 0x0c2a, 0x0c33, + 0x0c35, 0x0c39, + 0x0c3e, 0x0c44, + 0x0c46, 0x0c48, + 0x0c4a, 0x0c4d, + 0x0c55, 0x0c56, + 0x0c60, 0x0c61, + 0x0c66, 0x0c6f, + 0x0c82, 0x0c83, + 0x0c85, 0x0c8c, + 0x0c8e, 0x0c90, + 0x0c92, 0x0ca8, + 0x0caa, 0x0cb3, + 0x0cb5, 0x0cb9, + 0x0cbc, 0x0cc4, + 0x0cc6, 0x0cc8, + 0x0cca, 0x0ccd, + 0x0cd5, 0x0cd6, + 0x0cde, 0x0cde, + 0x0ce0, 0x0ce1, + 0x0ce6, 0x0cef, + 0x0d02, 0x0d03, + 0x0d05, 0x0d0c, + 0x0d0e, 0x0d10, + 0x0d12, 0x0d28, + 0x0d2a, 0x0d39, + 0x0d3e, 0x0d43, + 0x0d46, 0x0d48, + 0x0d4a, 0x0d4d, + 0x0d57, 0x0d57, + 0x0d60, 0x0d61, + 0x0d66, 0x0d6f, + 0x0d82, 0x0d83, + 0x0d85, 0x0d96, + 0x0d9a, 0x0db1, + 0x0db3, 0x0dbb, + 0x0dbd, 0x0dbd, + 0x0dc0, 0x0dc6, + 0x0dca, 0x0dca, + 0x0dcf, 0x0dd4, + 0x0dd6, 0x0dd6, + 0x0dd8, 0x0ddf, + 0x0df2, 0x0df3, + 0x0e01, 0x0e3a, + 0x0e40, 0x0e4e, + 0x0e50, 0x0e59, + 0x0e81, 0x0e82, + 0x0e84, 0x0e84, + 0x0e87, 0x0e88, + 0x0e8a, 0x0e8a, + 0x0e8d, 0x0e8d, + 0x0e94, 0x0e97, + 0x0e99, 0x0e9f, + 0x0ea1, 0x0ea3, + 0x0ea5, 0x0ea5, + 0x0ea7, 0x0ea7, + 0x0eaa, 0x0eab, + 0x0ead, 0x0eb9, + 0x0ebb, 0x0ebd, + 0x0ec0, 0x0ec4, + 0x0ec6, 0x0ec6, + 0x0ec8, 0x0ecd, + 0x0ed0, 0x0ed9, + 0x0edc, 0x0edd, + 0x0f00, 0x0f00, + 0x0f18, 0x0f19, + 0x0f20, 0x0f29, + 0x0f35, 0x0f35, + 0x0f37, 0x0f37, + 0x0f39, 0x0f39, + 0x0f3e, 0x0f47, + 0x0f49, 0x0f6a, + 0x0f71, 0x0f84, + 0x0f86, 0x0f8b, + 0x0f90, 0x0f97, + 0x0f99, 0x0fbc, + 0x0fc6, 0x0fc6, + 0x1000, 0x1021, + 0x1023, 0x1027, + 0x1029, 0x102a, + 0x102c, 0x1032, + 0x1036, 0x1039, + 0x1040, 0x1049, + 0x1050, 0x1059, + 0x10a0, 0x10c5, + 0x10d0, 0x10f8, + 0x1100, 0x1159, + 0x115f, 0x11a2, + 0x11a8, 0x11f9, + 0x1200, 0x1206, + 0x1208, 0x1246, + 0x1248, 0x1248, + 0x124a, 0x124d, + 0x1250, 0x1256, + 0x1258, 0x1258, + 0x125a, 0x125d, + 0x1260, 0x1286, + 0x1288, 0x1288, + 0x128a, 0x128d, + 0x1290, 0x12ae, + 0x12b0, 0x12b0, + 0x12b2, 0x12b5, + 0x12b8, 0x12be, + 0x12c0, 0x12c0, + 0x12c2, 0x12c5, + 0x12c8, 0x12ce, + 0x12d0, 0x12d6, + 0x12d8, 0x12ee, + 0x12f0, 0x130e, + 0x1310, 0x1310, + 0x1312, 0x1315, + 0x1318, 0x131e, + 0x1320, 0x1346, + 0x1348, 0x135a, + 0x1369, 0x1371, + 0x13a0, 0x13f4, + 0x1401, 0x166c, + 0x166f, 0x1676, + 0x1681, 0x169a, + 0x16a0, 0x16ea, + 0x1700, 0x170c, + 0x170e, 0x1714, + 0x1720, 0x1734, + 0x1740, 0x1753, + 0x1760, 0x176c, + 0x176e, 0x1770, + 0x1772, 0x1773, + 0x1780, 0x17b3, + 0x17b6, 0x17d3, + 0x17d7, 0x17d7, + 0x17dc, 0x17dd, + 0x17e0, 0x17e9, + 0x180b, 0x180d, + 0x1810, 0x1819, + 0x1820, 0x1877, + 0x1880, 0x18a9, + 0x1900, 0x191c, + 0x1920, 0x192b, + 0x1930, 0x193b, + 0x1946, 0x196d, + 0x1970, 0x1974, + 0x1d00, 0x1d6b, + 0x1e00, 0x1e9b, + 0x1ea0, 0x1ef9, + 0x1f00, 0x1f15, + 0x1f18, 0x1f1d, + 0x1f20, 0x1f45, + 0x1f48, 0x1f4d, + 0x1f50, 0x1f57, + 0x1f59, 0x1f59, + 0x1f5b, 0x1f5b, + 0x1f5d, 0x1f5d, + 0x1f5f, 0x1f7d, + 0x1f80, 0x1fb4, + 0x1fb6, 0x1fbc, + 0x1fbe, 0x1fbe, + 0x1fc2, 0x1fc4, + 0x1fc6, 0x1fcc, + 0x1fd0, 0x1fd3, + 0x1fd6, 0x1fdb, + 0x1fe0, 0x1fec, + 0x1ff2, 0x1ff4, + 0x1ff6, 0x1ffc, + 0x2071, 0x2071, + 0x207f, 0x207f, + 0x20d0, 0x20ea, + 0x2102, 0x2102, + 0x2107, 0x2107, + 0x210a, 0x2113, + 0x2115, 0x2115, + 0x2119, 0x211d, + 0x2124, 0x2124, + 0x2126, 0x2126, + 0x2128, 0x2128, + 0x212a, 0x212d, + 0x212f, 0x2131, + 0x2133, 0x2139, + 0x213d, 0x213f, + 0x2145, 0x2149, + 0x3005, 0x3006, + 0x302a, 0x302f, + 0x3031, 0x3035, + 0x303b, 0x303c, + 0x3041, 0x3096, + 0x3099, 0x309a, + 0x309d, 0x309f, + 0x30a1, 0x30fa, + 0x30fc, 0x30ff, + 0x3105, 0x312c, + 0x3131, 0x318e, + 0x31a0, 0x31b7, + 0x31f0, 0x31ff, + 0x3400, 0x4db5, + 0x4e00, 0x9fa5, + 0xa000, 0xa48c, + 0xac00, 0xd7a3, + 0xf900, 0xfa2d, + 0xfa30, 0xfa6a, + 0xfb00, 0xfb06, + 0xfb13, 0xfb17, + 0xfb1d, 0xfb28, + 0xfb2a, 0xfb36, + 0xfb38, 0xfb3c, + 0xfb3e, 0xfb3e, + 0xfb40, 0xfb41, + 0xfb43, 0xfb44, + 0xfb46, 0xfbb1, + 0xfbd3, 0xfd3d, + 0xfd50, 0xfd8f, + 0xfd92, 0xfdc7, + 0xfdf0, 0xfdfb, + 0xfe00, 0xfe0f, + 0xfe20, 0xfe23, + 0xfe70, 0xfe74, + 0xfe76, 0xfefc, + 0xff10, 0xff19, + 0xff21, 0xff3a, + 0xff41, 0xff5a, + 0xff66, 0xffbe, + 0xffc2, 0xffc7, + 0xffca, 0xffcf, + 0xffd2, 0xffd7, + 0xffda, 0xffdc, + 0x10000, 0x1000b, + 0x1000d, 0x10026, + 0x10028, 0x1003a, + 0x1003c, 0x1003d, + 0x1003f, 0x1004d, + 0x10050, 0x1005d, + 0x10080, 0x100fa, + 0x10300, 0x1031e, + 0x10330, 0x10349, + 0x10380, 0x1039d, + 0x10400, 0x1049d, + 0x104a0, 0x104a9, + 0x10800, 0x10805, + 0x10808, 0x10808, + 0x1080a, 0x10835, + 0x10837, 0x10838, + 0x1083c, 0x1083c, + 0x1083f, 0x1083f, + 0x1d165, 0x1d169, + 0x1d16d, 0x1d172, + 0x1d17b, 0x1d182, + 0x1d185, 0x1d18b, + 0x1d1aa, 0x1d1ad, + 0x1d400, 0x1d454, + 0x1d456, 0x1d49c, + 0x1d49e, 0x1d49f, + 0x1d4a2, 0x1d4a2, + 0x1d4a5, 0x1d4a6, + 0x1d4a9, 0x1d4ac, + 0x1d4ae, 0x1d4b9, + 0x1d4bb, 0x1d4bb, + 0x1d4bd, 0x1d4c3, + 0x1d4c5, 0x1d505, + 0x1d507, 0x1d50a, + 0x1d50d, 0x1d514, + 0x1d516, 0x1d51c, + 0x1d51e, 0x1d539, + 0x1d53b, 0x1d53e, + 0x1d540, 0x1d544, + 0x1d546, 0x1d546, + 0x1d54a, 0x1d550, + 0x1d552, 0x1d6a3, + 0x1d6a8, 0x1d6c0, + 0x1d6c2, 0x1d6da, + 0x1d6dc, 0x1d6fa, + 0x1d6fc, 0x1d714, + 0x1d716, 0x1d734, + 0x1d736, 0x1d74e, + 0x1d750, 0x1d76e, + 0x1d770, 0x1d788, + 0x1d78a, 0x1d7a8, + 0x1d7aa, 0x1d7c2, + 0x1d7c4, 0x1d7c9, + 0x1d7ce, 0x1d7ff, + 0x20000, 0x2a6d6, + 0x2f800, 0x2fa1d, + 0xe0100, 0xe01ef +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +}; /* end of MBAlnum */ + +static OnigCodePoint SBAlpha[] = { + 2, + 0x0041, 0x005a, + 0x0061, 0x007a +}; + +static OnigCodePoint MBAlpha[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 394, +#else + 6, +#endif + 0x00aa, 0x00aa, + 0x00b5, 0x00b5, + 0x00ba, 0x00ba, + 0x00c0, 0x00d6, + 0x00d8, 0x00f6, + 0x00f8, 0x0236 +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + , + 0x0250, 0x02c1, + 0x02c6, 0x02d1, + 0x02e0, 0x02e4, + 0x02ee, 0x02ee, + 0x0300, 0x0357, + 0x035d, 0x036f, + 0x037a, 0x037a, + 0x0386, 0x0386, + 0x0388, 0x038a, + 0x038c, 0x038c, + 0x038e, 0x03a1, + 0x03a3, 0x03ce, + 0x03d0, 0x03f5, + 0x03f7, 0x03fb, + 0x0400, 0x0481, + 0x0483, 0x0486, + 0x0488, 0x04ce, + 0x04d0, 0x04f5, + 0x04f8, 0x04f9, + 0x0500, 0x050f, + 0x0531, 0x0556, + 0x0559, 0x0559, + 0x0561, 0x0587, + 0x0591, 0x05a1, + 0x05a3, 0x05b9, + 0x05bb, 0x05bd, + 0x05bf, 0x05bf, + 0x05c1, 0x05c2, + 0x05c4, 0x05c4, + 0x05d0, 0x05ea, + 0x05f0, 0x05f2, + 0x0610, 0x0615, + 0x0621, 0x063a, + 0x0640, 0x0658, + 0x066e, 0x06d3, + 0x06d5, 0x06dc, + 0x06de, 0x06e8, + 0x06ea, 0x06ef, + 0x06fa, 0x06fc, + 0x06ff, 0x06ff, + 0x0710, 0x074a, + 0x074d, 0x074f, + 0x0780, 0x07b1, + 0x0901, 0x0939, + 0x093c, 0x094d, + 0x0950, 0x0954, + 0x0958, 0x0963, + 0x0981, 0x0983, + 0x0985, 0x098c, + 0x098f, 0x0990, + 0x0993, 0x09a8, + 0x09aa, 0x09b0, + 0x09b2, 0x09b2, + 0x09b6, 0x09b9, + 0x09bc, 0x09c4, + 0x09c7, 0x09c8, + 0x09cb, 0x09cd, + 0x09d7, 0x09d7, + 0x09dc, 0x09dd, + 0x09df, 0x09e3, + 0x09f0, 0x09f1, + 0x0a01, 0x0a03, + 0x0a05, 0x0a0a, + 0x0a0f, 0x0a10, + 0x0a13, 0x0a28, + 0x0a2a, 0x0a30, + 0x0a32, 0x0a33, + 0x0a35, 0x0a36, + 0x0a38, 0x0a39, + 0x0a3c, 0x0a3c, + 0x0a3e, 0x0a42, + 0x0a47, 0x0a48, + 0x0a4b, 0x0a4d, + 0x0a59, 0x0a5c, + 0x0a5e, 0x0a5e, + 0x0a70, 0x0a74, + 0x0a81, 0x0a83, + 0x0a85, 0x0a8d, + 0x0a8f, 0x0a91, + 0x0a93, 0x0aa8, + 0x0aaa, 0x0ab0, + 0x0ab2, 0x0ab3, + 0x0ab5, 0x0ab9, + 0x0abc, 0x0ac5, + 0x0ac7, 0x0ac9, + 0x0acb, 0x0acd, + 0x0ad0, 0x0ad0, + 0x0ae0, 0x0ae3, + 0x0b01, 0x0b03, + 0x0b05, 0x0b0c, + 0x0b0f, 0x0b10, + 0x0b13, 0x0b28, + 0x0b2a, 0x0b30, + 0x0b32, 0x0b33, + 0x0b35, 0x0b39, + 0x0b3c, 0x0b43, + 0x0b47, 0x0b48, + 0x0b4b, 0x0b4d, + 0x0b56, 0x0b57, + 0x0b5c, 0x0b5d, + 0x0b5f, 0x0b61, + 0x0b71, 0x0b71, + 0x0b82, 0x0b83, + 0x0b85, 0x0b8a, + 0x0b8e, 0x0b90, + 0x0b92, 0x0b95, + 0x0b99, 0x0b9a, + 0x0b9c, 0x0b9c, + 0x0b9e, 0x0b9f, + 0x0ba3, 0x0ba4, + 0x0ba8, 0x0baa, + 0x0bae, 0x0bb5, + 0x0bb7, 0x0bb9, + 0x0bbe, 0x0bc2, + 0x0bc6, 0x0bc8, + 0x0bca, 0x0bcd, + 0x0bd7, 0x0bd7, + 0x0c01, 0x0c03, + 0x0c05, 0x0c0c, + 0x0c0e, 0x0c10, + 0x0c12, 0x0c28, + 0x0c2a, 0x0c33, + 0x0c35, 0x0c39, + 0x0c3e, 0x0c44, + 0x0c46, 0x0c48, + 0x0c4a, 0x0c4d, + 0x0c55, 0x0c56, + 0x0c60, 0x0c61, + 0x0c82, 0x0c83, + 0x0c85, 0x0c8c, + 0x0c8e, 0x0c90, + 0x0c92, 0x0ca8, + 0x0caa, 0x0cb3, + 0x0cb5, 0x0cb9, + 0x0cbc, 0x0cc4, + 0x0cc6, 0x0cc8, + 0x0cca, 0x0ccd, + 0x0cd5, 0x0cd6, + 0x0cde, 0x0cde, + 0x0ce0, 0x0ce1, + 0x0d02, 0x0d03, + 0x0d05, 0x0d0c, + 0x0d0e, 0x0d10, + 0x0d12, 0x0d28, + 0x0d2a, 0x0d39, + 0x0d3e, 0x0d43, + 0x0d46, 0x0d48, + 0x0d4a, 0x0d4d, + 0x0d57, 0x0d57, + 0x0d60, 0x0d61, + 0x0d82, 0x0d83, + 0x0d85, 0x0d96, + 0x0d9a, 0x0db1, + 0x0db3, 0x0dbb, + 0x0dbd, 0x0dbd, + 0x0dc0, 0x0dc6, + 0x0dca, 0x0dca, + 0x0dcf, 0x0dd4, + 0x0dd6, 0x0dd6, + 0x0dd8, 0x0ddf, + 0x0df2, 0x0df3, + 0x0e01, 0x0e3a, + 0x0e40, 0x0e4e, + 0x0e81, 0x0e82, + 0x0e84, 0x0e84, + 0x0e87, 0x0e88, + 0x0e8a, 0x0e8a, + 0x0e8d, 0x0e8d, + 0x0e94, 0x0e97, + 0x0e99, 0x0e9f, + 0x0ea1, 0x0ea3, + 0x0ea5, 0x0ea5, + 0x0ea7, 0x0ea7, + 0x0eaa, 0x0eab, + 0x0ead, 0x0eb9, + 0x0ebb, 0x0ebd, + 0x0ec0, 0x0ec4, + 0x0ec6, 0x0ec6, + 0x0ec8, 0x0ecd, + 0x0edc, 0x0edd, + 0x0f00, 0x0f00, + 0x0f18, 0x0f19, + 0x0f35, 0x0f35, + 0x0f37, 0x0f37, + 0x0f39, 0x0f39, + 0x0f3e, 0x0f47, + 0x0f49, 0x0f6a, + 0x0f71, 0x0f84, + 0x0f86, 0x0f8b, + 0x0f90, 0x0f97, + 0x0f99, 0x0fbc, + 0x0fc6, 0x0fc6, + 0x1000, 0x1021, + 0x1023, 0x1027, + 0x1029, 0x102a, + 0x102c, 0x1032, + 0x1036, 0x1039, + 0x1050, 0x1059, + 0x10a0, 0x10c5, + 0x10d0, 0x10f8, + 0x1100, 0x1159, + 0x115f, 0x11a2, + 0x11a8, 0x11f9, + 0x1200, 0x1206, + 0x1208, 0x1246, + 0x1248, 0x1248, + 0x124a, 0x124d, + 0x1250, 0x1256, + 0x1258, 0x1258, + 0x125a, 0x125d, + 0x1260, 0x1286, + 0x1288, 0x1288, + 0x128a, 0x128d, + 0x1290, 0x12ae, + 0x12b0, 0x12b0, + 0x12b2, 0x12b5, + 0x12b8, 0x12be, + 0x12c0, 0x12c0, + 0x12c2, 0x12c5, + 0x12c8, 0x12ce, + 0x12d0, 0x12d6, + 0x12d8, 0x12ee, + 0x12f0, 0x130e, + 0x1310, 0x1310, + 0x1312, 0x1315, + 0x1318, 0x131e, + 0x1320, 0x1346, + 0x1348, 0x135a, + 0x13a0, 0x13f4, + 0x1401, 0x166c, + 0x166f, 0x1676, + 0x1681, 0x169a, + 0x16a0, 0x16ea, + 0x1700, 0x170c, + 0x170e, 0x1714, + 0x1720, 0x1734, + 0x1740, 0x1753, + 0x1760, 0x176c, + 0x176e, 0x1770, + 0x1772, 0x1773, + 0x1780, 0x17b3, + 0x17b6, 0x17d3, + 0x17d7, 0x17d7, + 0x17dc, 0x17dd, + 0x180b, 0x180d, + 0x1820, 0x1877, + 0x1880, 0x18a9, + 0x1900, 0x191c, + 0x1920, 0x192b, + 0x1930, 0x193b, + 0x1950, 0x196d, + 0x1970, 0x1974, + 0x1d00, 0x1d6b, + 0x1e00, 0x1e9b, + 0x1ea0, 0x1ef9, + 0x1f00, 0x1f15, + 0x1f18, 0x1f1d, + 0x1f20, 0x1f45, + 0x1f48, 0x1f4d, + 0x1f50, 0x1f57, + 0x1f59, 0x1f59, + 0x1f5b, 0x1f5b, + 0x1f5d, 0x1f5d, + 0x1f5f, 0x1f7d, + 0x1f80, 0x1fb4, + 0x1fb6, 0x1fbc, + 0x1fbe, 0x1fbe, + 0x1fc2, 0x1fc4, + 0x1fc6, 0x1fcc, + 0x1fd0, 0x1fd3, + 0x1fd6, 0x1fdb, + 0x1fe0, 0x1fec, + 0x1ff2, 0x1ff4, + 0x1ff6, 0x1ffc, + 0x2071, 0x2071, + 0x207f, 0x207f, + 0x20d0, 0x20ea, + 0x2102, 0x2102, + 0x2107, 0x2107, + 0x210a, 0x2113, + 0x2115, 0x2115, + 0x2119, 0x211d, + 0x2124, 0x2124, + 0x2126, 0x2126, + 0x2128, 0x2128, + 0x212a, 0x212d, + 0x212f, 0x2131, + 0x2133, 0x2139, + 0x213d, 0x213f, + 0x2145, 0x2149, + 0x3005, 0x3006, + 0x302a, 0x302f, + 0x3031, 0x3035, + 0x303b, 0x303c, + 0x3041, 0x3096, + 0x3099, 0x309a, + 0x309d, 0x309f, + 0x30a1, 0x30fa, + 0x30fc, 0x30ff, + 0x3105, 0x312c, + 0x3131, 0x318e, + 0x31a0, 0x31b7, + 0x31f0, 0x31ff, + 0x3400, 0x4db5, + 0x4e00, 0x9fa5, + 0xa000, 0xa48c, + 0xac00, 0xd7a3, + 0xf900, 0xfa2d, + 0xfa30, 0xfa6a, + 0xfb00, 0xfb06, + 0xfb13, 0xfb17, + 0xfb1d, 0xfb28, + 0xfb2a, 0xfb36, + 0xfb38, 0xfb3c, + 0xfb3e, 0xfb3e, + 0xfb40, 0xfb41, + 0xfb43, 0xfb44, + 0xfb46, 0xfbb1, + 0xfbd3, 0xfd3d, + 0xfd50, 0xfd8f, + 0xfd92, 0xfdc7, + 0xfdf0, 0xfdfb, + 0xfe00, 0xfe0f, + 0xfe20, 0xfe23, + 0xfe70, 0xfe74, + 0xfe76, 0xfefc, + 0xff21, 0xff3a, + 0xff41, 0xff5a, + 0xff66, 0xffbe, + 0xffc2, 0xffc7, + 0xffca, 0xffcf, + 0xffd2, 0xffd7, + 0xffda, 0xffdc, + 0x10000, 0x1000b, + 0x1000d, 0x10026, + 0x10028, 0x1003a, + 0x1003c, 0x1003d, + 0x1003f, 0x1004d, + 0x10050, 0x1005d, + 0x10080, 0x100fa, + 0x10300, 0x1031e, + 0x10330, 0x10349, + 0x10380, 0x1039d, + 0x10400, 0x1049d, + 0x10800, 0x10805, + 0x10808, 0x10808, + 0x1080a, 0x10835, + 0x10837, 0x10838, + 0x1083c, 0x1083c, + 0x1083f, 0x1083f, + 0x1d165, 0x1d169, + 0x1d16d, 0x1d172, + 0x1d17b, 0x1d182, + 0x1d185, 0x1d18b, + 0x1d1aa, 0x1d1ad, + 0x1d400, 0x1d454, + 0x1d456, 0x1d49c, + 0x1d49e, 0x1d49f, + 0x1d4a2, 0x1d4a2, + 0x1d4a5, 0x1d4a6, + 0x1d4a9, 0x1d4ac, + 0x1d4ae, 0x1d4b9, + 0x1d4bb, 0x1d4bb, + 0x1d4bd, 0x1d4c3, + 0x1d4c5, 0x1d505, + 0x1d507, 0x1d50a, + 0x1d50d, 0x1d514, + 0x1d516, 0x1d51c, + 0x1d51e, 0x1d539, + 0x1d53b, 0x1d53e, + 0x1d540, 0x1d544, + 0x1d546, 0x1d546, + 0x1d54a, 0x1d550, + 0x1d552, 0x1d6a3, + 0x1d6a8, 0x1d6c0, + 0x1d6c2, 0x1d6da, + 0x1d6dc, 0x1d6fa, + 0x1d6fc, 0x1d714, + 0x1d716, 0x1d734, + 0x1d736, 0x1d74e, + 0x1d750, 0x1d76e, + 0x1d770, 0x1d788, + 0x1d78a, 0x1d7a8, + 0x1d7aa, 0x1d7c2, + 0x1d7c4, 0x1d7c9, + 0x20000, 0x2a6d6, + 0x2f800, 0x2fa1d, + 0xe0100, 0xe01ef +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +}; /* end of MBAlpha */ + +static OnigCodePoint SBBlank[] = { + 2, + 0x0009, 0x0009, + 0x0020, 0x0020 +}; + +static OnigCodePoint MBBlank[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 7, +#else + 1, +#endif + 0x00a0, 0x00a0 +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + , + 0x1680, 0x1680, + 0x180e, 0x180e, + 0x2000, 0x200a, + 0x202f, 0x202f, + 0x205f, 0x205f, + 0x3000, 0x3000 +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +}; /* end of MBBlank */ + +static OnigCodePoint SBCntrl[] = { + 2, + 0x0000, 0x001f, + 0x007f, 0x007f +}; + +static OnigCodePoint MBCntrl[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 18, +#else + 2, +#endif + 0x0080, 0x009f, + 0x00ad, 0x00ad +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + , + 0x0600, 0x0603, + 0x06dd, 0x06dd, + 0x070f, 0x070f, + 0x17b4, 0x17b5, + 0x200b, 0x200f, + 0x202a, 0x202e, + 0x2060, 0x2063, + 0x206a, 0x206f, + 0xd800, 0xf8ff, + 0xfeff, 0xfeff, + 0xfff9, 0xfffb, + 0x1d173, 0x1d17a, + 0xe0001, 0xe0001, + 0xe0020, 0xe007f, + 0xf0000, 0xffffd, + 0x100000, 0x10fffd +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +}; /* end of MBCntrl */ + +static OnigCodePoint SBDigit[] = { + 1, + 0x0030, 0x0039 +}; + +static OnigCodePoint MBDigit[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 22, +#else + 0 +#endif +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 0x0660, 0x0669, + 0x06f0, 0x06f9, + 0x0966, 0x096f, + 0x09e6, 0x09ef, + 0x0a66, 0x0a6f, + 0x0ae6, 0x0aef, + 0x0b66, 0x0b6f, + 0x0be7, 0x0bef, + 0x0c66, 0x0c6f, + 0x0ce6, 0x0cef, + 0x0d66, 0x0d6f, + 0x0e50, 0x0e59, + 0x0ed0, 0x0ed9, + 0x0f20, 0x0f29, + 0x1040, 0x1049, + 0x1369, 0x1371, + 0x17e0, 0x17e9, + 0x1810, 0x1819, + 0x1946, 0x194f, + 0xff10, 0xff19, + 0x104a0, 0x104a9, + 0x1d7ce, 0x1d7ff +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +}; /* end of MBDigit */ + +static OnigCodePoint SBGraph[] = { + 1, + 0x0021, 0x007e +}; + +static OnigCodePoint MBGraph[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 404, +#else + 1, +#endif + 0x00a1, 0x0236 +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + , + 0x0250, 0x0357, + 0x035d, 0x036f, + 0x0374, 0x0375, + 0x037a, 0x037a, + 0x037e, 0x037e, + 0x0384, 0x038a, + 0x038c, 0x038c, + 0x038e, 0x03a1, + 0x03a3, 0x03ce, + 0x03d0, 0x03fb, + 0x0400, 0x0486, + 0x0488, 0x04ce, + 0x04d0, 0x04f5, + 0x04f8, 0x04f9, + 0x0500, 0x050f, + 0x0531, 0x0556, + 0x0559, 0x055f, + 0x0561, 0x0587, + 0x0589, 0x058a, + 0x0591, 0x05a1, + 0x05a3, 0x05b9, + 0x05bb, 0x05c4, + 0x05d0, 0x05ea, + 0x05f0, 0x05f4, + 0x0600, 0x0603, + 0x060c, 0x0615, + 0x061b, 0x061b, + 0x061f, 0x061f, + 0x0621, 0x063a, + 0x0640, 0x0658, + 0x0660, 0x070d, + 0x070f, 0x074a, + 0x074d, 0x074f, + 0x0780, 0x07b1, + 0x0901, 0x0939, + 0x093c, 0x094d, + 0x0950, 0x0954, + 0x0958, 0x0970, + 0x0981, 0x0983, + 0x0985, 0x098c, + 0x098f, 0x0990, + 0x0993, 0x09a8, + 0x09aa, 0x09b0, + 0x09b2, 0x09b2, + 0x09b6, 0x09b9, + 0x09bc, 0x09c4, + 0x09c7, 0x09c8, + 0x09cb, 0x09cd, + 0x09d7, 0x09d7, + 0x09dc, 0x09dd, + 0x09df, 0x09e3, + 0x09e6, 0x09fa, + 0x0a01, 0x0a03, + 0x0a05, 0x0a0a, + 0x0a0f, 0x0a10, + 0x0a13, 0x0a28, + 0x0a2a, 0x0a30, + 0x0a32, 0x0a33, + 0x0a35, 0x0a36, + 0x0a38, 0x0a39, + 0x0a3c, 0x0a3c, + 0x0a3e, 0x0a42, + 0x0a47, 0x0a48, + 0x0a4b, 0x0a4d, + 0x0a59, 0x0a5c, + 0x0a5e, 0x0a5e, + 0x0a66, 0x0a74, + 0x0a81, 0x0a83, + 0x0a85, 0x0a8d, + 0x0a8f, 0x0a91, + 0x0a93, 0x0aa8, + 0x0aaa, 0x0ab0, + 0x0ab2, 0x0ab3, + 0x0ab5, 0x0ab9, + 0x0abc, 0x0ac5, + 0x0ac7, 0x0ac9, + 0x0acb, 0x0acd, + 0x0ad0, 0x0ad0, + 0x0ae0, 0x0ae3, + 0x0ae6, 0x0aef, + 0x0af1, 0x0af1, + 0x0b01, 0x0b03, + 0x0b05, 0x0b0c, + 0x0b0f, 0x0b10, + 0x0b13, 0x0b28, + 0x0b2a, 0x0b30, + 0x0b32, 0x0b33, + 0x0b35, 0x0b39, + 0x0b3c, 0x0b43, + 0x0b47, 0x0b48, + 0x0b4b, 0x0b4d, + 0x0b56, 0x0b57, + 0x0b5c, 0x0b5d, + 0x0b5f, 0x0b61, + 0x0b66, 0x0b71, + 0x0b82, 0x0b83, + 0x0b85, 0x0b8a, + 0x0b8e, 0x0b90, + 0x0b92, 0x0b95, + 0x0b99, 0x0b9a, + 0x0b9c, 0x0b9c, + 0x0b9e, 0x0b9f, + 0x0ba3, 0x0ba4, + 0x0ba8, 0x0baa, + 0x0bae, 0x0bb5, + 0x0bb7, 0x0bb9, + 0x0bbe, 0x0bc2, + 0x0bc6, 0x0bc8, + 0x0bca, 0x0bcd, + 0x0bd7, 0x0bd7, + 0x0be7, 0x0bfa, + 0x0c01, 0x0c03, + 0x0c05, 0x0c0c, + 0x0c0e, 0x0c10, + 0x0c12, 0x0c28, + 0x0c2a, 0x0c33, + 0x0c35, 0x0c39, + 0x0c3e, 0x0c44, + 0x0c46, 0x0c48, + 0x0c4a, 0x0c4d, + 0x0c55, 0x0c56, + 0x0c60, 0x0c61, + 0x0c66, 0x0c6f, + 0x0c82, 0x0c83, + 0x0c85, 0x0c8c, + 0x0c8e, 0x0c90, + 0x0c92, 0x0ca8, + 0x0caa, 0x0cb3, + 0x0cb5, 0x0cb9, + 0x0cbc, 0x0cc4, + 0x0cc6, 0x0cc8, + 0x0cca, 0x0ccd, + 0x0cd5, 0x0cd6, + 0x0cde, 0x0cde, + 0x0ce0, 0x0ce1, + 0x0ce6, 0x0cef, + 0x0d02, 0x0d03, + 0x0d05, 0x0d0c, + 0x0d0e, 0x0d10, + 0x0d12, 0x0d28, + 0x0d2a, 0x0d39, + 0x0d3e, 0x0d43, + 0x0d46, 0x0d48, + 0x0d4a, 0x0d4d, + 0x0d57, 0x0d57, + 0x0d60, 0x0d61, + 0x0d66, 0x0d6f, + 0x0d82, 0x0d83, + 0x0d85, 0x0d96, + 0x0d9a, 0x0db1, + 0x0db3, 0x0dbb, + 0x0dbd, 0x0dbd, + 0x0dc0, 0x0dc6, + 0x0dca, 0x0dca, + 0x0dcf, 0x0dd4, + 0x0dd6, 0x0dd6, + 0x0dd8, 0x0ddf, + 0x0df2, 0x0df4, + 0x0e01, 0x0e3a, + 0x0e3f, 0x0e5b, + 0x0e81, 0x0e82, + 0x0e84, 0x0e84, + 0x0e87, 0x0e88, + 0x0e8a, 0x0e8a, + 0x0e8d, 0x0e8d, + 0x0e94, 0x0e97, + 0x0e99, 0x0e9f, + 0x0ea1, 0x0ea3, + 0x0ea5, 0x0ea5, + 0x0ea7, 0x0ea7, + 0x0eaa, 0x0eab, + 0x0ead, 0x0eb9, + 0x0ebb, 0x0ebd, + 0x0ec0, 0x0ec4, + 0x0ec6, 0x0ec6, + 0x0ec8, 0x0ecd, + 0x0ed0, 0x0ed9, + 0x0edc, 0x0edd, + 0x0f00, 0x0f47, + 0x0f49, 0x0f6a, + 0x0f71, 0x0f8b, + 0x0f90, 0x0f97, + 0x0f99, 0x0fbc, + 0x0fbe, 0x0fcc, + 0x0fcf, 0x0fcf, + 0x1000, 0x1021, + 0x1023, 0x1027, + 0x1029, 0x102a, + 0x102c, 0x1032, + 0x1036, 0x1039, + 0x1040, 0x1059, + 0x10a0, 0x10c5, + 0x10d0, 0x10f8, + 0x10fb, 0x10fb, + 0x1100, 0x1159, + 0x115f, 0x11a2, + 0x11a8, 0x11f9, + 0x1200, 0x1206, + 0x1208, 0x1246, + 0x1248, 0x1248, + 0x124a, 0x124d, + 0x1250, 0x1256, + 0x1258, 0x1258, + 0x125a, 0x125d, + 0x1260, 0x1286, + 0x1288, 0x1288, + 0x128a, 0x128d, + 0x1290, 0x12ae, + 0x12b0, 0x12b0, + 0x12b2, 0x12b5, + 0x12b8, 0x12be, + 0x12c0, 0x12c0, + 0x12c2, 0x12c5, + 0x12c8, 0x12ce, + 0x12d0, 0x12d6, + 0x12d8, 0x12ee, + 0x12f0, 0x130e, + 0x1310, 0x1310, + 0x1312, 0x1315, + 0x1318, 0x131e, + 0x1320, 0x1346, + 0x1348, 0x135a, + 0x1361, 0x137c, + 0x13a0, 0x13f4, + 0x1401, 0x1676, + 0x1681, 0x169c, + 0x16a0, 0x16f0, + 0x1700, 0x170c, + 0x170e, 0x1714, + 0x1720, 0x1736, + 0x1740, 0x1753, + 0x1760, 0x176c, + 0x176e, 0x1770, + 0x1772, 0x1773, + 0x1780, 0x17dd, + 0x17e0, 0x17e9, + 0x17f0, 0x17f9, + 0x1800, 0x180d, + 0x1810, 0x1819, + 0x1820, 0x1877, + 0x1880, 0x18a9, + 0x1900, 0x191c, + 0x1920, 0x192b, + 0x1930, 0x193b, + 0x1940, 0x1940, + 0x1944, 0x196d, + 0x1970, 0x1974, + 0x19e0, 0x19ff, + 0x1d00, 0x1d6b, + 0x1e00, 0x1e9b, + 0x1ea0, 0x1ef9, + 0x1f00, 0x1f15, + 0x1f18, 0x1f1d, + 0x1f20, 0x1f45, + 0x1f48, 0x1f4d, + 0x1f50, 0x1f57, + 0x1f59, 0x1f59, + 0x1f5b, 0x1f5b, + 0x1f5d, 0x1f5d, + 0x1f5f, 0x1f7d, + 0x1f80, 0x1fb4, + 0x1fb6, 0x1fc4, + 0x1fc6, 0x1fd3, + 0x1fd6, 0x1fdb, + 0x1fdd, 0x1fef, + 0x1ff2, 0x1ff4, + 0x1ff6, 0x1ffe, + 0x200b, 0x2027, + 0x202a, 0x202e, + 0x2030, 0x2054, + 0x2057, 0x2057, + 0x2060, 0x2063, + 0x206a, 0x2071, + 0x2074, 0x208e, + 0x20a0, 0x20b1, + 0x20d0, 0x20ea, + 0x2100, 0x213b, + 0x213d, 0x214b, + 0x2153, 0x2183, + 0x2190, 0x23d0, + 0x2400, 0x2426, + 0x2440, 0x244a, + 0x2460, 0x2617, + 0x2619, 0x267d, + 0x2680, 0x2691, + 0x26a0, 0x26a1, + 0x2701, 0x2704, + 0x2706, 0x2709, + 0x270c, 0x2727, + 0x2729, 0x274b, + 0x274d, 0x274d, + 0x274f, 0x2752, + 0x2756, 0x2756, + 0x2758, 0x275e, + 0x2761, 0x2794, + 0x2798, 0x27af, + 0x27b1, 0x27be, + 0x27d0, 0x27eb, + 0x27f0, 0x2b0d, + 0x2e80, 0x2e99, + 0x2e9b, 0x2ef3, + 0x2f00, 0x2fd5, + 0x2ff0, 0x2ffb, + 0x3001, 0x303f, + 0x3041, 0x3096, + 0x3099, 0x30ff, + 0x3105, 0x312c, + 0x3131, 0x318e, + 0x3190, 0x31b7, + 0x31f0, 0x321e, + 0x3220, 0x3243, + 0x3250, 0x327d, + 0x327f, 0x32fe, + 0x3300, 0x4db5, + 0x4dc0, 0x9fa5, + 0xa000, 0xa48c, + 0xa490, 0xa4c6, + 0xac00, 0xd7a3, + 0xe000, 0xfa2d, + 0xfa30, 0xfa6a, + 0xfb00, 0xfb06, + 0xfb13, 0xfb17, + 0xfb1d, 0xfb36, + 0xfb38, 0xfb3c, + 0xfb3e, 0xfb3e, + 0xfb40, 0xfb41, + 0xfb43, 0xfb44, + 0xfb46, 0xfbb1, + 0xfbd3, 0xfd3f, + 0xfd50, 0xfd8f, + 0xfd92, 0xfdc7, + 0xfdf0, 0xfdfd, + 0xfe00, 0xfe0f, + 0xfe20, 0xfe23, + 0xfe30, 0xfe52, + 0xfe54, 0xfe66, + 0xfe68, 0xfe6b, + 0xfe70, 0xfe74, + 0xfe76, 0xfefc, + 0xfeff, 0xfeff, + 0xff01, 0xffbe, + 0xffc2, 0xffc7, + 0xffca, 0xffcf, + 0xffd2, 0xffd7, + 0xffda, 0xffdc, + 0xffe0, 0xffe6, + 0xffe8, 0xffee, + 0xfff9, 0xfffd, + 0x10000, 0x1000b, + 0x1000d, 0x10026, + 0x10028, 0x1003a, + 0x1003c, 0x1003d, + 0x1003f, 0x1004d, + 0x10050, 0x1005d, + 0x10080, 0x100fa, + 0x10100, 0x10102, + 0x10107, 0x10133, + 0x10137, 0x1013f, + 0x10300, 0x1031e, + 0x10320, 0x10323, + 0x10330, 0x1034a, + 0x10380, 0x1039d, + 0x1039f, 0x1039f, + 0x10400, 0x1049d, + 0x104a0, 0x104a9, + 0x10800, 0x10805, + 0x10808, 0x10808, + 0x1080a, 0x10835, + 0x10837, 0x10838, + 0x1083c, 0x1083c, + 0x1083f, 0x1083f, + 0x1d000, 0x1d0f5, + 0x1d100, 0x1d126, + 0x1d12a, 0x1d1dd, + 0x1d300, 0x1d356, + 0x1d400, 0x1d454, + 0x1d456, 0x1d49c, + 0x1d49e, 0x1d49f, + 0x1d4a2, 0x1d4a2, + 0x1d4a5, 0x1d4a6, + 0x1d4a9, 0x1d4ac, + 0x1d4ae, 0x1d4b9, + 0x1d4bb, 0x1d4bb, + 0x1d4bd, 0x1d4c3, + 0x1d4c5, 0x1d505, + 0x1d507, 0x1d50a, + 0x1d50d, 0x1d514, + 0x1d516, 0x1d51c, + 0x1d51e, 0x1d539, + 0x1d53b, 0x1d53e, + 0x1d540, 0x1d544, + 0x1d546, 0x1d546, + 0x1d54a, 0x1d550, + 0x1d552, 0x1d6a3, + 0x1d6a8, 0x1d7c9, + 0x1d7ce, 0x1d7ff, + 0x20000, 0x2a6d6, + 0x2f800, 0x2fa1d, + 0xe0001, 0xe0001, + 0xe0020, 0xe007f, + 0xe0100, 0xe01ef, + 0xf0000, 0xffffd, + 0x100000, 0x10fffd +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +}; /* end of MBGraph */ + +static OnigCodePoint SBLower[] = { + 1, + 0x0061, 0x007a +}; + +static OnigCodePoint MBLower[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 423, +#else + 5, +#endif + 0x00aa, 0x00aa, + 0x00b5, 0x00b5, + 0x00ba, 0x00ba, + 0x00df, 0x00f6, + 0x00f8, 0x00ff +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + , + 0x0101, 0x0101, + 0x0103, 0x0103, + 0x0105, 0x0105, + 0x0107, 0x0107, + 0x0109, 0x0109, + 0x010b, 0x010b, + 0x010d, 0x010d, + 0x010f, 0x010f, + 0x0111, 0x0111, + 0x0113, 0x0113, + 0x0115, 0x0115, + 0x0117, 0x0117, + 0x0119, 0x0119, + 0x011b, 0x011b, + 0x011d, 0x011d, + 0x011f, 0x011f, + 0x0121, 0x0121, + 0x0123, 0x0123, + 0x0125, 0x0125, + 0x0127, 0x0127, + 0x0129, 0x0129, + 0x012b, 0x012b, + 0x012d, 0x012d, + 0x012f, 0x012f, + 0x0131, 0x0131, + 0x0133, 0x0133, + 0x0135, 0x0135, + 0x0137, 0x0138, + 0x013a, 0x013a, + 0x013c, 0x013c, + 0x013e, 0x013e, + 0x0140, 0x0140, + 0x0142, 0x0142, + 0x0144, 0x0144, + 0x0146, 0x0146, + 0x0148, 0x0149, + 0x014b, 0x014b, + 0x014d, 0x014d, + 0x014f, 0x014f, + 0x0151, 0x0151, + 0x0153, 0x0153, + 0x0155, 0x0155, + 0x0157, 0x0157, + 0x0159, 0x0159, + 0x015b, 0x015b, + 0x015d, 0x015d, + 0x015f, 0x015f, + 0x0161, 0x0161, + 0x0163, 0x0163, + 0x0165, 0x0165, + 0x0167, 0x0167, + 0x0169, 0x0169, + 0x016b, 0x016b, + 0x016d, 0x016d, + 0x016f, 0x016f, + 0x0171, 0x0171, + 0x0173, 0x0173, + 0x0175, 0x0175, + 0x0177, 0x0177, + 0x017a, 0x017a, + 0x017c, 0x017c, + 0x017e, 0x0180, + 0x0183, 0x0183, + 0x0185, 0x0185, + 0x0188, 0x0188, + 0x018c, 0x018d, + 0x0192, 0x0192, + 0x0195, 0x0195, + 0x0199, 0x019b, + 0x019e, 0x019e, + 0x01a1, 0x01a1, + 0x01a3, 0x01a3, + 0x01a5, 0x01a5, + 0x01a8, 0x01a8, + 0x01aa, 0x01ab, + 0x01ad, 0x01ad, + 0x01b0, 0x01b0, + 0x01b4, 0x01b4, + 0x01b6, 0x01b6, + 0x01b9, 0x01ba, + 0x01bd, 0x01bf, + 0x01c6, 0x01c6, + 0x01c9, 0x01c9, + 0x01cc, 0x01cc, + 0x01ce, 0x01ce, + 0x01d0, 0x01d0, + 0x01d2, 0x01d2, + 0x01d4, 0x01d4, + 0x01d6, 0x01d6, + 0x01d8, 0x01d8, + 0x01da, 0x01da, + 0x01dc, 0x01dd, + 0x01df, 0x01df, + 0x01e1, 0x01e1, + 0x01e3, 0x01e3, + 0x01e5, 0x01e5, + 0x01e7, 0x01e7, + 0x01e9, 0x01e9, + 0x01eb, 0x01eb, + 0x01ed, 0x01ed, + 0x01ef, 0x01f0, + 0x01f3, 0x01f3, + 0x01f5, 0x01f5, + 0x01f9, 0x01f9, + 0x01fb, 0x01fb, + 0x01fd, 0x01fd, + 0x01ff, 0x01ff, + 0x0201, 0x0201, + 0x0203, 0x0203, + 0x0205, 0x0205, + 0x0207, 0x0207, + 0x0209, 0x0209, + 0x020b, 0x020b, + 0x020d, 0x020d, + 0x020f, 0x020f, + 0x0211, 0x0211, + 0x0213, 0x0213, + 0x0215, 0x0215, + 0x0217, 0x0217, + 0x0219, 0x0219, + 0x021b, 0x021b, + 0x021d, 0x021d, + 0x021f, 0x021f, + 0x0221, 0x0221, + 0x0223, 0x0223, + 0x0225, 0x0225, + 0x0227, 0x0227, + 0x0229, 0x0229, + 0x022b, 0x022b, + 0x022d, 0x022d, + 0x022f, 0x022f, + 0x0231, 0x0231, + 0x0233, 0x0236, + 0x0250, 0x02af, + 0x0390, 0x0390, + 0x03ac, 0x03ce, + 0x03d0, 0x03d1, + 0x03d5, 0x03d7, + 0x03d9, 0x03d9, + 0x03db, 0x03db, + 0x03dd, 0x03dd, + 0x03df, 0x03df, + 0x03e1, 0x03e1, + 0x03e3, 0x03e3, + 0x03e5, 0x03e5, + 0x03e7, 0x03e7, + 0x03e9, 0x03e9, + 0x03eb, 0x03eb, + 0x03ed, 0x03ed, + 0x03ef, 0x03f3, + 0x03f5, 0x03f5, + 0x03f8, 0x03f8, + 0x03fb, 0x03fb, + 0x0430, 0x045f, + 0x0461, 0x0461, + 0x0463, 0x0463, + 0x0465, 0x0465, + 0x0467, 0x0467, + 0x0469, 0x0469, + 0x046b, 0x046b, + 0x046d, 0x046d, + 0x046f, 0x046f, + 0x0471, 0x0471, + 0x0473, 0x0473, + 0x0475, 0x0475, + 0x0477, 0x0477, + 0x0479, 0x0479, + 0x047b, 0x047b, + 0x047d, 0x047d, + 0x047f, 0x047f, + 0x0481, 0x0481, + 0x048b, 0x048b, + 0x048d, 0x048d, + 0x048f, 0x048f, + 0x0491, 0x0491, + 0x0493, 0x0493, + 0x0495, 0x0495, + 0x0497, 0x0497, + 0x0499, 0x0499, + 0x049b, 0x049b, + 0x049d, 0x049d, + 0x049f, 0x049f, + 0x04a1, 0x04a1, + 0x04a3, 0x04a3, + 0x04a5, 0x04a5, + 0x04a7, 0x04a7, + 0x04a9, 0x04a9, + 0x04ab, 0x04ab, + 0x04ad, 0x04ad, + 0x04af, 0x04af, + 0x04b1, 0x04b1, + 0x04b3, 0x04b3, + 0x04b5, 0x04b5, + 0x04b7, 0x04b7, + 0x04b9, 0x04b9, + 0x04bb, 0x04bb, + 0x04bd, 0x04bd, + 0x04bf, 0x04bf, + 0x04c2, 0x04c2, + 0x04c4, 0x04c4, + 0x04c6, 0x04c6, + 0x04c8, 0x04c8, + 0x04ca, 0x04ca, + 0x04cc, 0x04cc, + 0x04ce, 0x04ce, + 0x04d1, 0x04d1, + 0x04d3, 0x04d3, + 0x04d5, 0x04d5, + 0x04d7, 0x04d7, + 0x04d9, 0x04d9, + 0x04db, 0x04db, + 0x04dd, 0x04dd, + 0x04df, 0x04df, + 0x04e1, 0x04e1, + 0x04e3, 0x04e3, + 0x04e5, 0x04e5, + 0x04e7, 0x04e7, + 0x04e9, 0x04e9, + 0x04eb, 0x04eb, + 0x04ed, 0x04ed, + 0x04ef, 0x04ef, + 0x04f1, 0x04f1, + 0x04f3, 0x04f3, + 0x04f5, 0x04f5, + 0x04f9, 0x04f9, + 0x0501, 0x0501, + 0x0503, 0x0503, + 0x0505, 0x0505, + 0x0507, 0x0507, + 0x0509, 0x0509, + 0x050b, 0x050b, + 0x050d, 0x050d, + 0x050f, 0x050f, + 0x0561, 0x0587, + 0x1d00, 0x1d2b, + 0x1d62, 0x1d6b, + 0x1e01, 0x1e01, + 0x1e03, 0x1e03, + 0x1e05, 0x1e05, + 0x1e07, 0x1e07, + 0x1e09, 0x1e09, + 0x1e0b, 0x1e0b, + 0x1e0d, 0x1e0d, + 0x1e0f, 0x1e0f, + 0x1e11, 0x1e11, + 0x1e13, 0x1e13, + 0x1e15, 0x1e15, + 0x1e17, 0x1e17, + 0x1e19, 0x1e19, + 0x1e1b, 0x1e1b, + 0x1e1d, 0x1e1d, + 0x1e1f, 0x1e1f, + 0x1e21, 0x1e21, + 0x1e23, 0x1e23, + 0x1e25, 0x1e25, + 0x1e27, 0x1e27, + 0x1e29, 0x1e29, + 0x1e2b, 0x1e2b, + 0x1e2d, 0x1e2d, + 0x1e2f, 0x1e2f, + 0x1e31, 0x1e31, + 0x1e33, 0x1e33, + 0x1e35, 0x1e35, + 0x1e37, 0x1e37, + 0x1e39, 0x1e39, + 0x1e3b, 0x1e3b, + 0x1e3d, 0x1e3d, + 0x1e3f, 0x1e3f, + 0x1e41, 0x1e41, + 0x1e43, 0x1e43, + 0x1e45, 0x1e45, + 0x1e47, 0x1e47, + 0x1e49, 0x1e49, + 0x1e4b, 0x1e4b, + 0x1e4d, 0x1e4d, + 0x1e4f, 0x1e4f, + 0x1e51, 0x1e51, + 0x1e53, 0x1e53, + 0x1e55, 0x1e55, + 0x1e57, 0x1e57, + 0x1e59, 0x1e59, + 0x1e5b, 0x1e5b, + 0x1e5d, 0x1e5d, + 0x1e5f, 0x1e5f, + 0x1e61, 0x1e61, + 0x1e63, 0x1e63, + 0x1e65, 0x1e65, + 0x1e67, 0x1e67, + 0x1e69, 0x1e69, + 0x1e6b, 0x1e6b, + 0x1e6d, 0x1e6d, + 0x1e6f, 0x1e6f, + 0x1e71, 0x1e71, + 0x1e73, 0x1e73, + 0x1e75, 0x1e75, + 0x1e77, 0x1e77, + 0x1e79, 0x1e79, + 0x1e7b, 0x1e7b, + 0x1e7d, 0x1e7d, + 0x1e7f, 0x1e7f, + 0x1e81, 0x1e81, + 0x1e83, 0x1e83, + 0x1e85, 0x1e85, + 0x1e87, 0x1e87, + 0x1e89, 0x1e89, + 0x1e8b, 0x1e8b, + 0x1e8d, 0x1e8d, + 0x1e8f, 0x1e8f, + 0x1e91, 0x1e91, + 0x1e93, 0x1e93, + 0x1e95, 0x1e9b, + 0x1ea1, 0x1ea1, + 0x1ea3, 0x1ea3, + 0x1ea5, 0x1ea5, + 0x1ea7, 0x1ea7, + 0x1ea9, 0x1ea9, + 0x1eab, 0x1eab, + 0x1ead, 0x1ead, + 0x1eaf, 0x1eaf, + 0x1eb1, 0x1eb1, + 0x1eb3, 0x1eb3, + 0x1eb5, 0x1eb5, + 0x1eb7, 0x1eb7, + 0x1eb9, 0x1eb9, + 0x1ebb, 0x1ebb, + 0x1ebd, 0x1ebd, + 0x1ebf, 0x1ebf, + 0x1ec1, 0x1ec1, + 0x1ec3, 0x1ec3, + 0x1ec5, 0x1ec5, + 0x1ec7, 0x1ec7, + 0x1ec9, 0x1ec9, + 0x1ecb, 0x1ecb, + 0x1ecd, 0x1ecd, + 0x1ecf, 0x1ecf, + 0x1ed1, 0x1ed1, + 0x1ed3, 0x1ed3, + 0x1ed5, 0x1ed5, + 0x1ed7, 0x1ed7, + 0x1ed9, 0x1ed9, + 0x1edb, 0x1edb, + 0x1edd, 0x1edd, + 0x1edf, 0x1edf, + 0x1ee1, 0x1ee1, + 0x1ee3, 0x1ee3, + 0x1ee5, 0x1ee5, + 0x1ee7, 0x1ee7, + 0x1ee9, 0x1ee9, + 0x1eeb, 0x1eeb, + 0x1eed, 0x1eed, + 0x1eef, 0x1eef, + 0x1ef1, 0x1ef1, + 0x1ef3, 0x1ef3, + 0x1ef5, 0x1ef5, + 0x1ef7, 0x1ef7, + 0x1ef9, 0x1ef9, + 0x1f00, 0x1f07, + 0x1f10, 0x1f15, + 0x1f20, 0x1f27, + 0x1f30, 0x1f37, + 0x1f40, 0x1f45, + 0x1f50, 0x1f57, + 0x1f60, 0x1f67, + 0x1f70, 0x1f7d, + 0x1f80, 0x1f87, + 0x1f90, 0x1f97, + 0x1fa0, 0x1fa7, + 0x1fb0, 0x1fb4, + 0x1fb6, 0x1fb7, + 0x1fbe, 0x1fbe, + 0x1fc2, 0x1fc4, + 0x1fc6, 0x1fc7, + 0x1fd0, 0x1fd3, + 0x1fd6, 0x1fd7, + 0x1fe0, 0x1fe7, + 0x1ff2, 0x1ff4, + 0x1ff6, 0x1ff7, + 0x2071, 0x2071, + 0x207f, 0x207f, + 0x210a, 0x210a, + 0x210e, 0x210f, + 0x2113, 0x2113, + 0x212f, 0x212f, + 0x2134, 0x2134, + 0x2139, 0x2139, + 0x213d, 0x213d, + 0x2146, 0x2149, + 0xfb00, 0xfb06, + 0xfb13, 0xfb17, + 0xff41, 0xff5a, + 0x10428, 0x1044f, + 0x1d41a, 0x1d433, + 0x1d44e, 0x1d454, + 0x1d456, 0x1d467, + 0x1d482, 0x1d49b, + 0x1d4b6, 0x1d4b9, + 0x1d4bb, 0x1d4bb, + 0x1d4bd, 0x1d4c3, + 0x1d4c5, 0x1d4cf, + 0x1d4ea, 0x1d503, + 0x1d51e, 0x1d537, + 0x1d552, 0x1d56b, + 0x1d586, 0x1d59f, + 0x1d5ba, 0x1d5d3, + 0x1d5ee, 0x1d607, + 0x1d622, 0x1d63b, + 0x1d656, 0x1d66f, + 0x1d68a, 0x1d6a3, + 0x1d6c2, 0x1d6da, + 0x1d6dc, 0x1d6e1, + 0x1d6fc, 0x1d714, + 0x1d716, 0x1d71b, + 0x1d736, 0x1d74e, + 0x1d750, 0x1d755, + 0x1d770, 0x1d788, + 0x1d78a, 0x1d78f, + 0x1d7aa, 0x1d7c2, + 0x1d7c4, 0x1d7c9 +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +}; /* end of MBLower */ + +static OnigCodePoint SBPrint[] = { + 2, + 0x0009, 0x000d, + 0x0020, 0x007e +}; + +static OnigCodePoint MBPrint[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 403, +#else + 2, +#endif + 0x0085, 0x0085, + 0x00a0, 0x0236 +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + , + 0x0250, 0x0357, + 0x035d, 0x036f, + 0x0374, 0x0375, + 0x037a, 0x037a, + 0x037e, 0x037e, + 0x0384, 0x038a, + 0x038c, 0x038c, + 0x038e, 0x03a1, + 0x03a3, 0x03ce, + 0x03d0, 0x03fb, + 0x0400, 0x0486, + 0x0488, 0x04ce, + 0x04d0, 0x04f5, + 0x04f8, 0x04f9, + 0x0500, 0x050f, + 0x0531, 0x0556, + 0x0559, 0x055f, + 0x0561, 0x0587, + 0x0589, 0x058a, + 0x0591, 0x05a1, + 0x05a3, 0x05b9, + 0x05bb, 0x05c4, + 0x05d0, 0x05ea, + 0x05f0, 0x05f4, + 0x0600, 0x0603, + 0x060c, 0x0615, + 0x061b, 0x061b, + 0x061f, 0x061f, + 0x0621, 0x063a, + 0x0640, 0x0658, + 0x0660, 0x070d, + 0x070f, 0x074a, + 0x074d, 0x074f, + 0x0780, 0x07b1, + 0x0901, 0x0939, + 0x093c, 0x094d, + 0x0950, 0x0954, + 0x0958, 0x0970, + 0x0981, 0x0983, + 0x0985, 0x098c, + 0x098f, 0x0990, + 0x0993, 0x09a8, + 0x09aa, 0x09b0, + 0x09b2, 0x09b2, + 0x09b6, 0x09b9, + 0x09bc, 0x09c4, + 0x09c7, 0x09c8, + 0x09cb, 0x09cd, + 0x09d7, 0x09d7, + 0x09dc, 0x09dd, + 0x09df, 0x09e3, + 0x09e6, 0x09fa, + 0x0a01, 0x0a03, + 0x0a05, 0x0a0a, + 0x0a0f, 0x0a10, + 0x0a13, 0x0a28, + 0x0a2a, 0x0a30, + 0x0a32, 0x0a33, + 0x0a35, 0x0a36, + 0x0a38, 0x0a39, + 0x0a3c, 0x0a3c, + 0x0a3e, 0x0a42, + 0x0a47, 0x0a48, + 0x0a4b, 0x0a4d, + 0x0a59, 0x0a5c, + 0x0a5e, 0x0a5e, + 0x0a66, 0x0a74, + 0x0a81, 0x0a83, + 0x0a85, 0x0a8d, + 0x0a8f, 0x0a91, + 0x0a93, 0x0aa8, + 0x0aaa, 0x0ab0, + 0x0ab2, 0x0ab3, + 0x0ab5, 0x0ab9, + 0x0abc, 0x0ac5, + 0x0ac7, 0x0ac9, + 0x0acb, 0x0acd, + 0x0ad0, 0x0ad0, + 0x0ae0, 0x0ae3, + 0x0ae6, 0x0aef, + 0x0af1, 0x0af1, + 0x0b01, 0x0b03, + 0x0b05, 0x0b0c, + 0x0b0f, 0x0b10, + 0x0b13, 0x0b28, + 0x0b2a, 0x0b30, + 0x0b32, 0x0b33, + 0x0b35, 0x0b39, + 0x0b3c, 0x0b43, + 0x0b47, 0x0b48, + 0x0b4b, 0x0b4d, + 0x0b56, 0x0b57, + 0x0b5c, 0x0b5d, + 0x0b5f, 0x0b61, + 0x0b66, 0x0b71, + 0x0b82, 0x0b83, + 0x0b85, 0x0b8a, + 0x0b8e, 0x0b90, + 0x0b92, 0x0b95, + 0x0b99, 0x0b9a, + 0x0b9c, 0x0b9c, + 0x0b9e, 0x0b9f, + 0x0ba3, 0x0ba4, + 0x0ba8, 0x0baa, + 0x0bae, 0x0bb5, + 0x0bb7, 0x0bb9, + 0x0bbe, 0x0bc2, + 0x0bc6, 0x0bc8, + 0x0bca, 0x0bcd, + 0x0bd7, 0x0bd7, + 0x0be7, 0x0bfa, + 0x0c01, 0x0c03, + 0x0c05, 0x0c0c, + 0x0c0e, 0x0c10, + 0x0c12, 0x0c28, + 0x0c2a, 0x0c33, + 0x0c35, 0x0c39, + 0x0c3e, 0x0c44, + 0x0c46, 0x0c48, + 0x0c4a, 0x0c4d, + 0x0c55, 0x0c56, + 0x0c60, 0x0c61, + 0x0c66, 0x0c6f, + 0x0c82, 0x0c83, + 0x0c85, 0x0c8c, + 0x0c8e, 0x0c90, + 0x0c92, 0x0ca8, + 0x0caa, 0x0cb3, + 0x0cb5, 0x0cb9, + 0x0cbc, 0x0cc4, + 0x0cc6, 0x0cc8, + 0x0cca, 0x0ccd, + 0x0cd5, 0x0cd6, + 0x0cde, 0x0cde, + 0x0ce0, 0x0ce1, + 0x0ce6, 0x0cef, + 0x0d02, 0x0d03, + 0x0d05, 0x0d0c, + 0x0d0e, 0x0d10, + 0x0d12, 0x0d28, + 0x0d2a, 0x0d39, + 0x0d3e, 0x0d43, + 0x0d46, 0x0d48, + 0x0d4a, 0x0d4d, + 0x0d57, 0x0d57, + 0x0d60, 0x0d61, + 0x0d66, 0x0d6f, + 0x0d82, 0x0d83, + 0x0d85, 0x0d96, + 0x0d9a, 0x0db1, + 0x0db3, 0x0dbb, + 0x0dbd, 0x0dbd, + 0x0dc0, 0x0dc6, + 0x0dca, 0x0dca, + 0x0dcf, 0x0dd4, + 0x0dd6, 0x0dd6, + 0x0dd8, 0x0ddf, + 0x0df2, 0x0df4, + 0x0e01, 0x0e3a, + 0x0e3f, 0x0e5b, + 0x0e81, 0x0e82, + 0x0e84, 0x0e84, + 0x0e87, 0x0e88, + 0x0e8a, 0x0e8a, + 0x0e8d, 0x0e8d, + 0x0e94, 0x0e97, + 0x0e99, 0x0e9f, + 0x0ea1, 0x0ea3, + 0x0ea5, 0x0ea5, + 0x0ea7, 0x0ea7, + 0x0eaa, 0x0eab, + 0x0ead, 0x0eb9, + 0x0ebb, 0x0ebd, + 0x0ec0, 0x0ec4, + 0x0ec6, 0x0ec6, + 0x0ec8, 0x0ecd, + 0x0ed0, 0x0ed9, + 0x0edc, 0x0edd, + 0x0f00, 0x0f47, + 0x0f49, 0x0f6a, + 0x0f71, 0x0f8b, + 0x0f90, 0x0f97, + 0x0f99, 0x0fbc, + 0x0fbe, 0x0fcc, + 0x0fcf, 0x0fcf, + 0x1000, 0x1021, + 0x1023, 0x1027, + 0x1029, 0x102a, + 0x102c, 0x1032, + 0x1036, 0x1039, + 0x1040, 0x1059, + 0x10a0, 0x10c5, + 0x10d0, 0x10f8, + 0x10fb, 0x10fb, + 0x1100, 0x1159, + 0x115f, 0x11a2, + 0x11a8, 0x11f9, + 0x1200, 0x1206, + 0x1208, 0x1246, + 0x1248, 0x1248, + 0x124a, 0x124d, + 0x1250, 0x1256, + 0x1258, 0x1258, + 0x125a, 0x125d, + 0x1260, 0x1286, + 0x1288, 0x1288, + 0x128a, 0x128d, + 0x1290, 0x12ae, + 0x12b0, 0x12b0, + 0x12b2, 0x12b5, + 0x12b8, 0x12be, + 0x12c0, 0x12c0, + 0x12c2, 0x12c5, + 0x12c8, 0x12ce, + 0x12d0, 0x12d6, + 0x12d8, 0x12ee, + 0x12f0, 0x130e, + 0x1310, 0x1310, + 0x1312, 0x1315, + 0x1318, 0x131e, + 0x1320, 0x1346, + 0x1348, 0x135a, + 0x1361, 0x137c, + 0x13a0, 0x13f4, + 0x1401, 0x1676, + 0x1680, 0x169c, + 0x16a0, 0x16f0, + 0x1700, 0x170c, + 0x170e, 0x1714, + 0x1720, 0x1736, + 0x1740, 0x1753, + 0x1760, 0x176c, + 0x176e, 0x1770, + 0x1772, 0x1773, + 0x1780, 0x17dd, + 0x17e0, 0x17e9, + 0x17f0, 0x17f9, + 0x1800, 0x180e, + 0x1810, 0x1819, + 0x1820, 0x1877, + 0x1880, 0x18a9, + 0x1900, 0x191c, + 0x1920, 0x192b, + 0x1930, 0x193b, + 0x1940, 0x1940, + 0x1944, 0x196d, + 0x1970, 0x1974, + 0x19e0, 0x19ff, + 0x1d00, 0x1d6b, + 0x1e00, 0x1e9b, + 0x1ea0, 0x1ef9, + 0x1f00, 0x1f15, + 0x1f18, 0x1f1d, + 0x1f20, 0x1f45, + 0x1f48, 0x1f4d, + 0x1f50, 0x1f57, + 0x1f59, 0x1f59, + 0x1f5b, 0x1f5b, + 0x1f5d, 0x1f5d, + 0x1f5f, 0x1f7d, + 0x1f80, 0x1fb4, + 0x1fb6, 0x1fc4, + 0x1fc6, 0x1fd3, + 0x1fd6, 0x1fdb, + 0x1fdd, 0x1fef, + 0x1ff2, 0x1ff4, + 0x1ff6, 0x1ffe, + 0x2000, 0x2054, + 0x2057, 0x2057, + 0x205f, 0x2063, + 0x206a, 0x2071, + 0x2074, 0x208e, + 0x20a0, 0x20b1, + 0x20d0, 0x20ea, + 0x2100, 0x213b, + 0x213d, 0x214b, + 0x2153, 0x2183, + 0x2190, 0x23d0, + 0x2400, 0x2426, + 0x2440, 0x244a, + 0x2460, 0x2617, + 0x2619, 0x267d, + 0x2680, 0x2691, + 0x26a0, 0x26a1, + 0x2701, 0x2704, + 0x2706, 0x2709, + 0x270c, 0x2727, + 0x2729, 0x274b, + 0x274d, 0x274d, + 0x274f, 0x2752, + 0x2756, 0x2756, + 0x2758, 0x275e, + 0x2761, 0x2794, + 0x2798, 0x27af, + 0x27b1, 0x27be, + 0x27d0, 0x27eb, + 0x27f0, 0x2b0d, + 0x2e80, 0x2e99, + 0x2e9b, 0x2ef3, + 0x2f00, 0x2fd5, + 0x2ff0, 0x2ffb, + 0x3000, 0x303f, + 0x3041, 0x3096, + 0x3099, 0x30ff, + 0x3105, 0x312c, + 0x3131, 0x318e, + 0x3190, 0x31b7, + 0x31f0, 0x321e, + 0x3220, 0x3243, + 0x3250, 0x327d, + 0x327f, 0x32fe, + 0x3300, 0x4db5, + 0x4dc0, 0x9fa5, + 0xa000, 0xa48c, + 0xa490, 0xa4c6, + 0xac00, 0xd7a3, + 0xe000, 0xfa2d, + 0xfa30, 0xfa6a, + 0xfb00, 0xfb06, + 0xfb13, 0xfb17, + 0xfb1d, 0xfb36, + 0xfb38, 0xfb3c, + 0xfb3e, 0xfb3e, + 0xfb40, 0xfb41, + 0xfb43, 0xfb44, + 0xfb46, 0xfbb1, + 0xfbd3, 0xfd3f, + 0xfd50, 0xfd8f, + 0xfd92, 0xfdc7, + 0xfdf0, 0xfdfd, + 0xfe00, 0xfe0f, + 0xfe20, 0xfe23, + 0xfe30, 0xfe52, + 0xfe54, 0xfe66, + 0xfe68, 0xfe6b, + 0xfe70, 0xfe74, + 0xfe76, 0xfefc, + 0xfeff, 0xfeff, + 0xff01, 0xffbe, + 0xffc2, 0xffc7, + 0xffca, 0xffcf, + 0xffd2, 0xffd7, + 0xffda, 0xffdc, + 0xffe0, 0xffe6, + 0xffe8, 0xffee, + 0xfff9, 0xfffd, + 0x10000, 0x1000b, + 0x1000d, 0x10026, + 0x10028, 0x1003a, + 0x1003c, 0x1003d, + 0x1003f, 0x1004d, + 0x10050, 0x1005d, + 0x10080, 0x100fa, + 0x10100, 0x10102, + 0x10107, 0x10133, + 0x10137, 0x1013f, + 0x10300, 0x1031e, + 0x10320, 0x10323, + 0x10330, 0x1034a, + 0x10380, 0x1039d, + 0x1039f, 0x1039f, + 0x10400, 0x1049d, + 0x104a0, 0x104a9, + 0x10800, 0x10805, + 0x10808, 0x10808, + 0x1080a, 0x10835, + 0x10837, 0x10838, + 0x1083c, 0x1083c, + 0x1083f, 0x1083f, + 0x1d000, 0x1d0f5, + 0x1d100, 0x1d126, + 0x1d12a, 0x1d1dd, + 0x1d300, 0x1d356, + 0x1d400, 0x1d454, + 0x1d456, 0x1d49c, + 0x1d49e, 0x1d49f, + 0x1d4a2, 0x1d4a2, + 0x1d4a5, 0x1d4a6, + 0x1d4a9, 0x1d4ac, + 0x1d4ae, 0x1d4b9, + 0x1d4bb, 0x1d4bb, + 0x1d4bd, 0x1d4c3, + 0x1d4c5, 0x1d505, + 0x1d507, 0x1d50a, + 0x1d50d, 0x1d514, + 0x1d516, 0x1d51c, + 0x1d51e, 0x1d539, + 0x1d53b, 0x1d53e, + 0x1d540, 0x1d544, + 0x1d546, 0x1d546, + 0x1d54a, 0x1d550, + 0x1d552, 0x1d6a3, + 0x1d6a8, 0x1d7c9, + 0x1d7ce, 0x1d7ff, + 0x20000, 0x2a6d6, + 0x2f800, 0x2fa1d, + 0xe0001, 0xe0001, + 0xe0020, 0xe007f, + 0xe0100, 0xe01ef, + 0xf0000, 0xffffd, + 0x100000, 0x10fffd +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +}; /* end of MBPrint */ + +static OnigCodePoint SBPunct[] = { + 9, + 0x0021, 0x0023, + 0x0025, 0x002a, + 0x002c, 0x002f, + 0x003a, 0x003b, + 0x003f, 0x0040, + 0x005b, 0x005d, + 0x005f, 0x005f, + 0x007b, 0x007b, + 0x007d, 0x007d +}; /* end of SBPunct */ + +static OnigCodePoint MBPunct[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 77, +#else + 5, +#endif + 0x00a1, 0x00a1, + 0x00ab, 0x00ab, + 0x00b7, 0x00b7, + 0x00bb, 0x00bb, + 0x00bf, 0x00bf +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + , + 0x037e, 0x037e, + 0x0387, 0x0387, + 0x055a, 0x055f, + 0x0589, 0x058a, + 0x05be, 0x05be, + 0x05c0, 0x05c0, + 0x05c3, 0x05c3, + 0x05f3, 0x05f4, + 0x060c, 0x060d, + 0x061b, 0x061b, + 0x061f, 0x061f, + 0x066a, 0x066d, + 0x06d4, 0x06d4, + 0x0700, 0x070d, + 0x0964, 0x0965, + 0x0970, 0x0970, + 0x0df4, 0x0df4, + 0x0e4f, 0x0e4f, + 0x0e5a, 0x0e5b, + 0x0f04, 0x0f12, + 0x0f3a, 0x0f3d, + 0x0f85, 0x0f85, + 0x104a, 0x104f, + 0x10fb, 0x10fb, + 0x1361, 0x1368, + 0x166d, 0x166e, + 0x169b, 0x169c, + 0x16eb, 0x16ed, + 0x1735, 0x1736, + 0x17d4, 0x17d6, + 0x17d8, 0x17da, + 0x1800, 0x180a, + 0x1944, 0x1945, + 0x2010, 0x2027, + 0x2030, 0x2043, + 0x2045, 0x2051, + 0x2053, 0x2054, + 0x2057, 0x2057, + 0x207d, 0x207e, + 0x208d, 0x208e, + 0x2329, 0x232a, + 0x23b4, 0x23b6, + 0x2768, 0x2775, + 0x27e6, 0x27eb, + 0x2983, 0x2998, + 0x29d8, 0x29db, + 0x29fc, 0x29fd, + 0x3001, 0x3003, + 0x3008, 0x3011, + 0x3014, 0x301f, + 0x3030, 0x3030, + 0x303d, 0x303d, + 0x30a0, 0x30a0, + 0x30fb, 0x30fb, + 0xfd3e, 0xfd3f, + 0xfe30, 0xfe52, + 0xfe54, 0xfe61, + 0xfe63, 0xfe63, + 0xfe68, 0xfe68, + 0xfe6a, 0xfe6b, + 0xff01, 0xff03, + 0xff05, 0xff0a, + 0xff0c, 0xff0f, + 0xff1a, 0xff1b, + 0xff1f, 0xff20, + 0xff3b, 0xff3d, + 0xff3f, 0xff3f, + 0xff5b, 0xff5b, + 0xff5d, 0xff5d, + 0xff5f, 0xff65, + 0x10100, 0x10101, + 0x1039f, 0x1039f +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +}; /* end of MBPunct */ + +static OnigCodePoint SBSpace[] = { + 2, + 0x0009, 0x000d, + 0x0020, 0x0020 +}; + +static OnigCodePoint MBSpace[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 9, +#else + 2, +#endif + 0x0085, 0x0085, + 0x00a0, 0x00a0 +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + , + 0x1680, 0x1680, + 0x180e, 0x180e, + 0x2000, 0x200a, + 0x2028, 0x2029, + 0x202f, 0x202f, + 0x205f, 0x205f, + 0x3000, 0x3000 +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +}; /* end of MBSpace */ + +static OnigCodePoint SBUpper[] = { + 1, + 0x0041, 0x005a +}; + +static OnigCodePoint MBUpper[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 420, +#else + 2, +#endif + 0x00c0, 0x00d6, + 0x00d8, 0x00de +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + , + 0x0100, 0x0100, + 0x0102, 0x0102, + 0x0104, 0x0104, + 0x0106, 0x0106, + 0x0108, 0x0108, + 0x010a, 0x010a, + 0x010c, 0x010c, + 0x010e, 0x010e, + 0x0110, 0x0110, + 0x0112, 0x0112, + 0x0114, 0x0114, + 0x0116, 0x0116, + 0x0118, 0x0118, + 0x011a, 0x011a, + 0x011c, 0x011c, + 0x011e, 0x011e, + 0x0120, 0x0120, + 0x0122, 0x0122, + 0x0124, 0x0124, + 0x0126, 0x0126, + 0x0128, 0x0128, + 0x012a, 0x012a, + 0x012c, 0x012c, + 0x012e, 0x012e, + 0x0130, 0x0130, + 0x0132, 0x0132, + 0x0134, 0x0134, + 0x0136, 0x0136, + 0x0139, 0x0139, + 0x013b, 0x013b, + 0x013d, 0x013d, + 0x013f, 0x013f, + 0x0141, 0x0141, + 0x0143, 0x0143, + 0x0145, 0x0145, + 0x0147, 0x0147, + 0x014a, 0x014a, + 0x014c, 0x014c, + 0x014e, 0x014e, + 0x0150, 0x0150, + 0x0152, 0x0152, + 0x0154, 0x0154, + 0x0156, 0x0156, + 0x0158, 0x0158, + 0x015a, 0x015a, + 0x015c, 0x015c, + 0x015e, 0x015e, + 0x0160, 0x0160, + 0x0162, 0x0162, + 0x0164, 0x0164, + 0x0166, 0x0166, + 0x0168, 0x0168, + 0x016a, 0x016a, + 0x016c, 0x016c, + 0x016e, 0x016e, + 0x0170, 0x0170, + 0x0172, 0x0172, + 0x0174, 0x0174, + 0x0176, 0x0176, + 0x0178, 0x0179, + 0x017b, 0x017b, + 0x017d, 0x017d, + 0x0181, 0x0182, + 0x0184, 0x0184, + 0x0186, 0x0187, + 0x0189, 0x018b, + 0x018e, 0x0191, + 0x0193, 0x0194, + 0x0196, 0x0198, + 0x019c, 0x019d, + 0x019f, 0x01a0, + 0x01a2, 0x01a2, + 0x01a4, 0x01a4, + 0x01a6, 0x01a7, + 0x01a9, 0x01a9, + 0x01ac, 0x01ac, + 0x01ae, 0x01af, + 0x01b1, 0x01b3, + 0x01b5, 0x01b5, + 0x01b7, 0x01b8, + 0x01bc, 0x01bc, + 0x01c4, 0x01c4, + 0x01c7, 0x01c7, + 0x01ca, 0x01ca, + 0x01cd, 0x01cd, + 0x01cf, 0x01cf, + 0x01d1, 0x01d1, + 0x01d3, 0x01d3, + 0x01d5, 0x01d5, + 0x01d7, 0x01d7, + 0x01d9, 0x01d9, + 0x01db, 0x01db, + 0x01de, 0x01de, + 0x01e0, 0x01e0, + 0x01e2, 0x01e2, + 0x01e4, 0x01e4, + 0x01e6, 0x01e6, + 0x01e8, 0x01e8, + 0x01ea, 0x01ea, + 0x01ec, 0x01ec, + 0x01ee, 0x01ee, + 0x01f1, 0x01f1, + 0x01f4, 0x01f4, + 0x01f6, 0x01f8, + 0x01fa, 0x01fa, + 0x01fc, 0x01fc, + 0x01fe, 0x01fe, + 0x0200, 0x0200, + 0x0202, 0x0202, + 0x0204, 0x0204, + 0x0206, 0x0206, + 0x0208, 0x0208, + 0x020a, 0x020a, + 0x020c, 0x020c, + 0x020e, 0x020e, + 0x0210, 0x0210, + 0x0212, 0x0212, + 0x0214, 0x0214, + 0x0216, 0x0216, + 0x0218, 0x0218, + 0x021a, 0x021a, + 0x021c, 0x021c, + 0x021e, 0x021e, + 0x0220, 0x0220, + 0x0222, 0x0222, + 0x0224, 0x0224, + 0x0226, 0x0226, + 0x0228, 0x0228, + 0x022a, 0x022a, + 0x022c, 0x022c, + 0x022e, 0x022e, + 0x0230, 0x0230, + 0x0232, 0x0232, + 0x0386, 0x0386, + 0x0388, 0x038a, + 0x038c, 0x038c, + 0x038e, 0x038f, + 0x0391, 0x03a1, + 0x03a3, 0x03ab, + 0x03d2, 0x03d4, + 0x03d8, 0x03d8, + 0x03da, 0x03da, + 0x03dc, 0x03dc, + 0x03de, 0x03de, + 0x03e0, 0x03e0, + 0x03e2, 0x03e2, + 0x03e4, 0x03e4, + 0x03e6, 0x03e6, + 0x03e8, 0x03e8, + 0x03ea, 0x03ea, + 0x03ec, 0x03ec, + 0x03ee, 0x03ee, + 0x03f4, 0x03f4, + 0x03f7, 0x03f7, + 0x03f9, 0x03fa, + 0x0400, 0x042f, + 0x0460, 0x0460, + 0x0462, 0x0462, + 0x0464, 0x0464, + 0x0466, 0x0466, + 0x0468, 0x0468, + 0x046a, 0x046a, + 0x046c, 0x046c, + 0x046e, 0x046e, + 0x0470, 0x0470, + 0x0472, 0x0472, + 0x0474, 0x0474, + 0x0476, 0x0476, + 0x0478, 0x0478, + 0x047a, 0x047a, + 0x047c, 0x047c, + 0x047e, 0x047e, + 0x0480, 0x0480, + 0x048a, 0x048a, + 0x048c, 0x048c, + 0x048e, 0x048e, + 0x0490, 0x0490, + 0x0492, 0x0492, + 0x0494, 0x0494, + 0x0496, 0x0496, + 0x0498, 0x0498, + 0x049a, 0x049a, + 0x049c, 0x049c, + 0x049e, 0x049e, + 0x04a0, 0x04a0, + 0x04a2, 0x04a2, + 0x04a4, 0x04a4, + 0x04a6, 0x04a6, + 0x04a8, 0x04a8, + 0x04aa, 0x04aa, + 0x04ac, 0x04ac, + 0x04ae, 0x04ae, + 0x04b0, 0x04b0, + 0x04b2, 0x04b2, + 0x04b4, 0x04b4, + 0x04b6, 0x04b6, + 0x04b8, 0x04b8, + 0x04ba, 0x04ba, + 0x04bc, 0x04bc, + 0x04be, 0x04be, + 0x04c0, 0x04c1, + 0x04c3, 0x04c3, + 0x04c5, 0x04c5, + 0x04c7, 0x04c7, + 0x04c9, 0x04c9, + 0x04cb, 0x04cb, + 0x04cd, 0x04cd, + 0x04d0, 0x04d0, + 0x04d2, 0x04d2, + 0x04d4, 0x04d4, + 0x04d6, 0x04d6, + 0x04d8, 0x04d8, + 0x04da, 0x04da, + 0x04dc, 0x04dc, + 0x04de, 0x04de, + 0x04e0, 0x04e0, + 0x04e2, 0x04e2, + 0x04e4, 0x04e4, + 0x04e6, 0x04e6, + 0x04e8, 0x04e8, + 0x04ea, 0x04ea, + 0x04ec, 0x04ec, + 0x04ee, 0x04ee, + 0x04f0, 0x04f0, + 0x04f2, 0x04f2, + 0x04f4, 0x04f4, + 0x04f8, 0x04f8, + 0x0500, 0x0500, + 0x0502, 0x0502, + 0x0504, 0x0504, + 0x0506, 0x0506, + 0x0508, 0x0508, + 0x050a, 0x050a, + 0x050c, 0x050c, + 0x050e, 0x050e, + 0x0531, 0x0556, + 0x10a0, 0x10c5, + 0x1e00, 0x1e00, + 0x1e02, 0x1e02, + 0x1e04, 0x1e04, + 0x1e06, 0x1e06, + 0x1e08, 0x1e08, + 0x1e0a, 0x1e0a, + 0x1e0c, 0x1e0c, + 0x1e0e, 0x1e0e, + 0x1e10, 0x1e10, + 0x1e12, 0x1e12, + 0x1e14, 0x1e14, + 0x1e16, 0x1e16, + 0x1e18, 0x1e18, + 0x1e1a, 0x1e1a, + 0x1e1c, 0x1e1c, + 0x1e1e, 0x1e1e, + 0x1e20, 0x1e20, + 0x1e22, 0x1e22, + 0x1e24, 0x1e24, + 0x1e26, 0x1e26, + 0x1e28, 0x1e28, + 0x1e2a, 0x1e2a, + 0x1e2c, 0x1e2c, + 0x1e2e, 0x1e2e, + 0x1e30, 0x1e30, + 0x1e32, 0x1e32, + 0x1e34, 0x1e34, + 0x1e36, 0x1e36, + 0x1e38, 0x1e38, + 0x1e3a, 0x1e3a, + 0x1e3c, 0x1e3c, + 0x1e3e, 0x1e3e, + 0x1e40, 0x1e40, + 0x1e42, 0x1e42, + 0x1e44, 0x1e44, + 0x1e46, 0x1e46, + 0x1e48, 0x1e48, + 0x1e4a, 0x1e4a, + 0x1e4c, 0x1e4c, + 0x1e4e, 0x1e4e, + 0x1e50, 0x1e50, + 0x1e52, 0x1e52, + 0x1e54, 0x1e54, + 0x1e56, 0x1e56, + 0x1e58, 0x1e58, + 0x1e5a, 0x1e5a, + 0x1e5c, 0x1e5c, + 0x1e5e, 0x1e5e, + 0x1e60, 0x1e60, + 0x1e62, 0x1e62, + 0x1e64, 0x1e64, + 0x1e66, 0x1e66, + 0x1e68, 0x1e68, + 0x1e6a, 0x1e6a, + 0x1e6c, 0x1e6c, + 0x1e6e, 0x1e6e, + 0x1e70, 0x1e70, + 0x1e72, 0x1e72, + 0x1e74, 0x1e74, + 0x1e76, 0x1e76, + 0x1e78, 0x1e78, + 0x1e7a, 0x1e7a, + 0x1e7c, 0x1e7c, + 0x1e7e, 0x1e7e, + 0x1e80, 0x1e80, + 0x1e82, 0x1e82, + 0x1e84, 0x1e84, + 0x1e86, 0x1e86, + 0x1e88, 0x1e88, + 0x1e8a, 0x1e8a, + 0x1e8c, 0x1e8c, + 0x1e8e, 0x1e8e, + 0x1e90, 0x1e90, + 0x1e92, 0x1e92, + 0x1e94, 0x1e94, + 0x1ea0, 0x1ea0, + 0x1ea2, 0x1ea2, + 0x1ea4, 0x1ea4, + 0x1ea6, 0x1ea6, + 0x1ea8, 0x1ea8, + 0x1eaa, 0x1eaa, + 0x1eac, 0x1eac, + 0x1eae, 0x1eae, + 0x1eb0, 0x1eb0, + 0x1eb2, 0x1eb2, + 0x1eb4, 0x1eb4, + 0x1eb6, 0x1eb6, + 0x1eb8, 0x1eb8, + 0x1eba, 0x1eba, + 0x1ebc, 0x1ebc, + 0x1ebe, 0x1ebe, + 0x1ec0, 0x1ec0, + 0x1ec2, 0x1ec2, + 0x1ec4, 0x1ec4, + 0x1ec6, 0x1ec6, + 0x1ec8, 0x1ec8, + 0x1eca, 0x1eca, + 0x1ecc, 0x1ecc, + 0x1ece, 0x1ece, + 0x1ed0, 0x1ed0, + 0x1ed2, 0x1ed2, + 0x1ed4, 0x1ed4, + 0x1ed6, 0x1ed6, + 0x1ed8, 0x1ed8, + 0x1eda, 0x1eda, + 0x1edc, 0x1edc, + 0x1ede, 0x1ede, + 0x1ee0, 0x1ee0, + 0x1ee2, 0x1ee2, + 0x1ee4, 0x1ee4, + 0x1ee6, 0x1ee6, + 0x1ee8, 0x1ee8, + 0x1eea, 0x1eea, + 0x1eec, 0x1eec, + 0x1eee, 0x1eee, + 0x1ef0, 0x1ef0, + 0x1ef2, 0x1ef2, + 0x1ef4, 0x1ef4, + 0x1ef6, 0x1ef6, + 0x1ef8, 0x1ef8, + 0x1f08, 0x1f0f, + 0x1f18, 0x1f1d, + 0x1f28, 0x1f2f, + 0x1f38, 0x1f3f, + 0x1f48, 0x1f4d, + 0x1f59, 0x1f59, + 0x1f5b, 0x1f5b, + 0x1f5d, 0x1f5d, + 0x1f5f, 0x1f5f, + 0x1f68, 0x1f6f, + 0x1fb8, 0x1fbb, + 0x1fc8, 0x1fcb, + 0x1fd8, 0x1fdb, + 0x1fe8, 0x1fec, + 0x1ff8, 0x1ffb, + 0x2102, 0x2102, + 0x2107, 0x2107, + 0x210b, 0x210d, + 0x2110, 0x2112, + 0x2115, 0x2115, + 0x2119, 0x211d, + 0x2124, 0x2124, + 0x2126, 0x2126, + 0x2128, 0x2128, + 0x212a, 0x212d, + 0x2130, 0x2131, + 0x2133, 0x2133, + 0x213e, 0x213f, + 0x2145, 0x2145, + 0xff21, 0xff3a, + 0x10400, 0x10427, + 0x1d400, 0x1d419, + 0x1d434, 0x1d44d, + 0x1d468, 0x1d481, + 0x1d49c, 0x1d49c, + 0x1d49e, 0x1d49f, + 0x1d4a2, 0x1d4a2, + 0x1d4a5, 0x1d4a6, + 0x1d4a9, 0x1d4ac, + 0x1d4ae, 0x1d4b5, + 0x1d4d0, 0x1d4e9, + 0x1d504, 0x1d505, + 0x1d507, 0x1d50a, + 0x1d50d, 0x1d514, + 0x1d516, 0x1d51c, + 0x1d538, 0x1d539, + 0x1d53b, 0x1d53e, + 0x1d540, 0x1d544, + 0x1d546, 0x1d546, + 0x1d54a, 0x1d550, + 0x1d56c, 0x1d585, + 0x1d5a0, 0x1d5b9, + 0x1d5d4, 0x1d5ed, + 0x1d608, 0x1d621, + 0x1d63c, 0x1d655, + 0x1d670, 0x1d689, + 0x1d6a8, 0x1d6c0, + 0x1d6e2, 0x1d6fa, + 0x1d71c, 0x1d734, + 0x1d756, 0x1d76e, + 0x1d790, 0x1d7a8 +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +}; /* end of MBUpper */ + +static OnigCodePoint SBXDigit[] = { + 3, + 0x0030, 0x0039, + 0x0041, 0x0046, + 0x0061, 0x0066 +}; + +static OnigCodePoint SBASCII[] = { + 1, + 0x0000, 0x007f +}; + +static OnigCodePoint SBWord[] = { + 4, + 0x0030, 0x0039, + 0x0041, 0x005a, + 0x005f, 0x005f, + 0x0061, 0x007a +}; + +static OnigCodePoint MBWord[] = { +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + 432, +#else + 8, +#endif + 0x00aa, 0x00aa, + 0x00b2, 0x00b3, + 0x00b5, 0x00b5, + 0x00b9, 0x00ba, + 0x00bc, 0x00be, + 0x00c0, 0x00d6, + 0x00d8, 0x00f6, +#ifndef USE_UNICODE_FULL_RANGE_CTYPE + 0x00f8, 0x7fffffff +#else /* not USE_UNICODE_FULL_RANGE_CTYPE */ + 0x00f8, 0x0236, + 0x0250, 0x02c1, + 0x02c6, 0x02d1, + 0x02e0, 0x02e4, + 0x02ee, 0x02ee, + 0x0300, 0x0357, + 0x035d, 0x036f, + 0x037a, 0x037a, + 0x0386, 0x0386, + 0x0388, 0x038a, + 0x038c, 0x038c, + 0x038e, 0x03a1, + 0x03a3, 0x03ce, + 0x03d0, 0x03f5, + 0x03f7, 0x03fb, + 0x0400, 0x0481, + 0x0483, 0x0486, + 0x0488, 0x04ce, + 0x04d0, 0x04f5, + 0x04f8, 0x04f9, + 0x0500, 0x050f, + 0x0531, 0x0556, + 0x0559, 0x0559, + 0x0561, 0x0587, + 0x0591, 0x05a1, + 0x05a3, 0x05b9, + 0x05bb, 0x05bd, + 0x05bf, 0x05bf, + 0x05c1, 0x05c2, + 0x05c4, 0x05c4, + 0x05d0, 0x05ea, + 0x05f0, 0x05f2, + 0x0610, 0x0615, + 0x0621, 0x063a, + 0x0640, 0x0658, + 0x0660, 0x0669, + 0x066e, 0x06d3, + 0x06d5, 0x06dc, + 0x06de, 0x06e8, + 0x06ea, 0x06fc, + 0x06ff, 0x06ff, + 0x0710, 0x074a, + 0x074d, 0x074f, + 0x0780, 0x07b1, + 0x0901, 0x0939, + 0x093c, 0x094d, + 0x0950, 0x0954, + 0x0958, 0x0963, + 0x0966, 0x096f, + 0x0981, 0x0983, + 0x0985, 0x098c, + 0x098f, 0x0990, + 0x0993, 0x09a8, + 0x09aa, 0x09b0, + 0x09b2, 0x09b2, + 0x09b6, 0x09b9, + 0x09bc, 0x09c4, + 0x09c7, 0x09c8, + 0x09cb, 0x09cd, + 0x09d7, 0x09d7, + 0x09dc, 0x09dd, + 0x09df, 0x09e3, + 0x09e6, 0x09f1, + 0x09f4, 0x09f9, + 0x0a01, 0x0a03, + 0x0a05, 0x0a0a, + 0x0a0f, 0x0a10, + 0x0a13, 0x0a28, + 0x0a2a, 0x0a30, + 0x0a32, 0x0a33, + 0x0a35, 0x0a36, + 0x0a38, 0x0a39, + 0x0a3c, 0x0a3c, + 0x0a3e, 0x0a42, + 0x0a47, 0x0a48, + 0x0a4b, 0x0a4d, + 0x0a59, 0x0a5c, + 0x0a5e, 0x0a5e, + 0x0a66, 0x0a74, + 0x0a81, 0x0a83, + 0x0a85, 0x0a8d, + 0x0a8f, 0x0a91, + 0x0a93, 0x0aa8, + 0x0aaa, 0x0ab0, + 0x0ab2, 0x0ab3, + 0x0ab5, 0x0ab9, + 0x0abc, 0x0ac5, + 0x0ac7, 0x0ac9, + 0x0acb, 0x0acd, + 0x0ad0, 0x0ad0, + 0x0ae0, 0x0ae3, + 0x0ae6, 0x0aef, + 0x0b01, 0x0b03, + 0x0b05, 0x0b0c, + 0x0b0f, 0x0b10, + 0x0b13, 0x0b28, + 0x0b2a, 0x0b30, + 0x0b32, 0x0b33, + 0x0b35, 0x0b39, + 0x0b3c, 0x0b43, + 0x0b47, 0x0b48, + 0x0b4b, 0x0b4d, + 0x0b56, 0x0b57, + 0x0b5c, 0x0b5d, + 0x0b5f, 0x0b61, + 0x0b66, 0x0b6f, + 0x0b71, 0x0b71, + 0x0b82, 0x0b83, + 0x0b85, 0x0b8a, + 0x0b8e, 0x0b90, + 0x0b92, 0x0b95, + 0x0b99, 0x0b9a, + 0x0b9c, 0x0b9c, + 0x0b9e, 0x0b9f, + 0x0ba3, 0x0ba4, + 0x0ba8, 0x0baa, + 0x0bae, 0x0bb5, + 0x0bb7, 0x0bb9, + 0x0bbe, 0x0bc2, + 0x0bc6, 0x0bc8, + 0x0bca, 0x0bcd, + 0x0bd7, 0x0bd7, + 0x0be7, 0x0bf2, + 0x0c01, 0x0c03, + 0x0c05, 0x0c0c, + 0x0c0e, 0x0c10, + 0x0c12, 0x0c28, + 0x0c2a, 0x0c33, + 0x0c35, 0x0c39, + 0x0c3e, 0x0c44, + 0x0c46, 0x0c48, + 0x0c4a, 0x0c4d, + 0x0c55, 0x0c56, + 0x0c60, 0x0c61, + 0x0c66, 0x0c6f, + 0x0c82, 0x0c83, + 0x0c85, 0x0c8c, + 0x0c8e, 0x0c90, + 0x0c92, 0x0ca8, + 0x0caa, 0x0cb3, + 0x0cb5, 0x0cb9, + 0x0cbc, 0x0cc4, + 0x0cc6, 0x0cc8, + 0x0cca, 0x0ccd, + 0x0cd5, 0x0cd6, + 0x0cde, 0x0cde, + 0x0ce0, 0x0ce1, + 0x0ce6, 0x0cef, + 0x0d02, 0x0d03, + 0x0d05, 0x0d0c, + 0x0d0e, 0x0d10, + 0x0d12, 0x0d28, + 0x0d2a, 0x0d39, + 0x0d3e, 0x0d43, + 0x0d46, 0x0d48, + 0x0d4a, 0x0d4d, + 0x0d57, 0x0d57, + 0x0d60, 0x0d61, + 0x0d66, 0x0d6f, + 0x0d82, 0x0d83, + 0x0d85, 0x0d96, + 0x0d9a, 0x0db1, + 0x0db3, 0x0dbb, + 0x0dbd, 0x0dbd, + 0x0dc0, 0x0dc6, + 0x0dca, 0x0dca, + 0x0dcf, 0x0dd4, + 0x0dd6, 0x0dd6, + 0x0dd8, 0x0ddf, + 0x0df2, 0x0df3, + 0x0e01, 0x0e3a, + 0x0e40, 0x0e4e, + 0x0e50, 0x0e59, + 0x0e81, 0x0e82, + 0x0e84, 0x0e84, + 0x0e87, 0x0e88, + 0x0e8a, 0x0e8a, + 0x0e8d, 0x0e8d, + 0x0e94, 0x0e97, + 0x0e99, 0x0e9f, + 0x0ea1, 0x0ea3, + 0x0ea5, 0x0ea5, + 0x0ea7, 0x0ea7, + 0x0eaa, 0x0eab, + 0x0ead, 0x0eb9, + 0x0ebb, 0x0ebd, + 0x0ec0, 0x0ec4, + 0x0ec6, 0x0ec6, + 0x0ec8, 0x0ecd, + 0x0ed0, 0x0ed9, + 0x0edc, 0x0edd, + 0x0f00, 0x0f00, + 0x0f18, 0x0f19, + 0x0f20, 0x0f33, + 0x0f35, 0x0f35, + 0x0f37, 0x0f37, + 0x0f39, 0x0f39, + 0x0f3e, 0x0f47, + 0x0f49, 0x0f6a, + 0x0f71, 0x0f84, + 0x0f86, 0x0f8b, + 0x0f90, 0x0f97, + 0x0f99, 0x0fbc, + 0x0fc6, 0x0fc6, + 0x1000, 0x1021, + 0x1023, 0x1027, + 0x1029, 0x102a, + 0x102c, 0x1032, + 0x1036, 0x1039, + 0x1040, 0x1049, + 0x1050, 0x1059, + 0x10a0, 0x10c5, + 0x10d0, 0x10f8, + 0x1100, 0x1159, + 0x115f, 0x11a2, + 0x11a8, 0x11f9, + 0x1200, 0x1206, + 0x1208, 0x1246, + 0x1248, 0x1248, + 0x124a, 0x124d, + 0x1250, 0x1256, + 0x1258, 0x1258, + 0x125a, 0x125d, + 0x1260, 0x1286, + 0x1288, 0x1288, + 0x128a, 0x128d, + 0x1290, 0x12ae, + 0x12b0, 0x12b0, + 0x12b2, 0x12b5, + 0x12b8, 0x12be, + 0x12c0, 0x12c0, + 0x12c2, 0x12c5, + 0x12c8, 0x12ce, + 0x12d0, 0x12d6, + 0x12d8, 0x12ee, + 0x12f0, 0x130e, + 0x1310, 0x1310, + 0x1312, 0x1315, + 0x1318, 0x131e, + 0x1320, 0x1346, + 0x1348, 0x135a, + 0x1369, 0x137c, + 0x13a0, 0x13f4, + 0x1401, 0x166c, + 0x166f, 0x1676, + 0x1681, 0x169a, + 0x16a0, 0x16ea, + 0x16ee, 0x16f0, + 0x1700, 0x170c, + 0x170e, 0x1714, + 0x1720, 0x1734, + 0x1740, 0x1753, + 0x1760, 0x176c, + 0x176e, 0x1770, + 0x1772, 0x1773, + 0x1780, 0x17b3, + 0x17b6, 0x17d3, + 0x17d7, 0x17d7, + 0x17dc, 0x17dd, + 0x17e0, 0x17e9, + 0x17f0, 0x17f9, + 0x180b, 0x180d, + 0x1810, 0x1819, + 0x1820, 0x1877, + 0x1880, 0x18a9, + 0x1900, 0x191c, + 0x1920, 0x192b, + 0x1930, 0x193b, + 0x1946, 0x196d, + 0x1970, 0x1974, + 0x1d00, 0x1d6b, + 0x1e00, 0x1e9b, + 0x1ea0, 0x1ef9, + 0x1f00, 0x1f15, + 0x1f18, 0x1f1d, + 0x1f20, 0x1f45, + 0x1f48, 0x1f4d, + 0x1f50, 0x1f57, + 0x1f59, 0x1f59, + 0x1f5b, 0x1f5b, + 0x1f5d, 0x1f5d, + 0x1f5f, 0x1f7d, + 0x1f80, 0x1fb4, + 0x1fb6, 0x1fbc, + 0x1fbe, 0x1fbe, + 0x1fc2, 0x1fc4, + 0x1fc6, 0x1fcc, + 0x1fd0, 0x1fd3, + 0x1fd6, 0x1fdb, + 0x1fe0, 0x1fec, + 0x1ff2, 0x1ff4, + 0x1ff6, 0x1ffc, + 0x203f, 0x2040, + 0x2054, 0x2054, + 0x2070, 0x2071, + 0x2074, 0x2079, + 0x207f, 0x2089, + 0x20d0, 0x20ea, + 0x2102, 0x2102, + 0x2107, 0x2107, + 0x210a, 0x2113, + 0x2115, 0x2115, + 0x2119, 0x211d, + 0x2124, 0x2124, + 0x2126, 0x2126, + 0x2128, 0x2128, + 0x212a, 0x212d, + 0x212f, 0x2131, + 0x2133, 0x2139, + 0x213d, 0x213f, + 0x2145, 0x2149, + 0x2153, 0x2183, + 0x2460, 0x249b, + 0x24ea, 0x24ff, + 0x2776, 0x2793, + 0x3005, 0x3007, + 0x3021, 0x302f, + 0x3031, 0x3035, + 0x3038, 0x303c, + 0x3041, 0x3096, + 0x3099, 0x309a, + 0x309d, 0x309f, + 0x30a1, 0x30ff, + 0x3105, 0x312c, + 0x3131, 0x318e, + 0x3192, 0x3195, + 0x31a0, 0x31b7, + 0x31f0, 0x31ff, + 0x3220, 0x3229, + 0x3251, 0x325f, + 0x3280, 0x3289, + 0x32b1, 0x32bf, + 0x3400, 0x4db5, + 0x4e00, 0x9fa5, + 0xa000, 0xa48c, + 0xac00, 0xd7a3, + 0xf900, 0xfa2d, + 0xfa30, 0xfa6a, + 0xfb00, 0xfb06, + 0xfb13, 0xfb17, + 0xfb1d, 0xfb28, + 0xfb2a, 0xfb36, + 0xfb38, 0xfb3c, + 0xfb3e, 0xfb3e, + 0xfb40, 0xfb41, + 0xfb43, 0xfb44, + 0xfb46, 0xfbb1, + 0xfbd3, 0xfd3d, + 0xfd50, 0xfd8f, + 0xfd92, 0xfdc7, + 0xfdf0, 0xfdfb, + 0xfe00, 0xfe0f, + 0xfe20, 0xfe23, + 0xfe33, 0xfe34, + 0xfe4d, 0xfe4f, + 0xfe70, 0xfe74, + 0xfe76, 0xfefc, + 0xff10, 0xff19, + 0xff21, 0xff3a, + 0xff3f, 0xff3f, + 0xff41, 0xff5a, + 0xff65, 0xffbe, + 0xffc2, 0xffc7, + 0xffca, 0xffcf, + 0xffd2, 0xffd7, + 0xffda, 0xffdc, + 0x10000, 0x1000b, + 0x1000d, 0x10026, + 0x10028, 0x1003a, + 0x1003c, 0x1003d, + 0x1003f, 0x1004d, + 0x10050, 0x1005d, + 0x10080, 0x100fa, + 0x10107, 0x10133, + 0x10300, 0x1031e, + 0x10320, 0x10323, + 0x10330, 0x1034a, + 0x10380, 0x1039d, + 0x10400, 0x1049d, + 0x104a0, 0x104a9, + 0x10800, 0x10805, + 0x10808, 0x10808, + 0x1080a, 0x10835, + 0x10837, 0x10838, + 0x1083c, 0x1083c, + 0x1083f, 0x1083f, + 0x1d165, 0x1d169, + 0x1d16d, 0x1d172, + 0x1d17b, 0x1d182, + 0x1d185, 0x1d18b, + 0x1d1aa, 0x1d1ad, + 0x1d400, 0x1d454, + 0x1d456, 0x1d49c, + 0x1d49e, 0x1d49f, + 0x1d4a2, 0x1d4a2, + 0x1d4a5, 0x1d4a6, + 0x1d4a9, 0x1d4ac, + 0x1d4ae, 0x1d4b9, + 0x1d4bb, 0x1d4bb, + 0x1d4bd, 0x1d4c3, + 0x1d4c5, 0x1d505, + 0x1d507, 0x1d50a, + 0x1d50d, 0x1d514, + 0x1d516, 0x1d51c, + 0x1d51e, 0x1d539, + 0x1d53b, 0x1d53e, + 0x1d540, 0x1d544, + 0x1d546, 0x1d546, + 0x1d54a, 0x1d550, + 0x1d552, 0x1d6a3, + 0x1d6a8, 0x1d6c0, + 0x1d6c2, 0x1d6da, + 0x1d6dc, 0x1d6fa, + 0x1d6fc, 0x1d714, + 0x1d716, 0x1d734, + 0x1d736, 0x1d74e, + 0x1d750, 0x1d76e, + 0x1d770, 0x1d788, + 0x1d78a, 0x1d7a8, + 0x1d7aa, 0x1d7c2, + 0x1d7c4, 0x1d7c9, + 0x1d7ce, 0x1d7ff, + 0x20000, 0x2a6d6, + 0x2f800, 0x2fa1d, + 0xe0100, 0xe01ef +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ +}; /* end of MBWord */ + + static int -utf8_get_ctype_code_range(int ctype, int* nsb, int* nmb, - OnigCodePointRange* sbr[], OnigCodePointRange* mbr[]) +utf8_get_ctype_code_range(int ctype, + OnigCodePoint* sbr[], OnigCodePoint* mbr[]) { #define CR_SET(sbl,mbl) do { \ - *nsb = sizeof(sbl) / sizeof(OnigCodePointRange); \ - *nmb = sizeof(mbl) / sizeof(OnigCodePointRange); \ *sbr = sbl; \ *mbr = mbl; \ } while (0) #define CR_SB_SET(sbl) do { \ - *nsb = sizeof(sbl) / sizeof(OnigCodePointRange); \ - *nmb = 0; \ *sbr = sbl; \ + *mbr = EmptyRange; \ } while (0) - static OnigCodePointRange SBAlpha[] = { - { 0x41, 0x5a }, - { 0x61, 0x7a } - }; - - static OnigCodePointRange MBAlpha[] = { - { 0xaa, 0xaa }, - { 0xb5, 0xb5 }, - { 0xba, 0xba }, - { 0xc0, 0xd6 }, - { 0xd8, 0xf6 }, - { 0xf8, 0x220 } - }; - - static OnigCodePointRange SBBlank[] = { - { 0x09, 0x09 }, - { 0x20, 0x20 } - }; - - static OnigCodePointRange MBBlank[] = { - { 0xa0, 0xa0 } - }; - - static OnigCodePointRange SBCntrl[] = { - { 0x00, 0x1f }, - { 0x7f, 0x7f } - }; - - static OnigCodePointRange MBCntrl[] = { - { 0x80, 0x9f } - }; - - static OnigCodePointRange SBDigit[] = { - { 0x30, 0x39 } - }; - - static OnigCodePointRange SBGraph[] = { - { 0x21, 0x7e } - }; - - static OnigCodePointRange MBGraph[] = { - { 0xa1, 0x220 } - }; - - static OnigCodePointRange SBLower[] = { - { 0x61, 0x7a } - }; - - static OnigCodePointRange MBLower[] = { - { 0xaa, 0xaa }, - { 0xb5, 0xb5 }, - { 0xba, 0xba }, - { 0xdf, 0xf6 }, - { 0xf8, 0xff } - }; - - static OnigCodePointRange SBPrint[] = { - { 0x20, 0x7e } - }; - - static OnigCodePointRange MBPrint[] = { - { 0xa0, 0x220 } - }; - - static OnigCodePointRange SBPunct[] = { - { 0x21, 0x23 }, - { 0x25, 0x2a }, - { 0x2c, 0x2f }, - { 0x3a, 0x3b }, - { 0x3f, 0x40 }, - { 0x5b, 0x5d }, - { 0x5f, 0x5f }, - { 0x7b, 0x7b }, - { 0x7d, 0x7d } - }; - - static OnigCodePointRange MBPunct[] = { - { 0xa1, 0xa1 }, - { 0xab, 0xab }, - { 0xad, 0xad }, - { 0xb7, 0xb7 }, - { 0xbb, 0xbb }, - { 0xbf, 0xbf } - }; - - static OnigCodePointRange SBSpace[] = { - { 0x09, 0x0d }, - { 0x20, 0x20 } - }; - - static OnigCodePointRange MBSpace[] = { - { 0xa0, 0xa0 } - }; - - static OnigCodePointRange SBUpper[] = { - { 0x41, 0x5a } - }; - - static OnigCodePointRange MBUpper[] = { - { 0xc0, 0xd6 }, - { 0xd8, 0xde } - }; - - static OnigCodePointRange SBXDigit[] = { - { 0x30, 0x39 }, - { 0x41, 0x46 }, - { 0x61, 0x66 } - }; - - static OnigCodePointRange SBWord[] = { - { 0x30, 0x39 }, - { 0x41, 0x5a }, - { 0x5f, 0x5f }, - { 0x61, 0x7a } - }; - - static OnigCodePointRange MBWord[] = { - { 0xaa, 0xaa }, - { 0xb2, 0xb3 }, - { 0xb5, 0xb5 }, - { 0xb9, 0xba }, - { 0xbc, 0xbe }, - { 0xc0, 0xd6 }, - { 0xd8, 0xf6 }, -#if 0 - { 0xf8, 0x220 } -#else - { 0xf8, 0x7fffffff } /* all multibyte code as word */ -#endif - }; - - static OnigCodePointRange SBAscii[] = { - { 0x00, 0x7f } - }; - - static OnigCodePointRange SBAlnum[] = { - { 0x30, 0x39 }, - { 0x41, 0x5a }, - { 0x61, 0x7a } - }; - - static OnigCodePointRange MBAlnum[] = { - { 0xaa, 0xaa }, - { 0xb5, 0xb5 }, - { 0xba, 0xba }, - { 0xc0, 0xd6 }, - { 0xd8, 0xf6 }, - { 0xf8, 0x220 } - }; - switch (ctype) { case ONIGENC_CTYPE_ALPHA: CR_SET(SBAlpha, MBAlpha); @@ -383,7 +3577,7 @@ utf8_get_ctype_code_range(int ctype, int* nsb, int* nmb, CR_SET(SBCntrl, MBCntrl); break; case ONIGENC_CTYPE_DIGIT: - CR_SB_SET(SBDigit); + CR_SET(SBDigit, MBDigit); break; case ONIGENC_CTYPE_GRAPH: CR_SET(SBGraph, MBGraph); @@ -410,14 +3604,14 @@ utf8_get_ctype_code_range(int ctype, int* nsb, int* nmb, CR_SET(SBWord, MBWord); break; case ONIGENC_CTYPE_ASCII: - CR_SB_SET(SBAscii); + CR_SB_SET(SBASCII); break; case ONIGENC_CTYPE_ALNUM: CR_SET(SBAlnum, MBAlnum); break; default: - return ONIGERR_TYPE_BUG; + return ONIGENCERR_TYPE_BUG; break; } @@ -425,142 +3619,120 @@ utf8_get_ctype_code_range(int ctype, int* nsb, int* nmb, } static int -utf8_get_all_fold_match_code(OnigCodePoint** codes) +utf8_is_code_ctype(OnigCodePoint code, unsigned int ctype) { - static OnigCodePoint list[] = { - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, - 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, - }; - - *codes = list; - return sizeof(list) / sizeof(OnigCodePoint); -} +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + OnigCodePoint *range; +#endif -static int -utf8_get_fold_match_info(UChar* p, UChar* end, OnigEncFoldMatchInfo** info) -{ - - static OnigEncFoldMatchInfo xc[] = { - { 2, { 2, 2 }, { "\303\200", "\303\240" } }, /* CodePoint 0xc0 */ - { 2, { 2, 2 }, { "\303\201", "\303\241" } }, - { 2, { 2, 2 }, { "\303\202", "\303\242" } }, - { 2, { 2, 2 }, { "\303\203", "\303\243" } }, - { 2, { 2, 2 }, { "\303\204", "\303\244" } }, - { 2, { 2, 2 }, { "\303\205", "\303\245" } }, - { 2, { 2, 2 }, { "\303\206", "\303\246" } }, - { 2, { 2, 2 }, { "\303\207", "\303\247" } }, - { 2, { 2, 2 }, { "\303\210", "\303\250" } }, - { 2, { 2, 2 }, { "\303\211", "\303\251" } }, - { 2, { 2, 2 }, { "\303\212", "\303\252" } }, - { 2, { 2, 2 }, { "\303\213", "\303\253" } }, - { 2, { 2, 2 }, { "\303\214", "\303\254" } }, - { 2, { 2, 2 }, { "\303\215", "\303\255" } }, - { 2, { 2, 2 }, { "\303\216", "\303\256" } }, - { 2, { 2, 2 }, { "\303\217", "\303\257" } }, - { 2, { 2, 2 }, { "\303\220", "\303\260" } }, /* CodePoint 0xd0 */ - { 2, { 2, 2 }, { "\303\221", "\303\261" } }, - { 2, { 2, 2 }, { "\303\222", "\303\262" } }, - { 2, { 2, 2 }, { "\303\223", "\303\263" } }, - { 2, { 2, 2 }, { "\303\224", "\303\264" } }, - { 2, { 2, 2 }, { "\303\225", "\303\265" } }, - { 2, { 2, 2 }, { "\303\226", "\303\266" } }, - { 0, { 0 }, { "" } }, - { 2, { 2, 2 }, { "\303\230", "\303\270" } }, - { 2, { 2, 2 }, { "\303\231", "\303\271" } }, - { 2, { 2, 2 }, { "\303\232", "\303\272" } }, - { 2, { 2, 2 }, { "\303\233", "\303\273" } }, - { 2, { 2, 2 }, { "\303\234", "\303\274" } }, - { 2, { 2, 2 }, { "\303\235", "\303\275" } }, - { 2, { 2, 2 }, { "\303\236", "\303\276" } }, - { 3, { 2, 2, 2 }, { "\303\237", "ss", "SS" }} /* ess-tsett(U+00DF) */ - }; - - if (p + 1 >= end) return -1; - if (*p < 0x80) { - if ((*p == 'S' && *(p+1) == 'S') || - (*p == 's' && *(p+1) == 's')) { - *info = &(xc[0xdf - 0xc0]); - return 2; - } + if (code < 256) { + return ONIGENC_IS_UNICODE_ISO_8859_1_CTYPE(code, ctype); } - else if (*p == 195) { /* 195 == '\303' */ - int c = *(p+1); - if (c >= 128) { - if (c <= 159) { /* upper */ - if (c == 151) return -1; /* 0xd7 */ - *info = &(xc[c - 128]); - return 2; - } - else { /* lower */ - if (c == 183) return -1; /* 0xf7 */ - *info = &(xc[c - 160]); - return 2; - } - } + +#ifdef USE_UNICODE_FULL_RANGE_CTYPE + + switch (ctype) { + case ONIGENC_CTYPE_ALPHA: + range = MBAlpha; + break; + case ONIGENC_CTYPE_BLANK: + range = MBBlank; + break; + case ONIGENC_CTYPE_CNTRL: + range = MBCntrl; + break; + case ONIGENC_CTYPE_DIGIT: + range = MBDigit; + break; + case ONIGENC_CTYPE_GRAPH: + range = MBGraph; + break; + case ONIGENC_CTYPE_LOWER: + range = MBLower; + break; + case ONIGENC_CTYPE_PRINT: + range = MBPrint; + break; + case ONIGENC_CTYPE_PUNCT: + range = MBPunct; + break; + case ONIGENC_CTYPE_SPACE: + range = MBSpace; + break; + case ONIGENC_CTYPE_UPPER: + range = MBUpper; + break; + case ONIGENC_CTYPE_XDIGIT: + return FALSE; + break; + case ONIGENC_CTYPE_WORD: + range = MBWord; + break; + case ONIGENC_CTYPE_ASCII: + return FALSE; + break; + case ONIGENC_CTYPE_ALNUM: + range = MBAlnum; + break; + + default: + return ONIGENCERR_TYPE_BUG; + break; } - return -1; /* is not a fold string. */ -} + return onig_is_in_code_range((UChar* )range, code); + +#else + + if ((ctype & ONIGENC_CTYPE_WORD) != 0) { +#ifdef USE_INVALID_CODE_SCHEME + if (code <= VALID_CODE_LIMIT) +#endif + return TRUE; + } +#endif /* USE_UNICODE_FULL_RANGE_CTYPE */ + return FALSE; +} static UChar* -utf8_left_adjust_char_head(UChar* start, UChar* s) +utf8_left_adjust_char_head(const UChar* start, const UChar* s) { - UChar *p; + const UChar *p; - if (s <= start) return s; + if (s <= start) return (UChar* )s; p = s; while (!utf8_islead(*p) && p > start) p--; - return p; -} - -static int -utf8_is_allowed_reverse_match(UChar* s, UChar* end) -{ - return TRUE; + return (UChar* )p; } OnigEncodingType OnigEncodingUTF8 = { - { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1 - }, + utf8_mbc_enc_len, "UTF-8", /* name */ 6, /* max byte length */ - TRUE, /* is_fold_match */ - ONIGENC_CTYPE_SUPPORT_LEVEL_FULL, /* ctype_support_level */ - TRUE, /* is continuous sb mb codepoint */ + 1, /* min byte length */ + (ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_COMPOUND), + { + (OnigCodePoint )'\\' /* esc */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ + , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ + }, + onigenc_is_mbc_newline_0x0a, utf8_mbc_to_code, utf8_code_to_mbclen, utf8_code_to_mbc, - utf8_mbc_to_lower, - utf8_mbc_is_case_ambig, - utf8_code_is_ctype, + utf8_mbc_to_normalize, + utf8_is_mbc_ambiguous, + onigenc_iso_8859_1_get_all_pair_ambig_codes, + onigenc_ess_tsett_get_all_comp_ambig_codes, + utf8_is_code_ctype, utf8_get_ctype_code_range, utf8_left_adjust_char_head, - utf8_is_allowed_reverse_match, - utf8_get_all_fold_match_code, - utf8_get_fold_match_info + onigenc_always_true_is_allowed_reverse_match }; diff --git a/ext/mbstring/oniguruma/index.html b/ext/mbstring/oniguruma/index.html new file mode 100755 index 000000000000..293ea442a377 --- /dev/null +++ b/ext/mbstring/oniguruma/index.html @@ -0,0 +1,173 @@ + + + + Oniguruma + + + +

Oniguruma

+

+2005/02/19 (C) K.Kosako +

+

+ + + +

+ +

+Oniguruma is a regular expressions library.
+The characteristics of this library is that different character encoding +
for every regular expression object can be specified. +

+ +
+
Supported character encodings:
+ASCII, UTF-8, UTF-16BE, UTF-16LE, UTF-32BE, UTF-32LE,
+EUC-JP, EUC-TW, EUC-KR, EUC-CN,
+Shift_JIS, Big5, KOI8-R, KOI8,
+ISO-8859-1, ISO-8859-2, ISO-8859-3, ISO-8859-4, ISO-8859-5,
+ISO-8859-6, ISO-8859-7, ISO-8859-8, ISO-8859-9, ISO-8859-10,
+ISO-8859-11, ISO-8859-13, ISO-8859-14, ISO-8859-15, ISO-8859-16 +

+
+

+ +

+ +
What's new + +
    +
  • Character types(\w, \s, \d and POSIX bracket) were supported in full code point range with the Version 4.0.1 of the Unicode Standard. (since Version 3.5.0) +
+
+ +
+ +
+
There are two ways of using of it in this program. +
    +
  • (1) C library (supported APIs: GNU regex, POSIX and Oniguruma native) +
  • (2) Built-in regular expressions engine of Ruby 1.6/1.8/1.9
    + In Ruby 1.9, Oniguruma is already incorporated by Kazuo Saito. +
+
+ +
+
Platform: +
    +
  • Unix (include Mac OS X) +
  • Cygwin +
  • Win32 +
+ +
+
License:
+When this software is partly used or it is distributed with Ruby, +this of Ruby follows the license of Ruby.
+It follows the BSD license in the case of the one except for it. +

+ +
Download: + + +
+ +* 3.X.X supports UTF-16/UTF-32, Ruby 1.9.X.
+* 2.X.X does not support UTF-16/UTF-32, supports Ruby 1.6/1.8. +
+ +
+
+
Documents: (version 3.7.0) + + +
+
Sample Programs: + + +
+
Links: + + +
+
References: + + +
+ +
+

+and I'm thankful to Akinori MUSHA. +

+ + +
+ + diff --git a/ext/mbstring/oniguruma/oniggnu.h b/ext/mbstring/oniguruma/oniggnu.h index d78dc18b11e6..4a695154669a 100644 --- a/ext/mbstring/oniguruma/oniggnu.h +++ b/ext/mbstring/oniguruma/oniggnu.h @@ -1,15 +1,40 @@ +#ifndef ONIGGNU_H +#define ONIGGNU_H /********************************************************************** - oniggnu.h - Oniguruma (regular expression library) - - Copyright (C) 2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ -#ifndef ONIGGNU_H -#define ONIGGNU_H +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ #include "oniguruma.h" +#ifdef __cplusplus +extern "C" { +#endif + #define MBCTYPE_ASCII 0 #define MBCTYPE_EUC 1 #define MBCTYPE_SJIS 2 @@ -19,14 +44,31 @@ #ifndef RE_NREGS #define RE_NREGS ONIG_NREGION #endif -#define RE_OPTION_IGNORECASE ONIG_OPTION_IGNORECASE -#define RE_OPTION_EXTENDED ONIG_OPTION_EXTEND -#define RE_OPTION_MULTILINE ONIG_OPTION_MULTILINE -#define RE_OPTION_SINGLELINE ONIG_OPTION_SINGLELINE -#define RE_OPTION_LONGEST ONIG_OPTION_FIND_LONGEST -#define RE_OPTION_POSIXLINE (RE_OPTION_MULTILINE|RE_OPTION_SINGLELINE) + +#define RE_OPTION_IGNORECASE ONIG_OPTION_IGNORECASE +#define RE_OPTION_EXTENDED ONIG_OPTION_EXTEND +#define RE_OPTION_MULTILINE ONIG_OPTION_MULTILINE +#define RE_OPTION_SINGLELINE ONIG_OPTION_SINGLELINE +#define RE_OPTION_LONGEST ONIG_OPTION_FIND_LONGEST +#define RE_OPTION_POSIXLINE (RE_OPTION_MULTILINE|RE_OPTION_SINGLELINE) +#define RE_OPTION_FIND_NOT_EMPTY ONIG_OPTION_FIND_NOT_EMPTY +#define RE_OPTION_NEGATE_SINGLELINE ONIG_OPTION_NEGATE_SINGLELINE +#define RE_OPTION_DONT_CAPTURE_GROUP ONIG_OPTION_DONT_CAPTURE_GROUP +#define RE_OPTION_CAPTURE_GROUP ONIG_OPTION_CAPTURE_GROUP #ifdef RUBY_PLATFORM + +#ifndef ONIG_RUBY_M17N + +ONIG_EXTERN OnigEncoding OnigEncDefaultCharEncoding; + +#undef ismbchar +#define ismbchar(c) (mbclen((c)) != 1) +#define mbclen(c) \ + ONIGENC_MBC_ENC_LEN(OnigEncDefaultCharEncoding, (UChar* )(&c)) + +#endif /* ifndef ONIG_RUBY_M17N */ + #define re_mbcinit ruby_re_mbcinit #define re_compile_pattern ruby_re_compile_pattern #define re_recompile_pattern ruby_re_recompile_pattern @@ -74,4 +116,8 @@ void re_free_registers P_((struct re_registers*)); ONIG_EXTERN int re_alloc_pattern P_((struct re_pattern_buffer**)); /* added */ +#ifdef __cplusplus +} +#endif + #endif /* ONIGGNU_H */ diff --git a/ext/mbstring/oniguruma/onigposix.h b/ext/mbstring/oniguruma/onigposix.h index 3793ae6bd99a..cfeb88a2928e 100644 --- a/ext/mbstring/oniguruma/onigposix.h +++ b/ext/mbstring/oniguruma/onigposix.h @@ -1,12 +1,38 @@ +#ifndef ONIGPOSIX_H +#define ONIGPOSIX_H /********************************************************************** - onigposix.h - Oniguruma (regular expression library) - - Copyright (C) 2003-2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ -#ifndef ONIGPOSIX_H -#define ONIGPOSIX_H +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include + +#ifdef __cplusplus +extern "C" { +#endif /* options */ #define REG_ICASE (1<<0) @@ -38,12 +64,12 @@ #define REG_EONIG_THREAD 17 /* character encodings (for reg_set_encoding()) */ -#define REG_POSIX_ENCODING_ASCII 0 -#define REG_POSIX_ENCODING_EUC_JP 1 -#define REG_POSIX_ENCODING_SJIS 2 -#define REG_POSIX_ENCODING_UTF8 3 - -#include +#define REG_POSIX_ENCODING_ASCII 0 +#define REG_POSIX_ENCODING_EUC_JP 1 +#define REG_POSIX_ENCODING_SJIS 2 +#define REG_POSIX_ENCODING_UTF8 3 +#define REG_POSIX_ENCODING_UTF16_BE 4 +#define REG_POSIX_ENCODING_UTF16_LE 5 typedef int regoff_t; @@ -70,7 +96,7 @@ typedef struct { #endif #ifndef ONIG_EXTERN -#if defined(_WIN32) && !defined(__CYGWIN__) +#if defined(_WIN32) && !defined(__GNUC__) #if defined(EXPORT) || defined(RUBY_EXPORT) #define ONIG_EXTERN extern __declspec(dllexport) #else @@ -103,7 +129,7 @@ ONIG_EXTERN OnigSyntaxType OnigSyntaxJava; ONIG_EXTERN OnigSyntaxType OnigSyntaxPerl; ONIG_EXTERN OnigSyntaxType OnigSyntaxRuby; -/* predefined syntaxes (see regparse.c) */ +/* predefined syntaxes (see regsyntax.c) */ #define ONIG_SYNTAX_POSIX_BASIC (&OnigSyntaxPosixBasic) #define ONIG_SYNTAX_POSIX_EXTENDED (&OnigSyntaxPosixExtended) #define ONIG_SYNTAX_EMACS (&OnigSyntaxEmacs) @@ -119,6 +145,9 @@ ONIG_EXTERN OnigSyntaxType* OnigDefaultSyntax; ONIG_EXTERN int onig_set_default_syntax P_((OnigSyntaxType* syntax)); ONIG_EXTERN void onig_copy_syntax P_((OnigSyntaxType* to, OnigSyntaxType* from)); +ONIG_EXTERN const char* onig_version P_((void)); +ONIG_EXTERN const char* onig_copyright P_((void)); + #endif /* ONIGURUMA_H */ @@ -129,8 +158,12 @@ ONIG_EXTERN size_t regerror P_((int code, const regex_t* reg, char* buf, size_t /* extended API */ ONIG_EXTERN void reg_set_encoding P_((int enc)); -ONIG_EXTERN int reg_name_to_group_numbers P_((regex_t* reg, unsigned char* name, unsigned char* name_end, int** nums)); -ONIG_EXTERN int reg_foreach_name P_((regex_t* reg, int (*func)(unsigned char*,unsigned char*,int,int*,regex_t*,void*), void* arg)); +ONIG_EXTERN int reg_name_to_group_numbers P_((regex_t* reg, const unsigned char* name, const unsigned char* name_end, int** nums)); +ONIG_EXTERN int reg_foreach_name P_((regex_t* reg, int (*func)(const unsigned char*, const unsigned char*,int,int*,regex_t*,void*), void* arg)); ONIG_EXTERN int reg_number_of_names P_((regex_t* reg)); +#ifdef __cplusplus +} +#endif + #endif /* ONIGPOSIX_H */ diff --git a/ext/mbstring/oniguruma/oniguruma.h b/ext/mbstring/oniguruma/oniguruma.h index b4f5a84e6f26..2106774f7173 100644 --- a/ext/mbstring/oniguruma/oniguruma.h +++ b/ext/mbstring/oniguruma/oniguruma.h @@ -1,19 +1,53 @@ +#ifndef ONIGURUMA_H +#define ONIGURUMA_H /********************************************************************** - oniguruma.h - Oniguruma (regular expression library) - - Copyright (C) 2002-2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ -#ifndef ONIGURUMA_H -#define ONIGURUMA_H - -#include "php_compat.h" +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "php_onig_compat.h" + +#ifdef __cplusplus +extern "C" { +#endif #define ONIGURUMA -#define ONIGURUMA_VERSION_MAJOR 2 -#define ONIGURUMA_VERSION_MINOR 2 -#define ONIGURUMA_VERSION_TEENY 4 +#define ONIGURUMA_VERSION_MAJOR 3 +#define ONIGURUMA_VERSION_MINOR 7 +#define ONIGURUMA_VERSION_TEENY 0 + +#ifdef __cplusplus +# ifndef HAVE_PROTOTYPES +# define HAVE_PROTOTYPES 1 +# endif +# ifndef HAVE_STDARG_PROTOTYPES +# define HAVE_STDARG_PROTOTYPES 1 +# endif +#endif #ifndef P_ #if defined(__STDC__) || defined(_WIN32) @@ -32,7 +66,7 @@ #endif #ifndef ONIG_EXTERN -#if defined(_WIN32) && !defined(__CYGWIN__) +#if defined(_WIN32) && !defined(__GNUC__) #if defined(EXPORT) || defined(RUBY_EXPORT) #define ONIG_EXTERN extern __declspec(dllexport) #else @@ -53,17 +87,60 @@ typedef unsigned int OnigDistance; #define ONIG_INFINITE_DISTANCE ~((OnigDistance )0) +/* ambiguous match flag */ +typedef unsigned int OnigAmbigType; + +ONIG_EXTERN OnigAmbigType OnigDefaultAmbigFlag; + +#define ONIGENC_AMBIGUOUS_MATCH_NONE 0 +#define ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE (1<<0) +#define ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE (1<<1) +/* #define ONIGENC_AMBIGUOUS_MATCH_ACCENT (1<<2) */ +/* #define ONIGENC_AMBIGUOUS_MATCH_HIRAGANA_KATAKANA (1<<3) */ +/* #define ONIGENC_AMBIGUOUS_MATCH_KATAKANA_WIDTH (1<<4) */ + +#define ONIGENC_AMBIGUOUS_MATCH_LIMIT (1<<1) +#define ONIGENC_AMBIGUOUS_MATCH_COMPOUND (1<<30) + +#define ONIGENC_AMBIGUOUS_MATCH_FULL \ + ( ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE | \ + ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE | \ + ONIGENC_AMBIGUOUS_MATCH_COMPOUND ) +#define ONIGENC_AMBIGUOUS_MATCH_DEFAULT OnigDefaultAmbigFlag + + +#define ONIGENC_MAX_COMP_AMBIG_CODE_LEN 3 +#define ONIGENC_MAX_COMP_AMBIG_CODE_ITEM_NUM 4 + +/* code range */ +#define ONIGENC_CODE_RANGE_NUM(range) ((int )range[0]) +#define ONIGENC_CODE_RANGE_FROM(range,i) range[((i)*2) + 1] +#define ONIGENC_CODE_RANGE_TO(range,i) range[((i)*2) + 2] + +typedef struct { + int len; + OnigCodePoint code[ONIGENC_MAX_COMP_AMBIG_CODE_LEN]; +} OnigCompAmbigCodeItem; + +typedef struct { + int n; + OnigCodePoint code; + OnigCompAmbigCodeItem items[ONIGENC_MAX_COMP_AMBIG_CODE_ITEM_NUM]; +} OnigCompAmbigCodes; + typedef struct { OnigCodePoint from; OnigCodePoint to; -} OnigCodePointRange; +} OnigPairAmbigCodes; -#define ONIGENC_FOLD_MATCH_MAX_TARGET_NUM_SIZE 16 typedef struct { - int target_num; - int target_byte_len[ONIGENC_FOLD_MATCH_MAX_TARGET_NUM_SIZE]; - UChar* target_str[ONIGENC_FOLD_MATCH_MAX_TARGET_NUM_SIZE]; -} OnigEncFoldMatchInfo; + OnigCodePoint esc; + OnigCodePoint anychar; + OnigCodePoint anytime; + OnigCodePoint zero_or_one_time; + OnigCodePoint one_or_more_time; + OnigCodePoint anychar_anytime; +} OnigMetaCharTableType; #if defined(RUBY_PLATFORM) && defined(M17N_H) @@ -74,23 +151,24 @@ typedef m17n_encoding* OnigEncoding; #else typedef struct { - const char len_table[256]; - const char* name; - int max_enc_len; - int is_fold_match; - int ctype_support_level; /* sb-only/full */ - int is_continuous_sb_mb; /* code point is continuous from sb to mb */ - OnigCodePoint (*mbc_to_code)(UChar* p, UChar* end); + int (*mbc_enc_len)(const UChar* p); + const char* name; + int max_enc_len; + int min_enc_len; + OnigAmbigType support_ambig_flag; + OnigMetaCharTableType meta_char_table; + int (*is_mbc_newline)(const UChar* p, const UChar* end); + OnigCodePoint (*mbc_to_code)(const UChar* p, const UChar* end); int (*code_to_mbclen)(OnigCodePoint code); int (*code_to_mbc)(OnigCodePoint code, UChar *buf); - int (*mbc_to_lower)(UChar* p, UChar* lower); - int (*mbc_is_case_ambig)(UChar* p); - int (*code_is_ctype)(OnigCodePoint code, unsigned int ctype); - int (*get_ctype_code_range)(int ctype, int* nsb, int* nmb, OnigCodePointRange* sbr[], OnigCodePointRange* mbr[]); - UChar* (*left_adjust_char_head)(UChar* start, UChar* s); - int (*is_allowed_reverse_match)(UChar* p, UChar* e); - int (*get_all_fold_match_code)(OnigCodePoint** codes); - int (*get_fold_match_info)(UChar* p, UChar* end, OnigEncFoldMatchInfo** info); + int (*mbc_to_normalize)(OnigAmbigType flag, const UChar** pp, const UChar* end, UChar* to); + int (*is_mbc_ambiguous)(OnigAmbigType flag, const UChar** pp, const UChar* end); + int (*get_all_pair_ambig_codes)(OnigAmbigType flag, OnigPairAmbigCodes** acs); + int (*get_all_comp_ambig_codes)(OnigAmbigType flag, OnigCompAmbigCodes** acs); + int (*is_code_ctype)(OnigCodePoint code, unsigned int ctype); + int (*get_ctype_code_range)(int ctype, OnigCodePoint* sb_range[], OnigCodePoint* mb_range[]); + UChar* (*left_adjust_char_head)(const UChar* start, const UChar* p); + int (*is_allowed_reverse_match)(const UChar* p, const UChar* end); } OnigEncodingType; typedef OnigEncodingType* OnigEncoding; @@ -112,6 +190,10 @@ ONIG_EXTERN OnigEncodingType OnigEncodingISO_8859_14; ONIG_EXTERN OnigEncodingType OnigEncodingISO_8859_15; ONIG_EXTERN OnigEncodingType OnigEncodingISO_8859_16; ONIG_EXTERN OnigEncodingType OnigEncodingUTF8; +ONIG_EXTERN OnigEncodingType OnigEncodingUTF16_BE; +ONIG_EXTERN OnigEncodingType OnigEncodingUTF16_LE; +ONIG_EXTERN OnigEncodingType OnigEncodingUTF32_BE; +ONIG_EXTERN OnigEncodingType OnigEncodingUTF32_LE; ONIG_EXTERN OnigEncodingType OnigEncodingEUC_JP; ONIG_EXTERN OnigEncodingType OnigEncodingEUC_TW; ONIG_EXTERN OnigEncodingType OnigEncodingEUC_KR; @@ -138,6 +220,10 @@ ONIG_EXTERN OnigEncodingType OnigEncodingBIG5; #define ONIG_ENCODING_ISO_8859_15 (&OnigEncodingISO_8859_15) #define ONIG_ENCODING_ISO_8859_16 (&OnigEncodingISO_8859_16) #define ONIG_ENCODING_UTF8 (&OnigEncodingUTF8) +#define ONIG_ENCODING_UTF16_BE (&OnigEncodingUTF16_BE) +#define ONIG_ENCODING_UTF16_LE (&OnigEncodingUTF16_LE) +#define ONIG_ENCODING_UTF32_BE (&OnigEncodingUTF32_BE) +#define ONIG_ENCODING_UTF32_LE (&OnigEncodingUTF32_LE) #define ONIG_ENCODING_EUC_JP (&OnigEncodingEUC_JP) #define ONIG_ENCODING_EUC_TW (&OnigEncodingEUC_TW) #define ONIG_ENCODING_EUC_KR (&OnigEncodingEUC_KR) @@ -153,35 +239,31 @@ ONIG_EXTERN OnigEncodingType OnigEncodingBIG5; /* work size */ -#define ONIGENC_CODE_TO_MBC_MAXLEN 7 -#define ONIGENC_MBC_TO_LOWER_MAXLEN ONIGENC_CODE_TO_MBC_MAXLEN +#define ONIGENC_CODE_TO_MBC_MAXLEN 7 +#define ONIGENC_MBC_NORMALIZE_MAXLEN ONIGENC_CODE_TO_MBC_MAXLEN /* character types */ -#define ONIGENC_CTYPE_ALPHA (1<< 0) -#define ONIGENC_CTYPE_BLANK (1<< 1) -#define ONIGENC_CTYPE_CNTRL (1<< 2) -#define ONIGENC_CTYPE_DIGIT (1<< 3) -#define ONIGENC_CTYPE_GRAPH (1<< 4) -#define ONIGENC_CTYPE_LOWER (1<< 5) -#define ONIGENC_CTYPE_PRINT (1<< 6) -#define ONIGENC_CTYPE_PUNCT (1<< 7) -#define ONIGENC_CTYPE_SPACE (1<< 8) -#define ONIGENC_CTYPE_UPPER (1<< 9) -#define ONIGENC_CTYPE_XDIGIT (1<<10) -#define ONIGENC_CTYPE_WORD (1<<11) -#define ONIGENC_CTYPE_ASCII (1<<12) +#define ONIGENC_CTYPE_NEWLINE (1<< 0) +#define ONIGENC_CTYPE_ALPHA (1<< 1) +#define ONIGENC_CTYPE_BLANK (1<< 2) +#define ONIGENC_CTYPE_CNTRL (1<< 3) +#define ONIGENC_CTYPE_DIGIT (1<< 4) +#define ONIGENC_CTYPE_GRAPH (1<< 5) +#define ONIGENC_CTYPE_LOWER (1<< 6) +#define ONIGENC_CTYPE_PRINT (1<< 7) +#define ONIGENC_CTYPE_PUNCT (1<< 8) +#define ONIGENC_CTYPE_SPACE (1<< 9) +#define ONIGENC_CTYPE_UPPER (1<<10) +#define ONIGENC_CTYPE_XDIGIT (1<<11) +#define ONIGENC_CTYPE_WORD (1<<12) +#define ONIGENC_CTYPE_ASCII (1<<13) #define ONIGENC_CTYPE_ALNUM (ONIGENC_CTYPE_ALPHA | ONIGENC_CTYPE_DIGIT) -/* ctype support level */ -#define ONIGENC_CTYPE_SUPPORT_LEVEL_SB 0 -#define ONIGENC_CTYPE_SUPPORT_LEVEL_FULL 1 - - -#define enc_len(enc,byte) ONIGENC_MBC_LEN_BY_HEAD(enc,byte) +#define enc_len(enc,p) ONIGENC_MBC_ENC_LEN(enc, p) #define ONIGENC_IS_UNDEF(enc) ((enc) == ONIG_ENCODING_UNDEF) #define ONIGENC_IS_SINGLEBYTE(enc) (ONIGENC_MBC_MAXLEN(enc) == 1) -#define ONIGENC_IS_MBC_HEAD(enc,byte) (ONIGENC_MBC_LEN_BY_HEAD(enc,byte) != 1) +#define ONIGENC_IS_MBC_HEAD(enc,p) (ONIGENC_MBC_ENC_LEN(enc,p) != 1) #define ONIGENC_IS_MBC_ASCII(p) (*(p) < 128) #define ONIGENC_IS_CODE_ASCII(code) ((code) < 128) #define ONIGENC_IS_CODE_SB_WORD(enc,code) \ @@ -194,31 +276,33 @@ ONIG_EXTERN OnigEncodingType OnigEncodingBIG5; #include /* for isblank(), isgraph() */ -#define ONIGENC_MBC_TO_LOWER(enc,p,buf) onigenc_mbc_to_lower(enc,p,buf) -#define ONIGENC_IS_MBC_CASE_AMBIG(enc,p) onigenc_mbc_is_case_ambig(enc,p) +#define ONIGENC_MBC_TO_NORMALIZE(enc,flag,pp,end,buf) \ + onigenc_mbc_to_normalize(enc,flag,pp,end,buf) +#define ONIGENC_IS_MBC_AMBIGUOUS(enc,flag,pp,end) \ + onigenc_is_mbc_ambiguous(enc,flag,pp,end) -#define ONIGENC_IS_FOLD_MATCH(enc) FALSE -#define ONIGENC_IS_CONTINUOUS_SB_MB(enc) FALSE -#define ONIGENC_CTYPE_SUPPORT_LEVEL(enc) ONIGENC_CTYPE_SUPPORT_LEVEL_SB +#define ONIGENC_SUPPORT_AMBIG_FLAG(enc) ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE #define ONIGENC_IS_ALLOWED_REVERSE_MATCH(enc,s,end) \ onigenc_is_allowed_reverse_match(enc, s, end) #define ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc,start,s) \ onigenc_get_left_adjust_char_head(enc, start, s) -#define ONIGENC_GET_ALL_FOLD_MATCH_CODE(enc,codes) 0 -#define ONIGENC_GET_FOLD_MATCH_INFO(enc,p,end,info) ONIG_NO_SUPPORT_CONFIG -#define ONIGENC_GET_CTYPE_CODE_RANGE(enc,ctype,nsb,nmb,sbr,mbr) \ +#define ONIGENC_GET_ALL_PAIR_AMBIG_CODES(enc, ambig_flag, acs) 0 +#define ONIGENC_GET_ALL_COMP_AMBIG_CODES(enc, ambig_flag, acs) 0 +#define ONIGENC_GET_CTYPE_CODE_RANGE(enc,ctype,sbr,mbr) \ ONIG_NO_SUPPORT_CONFIG -#define ONIGENC_MBC_LEN_BY_HEAD(enc,b) m17n_mbclen(enc,(int )b) +#define ONIGENC_MBC_ENC_LEN(enc,p) m17n_mbclen(enc,(int )(*p)) #define ONIGENC_MBC_MAXLEN(enc) m17n_mbmaxlen(enc) #define ONIGENC_MBC_MAXLEN_DIST(enc) \ (ONIGENC_MBC_MAXLEN(enc) > 0 ? ONIGENC_MBC_MAXLEN(enc) \ : ONIG_INFINITE_DISTANCE) +#define ONIGENC_MBC_MINLEN(enc) 1 #define ONIGENC_MBC_TO_CODE(enc,p,e) m17n_codepoint((enc),(p),(e)) #define ONIGENC_CODE_TO_MBCLEN(enc,code) m17n_codelen((enc),(code)) #define ONIGENC_CODE_TO_MBC(enc,code,buf) onigenc_code_to_mbc(enc, code, buf) -#if 0 -#define ONIGENC_STEP_BACK(enc,start,s,n) /* !! not supported !! */ +#if 0 /* !! not supported !! */ +#define ONIGENC_IS_MBC_NEWLINE(enc,p,end) +#define ONIGENC_STEP_BACK(enc,start,s,n) #endif #define ONIGENC_IS_CODE_CTYPE(enc,code,ctype) \ @@ -253,42 +337,45 @@ int onigenc_is_code_ctype P_((OnigEncoding enc, OnigCodePoint code, int ctype)); ONIG_EXTERN int onigenc_code_to_mbc P_((OnigEncoding enc, OnigCodePoint code, UChar *buf)); ONIG_EXTERN -int onigenc_mbc_to_lower P_((OnigEncoding enc, UChar* p, UChar* buf)); +int onigenc_mbc_to_normalize P_((OnigEncoding enc, OnigAmbigType flag, const UChar** pp, const UChar* end, UChar* buf)); ONIG_EXTERN -int onigenc_mbc_is_case_ambig P_((OnigEncoding enc, UChar* p)); +int onigenc_is_mbc_ambiguous P_((OnigEncoding enc, OnigAmbigType flag, const UChar** pp, const UChar* end)); ONIG_EXTERN -int onigenc_is_allowed_reverse_match P_((OnigEncoding enc, UChar* s, UChar* end)); +int onigenc_is_allowed_reverse_match P_((OnigEncoding enc, const UChar* s, const UChar* end)); #else /* ONIG_RUBY_M17N */ #define ONIGENC_NAME(enc) ((enc)->name) -#define ONIGENC_MBC_TO_LOWER(enc,p,buf) (enc)->mbc_to_lower(p,buf) -#define ONIGENC_IS_MBC_CASE_AMBIG(enc,p) (enc)->mbc_is_case_ambig(p) - -#define ONIGENC_IS_FOLD_MATCH(enc) ((enc)->is_fold_match) -#define ONIGENC_IS_CONTINUOUS_SB_MB(enc) ((enc)->is_continuous_sb_mb) -#define ONIGENC_CTYPE_SUPPORT_LEVEL(enc) ((enc)->ctype_support_level) +#define ONIGENC_MBC_TO_NORMALIZE(enc,flag,pp,end,buf) \ + (enc)->mbc_to_normalize(flag,(const UChar** )pp,end,buf) +#define ONIGENC_IS_MBC_AMBIGUOUS(enc,flag,pp,end) \ + (enc)->is_mbc_ambiguous(flag,(const UChar** )pp,end) +#define ONIGENC_SUPPORT_AMBIG_FLAG(enc) ((enc)->support_ambig_flag) #define ONIGENC_IS_ALLOWED_REVERSE_MATCH(enc,s,end) \ (enc)->is_allowed_reverse_match(s,end) #define ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc,start,s) \ (enc)->left_adjust_char_head(start, s) -#define ONIGENC_GET_ALL_FOLD_MATCH_CODE(enc,codes) \ - (enc)->get_all_fold_match_code(codes) -#define ONIGENC_GET_FOLD_MATCH_INFO(enc,p,end,info) \ - (enc)->get_fold_match_info(p,end,info) +#define ONIGENC_GET_ALL_PAIR_AMBIG_CODES(enc,ambig_flag,acs) \ + (enc)->get_all_pair_ambig_codes(ambig_flag,acs) +#define ONIGENC_GET_ALL_COMP_AMBIG_CODES(enc,ambig_flag,acs) \ + (enc)->get_all_comp_ambig_codes(ambig_flag,acs) #define ONIGENC_STEP_BACK(enc,start,s,n) \ onigenc_step_back((enc),(start),(s),(n)) -#define ONIGENC_MBC_LEN_BY_HEAD(enc,byte) ((enc)->len_table[(int )(byte)]) +#define ONIGENC_MBC_ENC_LEN(enc,p) (enc)->mbc_enc_len(p) #define ONIGENC_MBC_MAXLEN(enc) ((enc)->max_enc_len) #define ONIGENC_MBC_MAXLEN_DIST(enc) ONIGENC_MBC_MAXLEN(enc) -#define ONIGENC_MBC_TO_CODE(enc,p,e) (enc)->mbc_to_code((p),(e)) +#define ONIGENC_MBC_MINLEN(enc) ((enc)->min_enc_len) +#define ONIGENC_IS_MBC_NEWLINE(enc,p,end) (enc)->is_mbc_newline((p),(end)) +#define ONIGENC_MBC_TO_CODE(enc,p,end) (enc)->mbc_to_code((p),(end)) #define ONIGENC_CODE_TO_MBCLEN(enc,code) (enc)->code_to_mbclen(code) #define ONIGENC_CODE_TO_MBC(enc,code,buf) (enc)->code_to_mbc(code,buf) -#define ONIGENC_IS_CODE_CTYPE(enc,code,ctype) (enc)->code_is_ctype(code,ctype) +#define ONIGENC_IS_CODE_CTYPE(enc,code,ctype) (enc)->is_code_ctype(code,ctype) +#define ONIGENC_IS_CODE_NEWLINE(enc,code) \ + ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_NEWLINE) #define ONIGENC_IS_CODE_GRAPH(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_GRAPH) #define ONIGENC_IS_CODE_PRINT(enc,code) \ @@ -316,11 +403,11 @@ int onigenc_is_allowed_reverse_match P_((OnigEncoding enc, UChar* s, UChar* end) #define ONIGENC_IS_CODE_WORD(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_WORD) -#define ONIGENC_GET_CTYPE_CODE_RANGE(enc,ctype,nsb,nmb,sbr,mbr) \ - (enc)->get_ctype_code_range(ctype,nsb,nmb,sbr,mbr) +#define ONIGENC_GET_CTYPE_CODE_RANGE(enc,ctype,sbr,mbr) \ + (enc)->get_ctype_code_range(ctype,sbr,mbr) ONIG_EXTERN -UChar* onigenc_step_back P_((OnigEncoding enc, UChar* start, UChar* s, int n)); +UChar* onigenc_step_back P_((OnigEncoding enc, const UChar* start, const UChar* s, int n)); #endif /* is not ONIG_RUBY_M17N */ @@ -333,15 +420,21 @@ int onigenc_set_default_encoding P_((OnigEncoding enc)); ONIG_EXTERN OnigEncoding onigenc_get_default_encoding P_(()); ONIG_EXTERN -void onigenc_set_default_caseconv_table P_((UChar* table)); +void onigenc_set_default_caseconv_table P_((const UChar* table)); +ONIG_EXTERN +UChar* onigenc_get_right_adjust_char_head_with_prev P_((OnigEncoding enc, const UChar* start, const UChar* s, const UChar** prev)); ONIG_EXTERN -UChar* onigenc_get_right_adjust_char_head_with_prev P_((OnigEncoding enc, UChar* start, UChar* s, UChar** prev)); +UChar* onigenc_get_prev_char_head P_((OnigEncoding enc, const UChar* start, const UChar* s)); ONIG_EXTERN -UChar* onigenc_get_prev_char_head P_((OnigEncoding enc, UChar* start, UChar* s)); +UChar* onigenc_get_left_adjust_char_head P_((OnigEncoding enc, const UChar* start, const UChar* s)); ONIG_EXTERN -UChar* onigenc_get_left_adjust_char_head P_((OnigEncoding enc, UChar* start, UChar* s)); +UChar* onigenc_get_right_adjust_char_head P_((OnigEncoding enc, const UChar* start, const UChar* s)); ONIG_EXTERN -UChar* onigenc_get_right_adjust_char_head P_((OnigEncoding enc, UChar* start, UChar* s)); +int onigenc_strlen P_((OnigEncoding enc, const UChar* p, const UChar* end)); +ONIG_EXTERN +int onigenc_strlen_null P_((OnigEncoding enc, const UChar* p)); +ONIG_EXTERN +int onigenc_str_bytelen_null P_((OnigEncoding enc, const UChar* p)); @@ -355,13 +448,6 @@ UChar* onigenc_get_right_adjust_char_head P_((OnigEncoding enc, UChar* start, UC /* constants */ #define ONIG_MAX_ERROR_MESSAGE_LEN 90 -#if defined(RUBY_PLATFORM) && !defined(ONIG_RUBY_M17N) -ONIG_EXTERN OnigEncoding OnigEncDefaultCharEncoding; -#undef ismbchar -#define ismbchar(c) (mbclen((c)) != 1) -#define mbclen(c) (OnigEncDefaultCharEncoding->len_table[(unsigned char )(c)]) -#endif - typedef unsigned int OnigOptionType; #define ONIG_OPTION_DEFAULT ONIG_OPTION_NONE @@ -403,7 +489,7 @@ ONIG_EXTERN OnigSyntaxType OnigSyntaxJava; ONIG_EXTERN OnigSyntaxType OnigSyntaxPerl; ONIG_EXTERN OnigSyntaxType OnigSyntaxRuby; -/* predefined syntaxes (see regparse.c) */ +/* predefined syntaxes (see regsyntax.c) */ #define ONIG_SYNTAX_POSIX_BASIC (&OnigSyntaxPosixBasic) #define ONIG_SYNTAX_POSIX_EXTENDED (&OnigSyntaxPosixExtended) #define ONIG_SYNTAX_EMACS (&OnigSyntaxEmacs) @@ -466,7 +552,10 @@ ONIG_EXTERN OnigSyntaxType* OnigDefaultSyntax; #define ONIG_SYN_OP2_ESC_V_VTAB (1<<13) /* \v as VTAB */ #define ONIG_SYN_OP2_ESC_U_HEX4 (1<<14) /* \uHHHH */ #define ONIG_SYN_OP2_ESC_GNU_BUF_ANCHOR (1<<15) /* \`, \' */ -#define ONIG_SYN_OP2_ESC_P_CHAR_PROPERTY (1<<16) /* \p{...}, \P{...} */ +#define ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY (1<<16) /* \p{...}, \P{...} */ +#define ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT (1<<17) /* \p{^..}, \P{^..} */ +#define ONIG_SYN_OP2_CHAR_PROPERTY_PREFIX_IS (1<<18) /* \p{IsXDigit} */ +#define ONIG_SYN_OP2_ESC_H_XDIGIT (1<<19) /* \h, \H */ /* syntax (behavior) */ #define ONIG_SYN_CONTEXT_INDEP_ANCHORS (1<<31) /* not implemented */ @@ -479,6 +568,7 @@ ONIG_EXTERN OnigSyntaxType* OnigDefaultSyntax; #define ONIG_SYN_DIFFERENT_LEN_ALT_LOOK_BEHIND (1<<6) /* (?<=a|bc) */ #define ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP (1<<7) /* see doc/RE */ #define ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME (1<<8) /* (?)(?) */ +#define ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY (1<<9) /* a{n}?=(?:a{n})? */ /* syntax (behavior) in char class [...] */ #define ONIG_SYN_NOT_NEWLINE_IN_NEGATIVE_CC (1<<20) /* [^...] */ @@ -505,7 +595,10 @@ ONIG_EXTERN OnigSyntaxType* OnigDefaultSyntax; #define ONIG_NORMAL 0 #define ONIG_MISMATCH -1 #define ONIG_NO_SUPPORT_CONFIG -2 + /* internal error */ +#define ONIGERR_MEMORY -5 +#define ONIGERR_TYPE_BUG -6 #define ONIGERR_PARSER_BUG -11 #define ONIGERR_STACK_BUG -12 #define ONIGERR_UNDEFINED_BYTECODE -13 @@ -520,7 +613,7 @@ ONIG_EXTERN OnigSyntaxType* OnigDefaultSyntax; #define ONIGERR_END_PATTERN_AT_LEFT_BRACKET -101 #define ONIGERR_EMPTY_CHAR_CLASS -102 #define ONIGERR_PREMATURE_END_OF_CHAR_CLASS -103 -#define ONIGERR_END_PATTERN_AT_BACKSLASH -104 +#define ONIGERR_END_PATTERN_AT_ESCAPE -104 #define ONIGERR_END_PATTERN_AT_META -105 #define ONIGERR_END_PATTERN_AT_CONTROL -106 #define ONIGERR_META_CODE_SYNTAX -108 @@ -560,8 +653,12 @@ ONIG_EXTERN OnigSyntaxType* OnigDefaultSyntax; #define ONIGERR_NEVER_ENDING_RECURSION -221 #define ONIGERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY -222 #define ONIGERR_INVALID_CHAR_PROPERTY_NAME -223 +#define ONIGERR_INVALID_WIDE_CHAR_VALUE -400 +#define ONIGERR_TOO_BIG_WIDE_CHAR_VALUE -401 +#define ONIGERR_NOT_SUPPORTED_ENCODING_COMBINATION -402 + /* errors related to thread */ -#define ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT -1001 +#define ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT -1001 /* must be smaller than BIT_STATUS_BITS_NUM (unsigned int * 8) */ @@ -569,6 +666,15 @@ ONIG_EXTERN OnigSyntaxType* OnigDefaultSyntax; #define ONIG_IS_CAPTURE_HISTORY_GROUP(r, i) \ ((i) <= ONIG_MAX_CAPTURE_HISTORY_GROUP && (r)->list && (r)->list[i]) +typedef struct OnigCaptureTreeNodeStruct { + int group; /* group number */ + int beg; + int end; + int allocated; + int num_childs; + struct OnigCaptureTreeNodeStruct** childs; +} OnigCaptureTreeNode; + /* match result region type */ struct re_registers { int allocated; @@ -576,9 +682,16 @@ struct re_registers { int* beg; int* end; /* extended */ - struct re_registers** list; /* capture history. list[1]-list[31] */ + OnigCaptureTreeNode* history_root; /* capture history tree root */ }; +/* capture tree traverse */ +#define ONIG_TRAVERSE_CALLBACK_AT_FIRST 1 +#define ONIG_TRAVERSE_CALLBACK_AT_LAST 2 +#define ONIG_TRAVERSE_CALLBACK_AT_BOTH \ + ( ONIG_TRAVERSE_CALLBACK_AT_FIRST | ONIG_TRAVERSE_CALLBACK_AT_LAST ) + + #define ONIG_REGION_NOTPOS -1 typedef struct re_registers OnigRegion; @@ -593,8 +706,8 @@ typedef struct { int upper; } OnigRepeatRange; -typedef void (*OnigWarnFunc) P_((char* s)); -extern void onig_null_warn P_((char* s)); +typedef void (*OnigWarnFunc) P_((const char* s)); +extern void onig_null_warn P_((const char* s)); #define ONIG_NULL_WARN onig_null_warn #define ONIG_CHAR_TABLE_SIZE 256 @@ -629,6 +742,7 @@ typedef struct re_pattern_buffer { OnigEncoding enc; OnigOptionType options; OnigSyntaxType* syntax; + OnigAmbigType ambig_flag; void* name_table; /* optimization info (string search, char-map and anchors) */ @@ -640,7 +754,7 @@ typedef struct re_pattern_buffer { int sub_anchor; /* start-anchor for exact or map */ unsigned char *exact; unsigned char *exact_end; - unsigned char map[ONIG_CHAR_TABLE_SIZE]; /* used as BM skip or char-map */ + unsigned char map[ONIG_CHAR_TABLE_SIZE]; /* used as BM skip or char-map */ int *int_map; /* BM skip for exact_len > 255 */ int *int_map_backward; /* BM skip for backward search */ OnigDistance dmin; /* min-distance of exact or map */ @@ -651,6 +765,15 @@ typedef struct re_pattern_buffer { } regex_t; +typedef struct { + int num_of_elements; + OnigEncoding pattern_enc; + OnigEncoding target_enc; + OnigSyntaxType* syntax; + OnigOptionType option; + OnigAmbigType ambig_flag; +} OnigCompileInfo; + /* Oniguruma Native API */ ONIG_EXTERN int onig_init P_((void)); @@ -661,18 +784,24 @@ void onig_set_warn_func P_((OnigWarnFunc f)); ONIG_EXTERN void onig_set_verb_warn_func P_((OnigWarnFunc f)); ONIG_EXTERN -int onig_new P_((regex_t**, UChar* pattern, UChar* pattern_end, OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax, OnigErrorInfo* einfo)); +int onig_new P_((regex_t**, const UChar* pattern, const UChar* pattern_end, OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax, OnigErrorInfo* einfo)); +ONIG_EXTERN +int onig_new_deluxe P_((regex_t** reg, const UChar* pattern, const UChar* pattern_end, OnigCompileInfo* ci, OnigErrorInfo* einfo)); ONIG_EXTERN void onig_free P_((regex_t*)); ONIG_EXTERN -int onig_recompile P_((regex_t*, UChar* pattern, UChar* pattern_end, OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax, OnigErrorInfo* einfo)); +int onig_recompile P_((regex_t*, const UChar* pattern, const UChar* pattern_end, OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax, OnigErrorInfo* einfo)); +ONIG_EXTERN +int onig_recompile_deluxe P_((regex_t* reg, const UChar* pattern, const UChar* pattern_end, OnigCompileInfo* ci, OnigErrorInfo* einfo)); ONIG_EXTERN -int onig_search P_((regex_t*, UChar* str, UChar* end, UChar* start, UChar* range, OnigRegion* region, OnigOptionType option)); +int onig_search P_((regex_t*, const UChar* str, const UChar* end, const UChar* start, const UChar* range, OnigRegion* region, OnigOptionType option)); ONIG_EXTERN -int onig_match P_((regex_t*, UChar* str, UChar* end, UChar* at, OnigRegion* region, OnigOptionType option)); +int onig_match P_((regex_t*, const UChar* str, const UChar* end, const UChar* at, OnigRegion* region, OnigOptionType option)); ONIG_EXTERN OnigRegion* onig_region_new P_((void)); ONIG_EXTERN +void onig_region_init P_((OnigRegion* region)); +ONIG_EXTERN void onig_region_free P_((OnigRegion* region, int free_self)); ONIG_EXTERN void onig_region_copy P_((OnigRegion* to, OnigRegion* from)); @@ -681,25 +810,44 @@ void onig_region_clear P_((OnigRegion* region)); ONIG_EXTERN int onig_region_resize P_((OnigRegion* region, int n)); ONIG_EXTERN -int onig_name_to_group_numbers P_((regex_t* reg, UChar* name, UChar* name_end, - int** nums)); +int onig_region_set P_((OnigRegion* region, int at, int beg, int end)); +ONIG_EXTERN +int onig_name_to_group_numbers P_((regex_t* reg, const UChar* name, const UChar* name_end, int** nums)); ONIG_EXTERN -int onig_name_to_backref_number P_((regex_t* reg, UChar* name, UChar* name_end, OnigRegion *region)); +int onig_name_to_backref_number P_((regex_t* reg, const UChar* name, const UChar* name_end, OnigRegion *region)); ONIG_EXTERN -int onig_foreach_name P_((regex_t* reg, int (*func)(UChar*,UChar*,int,int*,regex_t*,void*), void* arg)); +int onig_foreach_name P_((regex_t* reg, int (*func)(const UChar*, const UChar*,int,int*,regex_t*,void*), void* arg)); ONIG_EXTERN int onig_number_of_names P_((regex_t* reg)); ONIG_EXTERN +int onig_number_of_captures P_((regex_t* reg)); +ONIG_EXTERN +int onig_number_of_capture_histories P_((regex_t* reg)); +ONIG_EXTERN +OnigCaptureTreeNode* onig_get_capture_tree P_((OnigRegion* region)); +ONIG_EXTERN +int onig_capture_tree_traverse P_((OnigRegion* region, int at, int(*callback_func)(int,int,int,int,int,void*), void* arg)); +ONIG_EXTERN OnigEncoding onig_get_encoding P_((regex_t* reg)); ONIG_EXTERN OnigOptionType onig_get_options P_((regex_t* reg)); ONIG_EXTERN +OnigAmbigType onig_get_ambig_flag P_((regex_t* reg)); +ONIG_EXTERN OnigSyntaxType* onig_get_syntax P_((regex_t* reg)); ONIG_EXTERN int onig_set_default_syntax P_((OnigSyntaxType* syntax)); ONIG_EXTERN void onig_copy_syntax P_((OnigSyntaxType* to, OnigSyntaxType* from)); ONIG_EXTERN +unsigned int onig_get_syntax_op P_((OnigSyntaxType* syntax)); +ONIG_EXTERN +unsigned int onig_get_syntax_op2 P_((OnigSyntaxType* syntax)); +ONIG_EXTERN +unsigned int onig_get_syntax_behavior P_((OnigSyntaxType* syntax)); +ONIG_EXTERN +OnigOptionType onig_get_syntax_options P_((OnigSyntaxType* syntax)); +ONIG_EXTERN void onig_set_syntax_op P_((OnigSyntaxType* syntax, unsigned int op)); ONIG_EXTERN void onig_set_syntax_op2 P_((OnigSyntaxType* syntax, unsigned int op2)); @@ -708,10 +856,26 @@ void onig_set_syntax_behavior P_((OnigSyntaxType* syntax, unsigned int behavior) ONIG_EXTERN void onig_set_syntax_options P_((OnigSyntaxType* syntax, OnigOptionType options)); ONIG_EXTERN -int onig_set_meta_char P_((unsigned int what, unsigned int c)); +int onig_set_meta_char P_((OnigEncoding enc, unsigned int what, OnigCodePoint code)); +ONIG_EXTERN +void onig_copy_encoding P_((OnigEncoding to, OnigEncoding from)); +ONIG_EXTERN +OnigAmbigType onig_get_default_ambig_flag P_(()); +ONIG_EXTERN +int onig_set_default_ambig_flag P_((OnigAmbigType ambig_flag)); +ONIG_EXTERN +unsigned int onig_get_match_stack_limit_size P_((void)); +ONIG_EXTERN +int onig_set_match_stack_limit_size P_((unsigned int size)); ONIG_EXTERN int onig_end P_((void)); ONIG_EXTERN const char* onig_version P_((void)); +ONIG_EXTERN +const char* onig_copyright P_((void)); + +#ifdef __cplusplus +} +#endif #endif /* ONIGURUMA_H */ diff --git a/ext/mbstring/oniguruma/php_compat.h b/ext/mbstring/oniguruma/php_onig_compat.h similarity index 78% rename from ext/mbstring/oniguruma/php_compat.h rename to ext/mbstring/oniguruma/php_onig_compat.h index d7f1ad56f1ec..1de0d6073dc8 100644 --- a/ext/mbstring/oniguruma/php_compat.h +++ b/ext/mbstring/oniguruma/php_onig_compat.h @@ -3,5 +3,6 @@ #define re_pattern_buffer php_mb_re_pattern_buffer #define regex_t php_mb_regex_t +#define re_registers php_mb_re_registers #endif /* _PHP_MBREGEX_COMPAT_H */ diff --git a/ext/mbstring/oniguruma/regcomp.c b/ext/mbstring/oniguruma/regcomp.c index 24d44dd1b81e..5171b15a36f2 100644 --- a/ext/mbstring/oniguruma/regcomp.c +++ b/ext/mbstring/oniguruma/regcomp.c @@ -1,16 +1,75 @@ /********************************************************************** - regcomp.c - Oniguruma (regular expression library) - - Copyright (C) 2002-2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regparse.h" +OnigAmbigType OnigDefaultAmbigFlag = + (ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE | + ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE); + +extern OnigAmbigType +onig_get_default_ambig_flag() +{ + return OnigDefaultAmbigFlag; +} + +extern int +onig_set_default_ambig_flag(OnigAmbigType ambig_flag) +{ + OnigDefaultAmbigFlag = ambig_flag; + return 0; +} + + #ifndef PLATFORM_UNALIGNED_WORD_ACCESS static unsigned char PadBuf[WORD_ALIGNMENT_SIZE]; #endif +static UChar* +k_strdup(UChar* s, UChar* end) +{ + int len = end - s; + + if (len > 0) { + UChar* r = (UChar* )xmalloc(len + 1); + CHECK_NULL_RETURN(r); + xmemcpy(r, s, len); + r[len] = (UChar )0; + return r; + } + else return NULL; +} + +/* + Caution: node should not be a string node. + (s and end member address break) +*/ static void swap_node(Node* a, Node* b) { @@ -120,33 +179,6 @@ unset_addr_list_add(UnsetAddrList* uslist, int offset, struct _Node* node) #endif /* USE_SUBEXP_CALL */ -#if 0 -static int -bitset_mbmaxlen(BitSetRef bs, int negative, OnigEncoding enc) -{ - int i; - int len, maxlen = 0; - - if (negative) { - for (i = 0; i < SINGLE_BYTE_SIZE; i++) { - if (! BITSET_AT(bs, i)) { - len = enc_len(enc, i); - if (len > maxlen) maxlen = len; - } - } - } - else { - for (i = 0; i < SINGLE_BYTE_SIZE; i++) { - if (BITSET_AT(bs, i)) { - len = enc_len(enc, i); - if (len > maxlen) maxlen = len; - } - } - } - return maxlen; -} -#endif - static int add_opcode(regex_t* reg, int opcode) { @@ -159,13 +191,7 @@ add_rel_addr(regex_t* reg, int addr) { RelAddrType ra = (RelAddrType )addr; -#ifdef PLATFORM_UNALIGNED_WORD_ACCESS BBUF_ADD(reg, &ra, SIZE_RELADDR); -#else - UChar buf[SERIALIZE_BUFSIZE]; - SERIALIZE_RELADDR(ra, buf); - BBUF_ADD(reg, buf, SIZE_RELADDR); -#endif return 0; } @@ -174,13 +200,7 @@ add_abs_addr(regex_t* reg, int addr) { AbsAddrType ra = (AbsAddrType )addr; -#ifdef PLATFORM_UNALIGNED_WORD_ACCESS BBUF_ADD(reg, &ra, SIZE_ABSADDR); -#else - UChar buf[SERIALIZE_BUFSIZE]; - SERIALIZE_ABSADDR(ra, buf); - BBUF_ADD(reg, buf, SIZE_ABSADDR); -#endif return 0; } @@ -189,13 +209,7 @@ add_length(regex_t* reg, int len) { LengthType l = (LengthType )len; -#ifdef PLATFORM_UNALIGNED_WORD_ACCESS BBUF_ADD(reg, &l, SIZE_LENGTH); -#else - UChar buf[SERIALIZE_BUFSIZE]; - SERIALIZE_LENGTH(l, buf); - BBUF_ADD(reg, buf, SIZE_LENGTH); -#endif return 0; } @@ -204,43 +218,23 @@ add_mem_num(regex_t* reg, int num) { MemNumType n = (MemNumType )num; -#ifdef PLATFORM_UNALIGNED_WORD_ACCESS BBUF_ADD(reg, &n, SIZE_MEMNUM); -#else - UChar buf[SERIALIZE_BUFSIZE]; - SERIALIZE_MEMNUM(n, buf); - BBUF_ADD(reg, buf, SIZE_MEMNUM); -#endif return 0; } -#if 0 static int -add_repeat_num(regex_t* reg, int num) +add_pointer(regex_t* reg, void* addr) { - RepeatNumType n = (RepeatNumType )num; + PointerType ptr = (PointerType )addr; -#ifdef PLATFORM_UNALIGNED_WORD_ACCESS - BBUF_ADD(reg, &n, SIZE_REPEATNUM); -#else - UChar buf[SERIALIZE_BUFSIZE]; - SERIALIZE_REPEATNUM(n, buf); - BBUF_ADD(reg, buf, SIZE_REPEATNUM); -#endif + BBUF_ADD(reg, &ptr, SIZE_POINTER); return 0; } -#endif static int add_option(regex_t* reg, OnigOptionType option) { -#ifdef PLATFORM_UNALIGNED_WORD_ACCESS BBUF_ADD(reg, &option, SIZE_OPTION); -#else - UChar buf[SERIALIZE_BUFSIZE]; - SERIALIZE_OPTION(option, buf); - BBUF_ADD(reg, buf, SIZE_OPTION); -#endif return 0; } @@ -293,15 +287,15 @@ select_str_opcode(int mb_len, int str_len, int ignore_case) { int op; - switch (mb_len) { - case 1: - if (ignore_case) { - switch (str_len) { - case 1: op = OP_EXACT1_IC; break; - default: op = OP_EXACTN_IC; break; - } + if (ignore_case) { + switch (str_len) { + case 1: op = OP_EXACT1_IC; break; + default: op = OP_EXACTN_IC; break; } - else { + } + else { + switch (mb_len) { + case 1: switch (str_len) { case 1: op = OP_EXACT1; break; case 2: op = OP_EXACT2; break; @@ -310,25 +304,25 @@ select_str_opcode(int mb_len, int str_len, int ignore_case) case 5: op = OP_EXACT5; break; default: op = OP_EXACTN; break; } - } - break; + break; - case 2: - switch (str_len) { - case 1: op = OP_EXACTMB2N1; break; - case 2: op = OP_EXACTMB2N2; break; - case 3: op = OP_EXACTMB2N3; break; - default: op = OP_EXACTMB2N; break; - } - break; + case 2: + switch (str_len) { + case 1: op = OP_EXACTMB2N1; break; + case 2: op = OP_EXACTMB2N2; break; + case 3: op = OP_EXACTMB2N3; break; + default: op = OP_EXACTMB2N; break; + } + break; - case 3: - op = OP_EXACTMB3N; - break; + case 3: + op = OP_EXACTMB3N; + break; - default: - op = OP_EXACTMBN; - break; + default: + op = OP_EXACTMBN; + break; + } } return op; } @@ -373,7 +367,7 @@ compile_call(CallNode* node, regex_t* reg) r = add_opcode(reg, OP_CALL); if (r) return r; r = unset_addr_list_add(node->unset_addr_list, BBUF_GET_OFFSET_POS(reg), - node->target); + node->target); if (r) return r; r = add_abs_addr(reg, 0 /*dummy addr.*/); return r; @@ -394,15 +388,14 @@ compile_tree_n_times(Node* node, int n, regex_t* reg) static int add_compile_string_length(UChar* s, int mb_len, int str_len, - regex_t* reg, int ignore_case) + regex_t* reg, int ignore_case) { int len; int op = select_str_opcode(mb_len, str_len, ignore_case); len = SIZE_OPCODE; - if (op == OP_EXACTMBN) - len += SIZE_LENGTH; + if (op == OP_EXACTMBN) len += SIZE_LENGTH; if (IS_NEED_STR_LEN_OP_EXACT(op)) len += SIZE_LENGTH; @@ -412,7 +405,7 @@ add_compile_string_length(UChar* s, int mb_len, int str_len, static int add_compile_string(UChar* s, int mb_len, int str_len, - regex_t* reg, int ignore_case) + regex_t* reg, int ignore_case) { int op = select_str_opcode(mb_len, str_len, ignore_case); add_opcode(reg, op); @@ -420,8 +413,12 @@ add_compile_string(UChar* s, int mb_len, int str_len, if (op == OP_EXACTMBN) add_length(reg, mb_len); - if (IS_NEED_STR_LEN_OP_EXACT(op)) - add_length(reg, str_len); + if (IS_NEED_STR_LEN_OP_EXACT(op)) { + if (op == OP_EXACTN_IC) + add_length(reg, mb_len * str_len); + else + add_length(reg, str_len); + } add_bytes(reg, s, mb_len * str_len); return 0; @@ -429,49 +426,37 @@ add_compile_string(UChar* s, int mb_len, int str_len, static int -compile_length_string_node(StrNode* sn, regex_t* reg) +compile_length_string_node(Node* node, regex_t* reg) { - int rlen, r, len, prev_len, slen, ambig, ic; + int rlen, r, len, prev_len, slen, ambig; OnigEncoding enc = reg->enc; UChar *p, *prev; + StrNode* sn; + sn = &(NSTRING(node)); if (sn->end <= sn->s) return 0; - ic = IS_IGNORECASE(reg->options); + ambig = NSTRING_IS_AMBIG(node); p = prev = sn->s; - prev_len = enc_len(enc, *p); - if (ic != 0 && prev_len == 1) - ambig = ONIGENC_IS_MBC_CASE_AMBIG(reg->enc, p); - else - ambig = 0; - + prev_len = enc_len(enc, p); p += prev_len; slen = 1; rlen = 0; for (; p < sn->end; ) { - len = enc_len(enc, *p); + len = enc_len(enc, p); if (len == prev_len) { slen++; - if (ic != 0 && ambig == 0 && len == 1) - ambig = ONIGENC_IS_MBC_CASE_AMBIG(reg->enc, p); } else { r = add_compile_string_length(prev, prev_len, slen, reg, ambig); rlen += r; - - if (ic != 0 && len == 1) - ambig = ONIGENC_IS_MBC_CASE_AMBIG(reg->enc, p); - else - ambig = 0; - prev = p; slen = 1; prev_len = len; } - p += len; } r = add_compile_string_length(prev, prev_len, slen, reg, ambig); @@ -489,49 +474,33 @@ compile_length_string_raw_node(StrNode* sn, regex_t* reg) } static int -compile_string_node(StrNode* sn, regex_t* reg) +compile_string_node(Node* node, regex_t* reg) { - int r, len, prev_len, slen, ambig, ic; + int r, len, prev_len, slen, ambig; OnigEncoding enc = reg->enc; - UChar *p, *prev; + UChar *p, *prev, *end; + StrNode* sn; + sn = &(NSTRING(node)); if (sn->end <= sn->s) return 0; - ic = IS_IGNORECASE(reg->options); + end = sn->end; + ambig = NSTRING_IS_AMBIG(node); p = prev = sn->s; - prev_len = enc_len(enc, *p); - if (ic != 0 && prev_len == 1) { - ambig = ONIGENC_IS_MBC_CASE_AMBIG(reg->enc, p); - if (ambig != 0) - ONIGENC_MBC_TO_LOWER(reg->enc, p, p); - } - else - ambig = 0; - + prev_len = enc_len(enc, p); p += prev_len; slen = 1; - for (; p < sn->end; ) { - len = enc_len(enc, *p); + for (; p < end; ) { + len = enc_len(enc, p); if (len == prev_len) { slen++; - if (ic != 0 && len == 1) { - if (ambig == 0) - ambig = ONIGENC_IS_MBC_CASE_AMBIG(reg->enc, p); - if (ambig != 0) ONIGENC_MBC_TO_LOWER(reg->enc, p, p); - } } else { r = add_compile_string(prev, prev_len, slen, reg, ambig); if (r) return r; - if (ic != 0 && len == 1) { - ambig = ONIGENC_IS_MBC_CASE_AMBIG(reg->enc, p); - if (ambig != 0) ONIGENC_MBC_TO_LOWER(reg->enc, p, p); - } - else - ambig = 0; prev = p; slen = 1; @@ -580,12 +549,16 @@ compile_length_cclass_node(CClassNode* cc, regex_t* reg) { int len; + if (IS_CCLASS_SHARE(cc)) { + len = SIZE_OPCODE + SIZE_POINTER; + return len; + } + if (IS_NULL(cc->mbuf)) { len = SIZE_OPCODE + SIZE_BITSET; } else { - if (bitset_is_empty(cc->bs)) { - /* SIZE_BITSET is included in mbuf->used. */ + if (ONIGENC_MBC_MINLEN(reg->enc) > 1 || bitset_is_empty(cc->bs)) { len = SIZE_OPCODE; } else { @@ -606,22 +579,34 @@ compile_cclass_node(CClassNode* cc, regex_t* reg) { int r; + if (IS_CCLASS_SHARE(cc)) { + add_opcode(reg, OP_CCLASS_NODE); + r = add_pointer(reg, cc); + return r; + } + if (IS_NULL(cc->mbuf)) { - if (cc->not) add_opcode(reg, OP_CCLASS_NOT); - else add_opcode(reg, OP_CCLASS); + if (IS_CCLASS_NOT(cc)) + add_opcode(reg, OP_CCLASS_NOT); + else + add_opcode(reg, OP_CCLASS); r = add_bitset(reg, cc->bs); } else { - if (bitset_is_empty(cc->bs)) { - if (cc->not) add_opcode(reg, OP_CCLASS_MB_NOT); - else add_opcode(reg, OP_CCLASS_MB); + if (ONIGENC_MBC_MINLEN(reg->enc) > 1 || bitset_is_empty(cc->bs)) { + if (IS_CCLASS_NOT(cc)) + add_opcode(reg, OP_CCLASS_MB_NOT); + else + add_opcode(reg, OP_CCLASS_MB); r = add_multi_byte_cclass(cc->mbuf, reg); } else { - if (cc->not) add_opcode(reg, OP_CCLASS_MIX_NOT); - else add_opcode(reg, OP_CCLASS_MIX); + if (IS_CCLASS_NOT(cc)) + add_opcode(reg, OP_CCLASS_MIX_NOT); + else + add_opcode(reg, OP_CCLASS_MIX); r = add_bitset(reg, cc->bs); if (r) return r; @@ -649,7 +634,7 @@ entry_repeat_range(regex_t* reg, int id, int lower, int upper) int n; n = reg->repeat_range_alloc + REPEAT_RANGE_ALLOC; p = (OnigRepeatRange* )xrealloc(reg->repeat_range, - sizeof(OnigRepeatRange) * n); + sizeof(OnigRepeatRange) * n); CHECK_NULL_RETURN_VAL(p, ONIGERR_MEMORY); reg->repeat_range = p; reg->repeat_range_alloc = n; @@ -665,7 +650,7 @@ entry_repeat_range(regex_t* reg, int id, int lower, int upper) static int compile_range_repeat_node(QualifierNode* qn, int target_len, int empty_info, - regex_t* reg) + regex_t* reg) { int r; int num_repeat = reg->num_repeat; @@ -684,7 +669,16 @@ compile_range_repeat_node(QualifierNode* qn, int target_len, int empty_info, r = compile_tree_empty_check(qn->target, reg, empty_info); if (r) return r; - r = add_opcode(reg, qn->greedy ? OP_REPEAT_INC : OP_REPEAT_INC_NG); + if ( +#ifdef USE_SUBEXP_CALL + reg->num_call > 0 || +#endif + IS_QUALIFIER_IN_REPEAT(qn)) { + r = add_opcode(reg, qn->greedy ? OP_REPEAT_INC_SG : OP_REPEAT_INC_NG_SG); + } + else { + r = add_opcode(reg, qn->greedy ? OP_REPEAT_INC : OP_REPEAT_INC_NG); + } if (r) return r; r = add_mem_num(reg, num_repeat); /* OP_REPEAT ID */ return r; @@ -706,9 +700,9 @@ compile_length_qualifier_node(QualifierNode* qn, regex_t* reg) if (NTYPE(qn->target) == N_ANYCHAR) { if (qn->greedy && infinite) { if (IS_NOT_NULL(qn->next_head_exact)) - return SIZE_OP_ANYCHAR_STAR_PEEK_NEXT + tlen * qn->lower; + return SIZE_OP_ANYCHAR_STAR_PEEK_NEXT + tlen * qn->lower; else - return SIZE_OP_ANYCHAR_STAR + tlen * qn->lower; + return SIZE_OP_ANYCHAR_STAR + tlen * qn->lower; } } @@ -741,7 +735,8 @@ compile_length_qualifier_node(QualifierNode* qn, regex_t* reg) len = SIZE_OP_JUMP + tlen; } else if (!infinite && qn->greedy && - (tlen + SIZE_OP_PUSH) * qn->upper <= QUALIFIER_EXPAND_LIMIT_SIZE) { + (qn->upper == 1 || (tlen + SIZE_OP_PUSH) * qn->upper + <= QUALIFIER_EXPAND_LIMIT_SIZE)) { len = tlen * qn->lower; len += (SIZE_OP_PUSH + tlen) * (qn->upper - qn->lower); } @@ -865,7 +860,8 @@ compile_qualifier_node(QualifierNode* qn, regex_t* reg) r = compile_tree(qn->target, reg); } else if (!infinite && qn->greedy && - (tlen + SIZE_OP_PUSH) * qn->upper <= QUALIFIER_EXPAND_LIMIT_SIZE) { + (qn->upper == 1 || (tlen + SIZE_OP_PUSH) * qn->upper + <= QUALIFIER_EXPAND_LIMIT_SIZE)) { int n = qn->upper - qn->lower; r = compile_tree_n_times(qn->target, qn->lower, reg); @@ -925,18 +921,16 @@ compile_option_node(EffectNode* node, regex_t* reg) if (r) return r; r = add_opcode(reg, OP_FAIL); if (r) return r; + } - reg->options = node->option; - r = compile_tree(node->target, reg); - reg->options = prev; + reg->options = node->option; + r = compile_tree(node->target, reg); + reg->options = prev; + + if (IS_DYNAMIC_OPTION(prev ^ node->option)) { if (r) return r; r = add_opcode_option(reg, OP_SET_OPTION, prev); } - else { - reg->options = node->option; - r = compile_tree(node->target, reg); - reg->options = prev; - } return r; } @@ -983,7 +977,7 @@ compile_length_effect_node(EffectNode* node, regex_t* reg) break; case EFFECT_STOP_BACKTRACK: - if (IS_EFFECT_SIMPLE_REPEAT(node)) { + if (IS_EFFECT_STOP_BT_SIMPLE_REPEAT(node)) { QualifierNode* qn = &NQUALIFIER(node->target); tlen = compile_length_tree(qn->target, reg); if (tlen < 0) return tlen; @@ -1073,7 +1067,7 @@ compile_effect_node(EffectNode* node, regex_t* reg) break; case EFFECT_STOP_BACKTRACK: - if (IS_EFFECT_SIMPLE_REPEAT(node)) { + if (IS_EFFECT_STOP_BT_SIMPLE_REPEAT(node)) { QualifierNode* qn = &NQUALIFIER(node->target); r = compile_tree_n_times(qn->target, qn->lower, reg); if (r) return r; @@ -1258,7 +1252,7 @@ compile_length_tree(Node* node, regex_t* reg) if (NSTRING_IS_RAW(node)) r = compile_length_string_raw_node(&(NSTRING(node)), reg); else - r = compile_length_string_node(&(NSTRING(node)), reg); + r = compile_length_string_node(node, reg); break; case N_CCLASS: @@ -1356,7 +1350,7 @@ compile_tree(Node* node, regex_t* reg) if (NSTRING_IS_RAW(node)) r = compile_string_raw_node(&(NSTRING(node)), reg); else - r = compile_string_node(&(NSTRING(node)), reg); + r = compile_string_node(node, reg); break; case N_CCLASS: @@ -1412,8 +1406,14 @@ compile_tree(Node* node, regex_t* reg) } else { int* p; - add_opcode(reg, (IS_IGNORECASE(reg->options) ? - OP_BACKREF_MULTI_IC : OP_BACKREF_MULTI)); + + if (IS_IGNORECASE(reg->options)) { + add_opcode(reg, OP_BACKREF_MULTI_IC); + } + else { + add_opcode(reg, OP_BACKREF_MULTI); + } + if (r) return r; add_length(reg, br->back_num); if (r) return r; @@ -1455,12 +1455,9 @@ compile_tree(Node* node, regex_t* reg) } #ifdef USE_NAMED_GROUP -typedef struct { - int new_val; -} NumMap; static int -noname_disable_map(Node** plink, NumMap* map, int* counter) +noname_disable_map(Node** plink, GroupNumRemap* map, int* counter) { int r = 0; Node* node = *plink; @@ -1514,7 +1511,7 @@ noname_disable_map(Node** plink, NumMap* map, int* counter) } static int -renumber_node_backref(Node* node, NumMap* map) +renumber_node_backref(Node* node, GroupNumRemap* map) { int i, pos, n, old_num; int *backs; @@ -1542,7 +1539,7 @@ renumber_node_backref(Node* node, NumMap* map) } static int -renumber_by_map(Node* node, NumMap* map) +renumber_by_map(Node* node, GroupNumRemap* map) { int r = 0; @@ -1607,9 +1604,9 @@ disable_noname_group_capture(Node** root, regex_t* reg, ScanEnv* env) { int r, i, pos, counter; BitStatusType loc; - NumMap* map; + GroupNumRemap* map; - map = (NumMap* )xalloca(sizeof(NumMap) * (env->num_mem + 1)); + map = (GroupNumRemap* )xalloca(sizeof(GroupNumRemap) * (env->num_mem + 1)); CHECK_NULL_RETURN_VAL(map, ONIGERR_MEMORY); for (i = 1; i <= env->num_mem; i++) { map[i].new_val = 0; @@ -1638,7 +1635,8 @@ disable_noname_group_capture(Node** root, regex_t* reg, ScanEnv* env) env->num_mem = env->num_named; reg->num_mem = env->num_named; - return 0; + + return onig_renumber_name_table(reg, map); } #endif /* USE_NAMED_GROUP */ @@ -1649,9 +1647,6 @@ unset_addr_list_fix(UnsetAddrList* uslist, regex_t* reg) int i, offset; EffectNode* en; AbsAddrType addr; -#ifndef PLATFORM_UNALIGNED_WORD_ACCESS - UChar buf[SERIALIZE_BUFSIZE]; -#endif for (i = 0; i < uslist->num; i++) { en = &(NEFFECT(uslist->us[i].target)); @@ -1659,12 +1654,7 @@ unset_addr_list_fix(UnsetAddrList* uslist, regex_t* reg) addr = en->call_addr; offset = uslist->us[i].offset; -#ifdef PLATFORM_UNALIGNED_WORD_ACCESS BBUF_WRITE(reg, offset, &addr, SIZE_ABSADDR); -#else - SERIALIZE_ABSADDR(addr, buf); - BBUF_WRITE(reg, offset, buf, SIZE_ABSADDR); -#endif } return 0; } @@ -2044,7 +2034,7 @@ get_char_length_tree1(Node* node, regex_t* reg, int* len, int level) StrNode* sn = &(NSTRING(node)); UChar *s = sn->s; while (s < sn->end) { - s += enc_len(reg->enc, *s); + s += enc_len(reg->enc, s); (*len)++; } } @@ -2135,7 +2125,7 @@ onig_is_code_in_cc(OnigEncoding enc, OnigCodePoint code, CClassNode* cc) { int found; - if (code >= SINGLE_BYTE_SIZE) { + if (ONIGENC_MBC_MINLEN(enc) > 1 || (code >= SINGLE_BYTE_SIZE)) { if (IS_NULL(cc->mbuf)) { found = 0; } @@ -2147,10 +2137,10 @@ onig_is_code_in_cc(OnigEncoding enc, OnigCodePoint code, CClassNode* cc) found = (BITSET_AT(cc->bs, code) == 0 ? 0 : 1); } - if (cc->not == 0) - return found; - else + if (IS_CCLASS_NOT(cc)) return !found; + else + return found; } /* x is not included y ==> 1 : 0 */ @@ -2213,7 +2203,7 @@ is_not_included(Node* x, Node* y, regex_t* reg) case N_CTYPE: switch (NCTYPE(y).type) { case CTYPE_WORD: - if (IS_NULL(xc->mbuf) && xc->not == 0) { + if (IS_NULL(xc->mbuf) && !IS_CCLASS_NOT(xc)) { for (i = 0; i < SINGLE_BYTE_SIZE; i++) { if (BITSET_AT(xc->bs, i)) { if (ONIGENC_IS_CODE_SB_WORD(reg->enc, i)) return 0; @@ -2226,7 +2216,7 @@ is_not_included(Node* x, Node* y, regex_t* reg) case CTYPE_NOT_WORD: for (i = 0; i < SINGLE_BYTE_SIZE; i++) { if (! ONIGENC_IS_CODE_SB_WORD(reg->enc, i)) { - if (xc->not == 0) { + if (!IS_CCLASS_NOT(xc)) { if (BITSET_AT(xc->bs, i)) return 0; } @@ -2251,14 +2241,16 @@ is_not_included(Node* x, Node* y, regex_t* reg) for (i = 0; i < SINGLE_BYTE_SIZE; i++) { v = BITSET_AT(xc->bs, i); - if ((v != 0 && xc->not == 0) || (v == 0 && xc->not)) { + if ((v != 0 && !IS_CCLASS_NOT(xc)) || + (v == 0 && IS_CCLASS_NOT(xc))) { v = BITSET_AT(yc->bs, i); - if ((v != 0 && yc->not == 0) || (v == 0 && yc->not)) + if ((v != 0 && !IS_CCLASS_NOT(yc)) || + (v == 0 && IS_CCLASS_NOT(yc))) return 0; } } - if ((IS_NULL(xc->mbuf) && xc->not == 0) || - (IS_NULL(yc->mbuf) && yc->not == 0)) + if ((IS_NULL(xc->mbuf) && !IS_CCLASS_NOT(xc)) || + (IS_NULL(yc->mbuf) && !IS_CCLASS_NOT(yc))) return 1; return 0; } @@ -2300,7 +2292,7 @@ is_not_included(Node* x, Node* y, regex_t* reg) CClassNode* cc = &(NCCLASS(y)); code = ONIGENC_MBC_TO_CODE(reg->enc, xs->s, - xs->s + enc_len(reg->enc, c)); + xs->s + ONIGENC_MBC_MAXLEN(reg->enc)); return (onig_is_code_in_cc(reg->enc, code, cc) != 0 ? 0 : 1); } break; @@ -2311,18 +2303,9 @@ is_not_included(Node* x, Node* y, regex_t* reg) StrNode* ys = &(NSTRING(y)); len = NSTRING_LEN(x); if (len > NSTRING_LEN(y)) len = NSTRING_LEN(y); - if (NSTRING_IS_CASE_AMBIG(x) || NSTRING_IS_CASE_AMBIG(y)) { - UChar plow[ONIGENC_MBC_TO_LOWER_MAXLEN]; - UChar qlow[ONIGENC_MBC_TO_LOWER_MAXLEN]; - int plen, qlen; - for (p = ys->s, q = xs->s; q < xs->end; ) { - plen = ONIGENC_MBC_TO_LOWER(reg->enc, p, plow); - qlen = ONIGENC_MBC_TO_LOWER(reg->enc, q, qlow); - if (plen != qlen || onig_strncmp(plow, qlow, plen) != 0) - return 1; - p += enc_len(reg->enc, *p); - q += enc_len(reg->enc, *q); - } + if (NSTRING_IS_AMBIG(x) || NSTRING_IS_AMBIG(y)) { + /* tiny version */ + return 0; } else { for (i = 0, p = ys->s, q = xs->s; i < len; i++, p++, q++) { @@ -2379,8 +2362,12 @@ get_head_value_node(Node* node, int exact, regex_t* reg) if (exact != 0 && !NSTRING_IS_RAW(node) && IS_IGNORECASE(reg->options)) { - if (! ONIGENC_IS_MBC_CASE_AMBIG(reg->enc, sn->s)) +#if 0 + UChar* tmp = sn->s; + if (! ONIGENC_IS_MBC_AMBIGUOUS(reg->enc, reg->ambig_flag, + &tmp, sn->end)) n = node; +#endif } else { n = node; @@ -2937,7 +2924,7 @@ next_setup(Node* node, Node* next_node, regex_t* reg) if (IS_NOT_NULL(y) && is_not_included(x, y, reg)) { Node* en = onig_node_new_effect(EFFECT_STOP_BACKTRACK); CHECK_NULL_RETURN_VAL(en, ONIGERR_MEMORY); - SET_EFFECT_STATUS(en, NST_SIMPLE_REPEAT); + SET_EFFECT_STATUS(en, NST_STOP_BT_SIMPLE_REPEAT); swap_node(node, en); NEFFECT(node).target = en; } @@ -2956,9 +2943,114 @@ next_setup(Node* node, Node* next_node, regex_t* reg) return 0; } -#define IN_ALT (1<<0) -#define IN_NOT (1<<1) -#define IN_REPEAT (1<<2) +static int +divide_ambig_string_node(Node* node, regex_t* reg) +{ + StrNode* sn = &NSTRING(node); + int ambig, prev_ambig; + UChar *prev, *p, *end, *prev_start, *start, *tmp, *wp; + Node *snode; + Node *root = NULL_NODE; + Node **tailp = (Node** )0; + + start = prev_start = p = sn->s; + end = sn->end; + if (p >= end) return 0; + + prev_ambig = ONIGENC_IS_MBC_AMBIGUOUS(reg->enc, reg->ambig_flag, &p, end); + + while (p < end) { + prev = p; + if (prev_ambig != (ambig = ONIGENC_IS_MBC_AMBIGUOUS(reg->enc, + reg->ambig_flag, &p, end))) { + + if (prev_ambig != 0) { + tmp = prev_start; + wp = prev_start; + while (tmp < prev) { + wp += ONIGENC_MBC_TO_NORMALIZE(reg->enc, reg->ambig_flag, + &tmp, end, wp); + } + snode = onig_node_new_str(prev_start, wp); + CHECK_NULL_RETURN_VAL(snode, ONIGERR_MEMORY); + NSTRING_SET_AMBIG(snode); + if (wp != prev) NSTRING_SET_AMBIG_REDUCE(snode); + } + else { + snode = onig_node_new_str(prev_start, prev); + CHECK_NULL_RETURN_VAL(snode, ONIGERR_MEMORY); + } + + if (tailp == (Node** )0) { + root = onig_node_new_list(snode, NULL); + CHECK_NULL_RETURN_VAL(root, ONIGERR_MEMORY); + tailp = &(NCONS(root).right); + } + else { + *tailp = onig_node_new_list(snode, NULL); + CHECK_NULL_RETURN_VAL(*tailp, ONIGERR_MEMORY); + tailp = &(NCONS(*tailp).right); + } + + prev_ambig = ambig; + prev_start = prev; + } + } + + if (prev_start == start) { + if (prev_ambig != 0) { + NSTRING_SET_AMBIG(node); + tmp = start; + wp = start; + while (tmp < end) { + wp += ONIGENC_MBC_TO_NORMALIZE(reg->enc, reg->ambig_flag, + &tmp, end, wp); + } + if (wp != sn->end) NSTRING_SET_AMBIG_REDUCE(node); + sn->end = wp; + } + } + else { + if (prev_ambig != 0) { + tmp = prev_start; + wp = prev_start; + while (tmp < end) { + wp += ONIGENC_MBC_TO_NORMALIZE(reg->enc, reg->ambig_flag, + &tmp, end, wp); + } + snode = onig_node_new_str(prev_start, wp); + CHECK_NULL_RETURN_VAL(snode, ONIGERR_MEMORY); + NSTRING_SET_AMBIG(snode); + if (wp != end) NSTRING_SET_AMBIG_REDUCE(snode); + } + else { + snode = onig_node_new_str(prev_start, end); + CHECK_NULL_RETURN_VAL(snode, ONIGERR_MEMORY); + } + + if (tailp == (Node** )0) { + root = onig_node_new_list(snode, NULL); + CHECK_NULL_RETURN_VAL(root, ONIGERR_MEMORY); + tailp = &(NCONS(node).right); + } + else { + *tailp = onig_node_new_list(snode, NULL); + CHECK_NULL_RETURN_VAL(*tailp, ONIGERR_MEMORY); + tailp = &(NCONS(*tailp).right); + } + + swap_node(node, root); + onig_node_str_clear(root); /* should be after swap! */ + onig_node_free(root); /* free original string node */ + } + + return 0; +} + +#define IN_ALT (1<<0) +#define IN_NOT (1<<1) +#define IN_REPEAT (1<<2) +#define IN_VAR_REPEAT (1<<3) /* setup_tree does the following work. 1. check empty loop. (set qn->target_empty_info) @@ -2996,33 +3088,11 @@ setup_tree(Node* node, regex_t* reg, int state, ScanEnv* env) break; case N_CCLASS: - if (IS_IGNORECASE(reg->options)) { - int i; - UChar c, lowbuf[ONIGENC_MBC_TO_LOWER_MAXLEN]; - BitSetRef bs = NCCLASS(node).bs; - for (i = 0; i < SINGLE_BYTE_SIZE; i++) { - c = (UChar )i; - ONIGENC_MBC_TO_LOWER(reg->enc, &c, lowbuf); - if (*lowbuf != c) { - if (BITSET_AT(bs, c)) BITSET_SET_BIT(bs, *lowbuf); - if (BITSET_AT(bs, *lowbuf)) BITSET_SET_BIT(bs, c); - } - } - } break; case N_STRING: if (IS_IGNORECASE(reg->options) && !NSTRING_IS_RAW(node)) { - StrNode* sn = &NSTRING(node); - UChar* p = sn->s; - - while (p < sn->end) { - if (ONIGENC_IS_MBC_CASE_AMBIG(reg->enc, p)) { - NSTRING_SET_CASE_AMBIG(node); - break; - } - p++; - } + r = divide_ambig_string_node(node, reg); } break; @@ -3057,6 +3127,10 @@ setup_tree(Node* node, regex_t* reg, int state, ScanEnv* env) QualifierNode* qn = &(NQUALIFIER(node)); Node* target = qn->target; + if ((state & IN_REPEAT) != 0) { + qn->state |= NST_IN_REPEAT; + } + if (IS_REPEAT_INFINITE(qn->upper) || qn->upper >= 1) { r = get_min_match_length(target, &d, env); if (r) break; @@ -3083,8 +3157,9 @@ setup_tree(Node* node, regex_t* reg, int state, ScanEnv* env) } } + state |= IN_REPEAT; if (qn->lower != qn->upper) - state |= IN_REPEAT; + state |= IN_VAR_REPEAT; r = setup_tree(target, reg, state, env); if (r) break; @@ -3141,11 +3216,13 @@ setup_tree(Node* node, regex_t* reg, int state, ScanEnv* env) break; case EFFECT_MEMORY: - if ((state & (IN_ALT | IN_NOT | IN_REPEAT)) != 0) { + if ((state & (IN_ALT | IN_NOT | IN_VAR_REPEAT)) != 0) { BIT_STATUS_ON_AT(env->bt_mem_start, en->regnum); /* SET_EFFECT_STATUS(node, NST_MEM_IN_ALT_NOT); */ } - /* fall */ + r = setup_tree(en->target, reg, state, env); + break; + case EFFECT_STOP_BACKTRACK: { Node* target = en->target; @@ -3156,7 +3233,7 @@ setup_tree(Node* node, regex_t* reg, int state, ScanEnv* env) tqn->greedy != 0) { /* (?>a*), a*+ etc... */ int qtype = NTYPE(tqn->target); if (IS_NODE_TYPE_SIMPLE(qtype)) - SET_EFFECT_STATUS(node, NST_SIMPLE_REPEAT); + SET_EFFECT_STATUS(node, NST_STOP_BT_SIMPLE_REPEAT); } } } @@ -3228,26 +3305,17 @@ setup_tree(Node* node, regex_t* reg, int state, ScanEnv* env) /* set skip map for Boyer-Moor search */ static int -set_bm_skip(UChar* s, UChar* end, OnigEncoding enc, int ignore_case, +set_bm_skip(UChar* s, UChar* end, OnigEncoding enc, UChar skip[], int** int_skip) { int i, len; - UChar lowbuf[ONIGENC_MBC_TO_LOWER_MAXLEN]; len = end - s; if (len < ONIG_CHAR_TABLE_SIZE) { for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) skip[i] = len; - if (ignore_case) { - for (i = 0; i < len - 1; i++) { - ONIGENC_MBC_TO_LOWER(enc, &(s[i]), lowbuf); - skip[*lowbuf] = len - 1 - i; - } - } - else { - for (i = 0; i < len - 1; i++) - skip[s[i]] = len - 1 - i; - } + for (i = 0; i < len - 1; i++) + skip[s[i]] = len - 1 - i; } else { if (IS_NULL(*int_skip)) { @@ -3256,16 +3324,8 @@ set_bm_skip(UChar* s, UChar* end, OnigEncoding enc, int ignore_case, } for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) (*int_skip)[i] = len; - if (ignore_case) { - for (i = 0; i < len - 1; i++) { - ONIGENC_MBC_TO_LOWER(enc, &(s[i]), lowbuf); - (*int_skip)[*lowbuf] = len - 1 - i; - } - } - else { - for (i = 0; i < len - 1; i++) - (*int_skip)[s[i]] = len - 1 - i; - } + for (i = 0; i < len - 1; i++) + (*int_skip)[s[i]] = len - 1 - i; } return 0; } @@ -3278,11 +3338,12 @@ typedef struct { } MinMaxLen; typedef struct { - MinMaxLen mmd; - BitStatusType backrefed_status; - OnigEncoding enc; - OnigOptionType options; - ScanEnv* scan_env; + MinMaxLen mmd; + BitStatusType backrefed_status; + OnigEncoding enc; + OnigOptionType options; + OnigAmbigType ambig_flag; + ScanEnv* scan_env; } OptEnv; typedef struct { @@ -3321,29 +3382,34 @@ typedef struct { static int -map_position_value(int i) -{ - static int vals[] = { - 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 1, 10, 10, 1, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 1, 6, 3, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, - 5, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 4, 5, 5, 5, - 5, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 10, +map_position_value(OnigEncoding enc, int i) +{ + static short int ByteValTable[] = { + 5, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10, 1, 1, 10, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 12, 4, 7, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, + 5, 6, 6, 6, 6, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 5, 5, 5, + 5, 6, 6, 6, 6, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 1 }; - if (i < sizeof(vals)/sizeof(vals[0])) return vals[i]; - - return 7; /* Take it easy. */ + if (i < sizeof(ByteValTable)/sizeof(ByteValTable[0])) { + if (i == 0 && ONIGENC_MBC_MINLEN(enc) > 1) + return 20; + else + return (int )ByteValTable[i]; + } + else + return 4; /* Take it easy. */ } static int distance_value(MinMaxLen* mm) { /* 1000 / (min-max-dist + 1) */ - static int dist_vals[] = { + static short int dist_vals[] = { 1000, 500, 333, 250, 200, 167, 143, 125, 111, 100, 91, 83, 77, 71, 67, 63, 59, 56, 53, 50, 48, 45, 43, 42, 40, 38, 37, 36, 34, 33, @@ -3363,7 +3429,7 @@ distance_value(MinMaxLen* mm) d = mm->max - mm->min; if (d < sizeof(dist_vals)/sizeof(dist_vals[0])) /* return dist_vals[d] * 16 / (mm->min + 12); */ - return dist_vals[d]; + return (int )dist_vals[d]; else return 1; } @@ -3419,12 +3485,14 @@ add_mml(MinMaxLen* to, MinMaxLen* from) to->max = distance_add(to->max, from->max); } +#if 0 static void add_len_mml(MinMaxLen* to, OnigDistance len) { to->min = distance_add(to->min, len); to->max = distance_add(to->max, len); } +#endif static void alt_merge_mml(MinMaxLen* to, MinMaxLen* from) @@ -3571,7 +3639,7 @@ concat_opt_exact_info_str(OptExactInfo* to, to->s[i++] = *p++; } else { - len = enc_len(enc, *p); + len = enc_len(enc, p); if (i + len > OPT_EXACT_MAXLEN) break; for (j = 0; j < len; j++) to->s[i++] = *p++; @@ -3598,7 +3666,7 @@ alt_merge_opt_exact_info(OptExactInfo* to, OptExactInfo* add, OptEnv* env) for (i = 0; i < to->len && i < add->len; ) { if (to->s[i] != add->s[i]) break; - len = enc_len(env->enc, to->s[i]); + len = enc_len(env->enc, to->s + i); for (j = 1; j < len; j++) { if (to->s[i+j] != add->s[i+j]) break; @@ -3618,27 +3686,55 @@ alt_merge_opt_exact_info(OptExactInfo* to, OptExactInfo* add, OptEnv* env) } static void -select_opt_exact_info(OptExactInfo* now, OptExactInfo* alt) +select_opt_exact_info(OnigEncoding enc, OptExactInfo* now, OptExactInfo* alt) { - int vlen1, vlen2; + int v1, v2; + + v1 = now->len; + v2 = alt->len; + + if (v1 <= 2 && v2 <= 2) { + /* ByteValTable[x] is big value --> low price */ + v2 = map_position_value(enc, now->s[0]); + v1 = map_position_value(enc, alt->s[0]); + + if (now->len > 1) v1 += 5; + if (alt->len > 1) v2 += 5; + } - vlen1 = now->len * (now->ignore_case ? 1 : 2); - vlen2 = alt->len * (alt->ignore_case ? 1 : 2); + if (now->ignore_case == 0) v1 *= 2; + if (alt->ignore_case == 0) v2 *= 2; - if (comp_distance_value(&now->mmd, &alt->mmd, vlen1, vlen2) > 0) + if (comp_distance_value(&now->mmd, &alt->mmd, v1, v2) > 0) copy_opt_exact_info(now, alt); } static void clear_opt_map_info(OptMapInfo* map) { - int i; + static OptMapInfo clean_info = { + {0, 0}, {0, 0}, 0, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + } + }; - clear_mml(&map->mmd); - clear_opt_anc_info(&map->anc); - map->value = 0; - for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) - map->map[i] = 0; + xmemcpy(map, &clean_info, sizeof(OptMapInfo)); } static void @@ -3648,34 +3744,56 @@ copy_opt_map_info(OptMapInfo* to, OptMapInfo* from) } static void -add_char_opt_map_info(OptMapInfo* map, int c) +add_char_opt_map_info(OptMapInfo* map, UChar c, OnigEncoding enc) { if (map->map[c] == 0) { map->map[c] = 1; - map->value += map_position_value(c); + map->value += map_position_value(enc, c); } } -static void -add_char_amb_opt_map_info(OptMapInfo* map, int c, OnigEncoding enc) +static int +add_char_amb_opt_map_info(OptMapInfo* map, UChar* p, UChar* end, + OnigEncoding enc, OnigAmbigType ambig_flag) { - UChar x, low[ONIGENC_MBC_TO_LOWER_MAXLEN]; + int i, j, n, len; + UChar buf[ONIGENC_MBC_NORMALIZE_MAXLEN]; + OnigCodePoint code, ccode; + OnigCompAmbigCodes* ccs; + OnigPairAmbigCodes* pccs; + OnigAmbigType amb; - add_char_opt_map_info(map, c); + add_char_opt_map_info(map, p[0], enc); + code = ONIGENC_MBC_TO_CODE(enc, p, end); - x = (UChar )c; - ONIGENC_MBC_TO_LOWER(enc, &x, low); - if (*low != x) { - add_char_opt_map_info(map, (int )(*low)); - } - else { - int i; - for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) { - x = (UChar )i; - ONIGENC_MBC_TO_LOWER(enc, &x, low); - if ((int )(*low) == c) add_char_opt_map_info(map, i); + for (amb = 0x01; amb <= ONIGENC_AMBIGUOUS_MATCH_LIMIT; amb <<= 1) { + if ((amb & ambig_flag) == 0) continue; + + n = ONIGENC_GET_ALL_PAIR_AMBIG_CODES(enc, amb, &pccs); + for (i = 0; i < n; i++) { + if (pccs[i].from == code) { + len = ONIGENC_CODE_TO_MBC(enc, pccs[i].to, buf); + if (len < 0) return len; + add_char_opt_map_info(map, buf[0], enc); + } + } + + if ((ambig_flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + n = ONIGENC_GET_ALL_COMP_AMBIG_CODES(enc, amb, &ccs); + for (i = 0; i < n; i++) { + if (ccs[i].code == code) { + for (j = 0; j < ccs[i].n; j++) { + ccode = ccs[i].items[j].code[0]; + len = ONIGENC_CODE_TO_MBC(enc, ccode, buf); + if (len < 0) return len; + add_char_opt_map_info(map, buf[0], enc); + } + break; + } + } } } + return 0; } static void @@ -3711,7 +3829,7 @@ comp_opt_exact_or_map_info(OptExactInfo* e, OptMapInfo* m) } static void -alt_merge_opt_map_info(OptMapInfo* to, OptMapInfo* add) +alt_merge_opt_map_info(OnigEncoding enc, OptMapInfo* to, OptMapInfo* add) { int i, val; @@ -3730,7 +3848,7 @@ alt_merge_opt_map_info(OptMapInfo* to, OptMapInfo* add) to->map[i] = 1; if (to->map[i]) - val += map_position_value(i); + val += map_position_value(enc, i); } to->value = val; @@ -3763,7 +3881,7 @@ copy_node_opt_info(NodeOptInfo* to, NodeOptInfo* from) } static void -concat_left_node_opt_info(NodeOptInfo* to, NodeOptInfo* add) +concat_left_node_opt_info(OnigEncoding enc, NodeOptInfo* to, NodeOptInfo* add) { int exb_reach, exm_reach; OptAncInfo tanc; @@ -3798,8 +3916,8 @@ concat_left_node_opt_info(NodeOptInfo* to, NodeOptInfo* add) clear_opt_exact_info(&add->exb); } } - select_opt_exact_info(&to->exm, &add->exb); - select_opt_exact_info(&to->exm, &add->exm); + select_opt_exact_info(enc, &to->exm, &add->exb); + select_opt_exact_info(enc, &to->exm, &add->exm); if (to->expr.len > 0) { if (add->len.max > 0) { @@ -3807,9 +3925,9 @@ concat_left_node_opt_info(NodeOptInfo* to, NodeOptInfo* add) to->expr.len = add->len.max; if (to->expr.mmd.max == 0) - select_opt_exact_info(&to->exb, &to->expr); + select_opt_exact_info(enc, &to->exb, &to->expr); else - select_opt_exact_info(&to->exm, &to->expr); + select_opt_exact_info(enc, &to->exm, &to->expr); } } else if (add->expr.len > 0) { @@ -3828,7 +3946,7 @@ alt_merge_node_opt_info(NodeOptInfo* to, NodeOptInfo* add, OptEnv* env) alt_merge_opt_exact_info(&to->exb, &add->exb, env); alt_merge_opt_exact_info(&to->exm, &add->exm, env); alt_merge_opt_exact_info(&to->expr, &add->expr, env); - alt_merge_opt_map_info (&to->map, &add->map); + alt_merge_opt_map_info(env->enc, &to->map, &add->map); alt_merge_mml(&to->len, &add->len); } @@ -3858,7 +3976,7 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env) r = optimize_node_left(NCONS(nd).left, &nopt, &nenv); if (r == 0) { add_mml(&nenv.mmd, &nopt.len); - concat_left_node_opt_info(opt, &nopt); + concat_left_node_opt_info(env->enc, opt, &nopt); } } while (r == 0 && IS_NOT_NULL(nd = NCONS(nd).right)); } @@ -3881,148 +3999,110 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env) case N_STRING: { - UChar *p; - int len, plen; StrNode* sn = &(NSTRING(node)); int slen = sn->end - sn->s; int is_raw = NSTRING_IS_RAW(node); - if ((! IS_IGNORECASE(env->options)) || is_raw) { + if (! NSTRING_IS_AMBIG(node)) { concat_opt_exact_info_str(&opt->exb, sn->s, sn->end, NSTRING_IS_RAW(node), env->enc); if (slen > 0) { - add_char_opt_map_info(&opt->map, *(sn->s)); + add_char_opt_map_info(&opt->map, *(sn->s), env->enc); } + set_mml(&opt->len, slen, slen); } else { - for (p = sn->s; p < sn->end; ) { - len = enc_len(env->enc, *p); - if (len == 1 && ONIGENC_IS_MBC_CASE_AMBIG(env->enc, p)) { - break; - } - p += len; - } + int n, max; - plen = p - sn->s; - if (plen > slen / 5) { - concat_opt_exact_info_str(&opt->exb, sn->s, p, is_raw, env->enc); - concat_opt_exact_info_str(&opt->exm, p, sn->end, is_raw, env->enc); - opt->exm.ignore_case = 1; - if (opt->exm.len == sn->end - p) - opt->exm.reach_end = 1; - - copy_mml(&(opt->exm.mmd), &(opt->exb.mmd)); - add_len_mml(&(opt->exm.mmd), plen); - } - else { - concat_opt_exact_info_str(&opt->exb, sn->s, sn->end, - is_raw, env->enc); - opt->exb.ignore_case = 1; - } + concat_opt_exact_info_str(&opt->exb, sn->s, sn->end, + is_raw, env->enc); + opt->exb.ignore_case = 1; if (slen > 0) { - if (p == sn->s) - add_char_amb_opt_map_info(&opt->map, *(sn->s), env->enc); - else - add_char_opt_map_info(&opt->map, *(sn->s)); + r = add_char_amb_opt_map_info(&opt->map, sn->s, sn->end, + env->enc, env->ambig_flag); + if (r != 0) break; } + + if (NSTRING_IS_AMBIG_REDUCE(node)) { + n = onigenc_strlen(env->enc, sn->s, sn->end); + max = ONIGENC_MBC_MAXLEN_DIST(env->enc) * n; + } + else { + max = slen; + } + set_mml(&opt->len, slen, max); } if (opt->exb.len == slen) opt->exb.reach_end = 1; - - set_mml(&opt->len, slen, slen); } break; case N_CCLASS: { - int i, z, len, found, mb_found; + int i, z; CClassNode* cc = &(NCCLASS(node)); /* no need to check ignore case. (setted in setup_tree()) */ - found = mb_found = 0; - for (i = 0; i < SINGLE_BYTE_SIZE; i++) { - z = BITSET_AT(cc->bs, i); - if ((z && !cc->not) || (!z && cc->not)) { - found = 1; - add_char_opt_map_info(&opt->map, i); - } - } - if (IS_NULL(cc->mbuf)) { - if (cc->not) { - for (i = 0; i < SINGLE_BYTE_SIZE; i++) { - add_char_opt_map_info(&opt->map, i); - } - mb_found = 1; - } - } - else { - for (i = 0; i < SINGLE_BYTE_SIZE; i++) { - z = ONIGENC_IS_MBC_HEAD(env->enc, i); - if (z) { - mb_found = 1; - add_char_opt_map_info(&opt->map, i); - } - } - } + if (IS_NOT_NULL(cc->mbuf) || IS_CCLASS_NOT(cc)) { + OnigDistance min = ONIGENC_MBC_MINLEN(env->enc); + OnigDistance max = ONIGENC_MBC_MAXLEN_DIST(env->enc); - if (mb_found) { - len = ONIGENC_MBC_MAXLEN_DIST(env->enc); - set_mml(&opt->len, 1, len); + set_mml(&opt->len, min, max); } - else if (found) { - len = 1; - set_mml(&opt->len, 1, len); + else { + for (i = 0; i < SINGLE_BYTE_SIZE; i++) { + z = BITSET_AT(cc->bs, i); + if ((z && !IS_CCLASS_NOT(cc)) || (!z && IS_CCLASS_NOT(cc))) { + add_char_opt_map_info(&opt->map, (UChar )i, env->enc); + } + } + set_mml(&opt->len, 1, 1); } } break; case N_CTYPE: { - int c; - int len, min, max; + int i, min, max; - min = ONIGENC_MBC_MAXLEN_DIST(env->enc); - max = 0; + max = ONIGENC_MBC_MAXLEN_DIST(env->enc); -#define IS_WORD_HEAD_BYTE(enc,b) \ - (ONIGENC_IS_MBC_ASCII(&b) ? ONIGENC_IS_CODE_WORD(enc,((OnigCodePoint )b)) \ - : ONIGENC_IS_MBC_HEAD(enc,b)) + if (max == 1) { + min = 1; - switch (NCTYPE(node).type) { - case CTYPE_WORD: - for (c = 0; c < SINGLE_BYTE_SIZE; c++) { - if (IS_WORD_HEAD_BYTE(env->enc, c)) { - add_char_opt_map_info(&opt->map, c); - len = enc_len(env->enc, c); - if (len < min) min = len; - if (len > max) max = len; - } - } - break; + switch (NCTYPE(node).type) { + case CTYPE_NOT_WORD: + for (i = 0; i < SINGLE_BYTE_SIZE; i++) { + if (! ONIGENC_IS_CODE_WORD(env->enc, i)) { + add_char_opt_map_info(&opt->map, (UChar )i, env->enc); + } + } + break; - case CTYPE_NOT_WORD: - for (c = 0; c < SINGLE_BYTE_SIZE; c++) { - if (! IS_WORD_HEAD_BYTE(env->enc, c)) { - add_char_opt_map_info(&opt->map, c); - len = enc_len(env->enc, c); - if (len < min) min = len; - if (len > max) max = len; - } + case CTYPE_WORD: + for (i = 0; i < SINGLE_BYTE_SIZE; i++) { + if (ONIGENC_IS_CODE_WORD(env->enc, i)) { + add_char_opt_map_info(&opt->map, (UChar )i, env->enc); + } + } + break; } - break; } - + else { + min = ONIGENC_MBC_MINLEN(env->enc); + } set_mml(&opt->len, min, max); } break; case N_ANYCHAR: { - OnigDistance len = ONIGENC_MBC_MAXLEN_DIST(env->enc); - set_mml(&opt->len, 1, len); + OnigDistance min = ONIGENC_MBC_MINLEN(env->enc); + OnigDistance max = ONIGENC_MBC_MAXLEN_DIST(env->enc); + set_mml(&opt->len, min, max); } break; @@ -4223,36 +4303,20 @@ set_optimize_exact_info(regex_t* reg, OptExactInfo* e) if (e->len == 0) return 0; - reg->exact = onig_strdup(e->s, e->s + e->len); - CHECK_NULL_RETURN_VAL(reg->exact, ONIGERR_MEMORY); - - reg->exact_end = reg->exact + e->len; - if (e->ignore_case) { - UChar buf[ONIGENC_MBC_TO_LOWER_MAXLEN]; - int len, low_len, i, j, alloc_size; - - alloc_size = e->len; - i = j = 0; - while (i < e->len) { - low_len = ONIGENC_MBC_TO_LOWER(reg->enc, &(e->s[i]), buf); - len = enc_len(reg->enc, e->s[i]); - if (low_len > alloc_size - i) { - reg->exact = xrealloc(reg->exact, alloc_size * 2); - CHECK_NULL_RETURN_VAL(reg->exact, ONIGERR_MEMORY); - alloc_size *= 2; - } - - xmemcpy(&(reg->exact[j]), buf, low_len); - i += len; - j += low_len; - } - reg->exact_end = reg->exact + j; + reg->exact = (UChar* )xmalloc(e->len); + CHECK_NULL_RETURN_VAL(reg->exact, ONIGERR_MEMORY); + xmemcpy(reg->exact, e->s, e->len); + reg->exact_end = reg->exact + e->len; reg->optimize = ONIG_OPTIMIZE_EXACT_IC; } else { int allow_reverse; + reg->exact = k_strdup(e->s, e->s + e->len); + CHECK_NULL_RETURN_VAL(reg->exact, ONIGERR_MEMORY); + reg->exact_end = reg->exact + e->len; + if (e->anc.left_anchor & ANCHOR_BEGIN_LINE) allow_reverse = 1; else @@ -4260,7 +4324,7 @@ set_optimize_exact_info(regex_t* reg, OptExactInfo* e) ONIGENC_IS_ALLOWED_REVERSE_MATCH(reg->enc, reg->exact, reg->exact_end); if (e->len >= 3 || (e->len >= 2 && allow_reverse)) { - r = set_bm_skip(reg->exact, reg->exact_end, reg->enc, 0, + r = set_bm_skip(reg->exact, reg->exact_end, reg->enc, reg->map, &(reg->int_map)); if (r) return r; @@ -4320,6 +4384,7 @@ set_optimize_info_from_tree(Node* node, regex_t* reg, ScanEnv* scan_env) env.enc = reg->enc; env.options = reg->options; + env.ambig_flag = reg->ambig_flag; env.scan_env = scan_env; clear_mml(&env.mmd); @@ -4337,7 +4402,7 @@ set_optimize_info_from_tree(Node* node, regex_t* reg, ScanEnv* scan_env) } if (opt.exb.len > 0 || opt.exm.len > 0) { - select_opt_exact_info(&opt.exb, &opt.exm); + select_opt_exact_info(reg->enc, &opt.exb, &opt.exm); if (opt.map.value > 0 && comp_opt_exact_or_map_info(&opt.exb, &opt.map) > 0) { goto set_map; @@ -4474,17 +4539,26 @@ print_optimize_info(FILE* f, regex_t* reg) fprintf(f, "]: length: %d\n", (reg->exact_end - reg->exact)); } else if (reg->optimize & ONIG_OPTIMIZE_MAP) { - int i, n = 0; + int c, i, n = 0; + for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) if (reg->map[i]) n++; fprintf(f, "map: n=%d\n", n); if (n > 0) { + c = 0; fputc('[', f); - for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) - if (reg->map[i] && enc_len(reg->enc, i) == 1 && - ONIGENC_IS_CODE_PRINT(reg->enc, i)) - fputc(i, f); + for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) { + if (reg->map[i] != 0) { + if (c > 0) fputs(", ", f); + c++; + if (ONIGENC_MBC_MAXLEN(reg->enc) == 1 && + ONIGENC_IS_CODE_PRINT(reg->enc, (OnigCodePoint )i)) + fputc(i, f); + else + fprintf(f, "%d", i); + } + } fprintf(f, "]\n"); } } @@ -4500,7 +4574,7 @@ onig_free_body(regex_t* reg) if (IS_NOT_NULL(reg->int_map)) xfree(reg->int_map); if (IS_NOT_NULL(reg->int_map_backward)) xfree(reg->int_map_backward); if (IS_NOT_NULL(reg->repeat_range)) xfree(reg->repeat_range); - if (IS_NOT_NULL(reg->chain)) onig_free(reg->chain); + if (IS_NOT_NULL(reg->chain)) onig_free(reg->chain); #ifdef USE_NAMED_GROUP onig_names_free(reg); @@ -4523,7 +4597,7 @@ onig_free(regex_t* reg) xfree(from);\ } while (0) -static void +extern void onig_transfer(regex_t* to, regex_t* from) { THREAD_ATOMIC_START; @@ -4537,7 +4611,7 @@ onig_transfer(regex_t* to, regex_t* from) }\ } while (0) -static void +extern void onig_chain_link_add(regex_t* to, regex_t* add) { THREAD_ATOMIC_START; @@ -4573,11 +4647,12 @@ onig_clone(regex_t** to, regex_t* from) int r, size; regex_t* reg; - if (ONIG_STATE(from) == ONIG_STATE_NORMAL) { - from->state++; /* increment as search counter */ - if (IS_NOT_NULL(from->chain)) { +#ifdef USE_MULTI_THREAD_SYSTEM + if (ONIG_STATE(from) >= ONIG_STATE_NORMAL) { + ONIG_STATE_INC(from); + if (IS_NOT_NULL(from->chain) && ONIG_STATE(reg) == ONIG_STATE_NORMAL) { onig_chain_reduce(from); - from->state++; + ONIG_STATE_INC(from); } } else { @@ -4587,18 +4662,20 @@ onig_clone(regex_t** to, regex_t* from) return ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT; THREAD_PASS; } - from->state++; /* increment as search counter */ + ONIG_STATE_INC(from); } +#endif /* USE_MULTI_THREAD_SYSTEM */ - r = onig_alloc_init(®, ONIG_OPTION_NONE, from->enc, ONIG_SYNTAX_DEFAULT); + r = onig_alloc_init(®, ONIG_OPTION_NONE, ONIGENC_AMBIGUOUS_MATCH_DEFAULT, + from->enc, ONIG_SYNTAX_DEFAULT); if (r != 0) { - from->state--; + ONIG_STATE_DEC(from); return r; } xmemcpy(reg, from, sizeof(onig_t)); - reg->state = ONIG_STATE_NORMAL; reg->chain = (regex_t* )NULL; + reg->state = ONIG_STATE_NORMAL; if (from->p) { reg->p = (UChar* )xmalloc(reg->alloc); @@ -4631,12 +4708,12 @@ onig_clone(regex_t** to, regex_t* from) reg->name_table = names_clone(from); /* names_clone is not implemented */ #endif - from->state--; + ONIG_STATE_DEC(from); *to = reg; return 0; mem_error: - from->state--; + ONIG_STATE_DEC(from); return ONIGERR_MEMORY; } #endif @@ -4649,7 +4726,7 @@ static void print_tree P_((FILE* f, Node* node)); #endif extern int -onig_compile(regex_t* reg, UChar* pattern, UChar* pattern_end, +onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end, OnigErrorInfo* einfo) { #define COMPILE_INIT_SIZE 20 @@ -4800,7 +4877,7 @@ onig_compile(regex_t* reg, UChar* pattern, UChar* pattern_end, } extern int -onig_recompile(regex_t* reg, UChar* pattern, UChar* pattern_end, +onig_recompile(regex_t* reg, const UChar* pattern, const UChar* pattern_end, OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax, OnigErrorInfo* einfo) { @@ -4821,8 +4898,8 @@ onig_recompile(regex_t* reg, UChar* pattern, UChar* pattern_end, static int onig_inited = 0; extern int -onig_alloc_init(regex_t** reg, OnigOptionType option, OnigEncoding enc, - OnigSyntaxType* syntax) +onig_alloc_init(regex_t** reg, OnigOptionType option, OnigAmbigType ambig_flag, + OnigEncoding enc, OnigSyntaxType* syntax) { if (! onig_inited) onig_init(); @@ -4832,6 +4909,7 @@ onig_alloc_init(regex_t** reg, OnigOptionType option, OnigEncoding enc, *reg = (regex_t* )xmalloc(sizeof(regex_t)); if (IS_NULL(*reg)) return ONIGERR_MEMORY; + (*reg)->state = ONIG_STATE_MODIFY; if ((option & ONIG_OPTION_NEGATE_SINGLELINE) != 0) { option |= syntax->options; @@ -4840,7 +4918,6 @@ onig_alloc_init(regex_t** reg, OnigOptionType option, OnigEncoding enc, else option |= syntax->options; - (*reg)->state = ONIG_STATE_NORMAL; (*reg)->enc = enc; (*reg)->options = option; (*reg)->syntax = syntax; @@ -4855,11 +4932,14 @@ onig_alloc_init(regex_t** reg, OnigOptionType option, OnigEncoding enc, (*reg)->used = 0; (*reg)->name_table = (void* )NULL; + (*reg)->ambig_flag = ambig_flag; + (*reg)->ambig_flag &= ONIGENC_SUPPORT_AMBIG_FLAG(enc); + return 0; } extern int -onig_new(regex_t** reg, UChar* pattern, UChar* pattern_end, +onig_new(regex_t** reg, const UChar* pattern, const UChar* pattern_end, OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax, OnigErrorInfo* einfo) { @@ -4867,7 +4947,8 @@ onig_new(regex_t** reg, UChar* pattern, UChar* pattern_end, if (IS_NOT_NULL(einfo)) einfo->par = (UChar* )NULL; - r = onig_alloc_init(reg, option, enc, syntax); + r = onig_alloc_init(reg, option, ONIGENC_AMBIGUOUS_MATCH_DEFAULT, + enc, syntax); if (r) return r; r = onig_compile(*reg, pattern, pattern_end, einfo); @@ -4899,9 +4980,14 @@ onig_init() return 0; } + extern int onig_end() { + extern int onig_free_shared_cclass_table(); + + THREAD_ATOMIC_START; + #ifdef ONIG_DEBUG_STATISTICS onig_print_statistics(stderr); #endif @@ -4910,7 +4996,13 @@ onig_end() onig_free_node_list(); #endif +#ifdef USE_SHARED_CCLASS_TABLE + onig_free_shared_cclass_table(); +#endif + onig_inited = 0; + + THREAD_ATOMIC_END; return 0; } @@ -4940,6 +5032,7 @@ OnigOpInfoType OnigOpInfo[] = { { OP_CCLASS_NOT, "cclass-not", ARG_SPECIAL }, { OP_CCLASS_MB_NOT, "cclass-mb-not", ARG_SPECIAL }, { OP_CCLASS_MIX_NOT, "cclass-mix-not", ARG_SPECIAL }, + { OP_CCLASS_NODE, "cclass-node", ARG_SPECIAL }, { OP_ANYCHAR, "anychar", ARG_NON }, { OP_ANYCHAR_ML, "anychar-ml", ARG_NON }, { OP_ANYCHAR_STAR, "anychar*", ARG_NON }, @@ -4964,7 +5057,7 @@ OnigOpInfoType OnigOpInfo[] = { { OP_BACKREF2, "backref2", ARG_NON }, { OP_BACKREF3, "backref3", ARG_NON }, { OP_BACKREFN, "backrefn", ARG_MEMNUM }, - { OP_BACKREFN_IC, "backrefn-ic", ARG_MEMNUM }, + { OP_BACKREFN_IC, "backrefn-ic", ARG_SPECIAL }, { OP_BACKREF_MULTI, "backref_multi", ARG_SPECIAL }, { OP_BACKREF_MULTI_IC, "backref_multi-ic",ARG_SPECIAL }, { OP_MEMORY_START_PUSH, "mem-start-push", ARG_MEMNUM }, @@ -4985,6 +5078,8 @@ OnigOpInfoType OnigOpInfo[] = { { OP_REPEAT_NG, "repeat-ng", ARG_SPECIAL }, { OP_REPEAT_INC, "repeat-inc", ARG_MEMNUM }, { OP_REPEAT_INC_NG, "repeat-inc-ng", ARG_MEMNUM }, + { OP_REPEAT_INC_SG, "repeat-inc-sg", ARG_MEMNUM }, + { OP_REPEAT_INC_NG_SG, "repeat-inc-ng-sg", ARG_MEMNUM }, { OP_NULL_CHECK_START, "null-check-start",ARG_MEMNUM }, { OP_NULL_CHECK_END, "null-check-end", ARG_MEMNUM }, { OP_NULL_CHECK_END_MEMST,"null-check-end-memst", ARG_MEMNUM }, @@ -5051,7 +5146,8 @@ p_len_string(FILE* f, LengthType len, int mb_len, UChar* s) } extern void -onig_print_compiled_byte_code(FILE* f, UChar* bp, UChar** nextp) +onig_print_compiled_byte_code(FILE* f, UChar* bp, UChar** nextp, + OnigEncoding enc) { int i, n, arg_type; RelAddrType addr; @@ -5068,8 +5164,7 @@ onig_print_compiled_byte_code(FILE* f, UChar* bp, UChar** nextp) case ARG_NON: break; case ARG_RELADDR: - addr = *((RelAddrType* )bp); - bp += SIZE_RELADDR; + GET_RELADDR_INC(addr, bp); fprintf(f, ":(%d)", addr); break; case ARG_ABSADDR: @@ -5143,7 +5238,9 @@ onig_print_compiled_byte_code(FILE* f, UChar* bp, UChar** nextp) break; case OP_EXACT1_IC: - p_string(f, 1, bp++); + len = enc_len(enc, bp); + p_string(f, len, bp); + bp += len; break; case OP_EXACTN_IC: GET_LENGTH_INC(len, bp); @@ -5189,8 +5286,24 @@ onig_print_compiled_byte_code(FILE* f, UChar* bp, UChar** nextp) fprintf(f, ":%d:%d:%d", n, (int )code, len); break; - case OP_BACKREF_MULTI: + case OP_CCLASS_NODE: + { + CClassNode *cc; + + GET_POINTER_INC(cc, bp); + n = bitset_on_num(cc->bs); + fprintf(f, ":%u:%d", (unsigned int )cc, n); + } + break; + + case OP_BACKREFN_IC: + mem = *((MemNumType* )bp); + bp += SIZE_MEMNUM; + fprintf(f, ":%d", mem); + break; + case OP_BACKREF_MULTI_IC: + case OP_BACKREF_MULTI: fputs(" ", f); GET_LENGTH_INC(len, bp); for (i = 0; i < len; i++) { @@ -5258,7 +5371,7 @@ print_compiled_byte_code_list(FILE* f, regex_t* reg) else fputs(" ", f); } - onig_print_compiled_byte_code(f, bp, &bp); + onig_print_compiled_byte_code(f, bp, &bp, reg->enc); } fprintf(f, "\n"); @@ -5310,7 +5423,7 @@ print_indent_tree(FILE* f, Node* node, int indent) case N_CCLASS: fprintf(f, "", (int )node); - if (NCCLASS(node).not) fputs(" not", f); + if (IS_CCLASS_NOT(&NCCLASS(node))) fputs(" not", f); if (NCCLASS(node).mbuf) { BBuf* bbuf = NCCLASS(node).mbuf; for (i = 0; i < bbuf->used; i++) { @@ -5318,12 +5431,6 @@ print_indent_tree(FILE* f, Node* node, int indent) fprintf(f, "%0x", bbuf->p[i]); } } -#if 0 - fprintf(f, "\n"); - Indent(f, indent); - for (i = 0; i < SINGLE_BYTE_SIZE; i++) - fputc((BITSET_AT(NCCLASS(node).bs, i) ? '1' : '0'), f); -#endif break; case N_CTYPE: diff --git a/ext/mbstring/oniguruma/regenc.c b/ext/mbstring/oniguruma/regenc.c index 21598ca7c7d0..a767ca60b6af 100644 --- a/ext/mbstring/oniguruma/regenc.c +++ b/ext/mbstring/oniguruma/regenc.c @@ -1,11 +1,33 @@ /********************************************************************** - regenc.c - Oniguruma (regular expression library) - - Copyright (C) 2003-2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ -#include "regenc.h" +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "regint.h" OnigEncoding OnigEncDefaultCharEncoding = ONIG_ENCODING_INIT_DEFAULT; @@ -29,33 +51,33 @@ onigenc_set_default_encoding(OnigEncoding enc) } extern UChar* -onigenc_get_right_adjust_char_head(OnigEncoding enc, UChar* start, UChar* s) +onigenc_get_right_adjust_char_head(OnigEncoding enc, const UChar* start, const UChar* s) { UChar* p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s); if (p < s) { - p += enc_len(enc, *p); + p += enc_len(enc, p); } return p; } extern UChar* onigenc_get_right_adjust_char_head_with_prev(OnigEncoding enc, - UChar* start, UChar* s, UChar** prev) + const UChar* start, const UChar* s, const UChar** prev) { UChar* p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s); if (p < s) { - if (prev) *prev = p; - p += enc_len(enc, *p); + if (prev) *prev = (const UChar* )p; + p += enc_len(enc, p); } else { - if (prev) *prev = (UChar* )NULL; /* Sorry */ + if (prev) *prev = (const UChar* )NULL; /* Sorry */ } return p; } extern UChar* -onigenc_get_prev_char_head(OnigEncoding enc, UChar* start, UChar* s) +onigenc_get_prev_char_head(OnigEncoding enc, const UChar* start, const UChar* s) { if (s <= start) return (UChar* )NULL; @@ -64,7 +86,7 @@ onigenc_get_prev_char_head(OnigEncoding enc, UChar* start, UChar* s) } extern UChar* -onigenc_step_back(OnigEncoding enc, UChar* start, UChar* s, int n) +onigenc_step_back(OnigEncoding enc, const UChar* start, const UChar* s, int n) { while (ONIG_IS_NOT_NULL(s) && n-- > 0) { if (s <= start) @@ -72,20 +94,127 @@ onigenc_step_back(OnigEncoding enc, UChar* start, UChar* s, int n) s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s - 1); } - return s; + return (UChar* )s; } +extern UChar* +onigenc_step(OnigEncoding enc, const UChar* p, const UChar* end, int n) +{ + UChar* q = (UChar* )p; + while (n-- > 0) { + q += ONIGENC_MBC_ENC_LEN(enc, q); + } + return (q <= end ? q : NULL); +} + +extern int +onigenc_strlen(OnigEncoding enc, const UChar* p, const UChar* end) +{ + int n = 0; + UChar* q = (UChar* )p; + + while (q < end) { + q += ONIGENC_MBC_ENC_LEN(enc, q); + n++; + } + return n; +} + +extern int +onigenc_strlen_null(OnigEncoding enc, const UChar* s) +{ + int n = 0; + UChar* p = (UChar* )s; + + while (1) { + if (*p == '\0') { + UChar* q; + int len = ONIGENC_MBC_MINLEN(enc); + + if (len == 1) return n; + q = p + 1; + while (len > 1) { + if (*q != '\0') break; + q++; + len--; + } + if (len == 1) return n; + } + p += ONIGENC_MBC_ENC_LEN(enc, p); + n++; + } +} + +extern int +onigenc_str_bytelen_null(OnigEncoding enc, const UChar* s) +{ + UChar* start = (UChar* )s; + UChar* p = (UChar* )s; + + while (1) { + if (*p == '\0') { + UChar* q; + int len = ONIGENC_MBC_MINLEN(enc); + + if (len == 1) return (int )(p - start); + q = p + 1; + while (len > 1) { + if (*q != '\0') break; + q++; + len--; + } + if (len == 1) return (int )(p - start); + } + p += ONIGENC_MBC_ENC_LEN(enc, p); + } +} #ifndef ONIG_RUBY_M17N #ifndef NOT_RUBY + #define USE_APPLICATION_TO_LOWER_CASE_TABLE + +unsigned short OnigEnc_Unicode_ISO_8859_1_CtypeTable[256] = { + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x228c, 0x2289, 0x2288, 0x2288, 0x2288, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2284, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, + 0x38b0, 0x38b0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x21a0, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x31a0, + 0x21a0, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x2008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0288, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0284, 0x01a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, + 0x00a0, 0x00a0, 0x10e2, 0x01a0, 0x00a0, 0x00a8, 0x00a0, 0x00a0, + 0x00a0, 0x00a0, 0x10a0, 0x10a0, 0x00a0, 0x10e2, 0x00a0, 0x01a0, + 0x00a0, 0x10a0, 0x10e2, 0x01a0, 0x10a0, 0x10a0, 0x10a0, 0x01a0, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x00a0, + 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x14a2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x00a0, + 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2, 0x10e2 +}; #endif -UChar* OnigEncAsciiToLowerCaseTable = (UChar* )0; +const UChar* OnigEncAsciiToLowerCaseTable = (const UChar* )0; #ifndef USE_APPLICATION_TO_LOWER_CASE_TABLE -static UChar BuiltInAsciiToLowerCaseTable[] = { +static const UChar BuiltInAsciiToLowerCaseTable[] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', @@ -121,23 +250,61 @@ static UChar BuiltInAsciiToLowerCaseTable[] = { }; #endif /* not USE_APPLICATION_TO_LOWER_CASE_TABLE */ +#ifdef USE_UPPER_CASE_TABLE +UChar OnigEncAsciiToUpperCaseTable[256] = { + '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', + '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', + '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', + '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', + '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', + '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', + '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', + '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', + '\100', '\101', '\102', '\103', '\104', '\105', '\106', '\107', + '\110', '\111', '\112', '\113', '\114', '\115', '\116', '\117', + '\120', '\121', '\122', '\123', '\124', '\125', '\126', '\127', + '\130', '\131', '\132', '\133', '\134', '\135', '\136', '\137', + '\140', '\101', '\102', '\103', '\104', '\105', '\106', '\107', + '\110', '\111', '\112', '\113', '\114', '\115', '\116', '\117', + '\120', '\121', '\122', '\123', '\124', '\125', '\126', '\127', + '\130', '\131', '\132', '\173', '\174', '\175', '\176', '\177', + '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', + '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', + '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', + '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', + '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', + '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', + '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', + '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', + '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', + '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', + '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', + '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', + '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', + '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', + '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', + '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', +}; +#endif + unsigned short OnigEncAsciiCtypeTable[256] = { - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1106, 0x1104, 0x1104, 0x1104, 0x1104, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, 0x1004, - 0x1142, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, 0x1c58, - 0x1c58, 0x1c58, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x10d0, - 0x10d0, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1e51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, 0x1a51, - 0x1a51, 0x1a51, 0x1a51, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x18d0, - 0x10d0, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1c71, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, 0x1871, - 0x1871, 0x1871, 0x1871, 0x10d0, 0x10d0, 0x10d0, 0x10d0, 0x1004, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x220c, 0x2209, 0x2208, 0x2208, 0x2208, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, 0x2008, + 0x2284, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, 0x38b0, + 0x38b0, 0x38b0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a0, + 0x21a0, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, + 0x34a2, 0x34a2, 0x34a2, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x31a0, + 0x21a0, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x38e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, + 0x30e2, 0x30e2, 0x30e2, 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x2008, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, @@ -156,10 +323,82 @@ unsigned short OnigEncAsciiCtypeTable[256] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; +UChar OnigEncISO_8859_1_ToLowerCaseTable[256] = { + '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', + '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', + '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', + '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', + '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', + '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', + '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', + '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', + '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', + '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', + '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', + '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', + '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', + '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', + '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', + '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', + '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', + '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', + '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', + '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', + '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', + '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', + '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', + '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', + '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', + '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', + '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\327', + '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\337', + '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', + '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', + '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', + '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377' +}; + +#ifdef USE_UPPER_CASE_TABLE +UChar OnigEncISO_8859_1_ToUpperCaseTable[256] = { + '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', + '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', + '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', + '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', + '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', + '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', + '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', + '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', + '\100', '\101', '\102', '\103', '\104', '\105', '\106', '\107', + '\110', '\111', '\112', '\113', '\114', '\115', '\116', '\117', + '\120', '\121', '\122', '\123', '\124', '\125', '\126', '\127', + '\130', '\131', '\132', '\133', '\134', '\135', '\136', '\137', + '\140', '\101', '\102', '\103', '\104', '\105', '\106', '\107', + '\110', '\111', '\112', '\113', '\114', '\115', '\116', '\117', + '\120', '\121', '\122', '\123', '\124', '\125', '\126', '\127', + '\130', '\131', '\132', '\173', '\174', '\175', '\176', '\177', + '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', + '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', + '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', + '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', + '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', + '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', + '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', + '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', + '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', + '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', + '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', + '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', + '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', + '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', + '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\367', + '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\377', +}; +#endif + extern void -onigenc_set_default_caseconv_table(UChar* table) +onigenc_set_default_caseconv_table(const UChar* table) { - if (table == (UChar* )0) { + if (table == (const UChar* )0) { #ifndef USE_APPLICATION_TO_LOWER_CASE_TABLE table = BuiltInAsciiToLowerCaseTable; #else @@ -173,47 +412,240 @@ onigenc_set_default_caseconv_table(UChar* table) } extern UChar* -onigenc_get_left_adjust_char_head(OnigEncoding enc, UChar* start, UChar* s) +onigenc_get_left_adjust_char_head(OnigEncoding enc, const UChar* start, const UChar* s) { return ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s); } +OnigPairAmbigCodes OnigAsciiPairAmbigCodes[] = { + { 0x41, 0x61 }, + { 0x42, 0x62 }, + { 0x43, 0x63 }, + { 0x44, 0x64 }, + { 0x45, 0x65 }, + { 0x46, 0x66 }, + { 0x47, 0x67 }, + { 0x48, 0x68 }, + { 0x49, 0x69 }, + { 0x4a, 0x6a }, + { 0x4b, 0x6b }, + { 0x4c, 0x6c }, + { 0x4d, 0x6d }, + { 0x4e, 0x6e }, + { 0x4f, 0x6f }, + { 0x50, 0x70 }, + { 0x51, 0x71 }, + { 0x52, 0x72 }, + { 0x53, 0x73 }, + { 0x54, 0x74 }, + { 0x55, 0x75 }, + { 0x56, 0x76 }, + { 0x57, 0x77 }, + { 0x58, 0x78 }, + { 0x59, 0x79 }, + { 0x5a, 0x7a }, + + { 0x61, 0x41 }, + { 0x62, 0x42 }, + { 0x63, 0x43 }, + { 0x64, 0x44 }, + { 0x65, 0x45 }, + { 0x66, 0x46 }, + { 0x67, 0x47 }, + { 0x68, 0x48 }, + { 0x69, 0x49 }, + { 0x6a, 0x4a }, + { 0x6b, 0x4b }, + { 0x6c, 0x4c }, + { 0x6d, 0x4d }, + { 0x6e, 0x4e }, + { 0x6f, 0x4f }, + { 0x70, 0x50 }, + { 0x71, 0x51 }, + { 0x72, 0x52 }, + { 0x73, 0x53 }, + { 0x74, 0x54 }, + { 0x75, 0x55 }, + { 0x76, 0x56 }, + { 0x77, 0x57 }, + { 0x78, 0x58 }, + { 0x79, 0x59 }, + { 0x7a, 0x5a } +}; + extern int -onigenc_nothing_get_all_fold_match_code(OnigCodePoint** codes) +onigenc_ascii_get_all_pair_ambig_codes(OnigAmbigType flag, + OnigPairAmbigCodes** ccs) +{ + if (flag == ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) { + *ccs = OnigAsciiPairAmbigCodes; + return (sizeof(OnigAsciiPairAmbigCodes) / sizeof(OnigPairAmbigCodes)); + } + else { + return 0; + } +} + +extern int +onigenc_nothing_get_all_comp_ambig_codes(OnigAmbigType flag, + OnigCompAmbigCodes** ccs) { return 0; } extern int -onigenc_nothing_get_fold_match_info(UChar* p, UChar* end, - OnigEncFoldMatchInfo** info) +onigenc_iso_8859_1_get_all_pair_ambig_codes(OnigAmbigType flag, + OnigPairAmbigCodes** ccs) +{ + static OnigPairAmbigCodes cc[] = { + { 0xc0, 0xe0 }, + { 0xc1, 0xe1 }, + { 0xc2, 0xe2 }, + { 0xc3, 0xe3 }, + { 0xc4, 0xe4 }, + { 0xc5, 0xe5 }, + { 0xc6, 0xe6 }, + { 0xc7, 0xe7 }, + { 0xc8, 0xe8 }, + { 0xc9, 0xe9 }, + { 0xca, 0xea }, + { 0xcb, 0xeb }, + { 0xcc, 0xec }, + { 0xcd, 0xed }, + { 0xce, 0xee }, + { 0xcf, 0xef }, + + { 0xd0, 0xf0 }, + { 0xd1, 0xf1 }, + { 0xd2, 0xf2 }, + { 0xd3, 0xf3 }, + { 0xd4, 0xf4 }, + { 0xd5, 0xf5 }, + { 0xd6, 0xf6 }, + { 0xd8, 0xf8 }, + { 0xd9, 0xf9 }, + { 0xda, 0xfa }, + { 0xdb, 0xfb }, + { 0xdc, 0xfc }, + { 0xdd, 0xfd }, + { 0xde, 0xfe }, + + { 0xe0, 0xc0 }, + { 0xe1, 0xc1 }, + { 0xe2, 0xc2 }, + { 0xe3, 0xc3 }, + { 0xe4, 0xc4 }, + { 0xe5, 0xc5 }, + { 0xe6, 0xc6 }, + { 0xe7, 0xc7 }, + { 0xe8, 0xc8 }, + { 0xe9, 0xc9 }, + { 0xea, 0xca }, + { 0xeb, 0xcb }, + { 0xec, 0xcc }, + { 0xed, 0xcd }, + { 0xee, 0xce }, + { 0xef, 0xcf }, + + { 0xf0, 0xd0 }, + { 0xf1, 0xd1 }, + { 0xf2, 0xd2 }, + { 0xf3, 0xd3 }, + { 0xf4, 0xd4 }, + { 0xf5, 0xd5 }, + { 0xf6, 0xd6 }, + { 0xf8, 0xd8 }, + { 0xf9, 0xd9 }, + { 0xfa, 0xda }, + { 0xfb, 0xdb }, + { 0xfc, 0xdc }, + { 0xfd, 0xdd }, + { 0xfe, 0xde } + }; + + if (flag == ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) { + *ccs = OnigAsciiPairAmbigCodes; + return (sizeof(OnigAsciiPairAmbigCodes) / sizeof(OnigPairAmbigCodes)); + } + else if (flag == ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) { + *ccs = cc; + return sizeof(cc) / sizeof(OnigPairAmbigCodes); + } + else + return 0; +} + +extern int +onigenc_ess_tsett_get_all_comp_ambig_codes(OnigAmbigType flag, + OnigCompAmbigCodes** ccs) +{ + static OnigCompAmbigCodes folds[] = { + { 2, 0xdf, {{ 2, { 0x53, 0x53 } }, { 2, { 0x73, 0x73} } } } + }; + + if (flag == ONIGENC_AMBIGUOUS_MATCH_NONASCII_CASE) { + *ccs = folds; + return sizeof(folds) / sizeof(OnigCompAmbigCodes); + } + else + return 0; +} + +extern int +onigenc_not_support_get_ctype_code_range(int ctype, + OnigCodePoint* sbr[], OnigCodePoint* mbr[]) { - return -1; + return ONIG_NO_SUPPORT_CONFIG; } extern int -onigenc_nothing_get_ctype_code_range(int ctype, int* nsb, int* nmb, - OnigCodePointRange* sbr[], OnigCodePointRange* mbr[]) +onigenc_is_mbc_newline_0x0a(const UChar* p, const UChar* end) { - return -1; + if (p < end) { + if (*p == 0x0a) return 1; + } + return 0; } /* for single byte encodings */ extern int -onigenc_ascii_mbc_to_lower(UChar* p, UChar* lower) +onigenc_ascii_mbc_to_normalize(OnigAmbigType flag, const UChar** p, const UChar*end, + UChar* lower) { - *lower = ONIGENC_ASCII_CODE_TO_LOWER_CASE(*p); + if ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0) { + *lower = ONIGENC_ASCII_CODE_TO_LOWER_CASE(**p); + } + else { + *lower = **p; + } + + (*p)++; return 1; /* return byte length of converted char to lower */ } extern int -onigenc_ascii_mbc_is_case_ambig(UChar* p) +onigenc_ascii_is_mbc_ambiguous(OnigAmbigType flag, + const UChar** pp, const UChar* end) +{ + const UChar* p = *pp; + + (*pp)++; + if ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0) { + return ONIGENC_IS_ASCII_CODE_CASE_AMBIG(*p); + } + else { + return FALSE; + } +} + +extern int +onigenc_single_byte_mbc_enc_len(const UChar* p) { - return ONIGENC_IS_ASCII_CODE_CASE_AMBIG(*p); + return 1; } extern OnigCodePoint -onigenc_single_byte_mbc_to_code(UChar* p, UChar* end) +onigenc_single_byte_mbc_to_code(const UChar* p, const UChar* end) { return (OnigCodePoint )(*p); } @@ -238,26 +670,31 @@ onigenc_single_byte_code_to_mbc(OnigCodePoint code, UChar *buf) } extern UChar* -onigenc_single_byte_left_adjust_char_head(UChar* start, UChar* s) +onigenc_single_byte_left_adjust_char_head(const UChar* start, const UChar* s) { - return s; + return (UChar* )s; } extern int -onigenc_single_byte_is_allowed_reverse_match(UChar* s, UChar* end) +onigenc_always_true_is_allowed_reverse_match(const UChar* s, const UChar* end) { return TRUE; } +extern int +onigenc_always_false_is_allowed_reverse_match(const UChar* s, const UChar* end) +{ + return FALSE; +} + extern OnigCodePoint -onigenc_mbn_mbc_to_code(OnigEncoding enc, UChar* p, UChar* end) +onigenc_mbn_mbc_to_code(OnigEncoding enc, const UChar* p, const UChar* end) { int c, i, len; OnigCodePoint n; - c = *p++; - len = enc_len(enc, c); - n = c; + len = enc_len(enc, p); + n = (OnigCodePoint )(*p++); if (len == 1) return n; for (i = 1; i < len; i++) { @@ -269,33 +706,52 @@ onigenc_mbn_mbc_to_code(OnigEncoding enc, UChar* p, UChar* end) } extern int -onigenc_mbn_mbc_to_lower(OnigEncoding enc, UChar* p, UChar* lower) +onigenc_mbn_mbc_to_normalize(OnigEncoding enc, OnigAmbigType flag, + const UChar** pp, const UChar* end, UChar* lower) { int len; + const UChar *p = *pp; if (ONIGENC_IS_MBC_ASCII(p)) { - *lower = ONIGENC_ASCII_CODE_TO_LOWER_CASE(*p); + if ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0) { + *lower = ONIGENC_ASCII_CODE_TO_LOWER_CASE(*p); + } + else { + *lower = *p; + } + (*pp)++; return 1; } else { - len = enc_len(enc, *p); + len = enc_len(enc, p); if (lower != p) { - /* memcpy(lower, p, len); */ int i; for (i = 0; i < len; i++) { *lower++ = *p++; } } + (*pp) += len; return len; /* return byte length of converted to lower char */ } } extern int -onigenc_mbn_mbc_is_case_ambig(UChar* p) +onigenc_mbn_is_mbc_ambiguous(OnigEncoding enc, OnigAmbigType flag, + const UChar** pp, const UChar* end) { - if (ONIGENC_IS_MBC_ASCII(p)) - return ONIGENC_IS_ASCII_CODE_CASE_AMBIG(*p); + const UChar* p = *pp; + + if (ONIGENC_IS_MBC_ASCII(p)) { + (*pp)++; + if ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0) { + return ONIGENC_IS_ASCII_CODE_CASE_AMBIG(*p); + } + else { + return FALSE; + } + } + (*pp) += enc_len(enc, p); return FALSE; } @@ -360,8 +816,8 @@ onigenc_mb2_code_to_mbc(OnigEncoding enc, OnigCodePoint code, UChar *buf) *p++ = (UChar )(code & 0xff); #if 1 - if (enc_len(enc, buf[0]) != (p - buf)) - return ONIGERR_INVALID_WIDE_CHAR_VALUE; + if (enc_len(enc, buf) != (p - buf)) + return ONIGENCERR_INVALID_WIDE_CHAR_VALUE; #endif return p - buf; } @@ -383,23 +839,21 @@ onigenc_mb4_code_to_mbc(OnigEncoding enc, OnigCodePoint code, UChar *buf) *p++ = (UChar )(code & 0xff); #if 1 - if (enc_len(enc, buf[0]) != (p - buf)) - return ONIGERR_INVALID_WIDE_CHAR_VALUE; + if (enc_len(enc, buf) != (p - buf)) + return ONIGENCERR_INVALID_WIDE_CHAR_VALUE; #endif return p - buf; } extern int -onigenc_mb2_code_is_ctype(OnigEncoding enc, OnigCodePoint code, +onigenc_mb2_is_code_ctype(OnigEncoding enc, OnigCodePoint code, unsigned int ctype) { if ((ctype & ONIGENC_CTYPE_WORD) != 0) { if (code < 128) return ONIGENC_IS_ASCII_CODE_CTYPE(code, ctype); - else { - int first = onigenc_mb2_code_to_mbc_first(code); - return (enc_len(enc, first) > 1 ? TRUE : FALSE); - } + else + return (ONIGENC_CODE_TO_MBCLEN(enc, code) > 1 ? TRUE : FALSE); ctype &= ~ONIGENC_CTYPE_WORD; if (ctype == 0) return FALSE; @@ -412,16 +866,14 @@ onigenc_mb2_code_is_ctype(OnigEncoding enc, OnigCodePoint code, } extern int -onigenc_mb4_code_is_ctype(OnigEncoding enc, OnigCodePoint code, +onigenc_mb4_is_code_ctype(OnigEncoding enc, OnigCodePoint code, unsigned int ctype) { if ((ctype & ONIGENC_CTYPE_WORD) != 0) { if (code < 128) return ONIGENC_IS_ASCII_CODE_CTYPE(code, ctype); - else { - int first = onigenc_mb4_code_to_mbc_first(code); - return (enc_len(enc, first) > 1 ? TRUE : FALSE); - } + else + return (ONIGENC_CODE_TO_MBCLEN(enc, code) > 1 ? TRUE : FALSE); ctype &= ~ONIGENC_CTYPE_WORD; if (ctype == 0) return FALSE; @@ -434,39 +886,22 @@ onigenc_mb4_code_is_ctype(OnigEncoding enc, OnigCodePoint code, } extern int -onigenc_get_all_fold_match_code_ss_0xdf(OnigCodePoint** codes) +onigenc_with_ascii_strncmp(OnigEncoding enc, const UChar* p, const UChar* end, + const UChar* sascii /* ascii */, int n) { - static OnigCodePoint list[] = { 0xdf }; - *codes = list; - return 1; -} + int x, c; -extern int -onigenc_get_fold_match_info_ss_0xdf(UChar* p, UChar* end, - OnigEncFoldMatchInfo** info) -{ - /* German alphabet ess-tsett(U+00DF) */ - static OnigEncFoldMatchInfo ss = { - 3, - { 1, 2, 2 }, - { "\337", "ss", "SS" } /* 0337: 0xdf */ - }; + while (n-- > 0) { + if (p >= end) return (int )(*sascii); - if (p >= end) return -1; + c = (int )ONIGENC_MBC_TO_CODE(enc, p, end); + x = *sascii - c; + if (x) return x; - if (*p == 0xdf) { - *info = &ss; - return 1; - } - else if (p + 1 < end) { - if ((*p == 'S' && *(p+1) == 'S') || - (*p == 's' && *(p+1) == 's')) { - *info = &ss; - return 2; - } + sascii++; + p += enc_len(enc, p); } - - return -1; /* is not a fold string. */ + return 0; } #else /* ONIG_RUBY_M17N */ @@ -475,6 +910,10 @@ extern int onigenc_is_code_ctype(OnigEncoding enc, OnigCodePoint code, int ctype) { switch (ctype) { + case ONIGENC_CTYPE_NEWLINE: + if (code == 0x0a) return 1; + break; + case ONIGENC_CTYPE_ALPHA: return m17n_isalpha(enc, code); break; @@ -548,12 +987,22 @@ onigenc_mbc_to_lower(OnigEncoding enc, UChar* p, UChar* buf) } extern int -onigenc_mbc_is_case_ambig(OnigEncoding enc, UChar* p) +onigenc_is_mbc_ambiguous(OnigEncoding enc, OnigAmbigType flag, + UChar** pp, UChar* end) { - unsigned int c = m17n_codepoint(enc, p, p + enc_len(enc, *p)); + int len; + unsigned int c; + UChar* p = *pp; + + len = enc_len(enc, *p); + (*pp) += len; + c = m17n_codepoint(enc, p, p + len); + + if ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0) { + if (m17n_isupper(enc, c) || m17n_islower(enc, c)) + return TRUE; + } - if (m17n_isupper(enc, c) || m17n_islower(enc, c)) - return TRUE; return FALSE; } @@ -575,7 +1024,8 @@ onigenc_get_left_adjust_char_head(OnigEncoding enc, UChar* start, UChar* s) } extern int -onigenc_is_allowed_reverse_match(OnigEncoding enc, UChar* s, UChar* end) +onigenc_is_allowed_reverse_match(OnigEncoding enc, + const UChar* s, const UChar* end) { return ONIGENC_IS_SINGLEBYTE(enc); } diff --git a/ext/mbstring/oniguruma/regenc.h b/ext/mbstring/oniguruma/regenc.h index e0c6211d32dc..510455146ef2 100644 --- a/ext/mbstring/oniguruma/regenc.h +++ b/ext/mbstring/oniguruma/regenc.h @@ -1,12 +1,33 @@ +#ifndef REGENC_H +#define REGENC_H /********************************************************************** - regenc.h - Oniguruma (regular expression library) - - Copyright (C) 2003-2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ -#ifndef REGENC_H -#define REGENC_H +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ #ifndef RUBY_PLATFORM #include "config.h" @@ -26,15 +47,11 @@ #endif /* error codes */ -/* internal error */ -#define ONIGERR_MEMORY -5 -#define ONIGERR_TYPE_BUG -6 -/* syntax error [-400, -999] */ -#define ONIGERR_INVALID_WIDE_CHAR_VALUE -400 -#define ONIGERR_TOO_BIG_WIDE_CHAR_VALUE -401 - -#define ONIG_NEWLINE '\n' -#define ONIG_IS_NEWLINE(c) ((c) == ONIG_NEWLINE) +#define ONIGENCERR_MEMORY -5 +#define ONIGENCERR_TYPE_BUG -6 +#define ONIGENCERR_INVALID_WIDE_CHAR_VALUE -400 +#define ONIGENCERR_TOO_BIG_WIDE_CHAR_VALUE -401 + #define ONIG_IS_NULL(p) (((void*)(p)) == (void*)0) #define ONIG_IS_NOT_NULL(p) (((void*)(p)) != (void*)0) #define ONIG_CHECK_NULL_RETURN(p) if (ONIG_IS_NULL(p)) return NULL @@ -47,47 +64,79 @@ #else /* ONIG_RUBY_M17N */ +#define USE_UNICODE_FULL_RANGE_CTYPE + #define ONIG_ENCODING_INIT_DEFAULT ONIG_ENCODING_ASCII /* for encoding system implementation (internal) */ -ONIG_EXTERN int onigenc_nothing_get_all_fold_match_code P_((OnigCodePoint** codes)); -ONIG_EXTERN int onigenc_nothing_get_fold_match_info P_((UChar* p, UChar* end, OnigEncFoldMatchInfo** info)); -ONIG_EXTERN int onigenc_nothing_get_ctype_code_range P_((int ctype, int* nsb, int* nmb, OnigCodePointRange* sbr[], OnigCodePointRange* mbr[])); +ONIG_EXTERN int onigenc_ascii_get_all_pair_ambig_codes P_((OnigAmbigType flag, OnigPairAmbigCodes** acs)); +ONIG_EXTERN int onigenc_nothing_get_all_comp_ambig_codes P_((OnigAmbigType flag, OnigCompAmbigCodes** acs)); +ONIG_EXTERN int onigenc_iso_8859_1_get_all_pair_ambig_codes P_((OnigAmbigType flag, OnigPairAmbigCodes** acs)); +ONIG_EXTERN int onigenc_ess_tsett_get_all_comp_ambig_codes P_((OnigAmbigType flag, OnigCompAmbigCodes** acs)); +ONIG_EXTERN int onigenc_not_support_get_ctype_code_range P_((int ctype, OnigCodePoint* sbr[], OnigCodePoint* mbr[])); +ONIG_EXTERN int onigenc_is_mbc_newline_0x0a P_((const UChar* p, const UChar* end)); /* methods for single byte encoding */ -ONIG_EXTERN int onigenc_ascii_mbc_to_lower P_((UChar* p, UChar* lower)); -ONIG_EXTERN int onigenc_ascii_mbc_is_case_ambig P_((UChar* p)); -ONIG_EXTERN OnigCodePoint onigenc_single_byte_mbc_to_code P_((UChar* p, UChar* end)); +ONIG_EXTERN int onigenc_ascii_mbc_to_normalize P_((OnigAmbigType flag, const UChar** p, const UChar* end, UChar* lower)); +ONIG_EXTERN int onigenc_ascii_is_mbc_ambiguous P_((OnigAmbigType flag, const UChar** p, const UChar* end)); +ONIG_EXTERN int onigenc_single_byte_mbc_enc_len P_((const UChar* p)); +ONIG_EXTERN OnigCodePoint onigenc_single_byte_mbc_to_code P_((const UChar* p, const UChar* end)); ONIG_EXTERN int onigenc_single_byte_code_to_mbclen P_((OnigCodePoint code)); ONIG_EXTERN int onigenc_single_byte_code_to_mbc_first P_((OnigCodePoint code)); ONIG_EXTERN int onigenc_single_byte_code_to_mbc P_((OnigCodePoint code, UChar *buf)); -ONIG_EXTERN UChar* onigenc_single_byte_left_adjust_char_head P_((UChar* start, UChar* s)); -ONIG_EXTERN int onigenc_single_byte_is_allowed_reverse_match P_((UChar* s, UChar* end)); +ONIG_EXTERN UChar* onigenc_single_byte_left_adjust_char_head P_((const UChar* start, const UChar* s)); +ONIG_EXTERN int onigenc_always_true_is_allowed_reverse_match P_((const UChar* s, const UChar* end)); +ONIG_EXTERN int onigenc_always_false_is_allowed_reverse_match P_((const UChar* s, const UChar* end)); /* methods for multi byte encoding */ -ONIG_EXTERN OnigCodePoint onigenc_mbn_mbc_to_code P_((OnigEncoding enc, UChar* p, UChar* end)); -ONIG_EXTERN int onigenc_mbn_mbc_to_lower P_((OnigEncoding enc, UChar* p, UChar* lower)); -ONIG_EXTERN int onigenc_mbn_mbc_is_case_ambig P_((UChar* p)); +ONIG_EXTERN OnigCodePoint onigenc_mbn_mbc_to_code P_((OnigEncoding enc, const UChar* p, const UChar* end)); +ONIG_EXTERN int onigenc_mbn_mbc_to_normalize P_((OnigEncoding enc, OnigAmbigType flag, const UChar** p, const UChar* end, UChar* lower)); +ONIG_EXTERN int onigenc_mbn_is_mbc_ambiguous P_((OnigEncoding enc, OnigAmbigType flag, const UChar** p, const UChar* end)); ONIG_EXTERN int onigenc_mb2_code_to_mbclen P_((OnigCodePoint code)); ONIG_EXTERN int onigenc_mb2_code_to_mbc_first P_((OnigCodePoint code)); ONIG_EXTERN int onigenc_mb2_code_to_mbc P_((OnigEncoding enc, OnigCodePoint code, UChar *buf)); -ONIG_EXTERN int onigenc_mb2_code_is_ctype P_((OnigEncoding enc, OnigCodePoint code, unsigned int ctype)); +ONIG_EXTERN int onigenc_mb2_is_code_ctype P_((OnigEncoding enc, OnigCodePoint code, unsigned int ctype)); ONIG_EXTERN int onigenc_mb4_code_to_mbclen P_((OnigCodePoint code)); ONIG_EXTERN int onigenc_mb4_code_to_mbc_first P_((OnigCodePoint code)); ONIG_EXTERN int onigenc_mb4_code_to_mbc P_((OnigEncoding enc, OnigCodePoint code, UChar *buf)); -ONIG_EXTERN int onigenc_mb4_code_is_ctype P_((OnigEncoding enc, OnigCodePoint code, unsigned int ctype)); +ONIG_EXTERN int onigenc_mb4_is_code_ctype P_((OnigEncoding enc, OnigCodePoint code, unsigned int ctype)); ONIG_EXTERN int onigenc_get_all_fold_match_code_ss_0xdf P_((OnigCodePoint** codes)); -ONIG_EXTERN int onigenc_get_fold_match_info_ss_0xdf P_((UChar* p, UChar* end, OnigEncFoldMatchInfo** info)); + +/* in enc/unicode.c */ +ONIG_EXTERN int onigenc_unicode_is_code_ctype P_((OnigCodePoint code, unsigned int ctype)); +ONIG_EXTERN int onigenc_unicode_get_ctype_code_range P_((int ctype, OnigCodePoint* sbr[], OnigCodePoint* mbr[])); + + +#define ONIGENC_ISO_8859_1_TO_LOWER_CASE(c) \ + OnigEncISO_8859_1_ToLowerCaseTable[c] +#define ONIGENC_ISO_8859_1_TO_UPPER_CASE(c) \ + OnigEncISO_8859_1_ToUpperCaseTable[c] +#define ONIGENC_IS_UNICODE_ISO_8859_1_CTYPE(code,ctype) \ + ((OnigEnc_Unicode_ISO_8859_1_CtypeTable[code] & ctype) != 0) + +ONIG_EXTERN UChar OnigEncISO_8859_1_ToLowerCaseTable[]; +ONIG_EXTERN UChar OnigEncISO_8859_1_ToUpperCaseTable[]; +ONIG_EXTERN unsigned short OnigEnc_Unicode_ISO_8859_1_CtypeTable[]; +ONIG_EXTERN OnigPairAmbigCodes OnigAsciiPairAmbigCodes[]; #endif /* is not ONIG_RUBY_M17N */ +ONIG_EXTERN int +onigenc_with_ascii_strncmp P_((OnigEncoding enc, const UChar* p, const UChar* end, const UChar* sascii /* ascii */, int n)); +ONIG_EXTERN UChar* +onigenc_step P_((OnigEncoding enc, const UChar* p, const UChar* end, int n)); + +/* defined in regexec.c, but used in enc/xxx.c */ +extern int onig_is_in_code_range P_((const UChar* p, OnigCodePoint code)); ONIG_EXTERN OnigEncoding OnigEncDefaultCharEncoding; -ONIG_EXTERN UChar* OnigEncAsciiToLowerCaseTable; +ONIG_EXTERN const UChar* OnigEncAsciiToLowerCaseTable; +ONIG_EXTERN const UChar OnigEncAsciiToUpperCaseTable[]; ONIG_EXTERN unsigned short OnigEncAsciiCtypeTable[]; #define ONIGENC_ASCII_CODE_TO_LOWER_CASE(c) OnigEncAsciiToLowerCaseTable[c] +#define ONIGENC_ASCII_CODE_TO_UPPER_CASE(c) OnigEncAsciiToUpperCaseTable[c] #define ONIGENC_IS_ASCII_CODE_CTYPE(code,ctype) \ ((OnigEncAsciiCtypeTable[code] & ctype) != 0) #define ONIGENC_IS_ASCII_CODE_CASE_AMBIG(code) \ diff --git a/ext/mbstring/oniguruma/regerror.c b/ext/mbstring/oniguruma/regerror.c index 5a6c31b82ece..560b5e12c56c 100644 --- a/ext/mbstring/oniguruma/regerror.c +++ b/ext/mbstring/oniguruma/regerror.c @@ -1,10 +1,32 @@ /********************************************************************** - regerror.c - Oniguruma (regular expression library) - - Copyright (C) 2002-2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regint.h" #include /* for vsnprintf() */ @@ -56,8 +78,8 @@ onig_error_code_to_format(int code) p = "empty char-class"; break; case ONIGERR_PREMATURE_END_OF_CHAR_CLASS: p = "premature end of char-class"; break; - case ONIGERR_END_PATTERN_AT_BACKSLASH: - p = "end pattern at backslash"; break; + case ONIGERR_END_PATTERN_AT_ESCAPE: + p = "end pattern at escape"; break; case ONIGERR_END_PATTERN_AT_META: p = "end pattern at meta"; break; case ONIGERR_END_PATTERN_AT_CONTROL: @@ -145,7 +167,9 @@ onig_error_code_to_format(int code) case ONIGERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY: p = "group number is too big for capture history"; break; case ONIGERR_INVALID_CHAR_PROPERTY_NAME: - p = "invalid character property name"; break; + p = "invalid character property name {%n}"; break; + case ONIGERR_NOT_SUPPORTED_ENCODING_COMBINATION: + p = "not supported encoding combination"; break; case ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT: p = "over thread pass limit count"; break; @@ -184,6 +208,7 @@ onig_error_code_to_str(s, code, va_alist) case ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL: case ONIGERR_INVALID_GROUP_NAME: case ONIGERR_INVALID_CHAR_IN_GROUP_NAME: + case ONIGERR_INVALID_CHAR_PROPERTY_NAME: einfo = va_arg(vargs, OnigErrorInfo*); len = einfo->par_end - einfo->par; q = onig_error_code_to_format(code); @@ -218,7 +243,7 @@ onig_error_code_to_str(s, code, va_alist) default: q = onig_error_code_to_format(code); - len = strlen(q); + len = onigenc_str_bytelen_null(ONIG_ENCODING_ASCII, q); xmemcpy(s, q, len); s[len] = '\0'; break; @@ -245,7 +270,8 @@ onig_snprintf_with_pattern(buf, bufsize, enc, pat, pat_end, fmt, va_alist) #endif { int n, need, len; - UChar *p, *s; + UChar *p, *s, *bp; + char bs[6]; va_list args; va_init_list(args, fmt); @@ -256,29 +282,41 @@ onig_snprintf_with_pattern(buf, bufsize, enc, pat, pat_end, fmt, va_alist) if (n + need < bufsize) { strcat(buf, ": /"); - s = buf + strlen(buf); + s = buf + onigenc_str_bytelen_null(ONIG_ENCODING_ASCII, buf); p = pat; while (p < (UChar* )pat_end) { - if (*p == MC_ESC) { + if (*p == MC_ESC(enc)) { *s++ = *p++; - len = enc_len(enc, *p); + len = enc_len(enc, p); while (len-- > 0) *s++ = *p++; } else if (*p == '/') { - *s++ = MC_ESC; + *s++ = (unsigned char )MC_ESC(enc); *s++ = *p++; } - else if (ONIGENC_IS_MBC_HEAD(enc, *p)) { - len = enc_len(enc, *p); - while (len-- > 0) *s++ = *p++; + else if (ONIGENC_IS_MBC_HEAD(enc, p)) { + len = enc_len(enc, p); + if (ONIGENC_MBC_MINLEN(enc) == 1) { + while (len-- > 0) *s++ = *p++; + } + else { /* for UTF16 */ + int blen; + + while (len-- > 0) { + sprintf(bs, "\\%03o", *p++ & 0377); + blen = onigenc_str_bytelen_null(ONIG_ENCODING_ASCII, bs); + bp = bs; + while (blen-- > 0) *s++ = *bp++; + } + } } else if (!ONIGENC_IS_CODE_PRINT(enc, *p) && !ONIGENC_IS_CODE_SPACE(enc, *p)) { - char b[5]; - sprintf(b, "\\%03o", *p & 0377); - len = strlen(b); - while (len-- > 0) *s++ = *p++; + sprintf(bs, "\\%03o", *p++ & 0377); + len = onigenc_str_bytelen_null(ONIG_ENCODING_ASCII, bs); + bp = bs; + while (len-- > 0) *s++ = *bp++; } else { *s++ = *p++; diff --git a/ext/mbstring/oniguruma/regex.c b/ext/mbstring/oniguruma/regex.c deleted file mode 100644 index 2d79d000a8bb..000000000000 --- a/ext/mbstring/oniguruma/regex.c +++ /dev/null @@ -1,26 +0,0 @@ -/********************************************************************** - - regex.c - Oniguruma (regular expression library) - - Copyright (C) 2002-2004 K.Kosako (kosako@sofnec.co.jp) - -**********************************************************************/ -/* - * Source wrapper for Ruby. - */ -#include "regint.h" -#include "regex.h" - -#include "regparse.c" -#include "regcomp.c" -#include "regexec.c" -#include "regenc.c" -#include "reggnu.c" -#include "regerror.c" - -#ifndef ONIG_RUBY_M17N -#include "enc/ascii.c" -#include "enc/utf8.c" -#include "enc/euc_jp.c" -#include "enc/sjis.c" -#endif diff --git a/ext/mbstring/oniguruma/regexec.c b/ext/mbstring/oniguruma/regexec.c index 2ded602e15a6..2c082de423fc 100644 --- a/ext/mbstring/oniguruma/regexec.c +++ b/ext/mbstring/oniguruma/regexec.c @@ -1,53 +1,152 @@ /********************************************************************** - regexec.c - Oniguruma (regular expression library) - - Copyright (C) 2002-2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regint.h" +#ifdef USE_CAPTURE_HISTORY +static void history_tree_free(OnigCaptureTreeNode* node); + static void -region_list_clear(OnigRegion** list) +history_tree_clear(OnigCaptureTreeNode* node) { int i; - if (IS_NOT_NULL(list)) { - for (i = 1; i <= ONIG_MAX_CAPTURE_HISTORY_GROUP; i++) { - if (IS_NOT_NULL(list[i])) { - xfree(list[i]); - list[i] = (OnigRegion* )0; + if (IS_NOT_NULL(node)) { + for (i = 0; i < node->num_childs; i++) { + if (IS_NOT_NULL(node->childs[i])) { + history_tree_free(node->childs[i]); } } + for (i = 0; i < node->allocated; i++) { + node->childs[i] = (OnigCaptureTreeNode* )0; + } + node->num_childs = 0; + node->beg = ONIG_REGION_NOTPOS; + node->end = ONIG_REGION_NOTPOS; + node->group = -1; } } static void -region_list_free(OnigRegion* r) +history_tree_free(OnigCaptureTreeNode* node) +{ + history_tree_clear(node); + xfree(node); +} + +static void +history_root_free(OnigRegion* r) { - if (IS_NOT_NULL(r->list)) { - region_list_clear(r->list); - xfree(r->list); - r->list = (OnigRegion** )0; + if (IS_NOT_NULL(r->history_root)) { + history_tree_free(r->history_root); + r->history_root = (OnigCaptureTreeNode* )0; } } -static OnigRegion** -region_list_new() +static OnigCaptureTreeNode* +history_node_new() { - int i; - OnigRegion** list; + OnigCaptureTreeNode* node; + + node = (OnigCaptureTreeNode* )xmalloc(sizeof(OnigCaptureTreeNode)); + CHECK_NULL_RETURN(node); + node->childs = (OnigCaptureTreeNode** )0; + node->allocated = 0; + node->num_childs = 0; + node->group = -1; + node->beg = ONIG_REGION_NOTPOS; + node->end = ONIG_REGION_NOTPOS; + + return node; +} - list = (OnigRegion** )xmalloc(sizeof(OnigRegion*) - * (ONIG_MAX_CAPTURE_HISTORY_GROUP + 1)); - CHECK_NULL_RETURN(list); - for (i = 0; i <= ONIG_MAX_CAPTURE_HISTORY_GROUP; i++) { - list[i] = (OnigRegion* )0; +static int +history_tree_add_child(OnigCaptureTreeNode* parent, OnigCaptureTreeNode* child) +{ +#define HISTORY_TREE_INIT_ALLOC_SIZE 8 + + if (parent->num_childs >= parent->allocated) { + int n, i; + + if (IS_NULL(parent->childs)) { + n = HISTORY_TREE_INIT_ALLOC_SIZE; + parent->childs = + (OnigCaptureTreeNode** )xmalloc(sizeof(OnigCaptureTreeNode*) * n); + } + else { + n = parent->allocated * 2; + parent->childs = + (OnigCaptureTreeNode** )xrealloc(parent->childs, + sizeof(OnigCaptureTreeNode*) * n); + } + CHECK_NULL_RETURN_VAL(parent->childs, ONIGERR_MEMORY); + for (i = parent->allocated; i < n; i++) { + parent->childs[i] = (OnigCaptureTreeNode* )0; + } + parent->allocated = n; + } + + parent->childs[parent->num_childs] = child; + parent->num_childs++; + return 0; +} + +static OnigCaptureTreeNode* +history_tree_clone(OnigCaptureTreeNode* node) +{ + int i; + OnigCaptureTreeNode *clone, *child; + + clone = history_node_new(); + CHECK_NULL_RETURN(clone); + + clone->beg = node->beg; + clone->end = node->end; + for (i = 0; i < node->num_childs; i++) { + child = history_tree_clone(node->childs[i]); + if (IS_NULL(child)) { + history_tree_free(clone); + return (OnigCaptureTreeNode* )0; + } + history_tree_add_child(clone, child); } - return list; + return clone; } +extern OnigCaptureTreeNode* +onig_get_capture_tree(OnigRegion* region) +{ + return region->history_root; +} +#endif /* USE_CAPTURE_HISTORY */ + extern void onig_region_clear(OnigRegion* region) { @@ -56,14 +155,14 @@ onig_region_clear(OnigRegion* region) for (i = 0; i < region->num_regs; i++) { region->beg[i] = region->end[i] = ONIG_REGION_NOTPOS; } - region_list_clear(region->list); +#ifdef USE_CAPTURE_HISTORY + history_root_free(region); +#endif } extern int onig_region_resize(OnigRegion* region, int n) { - int i; - region->num_regs = n; if (n < ONIG_NREGION) @@ -88,92 +187,43 @@ onig_region_resize(OnigRegion* region, int n) region->allocated = n; } - for (i = 0; i < region->num_regs; i++) { - region->beg[i] = region->end[i] = ONIG_REGION_NOTPOS; - } - - if (IS_NOT_NULL(region->list)) - region_list_clear(region->list); - return 0; } -static int -region_ensure_size(OnigRegion* region, int n) +extern int +onig_region_resize_clear(OnigRegion* region, int n) { - int i, new_size; - - if (region->allocated >= n) - return 0; - - new_size = region->allocated; - if (new_size == 0) - new_size = ONIG_NREGION; - while (new_size < n) - new_size *= 2; - - if (region->allocated == 0) { - region->beg = (int* )xmalloc(new_size * sizeof(int)); - region->end = (int* )xmalloc(new_size * sizeof(int)); - if (region->beg == 0 || region->end == 0) - return ONIGERR_MEMORY; - - region->allocated = new_size; - } - else if (region->allocated < new_size) { - region->beg = (int* )xrealloc(region->beg, new_size * sizeof(int)); - region->end = (int* )xrealloc(region->end, new_size * sizeof(int)); - if (region->beg == 0 || region->end == 0) - return ONIGERR_MEMORY; - - region->allocated = new_size; - } - - for (i = region->num_regs; i < n; i++) { - region->beg[i] = region->end[i] = ONIG_REGION_NOTPOS; - } + int r; + + r = onig_region_resize(region, n); + if (r != 0) return r; + onig_region_clear(region); return 0; } - -static int -region_list_add_entry(OnigRegion* region, int group, int start, int end) + +extern int +onig_region_set(OnigRegion* region, int at, int beg, int end) { - int r, pos; - OnigRegion** list; - - if (group > ONIG_MAX_CAPTURE_HISTORY_GROUP) - return ONIGERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY; + if (at < 0) return ONIGERR_INVALID_ARGUMENT; - if (IS_NULL(region->list)) { - region->list = region_list_new(); - CHECK_NULL_RETURN_VAL(region->list, ONIGERR_MEMORY); + if (at >= region->allocated) { + int r = onig_region_resize(region, at + 1); + if (r < 0) return r; } - - list = region->list; - if (IS_NULL(list[group])) { - list[group] = onig_region_new(); - CHECK_NULL_RETURN_VAL(list[group], ONIGERR_MEMORY); - } - - r = region_ensure_size(list[group], list[group]->num_regs + 1); - if (r != 0) return r; - - pos = list[group]->num_regs; - list[group]->beg[pos] = start; - list[group]->end[pos] = end; - list[group]->num_regs++; - + + region->beg[at] = beg; + region->end[at] = end; return 0; } -static void +extern void onig_region_init(OnigRegion* region) { - region->num_regs = 0; - region->allocated = 0; - region->beg = (int* )0; - region->end = (int* )0; - region->list = (OnigRegion** )0; + region->num_regs = 0; + region->allocated = 0; + region->beg = (int* )0; + region->end = (int* )0; + region->history_root = (OnigCaptureTreeNode* )0; } extern OnigRegion* @@ -195,7 +245,9 @@ onig_region_free(OnigRegion* r, int free_self) if (r->end) xfree(r->end); r->allocated = 0; } - region_list_free(r); +#ifdef USE_CAPTURE_HISTORY + history_root_free(r); +#endif if (free_self) xfree(r); } } @@ -227,34 +279,19 @@ onig_region_copy(OnigRegion* to, OnigRegion* from) } to->num_regs = from->num_regs; - if (IS_NOT_NULL(from->list)) { - if (IS_NULL(to->list)) { - to->list = region_list_new(); - } - - for (i = 1; i <= ONIG_MAX_CAPTURE_HISTORY_GROUP; i++) { - if (IS_NOT_NULL(from->list[i])) { - if (IS_NULL(to->list[i])) - to->list[i] = onig_region_new(); +#ifdef USE_CAPTURE_HISTORY + history_root_free(to); - onig_region_copy(to->list[i], from->list[i]); - } - else { - if (IS_NOT_NULL(to->list[i])) { - xfree(to->list[i]); - to->list[i] = (OnigRegion* )0; - } - } - } + if (IS_NOT_NULL(from->history_root)) { + to->history_root = history_tree_clone(from->history_root); } - else - region_list_free(to); +#endif } /** stack **/ #define INVALID_STACK_INDEX -1 -typedef int StackIndex; +typedef long StackIndex; typedef struct _StackType { unsigned int type; @@ -324,7 +361,7 @@ typedef struct { int stack_n; OnigOptionType options; OnigRegion* region; - UChar* start; /* search start position (for \G: BEGIN_POSITION) */ + const UChar* start; /* search start position (for \G: BEGIN_POSITION) */ } MatchArg; #define MATCH_ARG_INIT(msa, arg_option, arg_region, arg_start) do {\ @@ -362,11 +399,26 @@ typedef struct { };\ } while(0) +static unsigned int MatchStackLimitSize = DEFAULT_MATCH_STACK_LIMIT_SIZE; + +extern unsigned int +onig_get_match_stack_limit_size(void) +{ + return MatchStackLimitSize; +} + +extern int +onig_set_match_stack_limit_size(unsigned int size) +{ + MatchStackLimitSize = size; + return 0; +} + static int stack_double(StackType** arg_stk_base, StackType** arg_stk_end, StackType** arg_stk, StackType* stk_alloc, MatchArg* msa) { - int n; + unsigned int n; StackType *x, *stk_base, *stk_end, *stk; stk_base = *arg_stk_base; @@ -385,7 +437,12 @@ stack_double(StackType** arg_stk_base, StackType** arg_stk_end, } else { n *= 2; - if (n > MATCH_STACK_LIMIT_SIZE) return ONIGERR_MATCH_STACK_LIMIT_OVER; + if (MatchStackLimitSize != 0 && n > MatchStackLimitSize) { + if ((unsigned int )(stk_end - stk_base) == MatchStackLimitSize) + return ONIGERR_MATCH_STACK_LIMIT_OVER; + else + n = MatchStackLimitSize; + } x = (StackType* )xrealloc(stk_base, sizeof(StackType) * n); if (IS_NULL(x)) { STACK_SAVE; @@ -831,24 +888,25 @@ stack_double(StackType** arg_stk_base, StackType** arg_stk_end, }\ } while(0) -#define STRING_CMP_IC(s1,ps2,len) do {\ - if (string_cmp_ic(encode, s1, ps2, len) == 0) \ +#define STRING_CMP_IC(ambig_flag,s1,ps2,len) do {\ + if (string_cmp_ic(encode, ambig_flag, s1, ps2, len) == 0) \ goto fail; \ } while(0) -static int string_cmp_ic(OnigEncoding enc, +static int string_cmp_ic(OnigEncoding enc, int ambig_flag, UChar* s1, UChar** ps2, int mblen) { - UChar buf1[ONIGENC_MBC_TO_LOWER_MAXLEN]; - UChar buf2[ONIGENC_MBC_TO_LOWER_MAXLEN]; - UChar *p1, *p2, *end, *s2; + UChar buf1[ONIGENC_MBC_NORMALIZE_MAXLEN]; + UChar buf2[ONIGENC_MBC_NORMALIZE_MAXLEN]; + UChar *p1, *p2, *end, *s2, *end2; int len1, len2; - s2 = *ps2; - end = s1 + mblen; + s2 = *ps2; + end = s1 + mblen; + end2 = s2 + mblen; while (s1 < end) { - len1 = ONIGENC_MBC_TO_LOWER(enc, s1, buf1); - len2 = ONIGENC_MBC_TO_LOWER(enc, s2, buf2); + len1 = ONIGENC_MBC_TO_NORMALIZE(enc, ambig_flag, &s1, end, buf1); + len2 = ONIGENC_MBC_TO_NORMALIZE(enc, ambig_flag, &s2, end2, buf2); if (len1 != len2) return 0; p1 = buf1; p2 = buf2; @@ -857,9 +915,6 @@ static int string_cmp_ic(OnigEncoding enc, p1++; p2++; } - - s1 += enc_len(enc, *s1); - s2 += enc_len(enc, *s2); } *ps2 = s2; @@ -875,8 +930,8 @@ static int string_cmp_ic(OnigEncoding enc, }\ } while(0) -#define STRING_CMP_VALUE_IC(s1,ps2,len,is_fail) do {\ - if (string_cmp_ic(encode, s1, ps2, len) == 0) \ +#define STRING_CMP_VALUE_IC(ambig_flag,s1,ps2,len,is_fail) do {\ + if (string_cmp_ic(encode, ambig_flag, s1, ps2, len) == 0) \ is_fail = 1; \ else \ is_fail = 0; \ @@ -891,6 +946,110 @@ static int string_cmp_ic(OnigEncoding enc, #define DATA_ENSURE_CHECK(n) (s + (n) <= end) +#ifdef USE_CAPTURE_HISTORY +static int +make_capture_history_tree(OnigCaptureTreeNode* node, StackType** kp, + StackType* stk_top, UChar* str, regex_t* reg) +{ + int n, r; + OnigCaptureTreeNode* child; + StackType* k = *kp; + + while (k < stk_top) { + if (k->type == STK_MEM_START) { + n = k->u.mem.num; + if (n <= ONIG_MAX_CAPTURE_HISTORY_GROUP && + BIT_STATUS_AT(reg->capture_history, n) != 0) { + child = history_node_new(); + CHECK_NULL_RETURN_VAL(child, ONIGERR_MEMORY); + child->group = n; + child->beg = (int )(k->u.mem.pstr - str); + r = history_tree_add_child(node, child); + if (r != 0) return r; + *kp = (k + 1); + r = make_capture_history_tree(child, kp, stk_top, str, reg); + if (r != 0) return r; + + k = *kp; + child->end = (int )(k->u.mem.pstr - str); + } + } + else if (k->type == STK_MEM_END) { + if (k->u.mem.num == node->group) { + node->end = (int )(k->u.mem.pstr - str); + *kp = k; + return 0; + } + } + k++; + } + + return 1; /* 1: root node ending. */ +} +#endif + +#ifdef RUBY_PLATFORM + +typedef struct { + int state; + regex_t* reg; + MatchArg* msa; + StackType* stk_base; +} TrapEnsureArg; + +static VALUE +trap_ensure(VALUE arg) +{ + TrapEnsureArg* ta = (TrapEnsureArg* )arg; + + if (ta->state == 0) { /* trap_exec() is not normal return */ + ONIG_STATE_DEC(ta->reg); + if (! IS_NULL(ta->msa->stack_p) && ta->stk_base != ta->msa->stack_p) + xfree(ta->stk_base); + + MATCH_ARG_FREE(*(ta->msa)); + } + + return Qnil; +} + +static VALUE +trap_exec(VALUE arg) +{ + TrapEnsureArg* ta; + + rb_trap_exec(); + + ta = (TrapEnsureArg* )arg; + ta->state = 1; /* normal return */ + return Qnil; +} + +extern void +onig_exec_trap(regex_t* reg, MatchArg* msa, StackType* stk_base) +{ + VALUE arg; + TrapEnsureArg ta; + + ta.state = 0; + ta.reg = reg; + ta.msa = msa; + ta.stk_base = stk_base; + arg = (VALUE )(&ta); + rb_ensure(trap_exec, arg, trap_ensure, arg); +} + +#define CHECK_INTERRUPT_IN_MATCH_AT do {\ + if (rb_trap_pending) {\ + if (! rb_prohibit_interrupt) {\ + onig_exec_trap(reg, msa, stk_base);\ + }\ + }\ +} while (0) +#else +#define CHECK_INTERRUPT_IN_MATCH_AT +#endif /* RUBY_PLATFORM */ + #ifdef ONIG_DEBUG_STATISTICS #define USE_TIMEOFDAY @@ -935,6 +1094,7 @@ static int MaxStackDepth = 0; } while (0) #ifdef RUBY_PLATFORM + /* * :nodoc: */ @@ -984,7 +1144,7 @@ onig_print_statistics(FILE* f) #endif extern int -onig_is_in_code_range(UChar* p, OnigCodePoint code) +onig_is_in_code_range(const UChar* p, OnigCodePoint code) { OnigCodePoint n, *data; OnigCodePoint low, high, x; @@ -1004,6 +1164,27 @@ onig_is_in_code_range(UChar* p, OnigCodePoint code) return ((low < n && code >= data[low * 2]) ? 1 : 0); } +static int +code_is_in_cclass_node(void* node, OnigCodePoint code, int enclen) +{ + unsigned int in_cc; + CClassNode* cc = (CClassNode* )node; + + if (enclen == 1) { + in_cc = BITSET_AT(cc->bs, code); + } + else { + UChar* p = ((BBuf* )(cc->mbuf))->p; + in_cc = onig_is_in_code_range(p, code); + } + + if (IS_CCLASS_NOT(cc)) { + return (in_cc ? 0 : 1); + } + else { + return (in_cc ? 1 : 0); + } +} /* matching region of POSIX API */ typedef int regoff_t; @@ -1016,7 +1197,7 @@ typedef struct { /* match data(str - end) from position (sstart). */ /* if sstart == str then set sprev to NULL. */ static int -match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, +match_at(regex_t* reg, const UChar* str, const UChar* end, const UChar* sstart, UChar* sprev, MatchArg* msa) { static UChar FinishCode[] = { OP_FINISH }; @@ -1027,18 +1208,18 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, RelAddrType addr; OnigOptionType option = reg->options; OnigEncoding encode = reg->enc; - int ignore_case; + OnigAmbigType ambig_flag = reg->ambig_flag; UChar *s, *q, *sbegin; UChar *p = reg->p; char *alloca_base; StackType *stk_alloc, *stk_base, *stk, *stk_end; StackType *stkp; /* used as any purpose. */ + StackIndex si; StackIndex *repeat_stk; StackIndex *mem_start_stk, *mem_end_stk; n = reg->num_repeat + reg->num_mem * 2; STACK_INIT(alloca_base, n, INIT_MATCH_STACK_SIZE); - ignore_case = IS_IGNORECASE(option); pop_level = reg->stack_pop_level; num_mem = reg->num_mem; repeat_stk = (StackIndex* )alloca_base; @@ -1062,7 +1243,7 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, STACK_PUSH_ENSURED(STK_ALT, FinishCode); /* bottom stack */ best_len = ONIG_MISMATCH; - s = sstart; + s = (UChar* )sstart; while (1) { #ifdef ONIG_DEBUG_MATCH { @@ -1071,7 +1252,7 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, fprintf(stderr, "%4d> \"", (int )(s - str)); bp = buf; for (i = 0, q = s; i < 7 && q < end; i++) { - len = enc_len(encode, *q); + len = enc_len(encode, q); while (len-- > 0) *bp++ = *q++; } if (q < end) { xmemcpy(bp, "...\"", 4); bp += 4; } @@ -1079,7 +1260,7 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, *bp = 0; fputs(buf, stderr); for (i = 0; i < 20 - (bp - buf); i++) fputc(' ', stderr); - onig_print_compiled_byte_code(stderr, p, NULL); + onig_print_compiled_byte_code(stderr, p, NULL, encode); fprintf(stderr, "\n"); } #endif @@ -1134,27 +1315,33 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, } } +#ifdef USE_CAPTURE_HISTORY if (reg->capture_history != 0) { - UChar *pstart, *pend; - for (i = 1; i <= ONIG_MAX_CAPTURE_HISTORY_GROUP; i++) { - if (BIT_STATUS_AT(reg->capture_history, i) != 0) { - stkp = stk_base; - do { - STACK_GET_MEM_RANGE(stkp, i, pstart, pend); - if (stkp < stk) { - int r; - r = region_list_add_entry(region, i, - pstart - str, pend - str); - if (r) { - STACK_SAVE; - return r; - } - } - stkp++; - } while (stkp < stk); - } - } - } /* list of captures */ + int r; + OnigCaptureTreeNode* node; + + if (IS_NULL(region->history_root)) { + region->history_root = node = history_node_new(); + CHECK_NULL_RETURN_VAL(node, ONIGERR_MEMORY); + } + else { + node = region->history_root; + history_tree_clear(node); + } + + node->group = 0; + node->beg = sstart - str; + node->end = s - str; + + stkp = stk_base; + r = make_capture_history_tree(region->history_root, &stkp, + stk, (UChar* )str, reg); + if (r < 0) { + best_len = r; /* error code */ + goto finish; + } + } +#endif /* USE_CAPTURE_HISTORY */ #ifdef USE_POSIX_REGION_OPTION } /* else IS_POSIX_REGION() */ #endif @@ -1171,10 +1358,9 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, goto fail; /* for retry */ } } - else { - /* default behavior: return first-matching result. */ - goto finish; - } + + /* default behavior: return first-matching result. */ + goto finish; break; case OP_EXACT1: STAT_OP_IN(OP_EXACT1); @@ -1192,14 +1378,31 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, case OP_EXACT1_IC: STAT_OP_IN(OP_EXACT1_IC); { int len; - UChar *q, lowbuf[ONIGENC_MBC_TO_LOWER_MAXLEN]; + UChar *q, *ss, *sp, lowbuf[ONIGENC_MBC_NORMALIZE_MAXLEN]; - len = ONIGENC_MBC_TO_LOWER(encode, s, lowbuf); - DATA_ENSURE(len); + DATA_ENSURE(1); + ss = s; + sp = p; + + exact1_ic_retry: + len = ONIGENC_MBC_TO_NORMALIZE(encode, ambig_flag, &s, end, lowbuf); + DATA_ENSURE(0); q = lowbuf; - s += enc_len(encode, *s); while (len-- > 0) { - if (*p != *q) goto fail; + if (*p != *q) { +#if 1 + if ((ambig_flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + ambig_flag &= ~ONIGENC_AMBIGUOUS_MATCH_COMPOUND; + s = ss; + p = sp; + goto exact1_ic_retry; + } + else + goto fail; +#else + goto fail; +#endif + } p++; q++; } } @@ -1276,19 +1479,36 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, case OP_EXACTN_IC: STAT_OP_IN(OP_EXACTN_IC); { int len; - UChar *q, *endp, lowbuf[ONIGENC_MBC_TO_LOWER_MAXLEN]; + UChar *ss, *sp, *q, *endp, lowbuf[ONIGENC_MBC_NORMALIZE_MAXLEN]; GET_LENGTH_INC(tlen, p); endp = p + tlen; while (p < endp) { - len = ONIGENC_MBC_TO_LOWER(encode, s, lowbuf); - DATA_ENSURE(len); sprev = s; - s += enc_len(encode, *s); + DATA_ENSURE(1); + ss = s; + sp = p; + + exactn_ic_retry: + len = ONIGENC_MBC_TO_NORMALIZE(encode, ambig_flag, &s, end, lowbuf); + DATA_ENSURE(0); q = lowbuf; while (len-- > 0) { - if (*p != *q) goto fail; + if (*p != *q) { +#if 1 + if ((ambig_flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + ambig_flag &= ~ONIGENC_AMBIGUOUS_MATCH_COMPOUND; + s = ss; + p = sp; + goto exactn_ic_retry; + } + else + goto fail; +#else + goto fail; +#endif + } p++; q++; } } @@ -1389,20 +1609,22 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, DATA_ENSURE(1); if (BITSET_AT(((BitSetRef )p), *s) == 0) goto fail; p += SIZE_BITSET; - s += enc_len(encode, *s); /* OP_CCLASS can match mb-code. \D, \S */ + s += enc_len(encode, s); /* OP_CCLASS can match mb-code. \D, \S */ STAT_OP_OUT; break; case OP_CCLASS_MB: STAT_OP_IN(OP_CCLASS_MB); - if (! ONIGENC_IS_MBC_HEAD(encode, *s)) goto fail; + if (! ONIGENC_IS_MBC_HEAD(encode, s)) goto fail; cclass_mb: GET_LENGTH_INC(tlen, p); { OnigCodePoint code; UChar *ss; - int mb_len = enc_len(encode, *s); + int mb_len; + DATA_ENSURE(1); + mb_len = enc_len(encode, s); DATA_ENSURE(mb_len); ss = s; s += mb_len; @@ -1422,7 +1644,7 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, case OP_CCLASS_MIX: STAT_OP_IN(OP_CCLASS_MIX); DATA_ENSURE(1); - if (ONIGENC_IS_MBC_HEAD(encode, *s)) { + if (ONIGENC_IS_MBC_HEAD(encode, s)) { p += SIZE_BITSET; goto cclass_mb; } @@ -1442,13 +1664,13 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, DATA_ENSURE(1); if (BITSET_AT(((BitSetRef )p), *s) != 0) goto fail; p += SIZE_BITSET; - s += enc_len(encode, *s); + s += enc_len(encode, s); STAT_OP_OUT; break; case OP_CCLASS_MB_NOT: STAT_OP_IN(OP_CCLASS_MB_NOT); - if (! ONIGENC_IS_MBC_HEAD(encode, *s)) { - DATA_ENSURE(1); + DATA_ENSURE(1); + if (! ONIGENC_IS_MBC_HEAD(encode, s)) { s++; GET_LENGTH_INC(tlen, p); p += tlen; @@ -1460,10 +1682,11 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, { OnigCodePoint code; UChar *ss; - int mb_len = enc_len(encode, *s); + int mb_len = enc_len(encode, s); if (s + mb_len > end) { - s = end; + DATA_ENSURE(1); + s = (UChar* )end; p += tlen; goto cc_mb_not_success; } @@ -1488,7 +1711,7 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, case OP_CCLASS_MIX_NOT: STAT_OP_IN(OP_CCLASS_MIX_NOT); DATA_ENSURE(1); - if (ONIGENC_IS_MBC_HEAD(encode, *s)) { + if (ONIGENC_IS_MBC_HEAD(encode, s)) { p += SIZE_BITSET; goto cclass_mb_not; } @@ -1504,22 +1727,36 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, STAT_OP_OUT; break; - case OP_ANYCHAR: STAT_OP_IN(OP_ANYCHAR); - n = enc_len(encode, *s); - if (n > 1) { - DATA_ENSURE(n); - s += n; - } - else { - DATA_ENSURE(1); - if (ONIG_IS_NEWLINE(*s)) goto fail; - s++; + case OP_CCLASS_NODE: STAT_OP_IN(OP_CCLASS_NODE); + { + OnigCodePoint code; + void *node; + int mb_len; + UChar *ss; + + DATA_ENSURE(1); + GET_POINTER_INC(node, p); + mb_len = enc_len(encode, s); + ss = s; + s += mb_len; + code = ONIGENC_MBC_TO_CODE(encode, ss, s); + if (code_is_in_cclass_node(node, code, mb_len) == 0) goto fail; } STAT_OP_OUT; break; + case OP_ANYCHAR: STAT_OP_IN(OP_ANYCHAR); + DATA_ENSURE(1); + n = enc_len(encode, s); + DATA_ENSURE(n); + if (ONIGENC_IS_MBC_NEWLINE(encode, s, end)) goto fail; + s += n; + STAT_OP_OUT; + break; + case OP_ANYCHAR_ML: STAT_OP_IN(OP_ANYCHAR_ML); - n = enc_len(encode, *s); + DATA_ENSURE(1); + n = enc_len(encode, s); DATA_ENSURE(n); s += n; STAT_OP_OUT; @@ -1528,17 +1765,11 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, case OP_ANYCHAR_STAR: STAT_OP_IN(OP_ANYCHAR_STAR); while (s < end) { STACK_PUSH_ALT(p, s, sprev); - n = enc_len(encode, *s); - if (n > 1) { - DATA_ENSURE(n); - sprev = s; - s += n; - } - else { - if (ONIG_IS_NEWLINE(*s)) goto fail; - sprev = s; - s++; - } + n = enc_len(encode, s); + DATA_ENSURE(n); + if (ONIGENC_IS_MBC_NEWLINE(encode, s, end)) goto fail; + sprev = s; + s += n; } STAT_OP_OUT; break; @@ -1546,7 +1777,7 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, case OP_ANYCHAR_ML_STAR: STAT_OP_IN(OP_ANYCHAR_ML_STAR); while (s < end) { STACK_PUSH_ALT(p, s, sprev); - n = enc_len(encode, *s); + n = enc_len(encode, s); if (n > 1) { DATA_ENSURE(n); sprev = s; @@ -1565,17 +1796,11 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, if (*p == *s) { STACK_PUSH_ALT(p + 1, s, sprev); } - n = enc_len(encode, *s); - if (n > 1) { - DATA_ENSURE(n); - sprev = s; - s += n; - } - else { - if (ONIG_IS_NEWLINE(*s)) goto fail; - sprev = s; - s++; - } + n = enc_len(encode, s); + DATA_ENSURE(n); + if (ONIGENC_IS_MBC_NEWLINE(encode, s, end)) goto fail; + sprev = s; + s += n; } p++; STAT_OP_OUT; @@ -1586,7 +1811,7 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, if (*p == *s) { STACK_PUSH_ALT(p + 1, s, sprev); } - n = enc_len(encode, *s); + n = enc_len(encode, s); if (n >1) { DATA_ENSURE(n); sprev = s; @@ -1606,7 +1831,7 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, if (! ONIGENC_IS_MBC_WORD(encode, s, end)) goto fail; - s += enc_len(encode, *s); + s += enc_len(encode, s); STAT_OP_OUT; break; @@ -1615,7 +1840,7 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, if (ONIGENC_IS_MBC_WORD(encode, s, end)) goto fail; - s += enc_len(encode, *s); + s += enc_len(encode, s); STAT_OP_OUT; break; @@ -1698,7 +1923,7 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, STAT_OP_OUT; continue; } - else if (ONIG_IS_NEWLINE(*sprev) && !ON_STR_END(s)) { + else if (ONIGENC_IS_MBC_NEWLINE(encode, sprev, end) && !ON_STR_END(s)) { STAT_OP_OUT; continue; } @@ -1708,7 +1933,7 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, case OP_END_LINE: STAT_OP_IN(OP_END_LINE); if (ON_STR_END(s)) { #ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE - if (IS_EMPTY_STR || !ONIG_IS_NEWLINE(*sprev)) { + if (IS_EMPTY_STR || !ONIGENC_IS_MBC_NEWLINE(encode, sprev, end)) { #endif if (IS_NOTEOL(msa->options)) goto fail; STAT_OP_OUT; @@ -1717,7 +1942,7 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, } #endif } - else if (ONIG_IS_NEWLINE(*s)) { + else if (ONIGENC_IS_MBC_NEWLINE(encode, s, end)) { STAT_OP_OUT; continue; } @@ -1727,7 +1952,7 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, case OP_SEMI_END_BUF: STAT_OP_IN(OP_SEMI_END_BUF); if (ON_STR_END(s)) { #ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE - if (IS_EMPTY_STR || !ONIG_IS_NEWLINE(*sprev)) { + if (IS_EMPTY_STR || !ONIGENC_IS_MBC_NEWLINE(encode, sprev, end)) { #endif if (IS_NOTEOL(msa->options)) goto fail; /* Is it needed? */ STAT_OP_OUT; @@ -1736,7 +1961,8 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, } #endif } - if (ONIG_IS_NEWLINE(*s) && ON_STR_END(s+1)) { + else if (ONIGENC_IS_MBC_NEWLINE(encode, s, end) && + ON_STR_END(s + enc_len(encode, s))) { STAT_OP_OUT; continue; } @@ -1845,7 +2071,7 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, DATA_ENSURE(n); sprev = s; STRING_CMP(pstart, s, n); - while (sprev + (len = enc_len(encode, *sprev)) < s) + while (sprev + (len = enc_len(encode, sprev)) < s) sprev += len; STAT_OP_OUT; @@ -1876,8 +2102,8 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, n = pend - pstart; DATA_ENSURE(n); sprev = s; - STRING_CMP_IC(pstart, &s, n); - while (sprev + (len = enc_len(encode, *sprev)) < s) + STRING_CMP_IC(ambig_flag, pstart, &s, n); + while (sprev + (len = enc_len(encode, sprev)) < s) sprev += len; STAT_OP_OUT; @@ -1912,7 +2138,7 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, STRING_CMP_VALUE(pstart, swork, n, is_fail); if (is_fail) continue; s = swork; - while (sprev + (len = enc_len(encode, *sprev)) < s) + while (sprev + (len = enc_len(encode, sprev)) < s) sprev += len; p += (SIZE_MEMNUM * (tlen - i - 1)); @@ -1948,10 +2174,10 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, DATA_ENSURE(n); sprev = s; swork = s; - STRING_CMP_VALUE_IC(pstart, &swork, n, is_fail); + STRING_CMP_VALUE_IC(ambig_flag, pstart, &swork, n, is_fail); if (is_fail) continue; s = swork; - while (sprev + (len = enc_len(encode, *sprev)) < s) + while (sprev + (len = enc_len(encode, sprev)) < s) sprev += len; p += (SIZE_MEMNUM * (tlen - i - 1)); @@ -1965,7 +2191,6 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, case OP_SET_OPTION_PUSH: STAT_OP_IN(OP_SET_OPTION_PUSH); GET_OPTION_INC(option, p); - ignore_case = IS_IGNORECASE(option); STACK_PUSH_ALT(p, s, sprev); p += SIZE_OP_SET_OPTION + SIZE_OP_FAIL; STAT_OP_OUT; @@ -1974,7 +2199,6 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, case OP_SET_OPTION: STAT_OP_IN(OP_SET_OPTION); GET_OPTION_INC(option, p); - ignore_case = IS_IGNORECASE(option); STAT_OP_OUT; continue; break; @@ -2006,6 +2230,8 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, break; case OP_REPEAT_INC: case OP_REPEAT_INC_NG: + case OP_REPEAT_INC_SG: + case OP_REPEAT_INC_NG_SG: p += SIZE_MEMNUM; break; default: @@ -2072,6 +2298,7 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, GET_RELADDR_INC(addr, p); p += addr; STAT_OP_OUT; + CHECK_INTERRUPT_IN_MATCH_AT; continue; break; @@ -2150,79 +2377,70 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, break; case OP_REPEAT_INC: STAT_OP_IN(OP_REPEAT_INC); - { - StackIndex si; + GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */ + si = repeat_stk[mem]; + stkp = STACK_AT(si); - GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */ -#ifdef USE_SUBEXP_CALL - if (reg->num_call > 0) { - STACK_GET_REPEAT(mem, stkp); - si = GET_STACK_INDEX(stkp); - } - else { - si = repeat_stk[mem]; - stkp = STACK_AT(si); - } -#else - si = repeat_stk[mem]; - stkp = STACK_AT(si); -#endif - stkp->u.repeat.count++; - if (stkp->u.repeat.count == reg->repeat_range[mem].upper) { - /* end of repeat. Nothing to do. */ - } - else if (stkp->u.repeat.count >= reg->repeat_range[mem].lower) { - STACK_PUSH_ALT(p, s, sprev); - p = stkp->u.repeat.pcode; - } - else { - p = stkp->u.repeat.pcode; - } - STACK_PUSH_REPEAT_INC(si); + repeat_inc: + stkp->u.repeat.count++; + if (stkp->u.repeat.count == reg->repeat_range[mem].upper) { + /* end of repeat. Nothing to do. */ } + else if (stkp->u.repeat.count >= reg->repeat_range[mem].lower) { + STACK_PUSH_ALT(p, s, sprev); + p = STACK_AT(si)->u.repeat.pcode; /* Don't use stkp after PUSH. */ + } + else { + p = stkp->u.repeat.pcode; + } + STACK_PUSH_REPEAT_INC(si); STAT_OP_OUT; + CHECK_INTERRUPT_IN_MATCH_AT; continue; break; - case OP_REPEAT_INC_NG: STAT_OP_IN(OP_REPEAT_INC_NG); - { - StackIndex si; - - GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */ -#ifdef USE_SUBEXP_CALL - if (reg->num_call > 0) { - STACK_GET_REPEAT(mem, stkp); - si = GET_STACK_INDEX(stkp); - } - else { - si = repeat_stk[mem]; - stkp = STACK_AT(si); - } -#else - si = repeat_stk[mem]; - stkp = STACK_AT(si); -#endif - stkp->u.repeat.count++; - if (stkp->u.repeat.count < reg->repeat_range[mem].upper) { - if (stkp->u.repeat.count >= reg->repeat_range[mem].lower) { - UChar* pcode = stkp->u.repeat.pcode; + case OP_REPEAT_INC_SG: STAT_OP_IN(OP_REPEAT_INC_SG); + GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */ + STACK_GET_REPEAT(mem, stkp); + si = GET_STACK_INDEX(stkp); + goto repeat_inc; + break; - STACK_PUSH_REPEAT_INC(si); - STACK_PUSH_ALT(pcode, s, sprev); - } - else { - p = stkp->u.repeat.pcode; - STACK_PUSH_REPEAT_INC(si); - } - } - else if (stkp->u.repeat.count == reg->repeat_range[mem].upper) { - STACK_PUSH_REPEAT_INC(si); - } - } - STAT_OP_OUT; + case OP_REPEAT_INC_NG: STAT_OP_IN(OP_REPEAT_INC_NG); + GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */ + si = repeat_stk[mem]; + stkp = STACK_AT(si); + + repeat_inc_ng: + stkp->u.repeat.count++; + if (stkp->u.repeat.count < reg->repeat_range[mem].upper || + IS_REPEAT_INFINITE(reg->repeat_range[mem].upper)) { + if (stkp->u.repeat.count >= reg->repeat_range[mem].lower) { + UChar* pcode = stkp->u.repeat.pcode; + + STACK_PUSH_REPEAT_INC(si); + STACK_PUSH_ALT(pcode, s, sprev); + } + else { + p = stkp->u.repeat.pcode; + STACK_PUSH_REPEAT_INC(si); + } + } + else if (stkp->u.repeat.count == reg->repeat_range[mem].upper) { + STACK_PUSH_REPEAT_INC(si); + } + STAT_OP_OUT; + CHECK_INTERRUPT_IN_MATCH_AT; continue; break; + case OP_REPEAT_INC_NG_SG: STAT_OP_IN(OP_REPEAT_INC_NG_SG); + GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */ + STACK_GET_REPEAT(mem, stkp); + si = GET_STACK_INDEX(stkp); + goto repeat_inc_ng; + break; + case OP_PUSH_POS: STAT_OP_IN(OP_PUSH_POS); STACK_PUSH_POS(s, sprev); STAT_OP_OUT; @@ -2265,9 +2483,9 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, case OP_LOOK_BEHIND: STAT_OP_IN(OP_LOOK_BEHIND); GET_LENGTH_INC(tlen, p); - s = ONIGENC_STEP_BACK(encode, str, s, (int )tlen); + s = (UChar* )ONIGENC_STEP_BACK(encode, str, s, (int )tlen); if (IS_NULL(s)) goto fail; - sprev = onigenc_get_prev_char_head(encode, str, s); + sprev = (UChar* )onigenc_get_prev_char_head(encode, str, s); STAT_OP_OUT; continue; break; @@ -2275,7 +2493,7 @@ match_at(regex_t* reg, UChar* str, UChar* end, UChar* sstart, case OP_PUSH_LOOK_BEHIND_NOT: STAT_OP_IN(OP_PUSH_LOOK_BEHIND_NOT); GET_RELADDR_INC(addr, p); GET_LENGTH_INC(tlen, p); - q = ONIGENC_STEP_BACK(encode, str, s, (int )tlen); + q = (UChar* )ONIGENC_STEP_BACK(encode, str, s, (int )tlen); if (IS_NULL(q)) { /* too short case -> success. ex. /(? text_range) end = text_range; - s = text; + s = (UChar* )text; while (s < end) { if (*s == *target) { @@ -2380,97 +2599,66 @@ slow_search(OnigEncoding enc, UChar* target, UChar* target_end, if (t == target_end) return s; } - s += enc_len(enc, *s); + s += enc_len(enc, s); } return (UChar* )NULL; } -#if 0 static int -str_trans_match_after_head_byte(OnigEncoding enc, - int len, UChar* t, UChar* tend, UChar* p) +str_lower_case_match(OnigEncoding enc, int ambig_flag, + const UChar* t, const UChar* tend, + const UChar* p, const UChar* end) { - while (--len > 0) { - if (*t != *p) break; - t++; p++; - } - - if (len == 0) { - int lowlen; - UChar *q, lowbuf[ONIGENC_MBC_TO_LOWER_MAXLEN]; - - while (t < tend) { - len = enc_len(enc, *p); - lowlen = ONIGENC_MBC_TO_LOWER(enc, p, lowbuf); - q = lowbuf; - while (lowlen > 0) { - if (*t++ != *q++) break; - lowlen--; - } - if (lowlen > 0) break; - p += len; - } - if (t == tend) - return 1; - } - - return 0; -} -#endif + int lowlen; + UChar *q, lowbuf[ONIGENC_MBC_NORMALIZE_MAXLEN]; + const UChar* tsave; + const UChar* psave; -static int -str_lower_case_match(OnigEncoding enc, UChar* t, UChar* tend, UChar* p) -{ - int len, lowlen; - UChar *q, lowbuf[ONIGENC_MBC_TO_LOWER_MAXLEN]; + tsave = t; + psave = p; + retry: while (t < tend) { - len = enc_len(enc, *p); - lowlen = ONIGENC_MBC_TO_LOWER(enc, p, lowbuf); + lowlen = ONIGENC_MBC_TO_NORMALIZE(enc, ambig_flag, &p, end, lowbuf); q = lowbuf; while (lowlen > 0) { - if (*t++ != *q++) return 0; + if (*t++ != *q++) { + if ((ambig_flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + ambig_flag &= ~ONIGENC_AMBIGUOUS_MATCH_COMPOUND; + t = tsave; + p = psave; + goto retry; + } + else + return 0; + } lowlen--; } - p += len; } return 1; } static UChar* -slow_search_ic(OnigEncoding enc, +slow_search_ic(OnigEncoding enc, int ambig_flag, UChar* target, UChar* target_end, - UChar* text, UChar* text_end, UChar* text_range) + const UChar* text, const UChar* text_end, UChar* text_range) { - int len, lowlen; - UChar *t, *p, *s, *end; - UChar lowbuf[ONIGENC_MBC_TO_LOWER_MAXLEN]; + UChar *s, *end; - end = text_end - (target_end - target) + 1; + end = (UChar* )text_end; + end -= target_end - target - 1; if (end > text_range) end = text_range; - s = text; + s = (UChar* )text; while (s < end) { - len = enc_len(enc, *s); - lowlen = ONIGENC_MBC_TO_LOWER(enc, s, lowbuf); - if (*target == *lowbuf) { - p = lowbuf + 1; - t = target + 1; - while (--lowlen > 0) { - if (*p != *t) break; - p++; *t++; - } - if (lowlen == 0) { - if (str_lower_case_match(enc, t, target_end, s + len)) - return s; - } - } + if (str_lower_case_match(enc, ambig_flag, target, target_end, s, text_end)) + return s; - s += len; + s += enc_len(enc, s); } return (UChar* )NULL; @@ -2478,13 +2666,15 @@ slow_search_ic(OnigEncoding enc, static UChar* slow_search_backward(OnigEncoding enc, UChar* target, UChar* target_end, - UChar* text, UChar* adjust_text, UChar* text_end, UChar* text_start) + const UChar* text, const UChar* adjust_text, + const UChar* text_end, const UChar* text_start) { UChar *t, *p, *s; - s = text_end - (target_end - target); + s = (UChar* )text_end; + s -= (target_end - target); if (s > text_start) - s = text_start; + s = (UChar* )text_start; else s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, adjust_text, s); @@ -2500,58 +2690,52 @@ slow_search_backward(OnigEncoding enc, UChar* target, UChar* target_end, if (t == target_end) return s; } - s = onigenc_get_prev_char_head(enc, adjust_text, s); + s = (UChar* )onigenc_get_prev_char_head(enc, adjust_text, s); } return (UChar* )NULL; } static UChar* -slow_search_backward_ic(OnigEncoding enc, - UChar* target,UChar* target_end, - UChar* text, UChar* adjust_text, - UChar* text_end, UChar* text_start) +slow_search_backward_ic(OnigEncoding enc, int ambig_flag, + UChar* target, UChar* target_end, + const UChar* text, const UChar* adjust_text, + const UChar* text_end, const UChar* text_start) { - int len, lowlen; - UChar *t, *p, *s; - UChar lowbuf[ONIGENC_MBC_TO_LOWER_MAXLEN]; + UChar *s; - s = text_end - (target_end - target); + s = (UChar* )text_end; + s -= (target_end - target); if (s > text_start) - s = text_start; + s = (UChar* )text_start; else s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, adjust_text, s); while (s >= text) { - len = enc_len(enc, *s); - lowlen = ONIGENC_MBC_TO_LOWER(enc, s, lowbuf); - if (*target == *lowbuf) { - p = lowbuf + 1; - t = target + 1; - while (--lowlen > 0) { - if (*p != *t) break; - p++; *t++; - } - if (lowlen == 0) { - if (str_lower_case_match(enc, t, target_end, s + len)) - return s; - } - } + if (str_lower_case_match(enc, ambig_flag, + target, target_end, s, text_end)) + return s; - s = onigenc_get_prev_char_head(enc, adjust_text, s); + s = (UChar* )onigenc_get_prev_char_head(enc, adjust_text, s); } return (UChar* )NULL; } static UChar* -bm_search_notrev(regex_t* reg, UChar* target, UChar* target_end, - UChar* text, UChar* text_end, UChar* text_range) +bm_search_notrev(regex_t* reg, const UChar* target, const UChar* target_end, + const UChar* text, const UChar* text_end, + const UChar* text_range) { - UChar *s, *t, *p, *end; - UChar *tail; + const UChar *s, *t, *p, *end; + const UChar *tail; int skip; +#ifdef ONIG_DEBUG_SEARCH + fprintf(stderr, "bm_search_notrev: text: %d, text_end: %d, text_range: %d\n", + (int )text, (int )text_end, (int )text_range); +#endif + end = text_range + (target_end - target) - 1; if (end > text_end) end = text_end; @@ -2559,7 +2743,7 @@ bm_search_notrev(regex_t* reg, UChar* target, UChar* target_end, tail = target_end - 1; s = text; while ((s - text) < target_end - target) { - s += enc_len(reg->enc, *s); + s += enc_len(reg->enc, s); } s--; /* set to text check tail position. */ @@ -2570,14 +2754,16 @@ bm_search_notrev(regex_t* reg, UChar* target, UChar* target_end, while (t >= target && *p == *t) { p--; t--; } - if (t < target) return p + 1; + if (t < target) return (UChar* )(p + 1); skip = reg->map[*s]; - p++; + p = s + 1; + if (p >= text_end) return (UChar* )NULL; t = p; - while ((p - t) < skip) { - p += enc_len(reg->enc, *p); - } + do { + p += enc_len(reg->enc, p); + } while ((p - t) < skip && p < text_end); + s += (p - t); } } @@ -2588,14 +2774,16 @@ bm_search_notrev(regex_t* reg, UChar* target, UChar* target_end, while (t >= target && *p == *t) { p--; t--; } - if (t < target) return p + 1; + if (t < target) return (UChar* )(p + 1); skip = reg->int_map[*s]; - p++; + p = s + 1; + if (p >= text_end) return (UChar* )NULL; t = p; - while ((p - t) < skip) { - p += enc_len(reg->enc, *p); - } + do { + p += enc_len(reg->enc, p); + } while ((p - t) < skip && p < text_end); + s += (p - t); } } @@ -2603,11 +2791,11 @@ bm_search_notrev(regex_t* reg, UChar* target, UChar* target_end, } static UChar* -bm_search(regex_t* reg, UChar* target, UChar* target_end, - UChar* text, UChar* text_end, UChar* text_range) +bm_search(regex_t* reg, const UChar* target, const UChar* target_end, + const UChar* text, const UChar* text_end, const UChar* text_range) { - UChar *s, *t, *p, *end; - UChar *tail; + const UChar *s, *t, *p, *end; + const UChar *tail; end = text_range + (target_end - target) - 1; if (end > text_end) @@ -2622,7 +2810,7 @@ bm_search(regex_t* reg, UChar* target, UChar* target_end, while (t >= target && *p == *t) { p--; t--; } - if (t < target) return p + 1; + if (t < target) return (UChar* )(p + 1); s += reg->map[*s]; } } @@ -2633,7 +2821,7 @@ bm_search(regex_t* reg, UChar* target, UChar* target_end, while (t >= target && *p == *t) { p--; t--; } - if (t < target) return p + 1; + if (t < target) return (UChar* )(p + 1); s += reg->int_map[*s]; } } @@ -2641,11 +2829,10 @@ bm_search(regex_t* reg, UChar* target, UChar* target_end, } static int -set_bm_backward_skip(UChar* s, UChar* end, OnigEncoding enc, - int ignore_case, int** skip) +set_bm_backward_skip(UChar* s, UChar* end, OnigEncoding enc, int** skip) + { int i, len; - UChar lowbuf[ONIGENC_MBC_TO_LOWER_MAXLEN]; if (IS_NULL(*skip)) { *skip = (int* )xmalloc(sizeof(int) * ONIG_CHAR_TABLE_SIZE); @@ -2656,24 +2843,18 @@ set_bm_backward_skip(UChar* s, UChar* end, OnigEncoding enc, for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) (*skip)[i] = len; - if (ignore_case) { - for (i = len - 1; i > 0; i--) { - ONIGENC_MBC_TO_LOWER(enc, &(s[i]), lowbuf); - (*skip)[*lowbuf] = i; - } - } - else { - for (i = len - 1; i > 0; i--) - (*skip)[s[i]] = i; - } + for (i = len - 1; i > 0; i--) + (*skip)[s[i]] = i; + return 0; } static UChar* -bm_search_backward(regex_t* reg, UChar* target, UChar* target_end, UChar* text, - UChar* adjust_text, UChar* text_end, UChar* text_start) +bm_search_backward(regex_t* reg, const UChar* target, const UChar* target_end, + const UChar* text, const UChar* adjust_text, + const UChar* text_end, const UChar* text_start) { - UChar *s, *t, *p; + const UChar *s, *t, *p; s = text_end - (target_end - target); if (text_start < s) @@ -2688,7 +2869,7 @@ bm_search_backward(regex_t* reg, UChar* target, UChar* target_end, UChar* text, p++; t++; } if (t == target_end) - return s; + return (UChar* )s; s -= reg->int_map_backward[*s]; s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, adjust_text, s); @@ -2698,26 +2879,28 @@ bm_search_backward(regex_t* reg, UChar* target, UChar* target_end, UChar* text, } static UChar* -map_search(OnigEncoding enc, UChar map[], UChar* text, UChar* text_range) +map_search(OnigEncoding enc, UChar map[], + const UChar* text, const UChar* text_range) { - UChar *s = text; + const UChar *s = text; while (s < text_range) { - if (map[*s]) return s; + if (map[*s]) return (UChar* )s; - s += enc_len(enc, *s); + s += enc_len(enc, s); } return (UChar* )NULL; } static UChar* map_search_backward(OnigEncoding enc, UChar map[], - UChar* text, UChar* adjust_text, UChar* text_start) + const UChar* text, const UChar* adjust_text, + const UChar* text_start) { - UChar *s = text_start; + const UChar *s = text_start; while (s >= text) { - if (map[*s]) return s; + if (map[*s]) return (UChar* )s; s = onigenc_get_prev_char_head(enc, adjust_text, s); } @@ -2725,13 +2908,32 @@ map_search_backward(OnigEncoding enc, UChar map[], } extern int -onig_match(regex_t* reg, UChar* str, UChar* end, UChar* at, OnigRegion* region, +onig_match(regex_t* reg, const UChar* str, const UChar* end, const UChar* at, OnigRegion* region, OnigOptionType option) { int r; UChar *prev; MatchArg msa; +#ifdef USE_MULTI_THREAD_SYSTEM + if (ONIG_STATE(reg) >= ONIG_STATE_NORMAL) { + ONIG_STATE_INC(reg); + if (IS_NOT_NULL(reg->chain) && ONIG_STATE(reg) == ONIG_STATE_NORMAL) { + onig_chain_reduce(reg); + ONIG_STATE_INC(reg); + } + } + else { + int n = 0; + while (ONIG_STATE(reg) < ONIG_STATE_NORMAL) { + if (++n > THREAD_PASS_LIMIT_COUNT) + return ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT; + THREAD_PASS; + } + ONIG_STATE_INC(reg); + } +#endif /* USE_MULTI_THREAD_SYSTEM */ + MATCH_ARG_INIT(msa, option, region, at); if (region @@ -2739,21 +2941,23 @@ onig_match(regex_t* reg, UChar* str, UChar* end, UChar* at, OnigRegion* region, && !IS_POSIX_REGION(option) #endif ) { - r = onig_region_resize(region, reg->num_mem + 1); + r = onig_region_resize_clear(region, reg->num_mem + 1); } else r = 0; if (r == 0) { - prev = onigenc_get_prev_char_head(reg->enc, str, at); + prev = (UChar* )onigenc_get_prev_char_head(reg->enc, str, at); r = match_at(reg, str, end, at, prev, &msa); } + MATCH_ARG_FREE(msa); + ONIG_STATE_DEC(reg); return r; } static int -forward_search_range(regex_t* reg, UChar* str, UChar* end, UChar* s, +forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s, UChar* range, UChar** low, UChar** high, UChar** low_prev) { UChar *p, *pprev = (UChar* )NULL; @@ -2770,7 +2974,7 @@ forward_search_range(regex_t* reg, UChar* str, UChar* end, UChar* s, } else { UChar *q = p + reg->dmin; - while (p < q) p += enc_len(reg->enc, *p); + while (p < q) p += enc_len(reg->enc, p); } } @@ -2780,7 +2984,8 @@ forward_search_range(regex_t* reg, UChar* str, UChar* end, UChar* s, p = slow_search(reg->enc, reg->exact, reg->exact_end, p, end, range); break; case ONIG_OPTIMIZE_EXACT_IC: - p = slow_search_ic(reg->enc, reg->exact, reg->exact_end, p, end, range); + p = slow_search_ic(reg->enc, reg->ambig_flag, + reg->exact, reg->exact_end, p, end, range); break; case ONIG_OPTIMIZE_EXACT_BM: @@ -2800,7 +3005,7 @@ forward_search_range(regex_t* reg, UChar* str, UChar* end, UChar* s, if (p - reg->dmin < s) { retry_gate: pprev = p; - p += enc_len(reg->enc, *p); + p += enc_len(reg->enc, p); goto retry; } @@ -2812,19 +3017,19 @@ forward_search_range(regex_t* reg, UChar* str, UChar* end, UChar* s, if (!ON_STR_BEGIN(p)) { prev = onigenc_get_prev_char_head(reg->enc, (pprev ? pprev : str), p); - if (!ONIG_IS_NEWLINE(*prev)) + if (!ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end)) goto retry_gate; } break; case ANCHOR_END_LINE: if (ON_STR_END(p)) { - prev = onigenc_get_prev_char_head(reg->enc, + prev = (UChar* )onigenc_get_prev_char_head(reg->enc, (pprev ? pprev : str), p); - if (prev && ONIG_IS_NEWLINE(*prev)) + if (prev && ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end)) goto retry_gate; } - else if (!ONIG_IS_NEWLINE(*p)) + else if (!ONIGENC_IS_MBC_NEWLINE(reg->enc, p, end)) goto retry_gate; break; } @@ -2845,7 +3050,7 @@ forward_search_range(regex_t* reg, UChar* str, UChar* end, UChar* s, *low = p - reg->dmax; if (*low > s) { *low = onigenc_get_right_adjust_char_head_with_prev(reg->enc, s, - *low, low_prev); + *low, (const UChar** )low_prev); if (low_prev && IS_NULL(*low_prev)) *low_prev = onigenc_get_prev_char_head(reg->enc, (pprev ? pprev : s), *low); @@ -2872,13 +3077,14 @@ forward_search_range(regex_t* reg, UChar* str, UChar* end, UChar* s, } static int set_bm_backward_skip P_((UChar* s, UChar* end, OnigEncoding enc, - int ignore_case, int** skip)); + int** skip)); #define BM_BACKWARD_SEARCH_LENGTH_THRESHOLD 100 static int -backward_search_range(regex_t* reg, UChar* str, UChar* end, UChar* s, - UChar* range, UChar* adjrange, UChar** low, UChar** high) +backward_search_range(regex_t* reg, const UChar* str, const UChar* end, + UChar* s, const UChar* range, UChar* adjrange, + UChar** low, UChar** high) { int r; UChar *p; @@ -2895,8 +3101,9 @@ backward_search_range(regex_t* reg, UChar* str, UChar* end, UChar* s, break; case ONIG_OPTIMIZE_EXACT_IC: - p = slow_search_backward_ic(reg->enc, reg->exact, - reg->exact_end, range, adjrange, end, p); + p = slow_search_backward_ic(reg->enc, reg->ambig_flag, + reg->exact, reg->exact_end, + range, adjrange, end, p); break; case ONIG_OPTIMIZE_EXACT_BM: @@ -2905,7 +3112,7 @@ backward_search_range(regex_t* reg, UChar* str, UChar* end, UChar* s, if (s - range < BM_BACKWARD_SEARCH_LENGTH_THRESHOLD) goto exact_method; - r = set_bm_backward_skip(reg->exact, reg->exact_end, reg->enc, 0, + r = set_bm_backward_skip(reg->exact, reg->exact_end, reg->enc, &(reg->int_map_backward)); if (r) return r; } @@ -2926,7 +3133,7 @@ backward_search_range(regex_t* reg, UChar* str, UChar* end, UChar* s, case ANCHOR_BEGIN_LINE: if (!ON_STR_BEGIN(p)) { prev = onigenc_get_prev_char_head(reg->enc, adjrange, p); - if (!ONIG_IS_NEWLINE(*prev)) { + if (!ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end)) { p = prev; goto retry; } @@ -2937,12 +3144,12 @@ backward_search_range(regex_t* reg, UChar* str, UChar* end, UChar* s, if (ON_STR_END(p)) { prev = onigenc_get_prev_char_head(reg->enc, adjrange, p); if (IS_NULL(prev)) goto fail; - if (ONIG_IS_NEWLINE(*prev)) { + if (ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end)) { p = prev; goto retry; } } - else if (!ONIG_IS_NEWLINE(*p)) { + else if (!ONIGENC_IS_MBC_NEWLINE(reg->enc, p, end)) { p = onigenc_get_prev_char_head(reg->enc, adjrange, p); if (IS_NULL(p)) goto fail; goto retry; @@ -2974,18 +3181,19 @@ backward_search_range(regex_t* reg, UChar* str, UChar* end, UChar* s, extern int -onig_search(regex_t* reg, UChar* str, UChar* end, - UChar* start, UChar* range, OnigRegion* region, OnigOptionType option) +onig_search(regex_t* reg, const UChar* str, const UChar* end, + const UChar* start, const UChar* range, OnigRegion* region, OnigOptionType option) { int r; UChar *s, *prev; MatchArg msa; - if (ONIG_STATE(reg) == ONIG_STATE_NORMAL) { - reg->state++; /* increment as search counter */ - if (IS_NOT_NULL(reg->chain)) { +#ifdef USE_MULTI_THREAD_SYSTEM + if (ONIG_STATE(reg) >= ONIG_STATE_NORMAL) { + ONIG_STATE_INC(reg); + if (IS_NOT_NULL(reg->chain) && ONIG_STATE(reg) == ONIG_STATE_NORMAL) { onig_chain_reduce(reg); - reg->state++; + ONIG_STATE_INC(reg); } } else { @@ -2995,12 +3203,14 @@ onig_search(regex_t* reg, UChar* str, UChar* end, return ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT; THREAD_PASS; } - reg->state++; /* increment as search counter */ + ONIG_STATE_INC(reg); } +#endif /* USE_MULTI_THREAD_SYSTEM */ #ifdef ONIG_DEBUG_SEARCH - fprintf(stderr, "onig_search (entry point): str: %d, end: %d, start: %d, range: %d\n", - (int )str, (int )(end - str), (int )(start - str), (int )(range - str)); + fprintf(stderr, + "onig_search (entry point): str: %d, end: %d, start: %d, range: %d\n", + (int )str, (int )(end - str), (int )(start - str), (int )(range - str)); #endif if (region @@ -3008,7 +3218,7 @@ onig_search(regex_t* reg, UChar* str, UChar* end, && !IS_POSIX_REGION(option) #endif ) { - r = onig_region_resize(region, reg->num_mem + 1); + r = onig_region_resize_clear(region, reg->num_mem + 1); if (r) goto finish_no_msa; } @@ -3049,7 +3259,7 @@ onig_search(regex_t* reg, UChar* str, UChar* end, } } else if (reg->anchor & ANCHOR_END_BUF) { - semi_end = end; + semi_end = (UChar* )end; end_buf: if ((OnigDistance )(semi_end - str) < reg->anchor_dmin) @@ -3082,14 +3292,16 @@ onig_search(regex_t* reg, UChar* str, UChar* end, } } else if (reg->anchor & ANCHOR_SEMI_END_BUF) { - if (ONIG_IS_NEWLINE(end[-1])) { - semi_end = end - 1; + UChar* pre_end = ONIGENC_STEP_BACK(reg->enc, str, end, 1); + + if (ONIGENC_IS_MBC_NEWLINE(reg->enc, pre_end, end)) { + semi_end = pre_end; if (semi_end > str && start <= semi_end) { goto end_buf; } } else { - semi_end = end; + semi_end = (UChar* )end; goto end_buf; } } @@ -3098,14 +3310,15 @@ onig_search(regex_t* reg, UChar* str, UChar* end, } } else if (str == end) { /* empty string */ - static UChar* address_for_empty_string = ""; + static const UChar* address_for_empty_string = ""; #ifdef ONIG_DEBUG_SEARCH fprintf(stderr, "onig_search: empty string.\n"); #endif if (reg->threshold_len == 0) { - s = start = end = str = address_for_empty_string; + start = end = str = address_for_empty_string; + s = (UChar* )start; prev = (UChar* )NULL; MATCH_ARG_INIT(msa, option, region, start); @@ -3122,7 +3335,7 @@ onig_search(regex_t* reg, UChar* str, UChar* end, MATCH_ARG_INIT(msa, option, region, start); - s = start; + s = (UChar* )start; if (range > start) { /* forward search */ if (s > str) prev = onigenc_get_prev_char_head(reg->enc, str, s); @@ -3132,13 +3345,13 @@ onig_search(regex_t* reg, UChar* str, UChar* end, if (reg->optimize != ONIG_OPTIMIZE_NONE) { UChar *sch_range, *low, *high, *low_prev; - sch_range = range; + sch_range = (UChar* )range; if (reg->dmax != 0) { if (reg->dmax == ONIG_INFINITE_DISTANCE) - sch_range = end; + sch_range = (UChar* )end; else { sch_range += reg->dmax; - if (sch_range > end) sch_range = end; + if (sch_range > end) sch_range = (UChar* )end; } } if (reg->dmax != ONIG_INFINITE_DISTANCE && @@ -3153,13 +3366,14 @@ onig_search(regex_t* reg, UChar* str, UChar* end, while (s <= high) { MATCH_AND_RETURN_CHECK; prev = s; - s += enc_len(reg->enc, *s); + s += enc_len(reg->enc, s); } if ((reg->anchor & ANCHOR_ANYCHAR_STAR) != 0) { if (IS_NOT_NULL(prev)) { - while (!ONIG_IS_NEWLINE(*prev) && s < range) { + while (!ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end) && + s < range) { prev = s; - s += enc_len(reg->enc, *s); + s += enc_len(reg->enc, s); } } } @@ -3176,19 +3390,23 @@ onig_search(regex_t* reg, UChar* str, UChar* end, do { MATCH_AND_RETURN_CHECK; prev = s; - s += enc_len(reg->enc, *s); + s += enc_len(reg->enc, s); } while (s <= range); /* exec s == range, because empty match with /$/. */ } else { /* backward search */ if (reg->optimize != ONIG_OPTIMIZE_NONE) { UChar *low, *high, *adjrange, *sch_start; - adjrange = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, range); + if (range < end) + adjrange = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, range); + else + adjrange = (UChar* )end; + if (reg->dmax != ONIG_INFINITE_DISTANCE && (end - range) >= reg->threshold_len) { do { sch_start = s + reg->dmax; - if (sch_start > end) sch_start = end; + if (sch_start > end) sch_start = (UChar* )end; if (backward_search_range(reg, str, end, sch_start, range, adjrange, &low, &high) <= 0) goto mismatch; @@ -3210,10 +3428,10 @@ onig_search(regex_t* reg, UChar* str, UChar* end, sch_start = s; if (reg->dmax != 0) { if (reg->dmax == ONIG_INFINITE_DISTANCE) - sch_start = end; + sch_start = (UChar* )end; else { sch_start += reg->dmax; - if (sch_start > end) sch_start = end; + if (sch_start > end) sch_start = (UChar* )end; else sch_start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, start, sch_start); @@ -3236,7 +3454,7 @@ onig_search(regex_t* reg, UChar* str, UChar* end, finish: MATCH_ARG_FREE(msa); - reg->state--; /* decrement as search counter */ + ONIG_STATE_DEC(reg); /* If result is mismatch and no FIND_NOT_EMPTY option, then the region is not setted in match_at(). */ @@ -3257,7 +3475,7 @@ onig_search(regex_t* reg, UChar* str, UChar* end, mismatch_no_msa: r = ONIG_MISMATCH; finish_no_msa: - reg->state--; /* decrement as search counter */ + ONIG_STATE_DEC(reg); #ifdef ONIG_DEBUG if (r != ONIG_MISMATCH) fprintf(stderr, "onig_search: error %d\n", r); @@ -3265,7 +3483,7 @@ onig_search(regex_t* reg, UChar* str, UChar* end, return r; match: - reg->state--; /* decrement as search counter */ + ONIG_STATE_DEC(reg); MATCH_ARG_FREE(msa); return s - str; } @@ -3282,18 +3500,44 @@ onig_get_options(regex_t* reg) return reg->options; } +extern OnigAmbigType +onig_get_ambig_flag(regex_t* reg) +{ + return reg->ambig_flag; +} + extern OnigSyntaxType* onig_get_syntax(regex_t* reg) { return reg->syntax; } -extern const char* -onig_version(void) +extern int +onig_number_of_captures(regex_t* reg) +{ + return reg->num_mem; +} + +extern int +onig_number_of_capture_histories(regex_t* reg) { -#define MSTR(a) # a +#ifdef USE_CAPTURE_HISTORY + int i, n; - return (MSTR(ONIGURUMA_VERSION_MAJOR) "." - MSTR(ONIGURUMA_VERSION_MINOR) "." - MSTR(ONIGURUMA_VERSION_TEENY)); + n = 0; + for (i = 0; i <= ONIG_MAX_CAPTURE_HISTORY_GROUP; i++) { + if (BIT_STATUS_AT(reg->capture_history, i) != 0) + n++; + } + return n; +#else + return 0; +#endif } + +extern void +onig_copy_encoding(OnigEncoding to, OnigEncoding from) +{ + *to = *from; +} + diff --git a/ext/mbstring/oniguruma/regext.c b/ext/mbstring/oniguruma/regext.c new file mode 100755 index 000000000000..6839708be7a3 --- /dev/null +++ b/ext/mbstring/oniguruma/regext.c @@ -0,0 +1,213 @@ +/********************************************************************** + regext.c - Oniguruma (regular expression library) +**********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "regint.h" + +static void +conv_ext0be32(const UChar* s, const UChar* end, UChar* conv) +{ + while (s < end) { + *conv++ = '\0'; + *conv++ = '\0'; + *conv++ = '\0'; + *conv++ = *s++; + } +} + +static void +conv_ext0le32(const UChar* s, const UChar* end, UChar* conv) +{ + while (s < end) { + *conv++ = *s++; + *conv++ = '\0'; + *conv++ = '\0'; + *conv++ = '\0'; + } +} + +static void +conv_ext0be(const UChar* s, const UChar* end, UChar* conv) +{ + while (s < end) { + *conv++ = '\0'; + *conv++ = *s++; + } +} + +static void +conv_ext0le(const UChar* s, const UChar* end, UChar* conv) +{ + while (s < end) { + *conv++ = *s++; + *conv++ = '\0'; + } +} + +static void +conv_swap4bytes(const UChar* s, const UChar* end, UChar* conv) +{ + while (s < end) { + *conv++ = s[3]; + *conv++ = s[2]; + *conv++ = s[1]; + *conv++ = s[0]; + s += 4; + } +} + +static void +conv_swap2bytes(const UChar* s, const UChar* end, UChar* conv) +{ + while (s < end) { + *conv++ = s[1]; + *conv++ = s[0]; + s += 2; + } +} + +static int +conv_encoding(OnigEncoding from, OnigEncoding to, const UChar* s, const UChar* end, + UChar** conv, UChar** conv_end) +{ + int len = end - s; + + if (to == ONIG_ENCODING_UTF16_BE) { + if (from == ONIG_ENCODING_ASCII || from == ONIG_ENCODING_ISO_8859_1) { + *conv = (UChar* )xmalloc(len * 2); + CHECK_NULL_RETURN_VAL(*conv, ONIGERR_MEMORY); + *conv_end = *conv + (len * 2); + conv_ext0be(s, end, *conv); + return 0; + } + else if (from == ONIG_ENCODING_UTF16_LE) { + swap16: + *conv = (UChar* )xmalloc(len); + CHECK_NULL_RETURN_VAL(*conv, ONIGERR_MEMORY); + *conv_end = *conv + len; + conv_swap2bytes(s, end, *conv); + return 0; + } + } + else if (to == ONIG_ENCODING_UTF16_LE) { + if (from == ONIG_ENCODING_ASCII || from == ONIG_ENCODING_ISO_8859_1) { + *conv = (UChar* )xmalloc(len * 2); + CHECK_NULL_RETURN_VAL(*conv, ONIGERR_MEMORY); + *conv_end = *conv + (len * 2); + conv_ext0le(s, end, *conv); + return 0; + } + else if (from == ONIG_ENCODING_UTF16_BE) { + goto swap16; + } + } + if (to == ONIG_ENCODING_UTF32_BE) { + if (from == ONIG_ENCODING_ASCII || from == ONIG_ENCODING_ISO_8859_1) { + *conv = (UChar* )xmalloc(len * 4); + CHECK_NULL_RETURN_VAL(*conv, ONIGERR_MEMORY); + *conv_end = *conv + (len * 4); + conv_ext0be32(s, end, *conv); + return 0; + } + else if (from == ONIG_ENCODING_UTF32_LE) { + swap32: + *conv = (UChar* )xmalloc(len); + CHECK_NULL_RETURN_VAL(*conv, ONIGERR_MEMORY); + *conv_end = *conv + len; + conv_swap4bytes(s, end, *conv); + return 0; + } + } + else if (to == ONIG_ENCODING_UTF32_LE) { + if (from == ONIG_ENCODING_ASCII || from == ONIG_ENCODING_ISO_8859_1) { + *conv = (UChar* )xmalloc(len * 4); + CHECK_NULL_RETURN_VAL(*conv, ONIGERR_MEMORY); + *conv_end = *conv + (len * 4); + conv_ext0le32(s, end, *conv); + return 0; + } + else if (from == ONIG_ENCODING_UTF32_BE) { + goto swap32; + } + } + + return ONIGERR_NOT_SUPPORTED_ENCODING_COMBINATION; +} + +extern int +onig_new_deluxe(regex_t** reg, const UChar* pattern, const UChar* pattern_end, + OnigCompileInfo* ci, OnigErrorInfo* einfo) +{ + int r; + UChar *cpat, *cpat_end; + + if (IS_NOT_NULL(einfo)) einfo->par = (UChar* )NULL; + + if (ci->pattern_enc != ci->target_enc) { + r = conv_encoding(ci->pattern_enc, ci->target_enc, pattern, pattern_end, + &cpat, &cpat_end); + if (r) return r; + } + else { + cpat = (UChar* )pattern; + cpat_end = (UChar* )pattern_end; + } + + r = onig_alloc_init(reg, ci->option, ci->ambig_flag, ci->target_enc, + ci->syntax); + if (r) goto err; + + r = onig_compile(*reg, cpat, cpat_end, einfo); + if (r) { + onig_free(*reg); + *reg = NULL; + } + + err: + if (cpat != pattern) xfree(cpat); + + return r; +} + +extern int +onig_recompile_deluxe(regex_t* reg, const UChar* pattern, const UChar* pattern_end, + OnigCompileInfo* ci, OnigErrorInfo* einfo) +{ + int r; + regex_t *new_reg; + + r = onig_new_deluxe(&new_reg, pattern, pattern_end, ci, einfo); + if (r) return r; + if (ONIG_STATE(reg) == ONIG_STATE_NORMAL) { + onig_transfer(reg, new_reg); + } + else { + onig_chain_link_add(reg, new_reg); + } + return 0; +} diff --git a/ext/mbstring/oniguruma/reggnu.c b/ext/mbstring/oniguruma/reggnu.c index 9c6a2161c2c1..2c8169c481f7 100644 --- a/ext/mbstring/oniguruma/reggnu.c +++ b/ext/mbstring/oniguruma/reggnu.c @@ -1,26 +1,38 @@ /********************************************************************** - reggnu.c - Oniguruma (regular expression library) - - Copyright (C) 2002-2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regint.h" #ifndef ONIGGNU_H /* name changes from oniggnu.h to regex.h in ruby. */ #include "oniggnu.h" #endif -#if defined(RUBY_PLATFORM) || defined(RUBY) -#ifndef ONIG_RUBY_M17N -#define USE_COMPATIBILITY_FOR_RUBY_EXTENSION_LIBRARY -#endif -#endif - -#ifndef NULL -#define NULL ((void* )0) -#endif - extern void re_free_registers(OnigRegion* r) { @@ -111,7 +123,9 @@ re_free_pattern(regex_t* reg) extern int re_alloc_pattern(regex_t** reg) { - return onig_alloc_init(reg, ONIG_OPTION_DEFAULT, OnigEncDefaultCharEncoding, + return onig_alloc_init(reg, ONIG_OPTION_DEFAULT, + ONIGENC_AMBIGUOUS_MATCH_DEFAULT, + OnigEncDefaultCharEncoding, OnigDefaultSyntax); } @@ -121,86 +135,6 @@ re_set_casetable(const char* table) onigenc_set_default_caseconv_table((UChar* )table); } -#ifdef USE_COMPATIBILITY_FOR_RUBY_EXTENSION_LIBRARY -static const unsigned char mbctab_ascii[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; - -static const unsigned char mbctab_euc[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, -}; - -static const unsigned char mbctab_sjis[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 -}; - -static const unsigned char mbctab_utf8[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 0, 0, -}; - -const unsigned char *re_mbctab = mbctab_ascii; -#endif - extern void #ifdef ONIG_RUBY_M17N re_mbcinit(OnigEncoding enc) @@ -236,21 +170,4 @@ re_mbcinit(int mb_code) onigenc_set_default_encoding(enc); #endif - -#ifdef USE_COMPATIBILITY_FOR_RUBY_EXTENSION_LIBRARY - switch (mb_code) { - case MBCTYPE_ASCII: - re_mbctab = mbctab_ascii; - break; - case MBCTYPE_EUC: - re_mbctab = mbctab_euc; - break; - case MBCTYPE_SJIS: - re_mbctab = mbctab_sjis; - break; - case MBCTYPE_UTF8: - re_mbctab = mbctab_utf8; - break; - } -#endif } diff --git a/ext/mbstring/oniguruma/regint.h b/ext/mbstring/oniguruma/regint.h index 35736b6dcbee..a704b0e26356 100644 --- a/ext/mbstring/oniguruma/regint.h +++ b/ext/mbstring/oniguruma/regint.h @@ -1,12 +1,33 @@ +#ifndef REGINT_H +#define REGINT_H /********************************************************************** - regint.h - Oniguruma (regular expression library) - - Copyright (C) 2002-2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ -#ifndef REGINT_H -#define REGINT_H +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ /* for debug */ /* #define ONIG_DEBUG_PARSE_TREE */ @@ -19,7 +40,8 @@ /* #define ONIG_DEBUG_STATISTICS */ #if defined(ONIG_DEBUG_PARSE_TREE) || defined(ONIG_DEBUG_MATCH) || \ - defined(ONIG_DEBUG_COMPILE) || defined(ONIG_DEBUG_STATISTICS) + defined(ONIG_DEBUG_SEARCH) || defined(ONIG_DEBUG_COMPILE) || \ + defined(ONIG_DEBUG_STATISTICS) #ifndef ONIG_DEBUG #define ONIG_DEBUG #endif @@ -34,9 +56,9 @@ /* config */ /* spec. config */ +/* #define USE_UNICODE_FULL_RANGE_CTYPE */ /* --> move to regenc.h */ #define USE_NAMED_GROUP #define USE_SUBEXP_CALL -#define USE_FOLD_MATCH /* ess-tsett etc... */ #define USE_INFINITE_REPEAT_MONOMANIAC_MEM_STATUS_CHECK /* /(?:()|())*\2/ */ #define USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE /* /\n$/ =~ "\n" */ #define USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR @@ -44,48 +66,55 @@ #define USE_RECYCLE_NODE #define USE_OP_PUSH_OR_JUMP_EXACT #define USE_QUALIFIER_PEEK_NEXT +#define USE_ST_HASH_TABLE +#define USE_SHARED_CCLASS_TABLE #define INIT_MATCH_STACK_SIZE 160 -#define MATCH_STACK_LIMIT_SIZE 500000 +#define DEFAULT_MATCH_STACK_LIMIT_SIZE 0 /* unlimited */ /* interface to external system */ #ifdef NOT_RUBY /* gived from Makefile */ #include "config.h" +#define USE_CAPTURE_HISTORY #define USE_VARIABLE_META_CHARS -#define USE_VARIABLE_SYNTAX #define USE_WORD_BEGIN_END /* "\<": word-begin, "\>": word-end */ #define USE_POSIX_REGION_OPTION /* needed for POSIX API support */ +/* #define USE_MULTI_THREAD_SYSTEM */ #define THREAD_ATOMIC_START /* depend on thread system */ #define THREAD_ATOMIC_END /* depend on thread system */ #define THREAD_PASS /* depend on thread system */ +#define CHECK_INTERRUPT /* depend on application */ #define xmalloc malloc #define xrealloc realloc +#define xcalloc calloc #define xfree free #else #include "ruby.h" #include "version.h" #include "rubysig.h" /* for DEFER_INTS, ENABLE_INTS */ + +#define USE_MULTI_THREAD_SYSTEM #define THREAD_ATOMIC_START DEFER_INTS #define THREAD_ATOMIC_END ENABLE_INTS #define THREAD_PASS rb_thread_schedule() +#define CHECK_INTERRUPT do {\ + if (rb_trap_pending) {\ + if (! rb_prohibit_interrupt) {\ + rb_trap_exec();\ + }\ + }\ +} while (0) + #define DEFAULT_WARN_FUNCTION rb_warn #define DEFAULT_VERB_WARN_FUNCTION rb_warning -#if defined(RUBY_VERSION_MAJOR) -#if RUBY_VERSION_MAJOR > 1 || \ -(RUBY_VERSION_MAJOR == 1 && \ - defined(RUBY_VERSION_MINOR) && RUBY_VERSION_MINOR >= 8) -#define USE_ST_HASH_TABLE -#endif -#endif - #endif /* else NOT_RUBY */ -#define THREAD_PASS_LIMIT_COUNT 10 +#define THREAD_PASS_LIMIT_COUNT 8 #define xmemset memset #define xmemcpy memcpy #define xmemmove memmove -#if defined(_WIN32) && !defined(__CYGWIN__) +#if defined(_WIN32) && !defined(__GNUC__) #define xalloca _alloca #ifdef NOT_RUBY #define vsnprintf _vsnprintf @@ -94,6 +123,69 @@ #define xalloca alloca #endif + +#ifdef USE_MULTI_THREAD_SYSTEM +#define ONIG_STATE_INC(reg) (reg)->state++ +#define ONIG_STATE_DEC(reg) (reg)->state-- +#else +#define ONIG_STATE_INC(reg) /* Nothing */ +#define ONIG_STATE_DEC(reg) /* Nothing */ +#endif /* USE_MULTI_THREAD_SYSTEM */ + + +#define onig_st_is_member st_is_member + +#ifdef NOT_RUBY + +#define st_init_table onig_st_init_table +#define st_init_table_with_size onig_st_init_table_with_size +#define st_init_numtable onig_st_init_numtable +#define st_init_numtable_with_size onig_st_init_numtable_with_size +#define st_init_strtable onig_st_init_strtable +#define st_init_strtable_with_size onig_st_init_strtable_with_size +#define st_init_strend_table_with_size onig_st_init_strend_table_with_size +#define st_delete onig_st_delete +#define st_delete_safe onig_st_delete_safe +#define st_insert onig_st_insert +#define st_insert_strend onig_st_insert_strend +#define st_lookup onig_st_lookup +#define st_lookup_strend onig_st_lookup_strend +#define st_foreach onig_st_foreach +#define st_add_direct onig_st_add_direct +#define st_add_direct_strend onig_st_add_direct_strend +#define st_free_table onig_st_free_table +#define st_cleanup_safe onig_st_cleanup_safe +#define st_copy onig_st_copy +#define st_nothing_key_clone onig_st_nothing_key_clone +#define st_nothing_key_free onig_st_nothing_key_free + +#else /* NOT_RUBY */ + +#define onig_st_init_table st_init_table +#define onig_st_init_table_with_size st_init_table_with_size +#define onig_st_init_numtable st_init_numtable +#define onig_st_init_numtable_with_size st_init_numtable_with_size +#define onig_st_init_strtable st_init_strtable +#define onig_st_init_strtable_with_size st_init_strtable_with_size +#define onig_st_init_strend_table_with_size st_init_strend_table_with_size +#define onig_st_delete st_delete +#define onig_st_delete_safe st_delete_safe +#define onig_st_insert st_insert +#define onig_st_insert_strend st_insert_strend +#define onig_st_lookup st_lookup +#define onig_st_lookup_strend st_lookup_strend +#define onig_st_foreach st_foreach +#define onig_st_add_direct st_add_direct +#define onig_st_add_direct_strend st_add_direct_strend +#define onig_st_free_table st_free_table +#define onig_st_cleanup_safe st_cleanup_safe +#define onig_st_copy st_copy +#define onig_st_nothing_key_clone st_nothing_key_clone +#define onig_st_nothing_key_free st_nothing_key_free + +#endif /* NOT_RUBY */ + + #ifdef HAVE_STDLIB_H #include #endif @@ -109,7 +201,11 @@ #endif #include +#ifdef HAVE_SYS_TYPES_H +#ifndef __BORLANDC__ #include +#endif +#endif #ifdef ONIG_DEBUG # include @@ -292,6 +388,8 @@ typedef unsigned int BitStatusType; /* ignore-case and multibyte status are included in compiled code. */ #define IS_DYNAMIC_OPTION(option) 0 +#define REPEAT_INFINITE -1 +#define IS_REPEAT_INFINITE(n) ((n) == REPEAT_INFINITE) /* bitset */ #define BITS_PER_BYTE 8 @@ -449,6 +547,7 @@ enum OpCode { OP_CCLASS_NOT, OP_CCLASS_MB_NOT, OP_CCLASS_MIX_NOT, + OP_CCLASS_NODE, /* pointer to CClassNode node */ OP_ANYCHAR, /* "." */ OP_ANYCHAR_ML, /* "." multi-line */ @@ -501,6 +600,8 @@ enum OpCode { OP_REPEAT_NG, /* {n,m}? (non greedy) */ OP_REPEAT_INC, OP_REPEAT_INC_NG, /* non greedy */ + OP_REPEAT_INC_SG, /* search and get in stack */ + OP_REPEAT_INC_NG_SG, /* search and get in stack (non greedy) */ OP_NULL_CHECK_START, /* null loop checker start */ OP_NULL_CHECK_END, /* null loop checker end */ OP_NULL_CHECK_END_MEMST, /* null loop checker end (with capture status) */ @@ -529,11 +630,12 @@ enum OpCode { #define ARG_MEMNUM 4 #define ARG_OPTION 5 -typedef short int RelAddrType; -typedef short int AbsAddrType; -typedef short int LengthType; -typedef short int MemNumType; -typedef int RepeatNumType; +typedef int RelAddrType; +typedef int AbsAddrType; +typedef int LengthType; +typedef int RepeatNumType; +typedef short int MemNumType; +typedef void* PointerType; #define SIZE_OPCODE 1 #define SIZE_RELADDR sizeof(RelAddrType) @@ -543,57 +645,33 @@ typedef int RepeatNumType; #define SIZE_REPEATNUM sizeof(RepeatNumType) #define SIZE_OPTION sizeof(OnigOptionType) #define SIZE_CODE_POINT sizeof(OnigCodePoint) +#define SIZE_POINTER sizeof(PointerType) -#ifdef PLATFORM_UNALIGNED_WORD_ACCESS -#define GET_RELADDR_INC(addr,p) do{\ - addr = *((RelAddrType* )(p));\ - (p) += SIZE_RELADDR;\ -} while(0) - -#define GET_ABSADDR_INC(addr,p) do{\ - addr = *((AbsAddrType* )(p));\ - (p) += SIZE_ABSADDR;\ -} while(0) - -#define GET_LENGTH_INC(len,p) do{\ - len = *((LengthType* )(p));\ - (p) += SIZE_LENGTH;\ -} while(0) -#define GET_MEMNUM_INC(num,p) do{\ - num = *((MemNumType* )(p));\ - (p) += SIZE_MEMNUM;\ -} while(0) +#ifdef PLATFORM_UNALIGNED_WORD_ACCESS -#define GET_REPEATNUM_INC(num,p) do{\ - num = *((RepeatNumType* )(p));\ - (p) += SIZE_REPEATNUM;\ +#define PLATFORM_GET_INC(val,p,type) do{\ + val = *(type* )p;\ + (p) += sizeof(type);\ } while(0) -#define GET_OPTION_INC(option,p) do{\ - option = *((OnigOptionType* )(p));\ - (p) += SIZE_OPTION;\ -} while(0) #else -#define GET_RELADDR_INC(addr,p) GET_SHORT_INC(addr,p) -#define GET_ABSADDR_INC(addr,p) GET_SHORT_INC(addr,p) -#define GET_LENGTH_INC(len,p) GET_SHORT_INC(len,p) -#define GET_MEMNUM_INC(num,p) GET_SHORT_INC(num,p) -#define GET_REPEATNUM_INC(num,p) GET_INT_INC(num,p) -#define GET_OPTION_INC(option,p) GET_UINT_INC(option,p) - -#define SERIALIZE_RELADDR(addr,p) SERIALIZE_SHORT(addr,p) -#define SERIALIZE_ABSADDR(addr,p) SERIALIZE_SHORT(addr,p) -#define SERIALIZE_LENGTH(len,p) SERIALIZE_SHORT(len,p) -#define SERIALIZE_MEMNUM(num,p) SERIALIZE_SHORT(num,p) -#define SERIALIZE_REPEATNUM(num,p) SERIALIZE_INT(num,p) -#define SERIALIZE_OPTION(option,p) SERIALIZE_UINT(option,p) - -#define SERIALIZE_BUFSIZE SIZEOF_INT +#define PLATFORM_GET_INC(val,p,type) do{\ + xmemcpy(&val, (p), sizeof(type));\ + (p) += sizeof(type);\ +} while(0) #endif /* PLATFORM_UNALIGNED_WORD_ACCESS */ +#define GET_RELADDR_INC(addr,p) PLATFORM_GET_INC(addr, p, RelAddrType) +#define GET_ABSADDR_INC(addr,p) PLATFORM_GET_INC(addr, p, AbsAddrType) +#define GET_LENGTH_INC(len,p) PLATFORM_GET_INC(len, p, LengthType) +#define GET_MEMNUM_INC(num,p) PLATFORM_GET_INC(num, p, MemNumType) +#define GET_REPEATNUM_INC(num,p) PLATFORM_GET_INC(num, p, RepeatNumType) +#define GET_OPTION_INC(option,p) PLATFORM_GET_INC(option, p, OnigOptionType) +#define GET_POINTER_INC(ptr,p) PLATFORM_GET_INC(ptr, p, PointerType) + /* code point's address must be aligned address. */ #define GET_CODE_POINT(code,p) code = *((OnigCodePoint* )(p)) #define GET_BYTE_INC(byte,p) do{\ @@ -636,23 +714,53 @@ typedef int RepeatNumType; #define SIZE_OP_RETURN SIZE_OPCODE -typedef struct { - UChar esc; - UChar anychar; - UChar anytime; - UChar zero_or_one_time; - UChar one_or_more_time; - UChar anychar_anytime; -} OnigMetaCharTableType; +#define MC_ESC(enc) (enc)->meta_char_table.esc +#define MC_ANYCHAR(enc) (enc)->meta_char_table.anychar +#define MC_ANYTIME(enc) (enc)->meta_char_table.anytime +#define MC_ZERO_OR_ONE_TIME(enc) (enc)->meta_char_table.zero_or_one_time +#define MC_ONE_OR_MORE_TIME(enc) (enc)->meta_char_table.one_or_more_time +#define MC_ANYCHAR_ANYTIME(enc) (enc)->meta_char_table.anychar_anytime + +#define SYN_POSIX_COMMON_OP \ + ( ONIG_SYN_OP_DOT_ANYCHAR | ONIG_SYN_OP_POSIX_BRACKET | \ + ONIG_SYN_OP_DECIMAL_BACKREF | \ + ONIG_SYN_OP_BRACKET_CC | ONIG_SYN_OP_ASTERISK_ZERO_INF | \ + ONIG_SYN_OP_LINE_ANCHOR | \ + ONIG_SYN_OP_ESC_CONTROL_CHARS ) + +#define SYN_GNU_REGEX_OP \ + ( ONIG_SYN_OP_DOT_ANYCHAR | ONIG_SYN_OP_BRACKET_CC | \ + ONIG_SYN_OP_POSIX_BRACKET | ONIG_SYN_OP_DECIMAL_BACKREF | \ + ONIG_SYN_OP_BRACE_INTERVAL | ONIG_SYN_OP_LPAREN_SUBEXP | \ + ONIG_SYN_OP_VBAR_ALT | \ + ONIG_SYN_OP_ASTERISK_ZERO_INF | ONIG_SYN_OP_PLUS_ONE_INF | \ + ONIG_SYN_OP_QMARK_ZERO_ONE | \ + ONIG_SYN_OP_ESC_AZ_BUF_ANCHOR | ONIG_SYN_OP_ESC_CAPITAL_G_BEGIN_ANCHOR | \ + ONIG_SYN_OP_ESC_W_WORD | \ + ONIG_SYN_OP_ESC_B_WORD_BOUND | ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END | \ + ONIG_SYN_OP_ESC_S_WHITE_SPACE | ONIG_SYN_OP_ESC_D_DIGIT | \ + ONIG_SYN_OP_LINE_ANCHOR ) + +#define SYN_GNU_REGEX_BV \ + ( ONIG_SYN_CONTEXT_INDEP_ANCHORS | ONIG_SYN_CONTEXT_INDEP_REPEAT_OPS | \ + ONIG_SYN_CONTEXT_INVALID_REPEAT_OPS | ONIG_SYN_ALLOW_INVALID_INTERVAL | \ + ONIG_SYN_BACKSLASH_ESCAPE_IN_CC | ONIG_SYN_ALLOW_DOUBLE_RANGE_OP_IN_CC ) + +/* cclass node */ +#define FLAG_CCLASS_NOT 1 +#define FLAG_CCLASS_SHARE (1<<1) + +#define CCLASS_SET_NOT(cc) (cc)->flags |= FLAG_CCLASS_NOT +#define CCLASS_CLEAR_NOT(cc) (cc)->flags &= ~FLAG_CCLASS_NOT +#define CCLASS_SET_SHARE(cc) (cc)->flags |= FLAG_CCLASS_SHARE +#define IS_CCLASS_NOT(cc) (((cc)->flags & FLAG_CCLASS_NOT) != 0) +#define IS_CCLASS_SHARE(cc) (((cc)->flags & FLAG_CCLASS_SHARE) != 0) -extern OnigMetaCharTableType OnigMetaCharTable; - -#define MC_ESC OnigMetaCharTable.esc -#define MC_ANYCHAR OnigMetaCharTable.anychar -#define MC_ANYTIME OnigMetaCharTable.anytime -#define MC_ZERO_OR_ONE_TIME OnigMetaCharTable.zero_or_one_time -#define MC_ONE_OR_MORE_TIME OnigMetaCharTable.one_or_more_time -#define MC_ANYCHAR_ANYTIME OnigMetaCharTable.anychar_anytime +typedef struct { + int flags; + BitSet bs; + BBuf* mbuf; /* multi-byte info or NULL */ +} CClassNode; #ifdef ONIG_DEBUG @@ -665,7 +773,7 @@ typedef struct { extern OnigOpInfoType OnigOpInfo[]; -extern void onig_print_compiled_byte_code P_((FILE* f, UChar* bp, UChar** nextp)); +extern void onig_print_compiled_byte_code P_((FILE* f, UChar* bp, UChar** nextp, OnigEncoding enc)); #ifdef ONIG_DEBUG_STATISTICS extern void onig_statistics_init P_((void)); @@ -675,11 +783,11 @@ extern void onig_print_statistics P_((FILE* f)); extern char* onig_error_code_to_format P_((int code)); extern void onig_snprintf_with_pattern PV_((char buf[], int bufsize, OnigEncoding enc, char* pat, char* pat_end, char *fmt, ...)); -extern UChar* onig_strdup P_((UChar* s, UChar* end)); extern int onig_bbuf_init P_((BBuf* buf, int size)); -extern int onig_alloc_init P_((regex_t** reg, OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax)); -extern int onig_compile P_((regex_t* reg, UChar* pattern, UChar* pattern_end, OnigErrorInfo* einfo)); +extern int onig_alloc_init P_((regex_t** reg, OnigOptionType option, OnigAmbigType ambig_flag, OnigEncoding enc, OnigSyntaxType* syntax)); +extern int onig_compile P_((regex_t* reg, const UChar* pattern, const UChar* pattern_end, OnigErrorInfo* einfo)); extern void onig_chain_reduce P_((regex_t* reg)); -extern int onig_is_in_code_range P_((UChar* p, OnigCodePoint code)); +extern void onig_chain_link_add P_((regex_t* to, regex_t* add)); +extern void onig_transfer P_((regex_t* to, regex_t* from)); #endif /* REGINT_H */ diff --git a/ext/mbstring/oniguruma/regparse.c b/ext/mbstring/oniguruma/regparse.c index 2260df415552..58e122f4869c 100644 --- a/ext/mbstring/oniguruma/regparse.c +++ b/ext/mbstring/oniguruma/regparse.c @@ -1,120 +1,36 @@ /********************************************************************** - regparse.c - Oniguruma (regular expression library) - - Copyright (C) 2003-2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "regparse.h" #define WARN_BUFSIZE 256 -#define SYN_POSIX_COMMON_OP \ - ( ONIG_SYN_OP_DOT_ANYCHAR | ONIG_SYN_OP_POSIX_BRACKET | \ - ONIG_SYN_OP_DECIMAL_BACKREF | \ - ONIG_SYN_OP_BRACKET_CC | ONIG_SYN_OP_ASTERISK_ZERO_INF | \ - ONIG_SYN_OP_LINE_ANCHOR | \ - ONIG_SYN_OP_ESC_CONTROL_CHARS ) - -#define SYN_GNU_REGEX_OP \ - ( ONIG_SYN_OP_DOT_ANYCHAR | ONIG_SYN_OP_BRACKET_CC | \ - ONIG_SYN_OP_POSIX_BRACKET | ONIG_SYN_OP_DECIMAL_BACKREF | \ - ONIG_SYN_OP_BRACE_INTERVAL | ONIG_SYN_OP_LPAREN_SUBEXP | \ - ONIG_SYN_OP_VBAR_ALT | \ - ONIG_SYN_OP_ASTERISK_ZERO_INF | ONIG_SYN_OP_PLUS_ONE_INF | \ - ONIG_SYN_OP_QMARK_ZERO_ONE | \ - ONIG_SYN_OP_ESC_AZ_BUF_ANCHOR | ONIG_SYN_OP_ESC_CAPITAL_G_BEGIN_ANCHOR | \ - ONIG_SYN_OP_ESC_W_WORD | \ - ONIG_SYN_OP_ESC_B_WORD_BOUND | ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END | \ - ONIG_SYN_OP_ESC_S_WHITE_SPACE | ONIG_SYN_OP_ESC_D_DIGIT | \ - ONIG_SYN_OP_LINE_ANCHOR ) - -#define SYN_GNU_REGEX_BV \ - ( ONIG_SYN_CONTEXT_INDEP_ANCHORS | ONIG_SYN_CONTEXT_INDEP_REPEAT_OPS | \ - ONIG_SYN_CONTEXT_INVALID_REPEAT_OPS | ONIG_SYN_ALLOW_INVALID_INTERVAL | \ - ONIG_SYN_BACKSLASH_ESCAPE_IN_CC | ONIG_SYN_ALLOW_DOUBLE_RANGE_OP_IN_CC ) - -#ifdef USE_VARIABLE_SYNTAX -OnigSyntaxType OnigSyntaxPosixBasic = { - ( SYN_POSIX_COMMON_OP | ONIG_SYN_OP_ESC_LPAREN_SUBEXP | - ONIG_SYN_OP_ESC_BRACE_INTERVAL ) - , 0 - , 0 - , ( ONIG_OPTION_SINGLELINE | ONIG_OPTION_MULTILINE ) -}; - -OnigSyntaxType OnigSyntaxPosixExtended = { - ( SYN_POSIX_COMMON_OP | ONIG_SYN_OP_LPAREN_SUBEXP | - ONIG_SYN_OP_BRACE_INTERVAL | - ONIG_SYN_OP_PLUS_ONE_INF | ONIG_SYN_OP_QMARK_ZERO_ONE | ONIG_SYN_OP_VBAR_ALT ) - , 0 - , ( ONIG_SYN_CONTEXT_INDEP_ANCHORS | - ONIG_SYN_CONTEXT_INDEP_REPEAT_OPS | ONIG_SYN_CONTEXT_INVALID_REPEAT_OPS | - ONIG_SYN_ALLOW_UNMATCHED_CLOSE_SUBEXP | - ONIG_SYN_ALLOW_DOUBLE_RANGE_OP_IN_CC ) - , ( ONIG_OPTION_SINGLELINE | ONIG_OPTION_MULTILINE ) -}; - -OnigSyntaxType OnigSyntaxEmacs = { - ( ONIG_SYN_OP_DOT_ANYCHAR | ONIG_SYN_OP_BRACKET_CC | - ONIG_SYN_OP_ESC_BRACE_INTERVAL | - ONIG_SYN_OP_ESC_LPAREN_SUBEXP | ONIG_SYN_OP_ESC_VBAR_ALT | - ONIG_SYN_OP_ASTERISK_ZERO_INF | ONIG_SYN_OP_PLUS_ONE_INF | - ONIG_SYN_OP_QMARK_ZERO_ONE | ONIG_SYN_OP_DECIMAL_BACKREF | - ONIG_SYN_OP_LINE_ANCHOR | ONIG_SYN_OP_ESC_CONTROL_CHARS ) - , ONIG_SYN_OP2_ESC_GNU_BUF_ANCHOR - , ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC - , ONIG_OPTION_NONE -}; - -OnigSyntaxType OnigSyntaxGrep = { - ( ONIG_SYN_OP_DOT_ANYCHAR | ONIG_SYN_OP_BRACKET_CC | ONIG_SYN_OP_POSIX_BRACKET | - ONIG_SYN_OP_BRACE_INTERVAL | ONIG_SYN_OP_ESC_LPAREN_SUBEXP | - ONIG_SYN_OP_ESC_VBAR_ALT | - ONIG_SYN_OP_ASTERISK_ZERO_INF | ONIG_SYN_OP_ESC_PLUS_ONE_INF | - ONIG_SYN_OP_ESC_QMARK_ZERO_ONE | ONIG_SYN_OP_LINE_ANCHOR | - ONIG_SYN_OP_ESC_W_WORD | ONIG_SYN_OP_ESC_B_WORD_BOUND | - ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END | ONIG_SYN_OP_DECIMAL_BACKREF ) - , 0 - , ( ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC | ONIG_SYN_NOT_NEWLINE_IN_NEGATIVE_CC ) - , ONIG_OPTION_NONE -}; - -OnigSyntaxType OnigSyntaxGnuRegex = { - SYN_GNU_REGEX_OP - , 0 - , SYN_GNU_REGEX_BV - , ONIG_OPTION_NONE -}; - -OnigSyntaxType OnigSyntaxJava = { - (( SYN_GNU_REGEX_OP | ONIG_SYN_OP_QMARK_NON_GREEDY | - ONIG_SYN_OP_ESC_CONTROL_CHARS | ONIG_SYN_OP_ESC_C_CONTROL | - ONIG_SYN_OP_ESC_OCTAL3 | ONIG_SYN_OP_ESC_X_HEX2 ) - & ~ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END ) - , ( ONIG_SYN_OP2_ESC_CAPITAL_Q_QUOTE | ONIG_SYN_OP2_QMARK_GROUP_EFFECT | - ONIG_SYN_OP2_OPTION_PERL | ONIG_SYN_OP2_PLUS_POSSESSIVE_REPEAT | - ONIG_SYN_OP2_PLUS_POSSESSIVE_INTERVAL | ONIG_SYN_OP2_CCLASS_SET_OP | - ONIG_SYN_OP2_ESC_V_VTAB | ONIG_SYN_OP2_ESC_U_HEX4 | - ONIG_SYN_OP2_ESC_P_CHAR_PROPERTY ) - , ( SYN_GNU_REGEX_BV | ONIG_SYN_DIFFERENT_LEN_ALT_LOOK_BEHIND ) - , ONIG_OPTION_SINGLELINE -}; - -OnigSyntaxType OnigSyntaxPerl = { - (( SYN_GNU_REGEX_OP | ONIG_SYN_OP_QMARK_NON_GREEDY | - ONIG_SYN_OP_ESC_OCTAL3 | ONIG_SYN_OP_ESC_X_HEX2 | - ONIG_SYN_OP_ESC_X_BRACE_HEX8 | ONIG_SYN_OP_ESC_CONTROL_CHARS | - ONIG_SYN_OP_ESC_C_CONTROL ) - & ~ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END ) - , ( ONIG_SYN_OP2_ESC_CAPITAL_Q_QUOTE | - ONIG_SYN_OP2_QMARK_GROUP_EFFECT | ONIG_SYN_OP2_OPTION_PERL | - ONIG_SYN_OP2_ESC_P_CHAR_PROPERTY ) - , SYN_GNU_REGEX_BV - , ONIG_OPTION_SINGLELINE -}; -#endif /* USE_VARIABLE_SYNTAX */ - OnigSyntaxType OnigSyntaxRuby = { (( SYN_GNU_REGEX_OP | ONIG_SYN_OP_QMARK_NON_GREEDY | ONIG_SYN_OP_ESC_OCTAL3 | ONIG_SYN_OP_ESC_X_HEX2 | @@ -127,12 +43,14 @@ OnigSyntaxType OnigSyntaxRuby = { ONIG_SYN_OP2_ESC_G_SUBEXP_CALL | ONIG_SYN_OP2_PLUS_POSSESSIVE_REPEAT | ONIG_SYN_OP2_CCLASS_SET_OP | ONIG_SYN_OP2_ESC_CAPITAL_C_BAR_CONTROL | - ONIG_SYN_OP2_ESC_CAPITAL_M_BAR_META | ONIG_SYN_OP2_ESC_V_VTAB ) + ONIG_SYN_OP2_ESC_CAPITAL_M_BAR_META | ONIG_SYN_OP2_ESC_V_VTAB | + ONIG_SYN_OP2_ESC_H_XDIGIT ) , ( SYN_GNU_REGEX_BV | ONIG_SYN_ALLOW_INTERVAL_LOW_ABBREV | ONIG_SYN_DIFFERENT_LEN_ALT_LOOK_BEHIND | ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP | ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME | + ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY | ONIG_SYN_WARN_CC_OP_NOT_ESCAPED | ONIG_SYN_WARN_REDUNDANT_NESTED_REPEAT ) , ONIG_OPTION_NONE @@ -140,89 +58,7 @@ OnigSyntaxType OnigSyntaxRuby = { OnigSyntaxType* OnigDefaultSyntax = ONIG_SYNTAX_RUBY; -#ifdef USE_VARIABLE_SYNTAX -extern int -onig_set_default_syntax(OnigSyntaxType* syntax) -{ - if (IS_NULL(syntax)) - syntax = ONIG_SYNTAX_RUBY; - - OnigDefaultSyntax = syntax; - return 0; -} - -extern void -onig_copy_syntax(OnigSyntaxType* to, OnigSyntaxType* from) -{ - *to = *from; -} - -extern void -onig_set_syntax_op(OnigSyntaxType* syntax, unsigned int op) -{ - syntax->op = op; -} - -extern void -onig_set_syntax_op2(OnigSyntaxType* syntax, unsigned int op2) -{ - syntax->op2 = op2; -} - -extern void -onig_set_syntax_behavior(OnigSyntaxType* syntax, unsigned int behavior) -{ - syntax->behavior = behavior; -} - -extern void -onig_set_syntax_options(OnigSyntaxType* syntax, OnigOptionType options) -{ - syntax->options = options; -} -#endif - -OnigMetaCharTableType OnigMetaCharTable = { - (OnigCodePoint )'\\' /* esc */ - , (OnigCodePoint )0 /* anychar '.' */ - , (OnigCodePoint )0 /* anytime '*' */ - , (OnigCodePoint )0 /* zero or one time '?' */ - , (OnigCodePoint )0 /* one or more time '+' */ - , (OnigCodePoint )0 /* anychar anytime */ -}; - -#ifdef USE_VARIABLE_META_CHARS -extern int onig_set_meta_char(unsigned int what, unsigned int c) -{ - switch (what) { - case ONIG_META_CHAR_ESCAPE: - OnigMetaCharTable.esc = c; - break; - case ONIG_META_CHAR_ANYCHAR: - OnigMetaCharTable.anychar = c; - break; - case ONIG_META_CHAR_ANYTIME: - OnigMetaCharTable.anytime = c; - break; - case ONIG_META_CHAR_ZERO_OR_ONE_TIME: - OnigMetaCharTable.zero_or_one_time = c; - break; - case ONIG_META_CHAR_ONE_OR_MORE_TIME: - OnigMetaCharTable.one_or_more_time = c; - break; - case ONIG_META_CHAR_ANYCHAR_ANYTIME: - OnigMetaCharTable.anychar_anytime = c; - break; - default: - return ONIGERR_INVALID_ARGUMENT; - break; - } - return 0; -} -#endif /* USE_VARIABLE_META_CHARS */ - - -extern void onig_null_warn(char* s) { } +extern void onig_null_warn(const char* s) { } #ifdef DEFAULT_WARN_FUNCTION static OnigWarnFunc onig_warn = (OnigWarnFunc )DEFAULT_WARN_FUNCTION; @@ -272,12 +108,15 @@ bbuf_clone(BBuf** rto, BBuf* from) #define ONOFF(v,f,negative) (negative) ? ((v) &= ~(f)) : ((v) |= (f)) -#define SET_ALL_MULTI_BYTE_RANGE(pbuf) \ - add_code_range_to_buf(pbuf, (OnigCodePoint )0x80, ~((OnigCodePoint )0)) +#define MBCODE_START_POS(enc) \ + (OnigCodePoint )(ONIGENC_MBC_MINLEN(enc) > 1 ? 0 : 0x80) + +#define SET_ALL_MULTI_BYTE_RANGE(enc, pbuf) \ + add_code_range_to_buf(pbuf, MBCODE_START_POS(enc), ~((OnigCodePoint )0)) -#define ADD_ALL_MULTI_BYTE_RANGE(code, mbuf) do {\ - if (! ONIGENC_IS_SINGLEBYTE(code)) {\ - r = SET_ALL_MULTI_BYTE_RANGE(&(mbuf));\ +#define ADD_ALL_MULTI_BYTE_RANGE(enc, mbuf) do {\ + if (! ONIGENC_IS_SINGLEBYTE(enc)) {\ + r = SET_ALL_MULTI_BYTE_RANGE(enc, &(mbuf));\ if (r) return r;\ }\ } while (0) @@ -359,7 +198,7 @@ bitset_copy(BitSetRef dest, BitSetRef bs) } extern int -onig_strncmp(UChar* s1, UChar* s2, int n) +onig_strncmp(const UChar* s1, const UChar* s2, int n) { int x; @@ -371,7 +210,7 @@ onig_strncmp(UChar* s1, UChar* s2, int n) } static void -k_strcpy(UChar* dest, UChar* src, UChar* end) +k_strcpy(UChar* dest, const UChar* src, const UChar* end) { int len = end - src; if (len > 0) { @@ -380,33 +219,47 @@ k_strcpy(UChar* dest, UChar* src, UChar* end) } } -extern UChar* -onig_strdup(UChar* s, UChar* end) +static UChar* +strdup_with_null(OnigEncoding enc, UChar* s, UChar* end) { - int len = end - s; + int slen, term_len, i; + UChar *r; - if (len > 0) { - UChar* r = (UChar* )xmalloc(len + 1); - CHECK_NULL_RETURN(r); - xmemcpy(r, s, len); - r[len] = (UChar )0; - return r; - } - else return NULL; + slen = end - s; + term_len = ONIGENC_MBC_MINLEN(enc); + + r = (UChar* )xmalloc(slen + term_len); + CHECK_NULL_RETURN(r); + xmemcpy(r, s, slen); + + for (i = 0; i < term_len; i++) + r[slen + i] = (UChar )0; + + return r; } -/* scan pattern methods */ -#define PEND_VALUE -1 -#define PFETCH(c) do { (c) = *p++; } while (0) -#define PUNFETCH p-- -#define PINC p++ -#define PPEEK (p < end ? *p : PEND_VALUE) -#define PEND (p < end ? 0 : 1) +/* scan pattern methods */ +#define PEND_VALUE 0 + +#define PFETCH_READY UChar* pfetch_prev +#define PEND (p < end ? 0 : 1) +#define PUNFETCH p = pfetch_prev +#define PINC do { \ + pfetch_prev = p; \ + p += ONIGENC_MBC_ENC_LEN(enc, p); \ +} while (0) +#define PFETCH(c) do { \ + c = ONIGENC_MBC_TO_CODE(enc, p, end); \ + pfetch_prev = p; \ + p += ONIGENC_MBC_ENC_LEN(enc, p); \ +} while (0) +#define PPEEK (p < end ? ONIGENC_MBC_TO_CODE(enc, p, end) : PEND_VALUE) +#define PPEEK_IS(c) (PPEEK == (OnigCodePoint )c) static UChar* -k_strcat_capa(UChar* dest, UChar* dest_end, UChar* src, UChar* src_end, +k_strcat_capa(UChar* dest, UChar* dest_end, const UChar* src, const UChar* src_end, int capa) { UChar* r; @@ -424,7 +277,7 @@ k_strcat_capa(UChar* dest, UChar* dest_end, UChar* src, UChar* src_end, /* dest on static area */ static UChar* strcat_capa_from_static(UChar* dest, UChar* dest_end, - UChar* src, UChar* src_end, int capa) + const UChar* src, const UChar* src_end, int capa) { UChar* r; @@ -450,7 +303,7 @@ typedef struct { #ifdef USE_ST_HASH_TABLE -#include +#include "st.h" typedef st_table NameTable; typedef st_data_t HashDataType; /* 1.6 st.h doesn't define st_data_t type */ @@ -487,7 +340,7 @@ onig_print_names(FILE* fp, regex_t* reg) if (IS_NOT_NULL(t)) { fprintf(fp, "name table\n"); - st_foreach(t, i_print_name_entry, (HashDataType )fp); + onig_st_foreach(t, i_print_name_entry, (HashDataType )fp); fputs("\n", fp); } return 0; @@ -508,7 +361,7 @@ names_clear(regex_t* reg) NameTable* t = (NameTable* )reg->name_table; if (IS_NOT_NULL(t)) { - st_foreach(t, i_free_name_entry, 0); + onig_st_foreach(t, i_free_name_entry, 0); } return 0; } @@ -523,56 +376,39 @@ onig_names_free(regex_t* reg) if (r) return r; t = (NameTable* )reg->name_table; - if (IS_NOT_NULL(t)) st_free_table(t); + if (IS_NOT_NULL(t)) onig_st_free_table(t); reg->name_table = (void* )NULL; return 0; } static NameEntry* -name_find(regex_t* reg, UChar* name, UChar* name_end) +name_find(regex_t* reg, const UChar* name, const UChar* name_end) { - int len; - UChar namebuf[NAMEBUF_SIZE_1]; - UChar *key; NameEntry* e; NameTable* t = (NameTable* )reg->name_table; e = (NameEntry* )NULL; if (IS_NOT_NULL(t)) { - if (*name_end == '\0') { - key = name; - } - else { - /* dirty, but st.c API claims NULL terminated key. */ - len = name_end - name; - if (len <= NAMEBUF_SIZE) { - xmemcpy(namebuf, name, len); - namebuf[len] = '\0'; - key = namebuf; - } - else { - key = onig_strdup(name, name_end); - if (IS_NULL(key)) return (NameEntry* )NULL; - } - } - - st_lookup(t, (HashDataType )key, (HashDataType * )&e); - if (key != name && key != namebuf) xfree(key); + onig_st_lookup_strend(t, name, name_end, (HashDataType* )((void* )(&e))); } return e; } typedef struct { - int (*func)(UChar*,UChar*,int,int*,regex_t*,void*); + int (*func)(const UChar*, const UChar*,int,int*,regex_t*,void*); regex_t* reg; void* arg; int ret; + OnigEncoding enc; } INamesArg; static int i_names(UChar* key, NameEntry* e, INamesArg* arg) { - int r = (*(arg->func))(e->name, e->name + strlen(e->name), e->back_num, + int r = (*(arg->func))(e->name, + /*e->name + onigenc_str_bytelen_null(arg->enc, e->name), */ + e->name + e->name_len, + e->back_num, (e->back_num > 1 ? e->back_refs : &(e->back_ref1)), arg->reg, arg->arg); if (r != 0) { @@ -584,8 +420,8 @@ i_names(UChar* key, NameEntry* e, INamesArg* arg) extern int onig_foreach_name(regex_t* reg, - int (*func)(UChar*,UChar*,int,int*,regex_t*,void*), - void* arg) + int (*func)(const UChar*, const UChar*,int,int*,regex_t*,void*), + void* arg) { INamesArg narg; NameTable* t = (NameTable* )reg->name_table; @@ -595,11 +431,41 @@ onig_foreach_name(regex_t* reg, narg.func = func; narg.reg = reg; narg.arg = arg; - st_foreach(t, i_names, (HashDataType )&narg); + narg.enc = reg->enc; /* should be pattern encoding. */ + onig_st_foreach(t, i_names, (HashDataType )&narg); } return narg.ret; } +static int +i_renumber_name(UChar* key, NameEntry* e, GroupNumRemap* map) +{ + int i; + + if (e->back_num > 1) { + for (i = 0; i < e->back_num; i++) { + e->back_refs[i] = map[e->back_refs[i]].new_val; + } + } + else if (e->back_num == 1) { + e->back_ref1 = map[e->back_ref1].new_val; + } + + return ST_CONTINUE; +} + +extern int +onig_renumber_name_table(regex_t* reg, GroupNumRemap* map) +{ + NameTable* t = (NameTable* )reg->name_table; + + if (IS_NOT_NULL(t)) { + onig_st_foreach(t, i_renumber_name, (HashDataType )map); + } + return 0; +} + + extern int onig_number_of_names(regex_t* reg) { @@ -719,8 +585,8 @@ name_find(regex_t* reg, UChar* name, UChar* name_end) extern int onig_foreach_name(regex_t* reg, - int (*func)(UChar*,UChar*,int,int*,regex_t*,void*), - void* arg) + int (*func)(const UChar*, const UChar*,int,int*,regex_t*,void*), + void* arg) { int i, r; NameEntry* e; @@ -765,14 +631,16 @@ name_add(regex_t* reg, UChar* name, UChar* name_end, int backref, ScanEnv* env) if (IS_NULL(e)) { #ifdef USE_ST_HASH_TABLE if (IS_NULL(t)) { - reg->name_table = t = st_init_strtable(); + t = onig_st_init_strend_table_with_size(5); + reg->name_table = (void* )t; } e = (NameEntry* )xmalloc(sizeof(NameEntry)); CHECK_NULL_RETURN_VAL(e, ONIGERR_MEMORY); - e->name = onig_strdup(name, name_end); + e->name = strdup_with_null(reg->enc, name, name_end); if (IS_NULL(e->name)) return ONIGERR_MEMORY; - st_insert(t, (HashDataType )e->name, (HashDataType )e); + onig_st_insert_strend(t, e->name, (e->name + (name_end - name)), + (HashDataType )e); e->name_len = name_end - name; e->back_num = 0; @@ -817,7 +685,7 @@ name_add(regex_t* reg, UChar* name, UChar* name_end, int backref, ScanEnv* env) } e = &(t->e[t->num]); t->num++; - e->name = onig_strdup(name, name_end); + e->name = strdup_with_null(reg->enc, name, name_end); e->name_len = name_end - name; #endif } @@ -857,8 +725,8 @@ name_add(regex_t* reg, UChar* name, UChar* name_end, int backref, ScanEnv* env) } extern int -onig_name_to_group_numbers(regex_t* reg, UChar* name, UChar* name_end, - int** nums) +onig_name_to_group_numbers(regex_t* reg, const UChar* name, + const UChar* name_end, int** nums) { NameEntry* e; @@ -879,8 +747,8 @@ onig_name_to_group_numbers(regex_t* reg, UChar* name, UChar* name_end, } extern int -onig_name_to_backref_number(regex_t* reg, UChar* name, UChar* name_end, - OnigRegion *region) +onig_name_to_backref_number(regex_t* reg, const UChar* name, + const UChar* name_end, OnigRegion *region) { int i, n, *nums; @@ -905,23 +773,23 @@ onig_name_to_backref_number(regex_t* reg, UChar* name, UChar* name_end, #else /* USE_NAMED_GROUP */ extern int -onig_name_to_group_numbers(regex_t* reg, UChar* name, UChar* name_end, - int** nums) +onig_name_to_group_numbers(regex_t* reg, const UChar* name, + const UChar* name_end, int** nums) { return ONIG_NO_SUPPORT_CONFIG; } extern int -onig_name_to_backref_number(regex_t* reg, UChar* name, UChar* name_end, - OnigRegion* region) +onig_name_to_backref_number(regex_t* reg, const UChar* name, + const UChar* name_end, OnigRegion* region) { return ONIG_NO_SUPPORT_CONFIG; } extern int onig_foreach_name(regex_t* reg, - int (*func)(UChar*,UChar*,int,int*,regex_t*,void*), - void* arg) + int (*func)(const UChar*, const UChar*,int,int*,regex_t*,void*), + void* arg) { return ONIG_NO_SUPPORT_CONFIG; } @@ -1014,6 +882,7 @@ static FreeNode* FreeNodeList = (FreeNode* )NULL; extern void onig_node_free(Node* node) { + start: if (IS_NULL(node)) return ; switch (NTYPE(node)) { @@ -1026,12 +895,38 @@ onig_node_free(Node* node) case N_LIST: case N_ALT: onig_node_free(NCONS(node).left); - onig_node_free(NCONS(node).right); + /* onig_node_free(NCONS(node).right); */ + { + Node* next_node = NCONS(node).right; + +#ifdef USE_RECYCLE_NODE + { + FreeNode* n = (FreeNode* )node; + + THREAD_ATOMIC_START; + n->next = FreeNodeList; + FreeNodeList = n; + THREAD_ATOMIC_END; + } +#else + xfree(node); +#endif + + node = next_node; + goto start; + } break; case N_CCLASS: - if (NCCLASS(node).mbuf) - bbuf_free(NCCLASS(node).mbuf); + { + CClassNode* cc = &(NCCLASS(node)); + + if (IS_CCLASS_SHARE(cc)) + return ; + + if (cc->mbuf) + bbuf_free(cc->mbuf); + } break; case N_QUALIFIER: @@ -1057,11 +952,12 @@ onig_node_free(Node* node) #ifdef USE_RECYCLE_NODE { - FreeNode* n; + FreeNode* n = (FreeNode* )node; - n = (FreeNode* )node; + THREAD_ATOMIC_START; n->next = FreeNodeList; FreeNodeList = n; + THREAD_ATOMIC_END; } #else xfree(node); @@ -1092,8 +988,10 @@ node_new() #ifdef USE_RECYCLE_NODE if (IS_NOT_NULL(FreeNodeList)) { + THREAD_ATOMIC_START; node = (Node* )FreeNodeList; FreeNodeList = FreeNodeList->next; + THREAD_ATOMIC_END; return node; } #endif @@ -1107,8 +1005,8 @@ static void initialize_cclass(CClassNode* cc) { BITSET_CLEAR(cc->bs); - cc->not = 0; - cc->mbuf = NULL; + cc->flags = 0; + cc->mbuf = NULL; } static Node* @@ -1122,6 +1020,54 @@ node_new_cclass() return node; } +extern Node* +node_new_cclass_by_codepoint_range(int not, + OnigCodePoint sbr[], OnigCodePoint mbr[]) +{ + CClassNode* cc; + int n, i, j; + + Node* node = node_new(); + CHECK_NULL_RETURN(node); + node->type = N_CCLASS; + + cc = &(NCCLASS(node)); + cc->flags = 0; + if (not != 0) CCLASS_SET_NOT(cc); + + BITSET_CLEAR(cc->bs); + if (IS_NOT_NULL(sbr)) { + n = ONIGENC_CODE_RANGE_NUM(sbr); + for (i = 0; i < n; i++) { + for (j = ONIGENC_CODE_RANGE_FROM(sbr, i); + j <= (int )ONIGENC_CODE_RANGE_TO(sbr, i); j++) { + BITSET_SET_BIT(cc->bs, j); + } + } + } + + if (IS_NULL(mbr)) { + is_null: + cc->mbuf = NULL; + } + else { + BBuf* bbuf; + + n = ONIGENC_CODE_RANGE_NUM(mbr); + if (n == 0) goto is_null; + + bbuf = (BBuf* )xmalloc(sizeof(BBuf)); + CHECK_NULL_RETURN_VAL(bbuf, NULL); + bbuf->alloc = n + 1; + bbuf->used = n + 1; + bbuf->p = (UChar* )((void* )mbr); + + cc->mbuf = bbuf; + } + + return node; +} + static Node* node_new_ctype(int type) { @@ -1152,6 +1098,12 @@ node_new_list(Node* left, Node* right) return node; } +extern Node* +onig_node_new_list(Node* left, Node* right) +{ + return node_new_list(left, right); +} + static Node* node_new_alt(Node* left, Node* right) { @@ -1237,6 +1189,7 @@ node_new_qualifier(int lower, int upper, int by_number) Node* node = node_new(); CHECK_NULL_RETURN(node); node->type = N_QUALIFIER; + NQUALIFIER(node).state = 0; NQUALIFIER(node).target = NULL; NQUALIFIER(node).lower = lower; NQUALIFIER(node).upper = upper; @@ -1295,7 +1248,7 @@ node_new_option(OnigOptionType option) } extern int -onig_node_str_cat(Node* node, UChar* s, UChar* end) +onig_node_str_cat(Node* node, const UChar* s, const UChar* end) { int addlen = end - s; @@ -1350,8 +1303,22 @@ onig_node_conv_to_str_node(Node* node, int flag) NSTRING(node).end = NSTRING(node).buf; } +extern void +onig_node_str_clear(Node* node) +{ + if (NSTRING(node).capa != 0 && + IS_NOT_NULL(NSTRING(node).s) && NSTRING(node).s != NSTRING(node).buf) { + xfree(NSTRING(node).s); + } + + NSTRING(node).capa = 0; + NSTRING(node).flag = 0; + NSTRING(node).s = NSTRING(node).buf; + NSTRING(node).end = NSTRING(node).buf; +} + static Node* -node_new_str(UChar* s, UChar* end) +node_new_str(const UChar* s, const UChar* end) { Node* node = node_new(); CHECK_NULL_RETURN(node); @@ -1368,6 +1335,12 @@ node_new_str(UChar* s, UChar* end) return node; } +extern Node* +onig_node_new_str(const UChar* s, const UChar* end) +{ + return node_new_str(s, end); +} + static Node* node_new_str_raw(UChar* s, UChar* end) { @@ -1382,15 +1355,6 @@ node_new_empty() return node_new_str(NULL, NULL); } -static Node* -node_new_str_char(UChar c) -{ - UChar p[1]; - - p[0] = c; - return node_new_str(p, p + 1); -} - static Node* node_new_str_raw_char(UChar c) { @@ -1403,7 +1367,7 @@ node_new_str_raw_char(UChar c) static Node* str_node_split_last_char(StrNode* sn, OnigEncoding enc) { - UChar *p; + const UChar *p; Node* n = NULL_NODE; if (sn->end > sn->s) { @@ -1412,7 +1376,7 @@ str_node_split_last_char(StrNode* sn, OnigEncoding enc) n = node_new_str(p, sn->end); if ((sn->flag & NSTR_RAW) != 0) NSTRING_SET_RAW(n); - sn->end = p; + sn->end = (UChar* )p; } } return n; @@ -1422,17 +1386,18 @@ static int str_node_can_be_split(StrNode* sn, OnigEncoding enc) { if (sn->end > sn->s) { - return ((enc_len(enc, *(sn->s)) < sn->end - sn->s) ? 1 : 0); + return ((enc_len(enc, sn->s) < sn->end - sn->s) ? 1 : 0); } return 0; } extern int -onig_scan_unsigned_number(UChar** src, UChar* end, OnigEncoding enc) +onig_scan_unsigned_number(UChar** src, const UChar* end, OnigEncoding enc) { unsigned int num, val; - int c; + OnigCodePoint c; UChar* p = *src; + PFETCH_READY; num = 0; while (!PEND) { @@ -1457,9 +1422,10 @@ static int scan_unsigned_hexadecimal_number(UChar** src, UChar* end, int maxlen, OnigEncoding enc) { - int c; + OnigCodePoint c; unsigned int num, val; UChar* p = *src; + PFETCH_READY; num = 0; while (!PEND && maxlen-- != 0) { @@ -1484,9 +1450,10 @@ static int scan_unsigned_octal_number(UChar** src, UChar* end, int maxlen, OnigEncoding enc) { - int c; + OnigCodePoint c; unsigned int num, val; UChar* p = *src; + PFETCH_READY; num = 0; while (!PEND && maxlen-- != 0) { @@ -1622,15 +1589,15 @@ add_code_range(BBuf** pbuf, ScanEnv* env, OnigCodePoint from, OnigCodePoint to) } static int -not_code_range_buf(BBuf* bbuf, BBuf** pbuf) +not_code_range_buf(OnigEncoding enc, BBuf* bbuf, BBuf** pbuf) { int r, i, n; - OnigCodePoint pre, from, to, *data; + OnigCodePoint pre, from, *data, to = 0; *pbuf = (BBuf* )NULL; if (IS_NULL(bbuf)) { set_all: - return SET_ALL_MULTI_BYTE_RANGE(pbuf); + return SET_ALL_MULTI_BYTE_RANGE(enc, pbuf); } data = (OnigCodePoint* )(bbuf->p); @@ -1639,7 +1606,7 @@ not_code_range_buf(BBuf* bbuf, BBuf** pbuf) if (n <= 0) goto set_all; r = 0; - pre = 0x80; + pre = MBCODE_START_POS(enc); for (i = 0; i < n; i++) { from = data[i*2]; to = data[i*2+1]; @@ -1664,7 +1631,8 @@ not_code_range_buf(BBuf* bbuf, BBuf** pbuf) } while (0) static int -or_code_range_buf(BBuf* bbuf1, int not1, BBuf* bbuf2, int not2, BBuf** pbuf) +or_code_range_buf(OnigEncoding enc, BBuf* bbuf1, int not1, + BBuf* bbuf2, int not2, BBuf** pbuf) { int r; OnigCodePoint i, n1, *data1; @@ -1673,7 +1641,7 @@ or_code_range_buf(BBuf* bbuf1, int not1, BBuf* bbuf2, int not2, BBuf** pbuf) *pbuf = (BBuf* )NULL; if (IS_NULL(bbuf1) && IS_NULL(bbuf2)) { if (not1 != 0 || not2 != 0) - return SET_ALL_MULTI_BYTE_RANGE(pbuf); + return SET_ALL_MULTI_BYTE_RANGE(enc, pbuf); return 0; } @@ -1683,14 +1651,14 @@ or_code_range_buf(BBuf* bbuf1, int not1, BBuf* bbuf2, int not2, BBuf** pbuf) if (IS_NULL(bbuf1)) { if (not1 != 0) { - return SET_ALL_MULTI_BYTE_RANGE(pbuf); + return SET_ALL_MULTI_BYTE_RANGE(enc, pbuf); } else { if (not2 == 0) { return bbuf_clone(pbuf, bbuf2); } else { - return not_code_range_buf(bbuf2, pbuf); + return not_code_range_buf(enc, bbuf2, pbuf); } } } @@ -1706,7 +1674,7 @@ or_code_range_buf(BBuf* bbuf1, int not1, BBuf* bbuf2, int not2, BBuf** pbuf) r = bbuf_clone(pbuf, bbuf2); } else if (not1 == 0) { /* 1 OR (not 2) */ - r = not_code_range_buf(bbuf2, pbuf); + r = not_code_range_buf(enc, bbuf2, pbuf); } if (r != 0) return r; @@ -1816,6 +1784,29 @@ and_code_range_buf(BBuf* bbuf1, int not1, BBuf* bbuf2, int not2, BBuf** pbuf) return 0; } +static int +clear_not_flag_cclass(CClassNode* cc, OnigEncoding enc) +{ + BBuf *tbuf; + int r; + + if (IS_CCLASS_NOT(cc)) { + bitset_invert(cc->bs); + + if (! ONIGENC_IS_SINGLEBYTE(enc)) { + r = not_code_range_buf(enc, cc->mbuf, &tbuf); + if (r != 0) return r; + + bbuf_free(cc->mbuf); + cc->mbuf = tbuf; + } + + CCLASS_CLEAR_NOT(cc); + } + + return 0; +} + static int and_cclass(CClassNode* dest, CClassNode* cc, OnigEncoding enc) { @@ -1824,10 +1815,10 @@ and_cclass(CClassNode* dest, CClassNode* cc, OnigEncoding enc) BitSetRef bsr1, bsr2; BitSet bs1, bs2; - not1 = dest->not; + not1 = IS_CCLASS_NOT(dest); bsr1 = dest->bs; buf1 = dest->mbuf; - not2 = cc->not; + not2 = IS_CCLASS_NOT(cc); bsr2 = cc->bs; buf2 = cc->mbuf; @@ -1850,13 +1841,13 @@ and_cclass(CClassNode* dest, CClassNode* cc, OnigEncoding enc) if (! ONIGENC_IS_SINGLEBYTE(enc)) { if (not1 != 0 && not2 != 0) { - r = or_code_range_buf(buf1, 0, buf2, 0, &pbuf); + r = or_code_range_buf(enc, buf1, 0, buf2, 0, &pbuf); } else { r = and_code_range_buf(buf1, not1, buf2, not2, &pbuf); if (r == 0 && not1 != 0) { BBuf *tbuf; - r = not_code_range_buf(pbuf, &tbuf); + r = not_code_range_buf(enc, pbuf, &tbuf); if (r != 0) { bbuf_free(pbuf); return r; @@ -1882,10 +1873,10 @@ or_cclass(CClassNode* dest, CClassNode* cc, OnigEncoding enc) BitSetRef bsr1, bsr2; BitSet bs1, bs2; - not1 = dest->not; + not1 = IS_CCLASS_NOT(dest); bsr1 = dest->bs; buf1 = dest->mbuf; - not2 = cc->not; + not2 = IS_CCLASS_NOT(cc); bsr2 = cc->bs; buf2 = cc->mbuf; @@ -1911,10 +1902,10 @@ or_cclass(CClassNode* dest, CClassNode* cc, OnigEncoding enc) r = and_code_range_buf(buf1, 0, buf2, 0, &pbuf); } else { - r = or_code_range_buf(buf1, not1, buf2, not2, &pbuf); + r = or_code_range_buf(enc, buf1, not1, buf2, not2, &pbuf); if (r == 0 && not1 != 0) { BBuf *tbuf; - r = not_code_range_buf(pbuf, &tbuf); + r = not_code_range_buf(enc, pbuf, &tbuf); if (r != 0) { bbuf_free(pbuf); return r; @@ -2014,26 +2005,29 @@ popular_qualifier_num(QualifierNode* qf) return -1; } + +enum ReduceType { + RQ_ASIS = 0, /* as is */ + RQ_DEL = 1, /* delete parent */ + RQ_A, /* to '*' */ + RQ_AQ, /* to '*?' */ + RQ_QQ, /* to '??' */ + RQ_P_QQ, /* to '+)??' */ + RQ_PQ_Q, /* to '+?)?' */ +}; + +static enum ReduceType ReduceTypeTable[6][6] = { + {RQ_DEL, RQ_A, RQ_A, RQ_QQ, RQ_AQ, RQ_ASIS}, /* '?' */ + {RQ_DEL, RQ_DEL, RQ_DEL, RQ_P_QQ, RQ_P_QQ, RQ_DEL}, /* '*' */ + {RQ_A, RQ_A, RQ_DEL, RQ_ASIS, RQ_P_QQ, RQ_DEL}, /* '+' */ + {RQ_DEL, RQ_AQ, RQ_AQ, RQ_DEL, RQ_AQ, RQ_AQ}, /* '??' */ + {RQ_DEL, RQ_DEL, RQ_DEL, RQ_DEL, RQ_DEL, RQ_DEL}, /* '*?' */ + {RQ_ASIS, RQ_PQ_Q, RQ_DEL, RQ_AQ, RQ_AQ, RQ_DEL} /* '+?' */ +}; + extern void onig_reduce_nested_qualifier(Node* pnode, Node* cnode) { -#define NQ_ASIS 0 /* as is */ -#define NQ_DEL 1 /* delete parent */ -#define NQ_A 2 /* to '*' */ -#define NQ_AQ 3 /* to '*?' */ -#define NQ_QQ 4 /* to '??' */ -#define NQ_P_QQ 5 /* to '+)??' */ -#define NQ_PQ_Q 6 /* to '+?)?' */ - - static char reduces[][6] = { - {NQ_DEL, NQ_A, NQ_A, NQ_QQ, NQ_AQ, NQ_ASIS}, /* '?' */ - {NQ_DEL, NQ_DEL, NQ_DEL, NQ_P_QQ, NQ_P_QQ, NQ_DEL}, /* '*' */ - {NQ_A, NQ_A, NQ_DEL, NQ_ASIS, NQ_P_QQ, NQ_DEL}, /* '+' */ - {NQ_DEL, NQ_AQ, NQ_AQ, NQ_DEL, NQ_AQ, NQ_AQ}, /* '??' */ - {NQ_DEL, NQ_DEL, NQ_DEL, NQ_DEL, NQ_DEL, NQ_DEL}, /* '*?' */ - {NQ_ASIS, NQ_PQ_Q, NQ_DEL, NQ_AQ, NQ_AQ, NQ_DEL} /* '+?' */ - }; - int pnum, cnum; QualifierNode *p, *c; @@ -2042,35 +2036,35 @@ onig_reduce_nested_qualifier(Node* pnode, Node* cnode) pnum = popular_qualifier_num(p); cnum = popular_qualifier_num(c); - switch(reduces[cnum][pnum]) { - case NQ_DEL: + switch(ReduceTypeTable[cnum][pnum]) { + case RQ_DEL: *p = *c; break; - case NQ_A: + case RQ_A: p->target = c->target; p->lower = 0; p->upper = REPEAT_INFINITE; p->greedy = 1; break; - case NQ_AQ: + case RQ_AQ: p->target = c->target; p->lower = 0; p->upper = REPEAT_INFINITE; p->greedy = 0; break; - case NQ_QQ: + case RQ_QQ: p->target = c->target; p->lower = 0; p->upper = 1; p->greedy = 0; break; - case NQ_P_QQ: + case RQ_P_QQ: p->target = cnode; p->lower = 0; p->upper = 1; p->greedy = 0; c->lower = 1; c->upper = REPEAT_INFINITE; c->greedy = 1; return ; break; - case NQ_PQ_Q: + case RQ_PQ_Q: p->target = cnode; p->lower = 0; p->upper = 1; p->greedy = 1; c->lower = 1; c->upper = REPEAT_INFINITE; c->greedy = 0; return ; break; - case NQ_ASIS: + case RQ_ASIS: p->target = cnode; return ; break; @@ -2083,8 +2077,9 @@ onig_reduce_nested_qualifier(Node* pnode, Node* cnode) enum TokenSyms { TK_EOT = 0, /* end of token */ - TK_BYTE = 1, - TK_RAW_BYTE = 2, + TK_RAW_BYTE = 1, + TK_CHAR, + TK_STRING, TK_CODE_POINT, TK_ANYCHAR, TK_CHAR_TYPE, @@ -2114,6 +2109,7 @@ typedef struct { int base; /* is number: 8, 16 (used in [....]) */ UChar* backp; union { + UChar* s; int c; OnigCodePoint code; int anchor; @@ -2145,8 +2141,11 @@ static int fetch_range_qualifier(UChar** src, UChar* end, OnigToken* tok, ScanEnv* env) { int low, up, syn_allow, non_low = 0; - int c; + int r = 0; + OnigCodePoint c; + OnigEncoding enc = env->enc; UChar* p = *src; + PFETCH_READY; syn_allow = IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_INVALID_INTERVAL); @@ -2200,12 +2199,13 @@ fetch_range_qualifier(UChar** src, UChar* end, OnigToken* tok, ScanEnv* env) PUNFETCH; up = low; /* {n} : exact n times */ + r = 2; /* fixed */ } if (PEND) goto invalid; PFETCH(c); if (IS_SYNTAX_OP(env->syntax, ONIG_SYN_OP_ESC_BRACE_INTERVAL)) { - if (c != MC_ESC) goto invalid; + if (c != MC_ESC(enc)) goto invalid; PFETCH(c); } if (c != '}') goto invalid; @@ -2218,7 +2218,7 @@ fetch_range_qualifier(UChar** src, UChar* end, OnigToken* tok, ScanEnv* env) tok->u.repeat.lower = low; tok->u.repeat.upper = up; *src = p; - return 0; + return r; /* 0: normal {n,m}, 2: fixed {n} */ invalid: if (syn_allow) @@ -2231,10 +2231,13 @@ fetch_range_qualifier(UChar** src, UChar* end, OnigToken* tok, ScanEnv* env) static int fetch_escaped_value(UChar** src, UChar* end, ScanEnv* env) { - int c; + int v; + OnigCodePoint c; + OnigEncoding enc = env->enc; UChar* p = *src; + PFETCH_READY; - if (PEND) return ONIGERR_END_PATTERN_AT_BACKSLASH; + if (PEND) return ONIGERR_END_PATTERN_AT_ESCAPE; PFETCH(c); switch (c) { @@ -2245,9 +2248,10 @@ fetch_escaped_value(UChar** src, UChar* end, ScanEnv* env) if (c != '-') return ONIGERR_META_CODE_SYNTAX; if (PEND) return ONIGERR_END_PATTERN_AT_META; PFETCH(c); - if (c == MC_ESC) { - c = fetch_escaped_value(&p, end, env); - if (c < 0) return c; + if (c == MC_ESC(enc)) { + v = fetch_escaped_value(&p, end, env); + if (v < 0) return v; + c = (OnigCodePoint )v; } c = ((c & 0xff) | 0x80); } @@ -2270,9 +2274,10 @@ fetch_escaped_value(UChar** src, UChar* end, ScanEnv* env) control: if (PEND) return ONIGERR_END_PATTERN_AT_CONTROL; PFETCH(c); - if (c == MC_ESC) { - c = fetch_escaped_value(&p, end, env); - if (c < 0) return c; + if (c == MC_ESC(enc)) { + v = fetch_escaped_value(&p, end, env); + if (v < 0) return v; + c = (OnigCodePoint )v; } else if (c == '?') c = 0177; @@ -2304,10 +2309,13 @@ static int fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env); static int fetch_name(UChar** src, UChar* end, UChar** rname_end, ScanEnv* env, int ref) { - int r, len, is_num; - int c = 0; + int r, is_num; + OnigCodePoint c = 0; + OnigCodePoint first_code; + OnigEncoding enc = env->enc; UChar *name_end; UChar *p = *src; + PFETCH_READY; name_end = end; r = 0; @@ -2317,19 +2325,20 @@ fetch_name(UChar** src, UChar* end, UChar** rname_end, ScanEnv* env, int ref) } else { PFETCH(c); + first_code = c; if (c == '>') return ONIGERR_EMPTY_GROUP_NAME; - if (ONIGENC_IS_CODE_DIGIT(env->enc, c)) { + if (ONIGENC_IS_CODE_DIGIT(enc, c)) { if (ref == 1) is_num = 1; else { r = ONIGERR_INVALID_GROUP_NAME; } } - len = enc_len(env->enc, c); - while (!PEND && len-- > 1) - PFETCH(c); + else if (!ONIGENC_IS_CODE_WORD(enc, c)) { + r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME; + } } while (!PEND) { @@ -2337,35 +2346,28 @@ fetch_name(UChar** src, UChar* end, UChar** rname_end, ScanEnv* env, int ref) PFETCH(c); if (c == '>' || c == ')') break; - len = enc_len(env->enc, c); if (is_num == 1) { - if (! ONIGENC_IS_CODE_DIGIT(env->enc, c)) { - if (!ONIGENC_IS_CODE_ALPHA(env->enc, c) && c != '_') + if (! ONIGENC_IS_CODE_DIGIT(enc, c)) { + if (!ONIGENC_IS_CODE_WORD(enc, c)) r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME; else r = ONIGERR_INVALID_GROUP_NAME; } } else { - if (len == 1) { - if (!ONIGENC_IS_CODE_ALPHA(env->enc, c) && - !ONIGENC_IS_CODE_DIGIT(env->enc, c) && - c != '_') { - r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME; - } + if (!ONIGENC_IS_CODE_WORD(enc, c)) { + r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME; } } - - while (!PEND && len-- > 1) - PFETCH(c); } + if (c != '>') { r = ONIGERR_INVALID_GROUP_NAME; name_end = end; } else { - c = **src; - if (ONIGENC_IS_CODE_UPPER(env->enc, c)) + if (ONIGENC_IS_CODE_ASCII(first_code) && + ONIGENC_IS_CODE_UPPER(enc, first_code)) r = ONIGERR_INVALID_GROUP_NAME; } @@ -2384,19 +2386,21 @@ static int fetch_name(UChar** src, UChar* end, UChar** rname_end, ScanEnv* env, int ref) { int r, len; - int c = 0; + OnigCodePoint c = 0; UChar *name_end; + OnigEncoding enc = env->enc; UChar *p = *src; + PFETCH_READY; r = 0; while (!PEND) { name_end = p; - PFETCH(c); - if (enc_len(env->enc, c) > 1) + if (enc_len(enc, p) > 1) r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME; + PFETCH(c); if (c == '>' || c == ')') break; - if (! ONIGENC_IS_CODE_DIGIT(env->enc, c)) + if (! ONIGENC_IS_CODE_DIGIT(enc, c)) r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME; } if (c != '>') { @@ -2457,12 +2461,12 @@ find_str_position(OnigCodePoint s[], int n, UChar* from, UChar* to, while (p < to) { x = ONIGENC_MBC_TO_CODE(enc, p, to); - q = p + enc_len(enc, *p); + q = p + enc_len(enc, p); if (x == s[0]) { for (i = 1; i < n && q < to; i++) { x = ONIGENC_MBC_TO_CODE(enc, q, to); if (x != s[i]) break; - q += enc_len(enc, *q); + q += enc_len(enc, q); } if (i >= n) { if (IS_NOT_NULL(next)) @@ -2488,24 +2492,24 @@ str_exist_check_with_esc(OnigCodePoint s[], int n, UChar* from, UChar* to, while (p < to) { if (in_esc) { in_esc = 0; - p += enc_len(enc, *p); + p += enc_len(enc, p); } else { x = ONIGENC_MBC_TO_CODE(enc, p, to); - q = p + enc_len(enc, *p); + q = p + enc_len(enc, p); if (x == s[0]) { for (i = 1; i < n && q < to; i++) { x = ONIGENC_MBC_TO_CODE(enc, q, to); if (x != s[i]) break; - q += enc_len(enc, *q); + q += enc_len(enc, q); } if (i >= n) return 1; - p += enc_len(enc, *p); + p += enc_len(enc, p); } else { x = ONIGENC_MBC_TO_CODE(enc, p, to); if (x == bad) return 0; - else if (x == MC_ESC) in_esc = 1; + else if (x == MC_ESC(enc)) in_esc = 1; p = q; } } @@ -2516,10 +2520,13 @@ str_exist_check_with_esc(OnigCodePoint s[], int n, UChar* from, UChar* to, static int fetch_token_in_cc(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) { - int c, num; + int num; + OnigCodePoint c, c2; OnigSyntaxType* syn = env->syntax; + OnigEncoding enc = env->enc; UChar* prev; UChar* p = *src; + PFETCH_READY; if (PEND) { tok->type = TK_EOT; @@ -2527,7 +2534,7 @@ fetch_token_in_cc(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) } PFETCH(c); - tok->type = TK_BYTE; + tok->type = TK_CHAR; tok->base = 0; tok->u.c = c; if (c == ']') { @@ -2536,11 +2543,11 @@ fetch_token_in_cc(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) else if (c == '-') { tok->type = TK_CC_RANGE; } - else if (c == MC_ESC) { + else if (c == MC_ESC(enc)) { if (! IS_SYNTAX_BV(syn, ONIG_SYN_BACKSLASH_ESCAPE_IN_CC)) goto end; - if (PEND) return ONIGERR_END_PATTERN_AT_BACKSLASH; + if (PEND) return ONIGERR_END_PATTERN_AT_ESCAPE; PFETCH(c); tok->escaped = 1; @@ -2570,14 +2577,34 @@ fetch_token_in_cc(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) tok->type = TK_CHAR_TYPE; tok->u.subtype = CTYPE_NOT_WHITE_SPACE; break; + case 'h': + if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_H_XDIGIT)) break; + tok->type = TK_CHAR_TYPE; + tok->u.subtype = CTYPE_XDIGIT; + break; + case 'H': + if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_H_XDIGIT)) break; + tok->type = TK_CHAR_TYPE; + tok->u.subtype = CTYPE_NOT_XDIGIT; + break; case 'p': case 'P': - if (PPEEK == '{' && - IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_CHAR_PROPERTY)) { + c2 = PPEEK; + if (c2 == '{' && + IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY)) { PINC; tok->type = TK_CHAR_PROPERTY; tok->u.prop.not = (c == 'P' ? 1 : 0); + + if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT)) { + PFETCH(c2); + if (c2 == '^') { + tok->u.prop.not = (tok->u.prop.not == 0 ? 1 : 0); + } + else + PUNFETCH; + } } break; @@ -2585,14 +2612,17 @@ fetch_token_in_cc(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) if (PEND) break; prev = p; - if (PPEEK == '{' && IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_X_BRACE_HEX8)) { + if (PPEEK_IS('{') && IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_X_BRACE_HEX8)) { PINC; - num = scan_unsigned_hexadecimal_number(&p, end, 8, env->enc); + num = scan_unsigned_hexadecimal_number(&p, end, 8, enc); if (num < 0) return ONIGERR_TOO_BIG_WIDE_CHAR_VALUE; - if (!PEND && ONIGENC_IS_CODE_XDIGIT(env->enc, *p) && p - prev >= 9) - return ONIGERR_TOO_LONG_WIDE_CHAR_VALUE; + if (!PEND) { + c2 = PPEEK; + if (ONIGENC_IS_CODE_XDIGIT(enc, c2)) + return ONIGERR_TOO_LONG_WIDE_CHAR_VALUE; + } - if (p > prev + 1 && !PEND && PPEEK == '}') { + if (p > prev + enc_len(enc, prev) && !PEND && (PPEEK_IS('}'))) { PINC; tok->type = TK_CODE_POINT; tok->base = 16; @@ -2604,7 +2634,7 @@ fetch_token_in_cc(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) } } else if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_X_HEX2)) { - num = scan_unsigned_hexadecimal_number(&p, end, 2, env->enc); + num = scan_unsigned_hexadecimal_number(&p, end, 2, enc); if (num < 0) return ONIGERR_TOO_BIG_NUMBER; if (p == prev) { /* can't read nothing. */ num = 0; /* but, it's not error */ @@ -2620,14 +2650,14 @@ fetch_token_in_cc(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) prev = p; if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_U_HEX4)) { - num = scan_unsigned_hexadecimal_number(&p, end, 4, env->enc); + num = scan_unsigned_hexadecimal_number(&p, end, 4, enc); if (num < 0) return ONIGERR_TOO_BIG_NUMBER; if (p == prev) { /* can't read nothing. */ num = 0; /* but, it's not error */ } - tok->type = TK_RAW_BYTE; - tok->base = 16; - tok->u.c = num; + tok->type = TK_CODE_POINT; + tok->base = 16; + tok->u.code = (OnigCodePoint )num; } break; @@ -2636,7 +2666,7 @@ fetch_token_in_cc(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_OCTAL3)) { PUNFETCH; prev = p; - num = scan_unsigned_octal_number(&p, end, 3, env->enc); + num = scan_unsigned_octal_number(&p, end, 3, enc); if (num < 0) return ONIGERR_TOO_BIG_NUMBER; if (p == prev) { /* can't read nothing. */ num = 0; /* but, it's not error */ @@ -2652,19 +2682,19 @@ fetch_token_in_cc(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) num = fetch_escaped_value(&p, end, env); if (num < 0) return num; if (tok->u.c != num) { - tok->u.c = num; - tok->type = TK_RAW_BYTE; + tok->u.code = (OnigCodePoint )num; + tok->type = TK_CODE_POINT; } break; } } else if (c == '[') { - if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_POSIX_BRACKET) && PPEEK == ':') { + if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_POSIX_BRACKET) && (PPEEK_IS(':'))) { OnigCodePoint send[] = { (OnigCodePoint )':', (OnigCodePoint )']' }; tok->backp = p; /* point at '[' is readed */ PINC; - if (str_exist_check_with_esc(send, 2, p, end, (OnigCodePoint )']', - env->enc)) { + if (str_exist_check_with_esc(send, 2, p, end, + (OnigCodePoint )']', enc)) { tok->type = TK_POSIX_BRACKET_OPEN; } else { @@ -2684,7 +2714,7 @@ fetch_token_in_cc(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) } else if (c == '&') { if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_CCLASS_SET_OP) && - !PEND && PPEEK == '&') { + !PEND && (PPEEK_IS('&'))) { PINC; tok->type = TK_CC_AND; } @@ -2698,10 +2728,13 @@ fetch_token_in_cc(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) static int fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) { - int r, c, num; + int r, num; + OnigCodePoint c; + OnigEncoding enc = env->enc; OnigSyntaxType* syn = env->syntax; UChar* prev; UChar* p = *src; + PFETCH_READY; start: if (PEND) { @@ -2709,13 +2742,17 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) return tok->type; } - tok->type = TK_BYTE; - tok->base = 0; + tok->type = TK_STRING; + tok->base = 0; + tok->backp = p; + PFETCH(c); - if (c == MC_ESC) { - if (PEND) return ONIGERR_END_PATTERN_AT_BACKSLASH; + if (c == MC_ESC(enc)) { + if (PEND) return ONIGERR_END_PATTERN_AT_ESCAPE; + tok->backp = p; PFETCH(c); + tok->u.c = c; tok->escaped = 1; switch (c) { @@ -2741,37 +2778,42 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) tok->u.repeat.lower = 0; tok->u.repeat.upper = 1; greedy_check: - if (!PEND && PPEEK == '?' && + if (!PEND && PPEEK_IS('?') && IS_SYNTAX_OP(syn, ONIG_SYN_OP_QMARK_NON_GREEDY)) { PFETCH(c); tok->u.repeat.greedy = 0; tok->u.repeat.possessive = 0; } - else if (!PEND && PPEEK == '+' && - ((IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_PLUS_POSSESSIVE_REPEAT) && - tok->type != TK_INTERVAL) || - (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_PLUS_POSSESSIVE_INTERVAL) && - tok->type == TK_INTERVAL))) { - PFETCH(c); - tok->u.repeat.greedy = 1; - tok->u.repeat.possessive = 1; - } else { - tok->u.repeat.greedy = 1; - tok->u.repeat.possessive = 0; + possessive_check: + if (!PEND && PPEEK_IS('+') && + ((IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_PLUS_POSSESSIVE_REPEAT) && + tok->type != TK_INTERVAL) || + (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_PLUS_POSSESSIVE_INTERVAL) && + tok->type == TK_INTERVAL))) { + PFETCH(c); + tok->u.repeat.greedy = 1; + tok->u.repeat.possessive = 1; + } + else { + tok->u.repeat.greedy = 1; + tok->u.repeat.possessive = 0; + } } break; case '{': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_BRACE_INTERVAL)) break; - tok->backp = p; r = fetch_range_qualifier(&p, end, tok, env); if (r < 0) return r; /* error */ - if (r > 0) { - /* normal char */ - } - else + if (r == 0) goto greedy_check; + else if (r == 2) { /* {n} */ + if (IS_SYNTAX_BV(syn, ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY)) + goto possessive_check; + goto greedy_check; + } + /* r == 1 : normal char */ break; case '|': @@ -2851,6 +2893,18 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) tok->u.subtype = CTYPE_NOT_DIGIT; break; + case 'h': + if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_H_XDIGIT)) break; + tok->type = TK_CHAR_TYPE; + tok->u.subtype = CTYPE_XDIGIT; + break; + + case 'H': + if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_H_XDIGIT)) break; + tok->type = TK_CHAR_TYPE; + tok->u.subtype = CTYPE_NOT_XDIGIT; + break; + case 'A': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_AZ_BUF_ANCHOR)) break; begin_buf: @@ -2891,14 +2945,16 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) if (PEND) break; prev = p; - if (PPEEK == '{' && IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_X_BRACE_HEX8)) { + if (PPEEK_IS('{') && IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_X_BRACE_HEX8)) { PINC; - num = scan_unsigned_hexadecimal_number(&p, end, 8, env->enc); + num = scan_unsigned_hexadecimal_number(&p, end, 8, enc); if (num < 0) return ONIGERR_TOO_BIG_WIDE_CHAR_VALUE; - if (!PEND && ONIGENC_IS_CODE_XDIGIT(env->enc, *p) && p - prev >= 9) - return ONIGERR_TOO_LONG_WIDE_CHAR_VALUE; + if (!PEND) { + if (ONIGENC_IS_CODE_XDIGIT(enc, PPEEK)) + return ONIGERR_TOO_LONG_WIDE_CHAR_VALUE; + } - if (p > prev + 1 && !PEND && PPEEK == '}') { + if ((p > prev + enc_len(enc, prev)) && !PEND && PPEEK_IS('}')) { PINC; tok->type = TK_CODE_POINT; tok->u.code = (OnigCodePoint )num; @@ -2909,7 +2965,7 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) } } else if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_X_HEX2)) { - num = scan_unsigned_hexadecimal_number(&p, end, 2, env->enc); + num = scan_unsigned_hexadecimal_number(&p, end, 2, enc); if (num < 0) return ONIGERR_TOO_BIG_NUMBER; if (p == prev) { /* can't read nothing. */ num = 0; /* but, it's not error */ @@ -2925,14 +2981,14 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) prev = p; if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_U_HEX4)) { - num = scan_unsigned_hexadecimal_number(&p, end, 4, env->enc); + num = scan_unsigned_hexadecimal_number(&p, end, 4, enc); if (num < 0) return ONIGERR_TOO_BIG_NUMBER; if (p == prev) { /* can't read nothing. */ num = 0; /* but, it's not error */ } - tok->type = TK_RAW_BYTE; - tok->base = 16; - tok->u.c = num; + tok->type = TK_CODE_POINT; + tok->base = 16; + tok->u.code = (OnigCodePoint )num; } break; @@ -2940,9 +2996,10 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) case '5': case '6': case '7': case '8': case '9': PUNFETCH; prev = p; - num = onig_scan_unsigned_number(&p, end, env->enc); - if (num < 0) return ONIGERR_TOO_BIG_NUMBER; - if (num > ONIG_MAX_BACKREF_NUM) return ONIGERR_TOO_BIG_BACKREF_NUMBER; + num = onig_scan_unsigned_number(&p, end, enc); + if (num < 0 || num > ONIG_MAX_BACKREF_NUM) { + goto skip_backref; + } if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_DECIMAL_BACKREF) && (num <= env->num_mem || num <= 9)) { /* This spec. from GNU regex */ @@ -2957,7 +3014,9 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) tok->u.backref.by_name = 0; break; } - else if (c == '8' || c == '9') { + + skip_backref: + if (c == '8' || c == '9') { /* normal char */ p = prev; PINC; break; @@ -2968,7 +3027,7 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) case '0': if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_OCTAL3)) { prev = p; - num = scan_unsigned_octal_number(&p, end, (c == '0' ? 2:3), env->enc); + num = scan_unsigned_octal_number(&p, end, (c == '0' ? 2:3), enc); if (num < 0) return ONIGERR_TOO_BIG_NUMBER; if (p == prev) { /* can't read nothing. */ num = 0; /* but, it's not error */ @@ -3054,11 +3113,20 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) case 'p': case 'P': - if (PPEEK == '{' && - IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_CHAR_PROPERTY)) { + if (PPEEK_IS('{') && + IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY)) { PINC; tok->type = TK_CHAR_PROPERTY; tok->u.prop.not = (c == 'P' ? 1 : 0); + + if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT)) { + PFETCH(c); + if (c == '^') { + tok->u.prop.not = (tok->u.prop.not == 0 ? 1 : 0); + } + else + PUNFETCH; + } } break; @@ -3068,8 +3136,11 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) if (num < 0) return num; /* set_raw: */ if (tok->u.c != num) { - tok->type = TK_RAW_BYTE; - tok->u.c = num; + tok->type = TK_CODE_POINT; + tok->u.code = (OnigCodePoint )num; + } + else { /* string */ + p = tok->backp + enc_len(enc, tok->backp); } break; } @@ -3081,15 +3152,15 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) #ifdef USE_VARIABLE_META_CHARS if ((c != ONIG_INEFFECTIVE_META_CHAR) && IS_SYNTAX_OP(syn, ONIG_SYN_OP_VARIABLE_META_CHARACTERS)) { - if (c == MC_ANYCHAR) + if (c == MC_ANYCHAR(enc)) goto any_char; - else if (c == MC_ANYTIME) + else if (c == MC_ANYTIME(enc)) goto anytime; - else if (c == MC_ZERO_OR_ONE_TIME) + else if (c == MC_ZERO_OR_ONE_TIME(enc)) goto zero_or_one_time; - else if (c == MC_ONE_OR_MORE_TIME) + else if (c == MC_ONE_OR_MORE_TIME(enc)) goto one_or_more_time; - else if (c == MC_ANYCHAR_ANYTIME) { + else if (c == MC_ANYCHAR_ANYTIME(enc)) { tok->type = TK_ANYCHAR_ANYTIME; goto out; } @@ -3132,14 +3203,16 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) case '{': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_BRACE_INTERVAL)) break; - tok->backp = p; r = fetch_range_qualifier(&p, end, tok, env); if (r < 0) return r; /* error */ - if (r > 0) { - /* normal char */ - } - else + if (r == 0) goto greedy_check; + else if (r == 2) { /* {n} */ + if (IS_SYNTAX_BV(syn, ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY)) + goto possessive_check; + goto greedy_check; + } + /* r == 1 : normal char */ break; case '|': @@ -3148,6 +3221,26 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) break; case '(': + if (PPEEK_IS('?') && + IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_QMARK_GROUP_EFFECT)) { + PINC; + if (PPEEK_IS('#')) { + PFETCH(c); + while (1) { + if (PEND) return ONIGERR_END_PATTERN_IN_GROUP; + PFETCH(c); + if (c == MC_ESC(enc)) { + if (!PEND) PFETCH(c); + } + else { + if (c == ')') break; + } + } + goto start; + } + PUNFETCH; + } + if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_LPAREN_SUBEXP)) break; tok->type = TK_SUBEXP_OPEN; break; @@ -3185,7 +3278,7 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) if (IS_EXTEND(env->option)) { while (!PEND) { PFETCH(c); - if (ONIG_IS_NEWLINE(c)) + if (ONIGENC_IS_CODE_NEWLINE(enc, c)) break; } goto start; @@ -3199,6 +3292,7 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) break; default: + /* string */ break; } } @@ -3209,48 +3303,57 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) } static int -add_ctype_to_cc_by_list(CClassNode* cc, int ctype, int not, - OnigEncoding enc) +add_ctype_to_cc_by_range(CClassNode* cc, int ctype, int not, OnigEncoding enc, + OnigCodePoint sbr[], OnigCodePoint mbr[]) { - int i, r, nsb, nmb; - OnigCodePointRange *sbr, *mbr; + int i, r; OnigCodePoint j; - r = ONIGENC_GET_CTYPE_CODE_RANGE(enc, ctype, &nsb, &nmb, &sbr, &mbr); - if (r != 0) return r; + int nsb = ONIGENC_CODE_RANGE_NUM(sbr); + int nmb = ONIGENC_CODE_RANGE_NUM(mbr); if (not == 0) { for (i = 0; i < nsb; i++) { - for (j = sbr[i].from; j <= sbr[i].to; j++) { - BITSET_SET_BIT(cc->bs, j); + for (j = ONIGENC_CODE_RANGE_FROM(sbr, i); + j <= ONIGENC_CODE_RANGE_TO(sbr, i); j++) { + BITSET_SET_BIT(cc->bs, j); } } + for (i = 0; i < nmb; i++) { - r = add_code_range_to_buf(&(cc->mbuf), mbr[i].from, mbr[i].to); + r = add_code_range_to_buf(&(cc->mbuf), + ONIGENC_CODE_RANGE_FROM(mbr, i), + ONIGENC_CODE_RANGE_TO(mbr, i)); if (r != 0) return r; } } else { OnigCodePoint prev = 0; - for (i = 0; i < nsb; i++) { - for (j = prev; j < sbr[i].from; j++) { - BITSET_SET_BIT(cc->bs, j); + + if (ONIGENC_MBC_MINLEN(enc) == 1) { + for (i = 0; i < nsb; i++) { + for (j = prev; + j < ONIGENC_CODE_RANGE_FROM(sbr, i); j++) { + BITSET_SET_BIT(cc->bs, j); + } + prev = ONIGENC_CODE_RANGE_TO(sbr, i) + 1; } - prev = sbr[i].to + 1; - } - if (prev < 0x7f) { - for (j = prev; j < 0x7f; j++) { - BITSET_SET_BIT(cc->bs, j); + if (prev < 0x7f) { + for (j = prev; j < 0x7f; j++) { + BITSET_SET_BIT(cc->bs, j); + } } + + prev = 0x80; } - prev = 0x80; for (i = 0; i < nmb; i++) { - if (prev < mbr[i].from) { - r = add_code_range_to_buf(&(cc->mbuf), prev, mbr[i].from - 1); + if (prev < ONIGENC_CODE_RANGE_FROM(mbr, i)) { + r = add_code_range_to_buf(&(cc->mbuf), prev, + ONIGENC_CODE_RANGE_FROM(mbr, i) - 1); if (r != 0) return r; } - prev = mbr[i].to + 1; + prev = ONIGENC_CODE_RANGE_TO(mbr, i) + 1; } if (prev < 0x7fffffff) { r = add_code_range_to_buf(&(cc->mbuf), prev, 0x7fffffff); @@ -3258,17 +3361,21 @@ add_ctype_to_cc_by_list(CClassNode* cc, int ctype, int not, } } - return r; + return 0; } static int add_ctype_to_cc(CClassNode* cc, int ctype, int not, ScanEnv* env) { int c, r; + OnigCodePoint *sbr, *mbr; OnigEncoding enc = env->enc; - if (ONIGENC_CTYPE_SUPPORT_LEVEL(enc) != ONIGENC_CTYPE_SUPPORT_LEVEL_SB) { - r = add_ctype_to_cc_by_list(cc, ctype, not, env->enc); + r = ONIGENC_GET_CTYPE_CODE_RANGE(enc, ctype, &sbr, &mbr); + if (r == 0) { + return add_ctype_to_cc_by_range(cc, ctype, not, env->enc, sbr, mbr); + } + else if (r != ONIG_NO_SUPPORT_CONFIG) { return r; } @@ -3326,7 +3433,8 @@ add_ctype_to_cc(CClassNode* cc, int ctype, int not, ScanEnv* env) } else { for (c = 0; c < SINGLE_BYTE_SIZE; c++) { - if (! ONIGENC_IS_CODE_SB_WORD(enc, c) && ! ONIGENC_IS_MBC_HEAD(enc, c)) + if ((ONIGENC_CODE_TO_MBCLEN(enc, c) > 0) /* 0: invalid code point */ + && ! ONIGENC_IS_CODE_WORD(enc, c)) BITSET_SET_BIT(cc->bs, c); } } @@ -3370,6 +3478,14 @@ parse_ctype_to_enc_ctype(int pctype, int* not) ctype = ONIGENC_CTYPE_DIGIT; *not = 1; break; + case CTYPE_XDIGIT: + ctype = ONIGENC_CTYPE_XDIGIT; + *not = 0; + break; + case CTYPE_NOT_XDIGIT: + ctype = ONIGENC_CTYPE_XDIGIT; + *not = 1; + break; default: return ONIGERR_PARSER_BUG; break; @@ -3407,23 +3523,26 @@ parse_posix_bracket(CClassNode* cc, UChar** src, UChar* end, ScanEnv* env) }; PosixBracketEntryType *pb; - int not, i, c, r; + int not, i, r; + OnigCodePoint c; + OnigEncoding enc = env->enc; UChar *p = *src; + PFETCH_READY; - if (PPEEK == '^') { + if (PPEEK_IS('^')) { PINC; not = 1; } else not = 0; - if (end - p < POSIX_BRACKET_NAME_MAX_LEN + 1) + if (onigenc_strlen(enc, p, end) < POSIX_BRACKET_NAME_MAX_LEN + 2) goto not_posix_bracket; for (pb = PBS; IS_NOT_NULL(pb->name); pb++) { - if (onig_strncmp(p, pb->name, pb->len) == 0) { - p += pb->len; - if (end - p < 2 || *p != ':' || *(p+1) != ']') + if (onigenc_with_ascii_strncmp(enc, p, end, pb->name, pb->len) == 0) { + p = (UChar* )onigenc_step(enc, p, end, pb->len); + if (onigenc_with_ascii_strncmp(enc, p, end, ":]", 2) != 0) return ONIGERR_INVALID_POSIX_BRACKET_TYPE; r = add_ctype_to_cc(cc, pb->ctype, not, env); @@ -3442,9 +3561,9 @@ parse_posix_bracket(CClassNode* cc, UChar** src, UChar* end, ScanEnv* env) PINC; if (++i > POSIX_BRACKET_CHECK_LIMIT_LENGTH) break; } - if (c == ':' && !PEND) { + if (c == ':' && ! PEND) { PINC; - if (!PEND) { + if (! PEND) { PFETCH(c); if (c == ']') return ONIGERR_INVALID_POSIX_BRACKET_TYPE; @@ -3455,7 +3574,7 @@ parse_posix_bracket(CClassNode* cc, UChar** src, UChar* end, ScanEnv* env) } static int -property_name_to_ctype(UChar* p, UChar* end) +property_name_to_ctype(UChar* p, UChar* end, OnigEncoding enc) { static PosixBracketEntryType PBS[] = { { "Alnum", ONIGENC_CTYPE_ALNUM, 5 }, @@ -3477,28 +3596,49 @@ property_name_to_ctype(UChar* p, UChar* end) PosixBracketEntryType *pb; int len; - len = end - p; + len = onigenc_strlen(enc, p, end); for (pb = PBS; IS_NOT_NULL(pb->name); pb++) { - if (len == pb->len && onig_strncmp(p, pb->name, pb->len) == 0) + if (len == pb->len && + onigenc_with_ascii_strncmp(enc, p, end, pb->name, pb->len) == 0) return pb->ctype; } - return ONIGERR_INVALID_CHAR_PROPERTY_NAME; + return -1; } static int fetch_char_property_to_ctype(UChar** src, UChar* end, ScanEnv* env) { int ctype; - UChar *prev, *p = *src; - int c = 0; + OnigCodePoint c; + OnigEncoding enc = env->enc; + UChar *prev, *start, *p = *src; + PFETCH_READY; + + /* 'IsXXXX' => 'XXXX' */ + if (!PEND && + IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_CHAR_PROPERTY_PREFIX_IS)) { + c = PPEEK; + if (c == 'I') { + PINC; + if (! PEND) { + c = PPEEK; + if (c == 's') + PINC; + else + PUNFETCH; + } + } + } + + start = prev = p; while (!PEND) { prev = p; PFETCH(c); if (c == '}') { - ctype = property_name_to_ctype(*src, prev); - if (ctype < 0) return ctype; + ctype = property_name_to_ctype(start, prev, enc); + if (ctype < 0) break; *src = p; return ctype; @@ -3507,6 +3647,8 @@ fetch_char_property_to_ctype(UChar** src, UChar* end, ScanEnv* env) break; } + onig_scan_env_set_error_string(env, ONIGERR_INVALID_CHAR_PROPERTY_NAME, + *src, prev); return ONIGERR_INVALID_CHAR_PROPERTY_NAME; } @@ -3588,6 +3730,9 @@ next_state_val(CClassNode* cc, OnigCodePoint *vs, OnigCodePoint v, case CCS_RANGE: if (intype == *type) { if (intype == CCV_SB) { + if (*vs > 0xff || v > 0xff) + return ONIGERR_INVALID_WIDE_CHAR_VALUE; + if (*vs > v) { if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC)) goto ccs_range_end; @@ -3602,14 +3747,23 @@ next_state_val(CClassNode* cc, OnigCodePoint *vs, OnigCodePoint v, } } else { - if (intype == CCV_CODE_POINT && *type == CCV_SB && - ONIGENC_IS_CONTINUOUS_SB_MB(env->enc)) { - bitset_set_range(cc->bs, (int )*vs, 0x7f); - r = add_code_range(&(cc->mbuf), env, (OnigCodePoint )0x80, v); +#if 0 + if (intype == CCV_CODE_POINT && *type == CCV_SB) { +#endif + if (*vs > v) { + if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC)) + goto ccs_range_end; + else + return ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS; + } + bitset_set_range(cc->bs, (int )*vs, (int )(v < 0xff ? v : 0xff)); + r = add_code_range(&(cc->mbuf), env, (OnigCodePoint )*vs, v); if (r < 0) return r; +#if 0 } else return ONIGERR_MISMATCH_CODE_LENGTH_IN_CLASS_RANGE; +#endif } ccs_range_end: *state = CCS_COMPLETE; @@ -3631,22 +3785,24 @@ next_state_val(CClassNode* cc, OnigCodePoint *vs, OnigCodePoint v, } static int -char_exist_check(UChar c, UChar* from, UChar* to, int ignore_escaped, +code_exist_check(OnigCodePoint c, UChar* from, UChar* end, int ignore_escaped, OnigEncoding enc) { int in_esc; + OnigCodePoint code; UChar* p = from; + PFETCH_READY; in_esc = 0; - while (p < to) { + while (! PEND) { if (ignore_escaped && in_esc) { in_esc = 0; } else { - if (*p == c) return 1; - if (*p == MC_ESC) in_esc = 1; + PFETCH(code); + if (code == c) return 1; + if (code == MC_ESC(enc)) in_esc = 1; } - p += enc_len(enc, *p); } return 0; } @@ -3669,7 +3825,7 @@ parse_char_class(Node** np, OnigToken* tok, UChar** src, UChar* end, prev_cc = (CClassNode* )NULL; *np = NULL_NODE; r = fetch_token_in_cc(tok, src, end, env); - if (r == TK_BYTE && tok->u.c == '^' && tok->escaped == 0) { + if (r == TK_CHAR && tok->u.c == '^' && tok->escaped == 0) { neg = 1; r = fetch_token_in_cc(tok, src, end, env); } @@ -3679,11 +3835,12 @@ parse_char_class(Node** np, OnigToken* tok, UChar** src, UChar* end, if (r < 0) return r; if (r == TK_CC_CLOSE) { - if (! char_exist_check(']', *src, env->pattern_end, 1, env->enc)) + if (! code_exist_check((OnigCodePoint )']', + *src, env->pattern_end, 1, env->enc)) return ONIGERR_EMPTY_CHAR_CLASS; CC_ESC_WARN(env, "]"); - r = tok->type = TK_BYTE; /* allow []...] */ + r = tok->type = TK_CHAR; /* allow []...] */ } *np = node = node_new_cclass(); @@ -3696,58 +3853,69 @@ parse_char_class(Node** np, OnigToken* tok, UChar** src, UChar* end, while (r != TK_CC_CLOSE) { fetched = 0; switch (r) { - case TK_BYTE: - len = enc_len(env->enc, tok->u.c); + case TK_CHAR: + len = ONIGENC_CODE_TO_MBCLEN(env->enc, tok->u.c); if (len > 1) { - PUNFETCH; - v = ONIGENC_MBC_TO_CODE(env->enc, p, end); - p += len; in_type = CCV_CODE_POINT; } else { sb_char: - v = (OnigCodePoint )tok->u.c; in_type = CCV_SB; } + v = (OnigCodePoint )tok->u.c; in_israw = 0; goto val_entry2; break; case TK_RAW_BYTE: - len = enc_len(env->enc, tok->u.c); - if (len > 1 && tok->base != 0) { /* tok->base != 0 : octal or hexadec. */ + /* tok->base != 0 : octal or hexadec. */ + if (! ONIGENC_IS_SINGLEBYTE(env->enc) && tok->base != 0) { UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN]; - UChar* bufp = buf; UChar* bufe = buf + ONIGENC_CODE_TO_MBC_MAXLEN; + UChar* psave = p; int i, base = tok->base; - if (len > ONIGENC_CODE_TO_MBC_MAXLEN) { - bufp = (UChar* )xmalloc(len); - if (IS_NULL(bufp)) { - r = ONIGERR_MEMORY; - goto err; + buf[0] = tok->u.c; + for (i = 1; i < ONIGENC_MBC_MAXLEN(env->enc); i++) { + r = fetch_token_in_cc(tok, &p, end, env); + if (r < 0) goto err; + if (r != TK_RAW_BYTE || tok->base != base) { + fetched = 1; + break; } - bufe = bufp + len; + buf[i] = tok->u.c; } - bufp[0] = tok->u.c; - for (i = 1; i < len; i++) { - r = fetch_token_in_cc(tok, &p, end, env); - if (r < 0) goto raw_byte_err; - if (r != TK_RAW_BYTE || tok->base != base) break; - bufp[i] = tok->u.c; + + if (i < ONIGENC_MBC_MINLEN(env->enc)) { + r = ONIGERR_TOO_SHORT_MULTI_BYTE_STRING; + goto err; } + + len = enc_len(env->enc, buf); if (i < len) { r = ONIGERR_TOO_SHORT_MULTI_BYTE_STRING; - raw_byte_err: - if (bufp != buf) xfree(bufp); goto err; } - v = ONIGENC_MBC_TO_CODE(env->enc, bufp, bufe); - if (bufp != buf) xfree(bufp); - in_type = CCV_CODE_POINT; + else if (i > len) { /* fetch back */ + p = psave; + for (i = 1; i < len; i++) { + r = fetch_token_in_cc(tok, &p, end, env); + } + fetched = 0; + } + + if (i == 1) { + v = (OnigCodePoint )buf[0]; + goto raw_single; + } + else { + v = ONIGENC_MBC_TO_CODE(env->enc, buf, bufe); + in_type = CCV_CODE_POINT; + } } else { v = (OnigCodePoint )tok->u.c; + raw_single: in_type = CCV_SB; } in_israw = 1; @@ -3881,7 +4049,7 @@ parse_char_class(Node** np, OnigToken* tok, UChar** src, UChar* end, case TK_CC_AND: /* && */ { if (state == CCS_VALUE) { - r = next_state_val(cc, &vs, 0, &val_israw, 0, CCV_SB, + r = next_state_val(cc, &vs, 0, &val_israw, 0, val_type, &val_type, &state, env); if (r != 0) goto err; } @@ -3921,7 +4089,7 @@ parse_char_class(Node** np, OnigToken* tok, UChar** src, UChar* end, } if (state == CCS_VALUE) { - r = next_state_val(cc, &vs, 0, &val_israw, 0, CCV_SB, + r = next_state_val(cc, &vs, 0, &val_israw, 0, val_type, &val_type, &state, env); if (r != 0) goto err; } @@ -3933,16 +4101,28 @@ parse_char_class(Node** np, OnigToken* tok, UChar** src, UChar* end, cc = prev_cc; } - cc->not = neg; - if (cc->not != 0 && + if (neg != 0) + CCLASS_SET_NOT(cc); + else + CCLASS_CLEAR_NOT(cc); + if (IS_CCLASS_NOT(cc) && IS_SYNTAX_BV(env->syntax, ONIG_SYN_NOT_NEWLINE_IN_NEGATIVE_CC)) { int is_empty; is_empty = (IS_NULL(cc->mbuf) ? 1 : 0); if (is_empty != 0) BITSET_IS_EMPTY(cc->bs, is_empty); - if (is_empty == 0) - BITSET_SET_BIT(cc->bs, ONIG_NEWLINE); + + if (is_empty == 0) { +#define NEWLINE_CODE 0x0a + + if (ONIGENC_IS_CODE_NEWLINE(env->enc, NEWLINE_CODE)) { + if (ONIGENC_CODE_TO_MBCLEN(env->enc, NEWLINE_CODE) == 1) + BITSET_SET_BIT(cc->bs, NEWLINE_CODE); + else + add_code_range(&(cc->mbuf), env, NEWLINE_CODE, NEWLINE_CODE); + } + } } *src = p; return 0; @@ -3961,33 +4141,26 @@ static int parse_effect(Node** np, OnigToken* tok, int term, UChar** src, UChar* end, ScanEnv* env) { + int r, num; + int list_capture; Node *target; OnigOptionType option; - int r, c, num; - int list_capture; + OnigEncoding enc = env->enc; + OnigCodePoint c; UChar* p = *src; + PFETCH_READY; *np = NULL; if (PEND) return ONIGERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS; option = env->option; - if (PPEEK == '?' && + if (PPEEK_IS('?') && IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_GROUP_EFFECT)) { PINC; if (PEND) return ONIGERR_END_PATTERN_IN_GROUP; PFETCH(c); switch (c) { - case '#': /* (?#...) comment */ - while (1) { - if (PEND) return ONIGERR_END_PATTERN_IN_GROUP; - PFETCH(c); - if (c == ')') break; - } - *src = p; - return 3; /* 3: comment */ - break; - case ':': /* (?:...) grouping only */ group: r = fetch_token(tok, &p, end, env); @@ -4129,7 +4302,7 @@ parse_effect(Node** np, OnigToken* tok, int term, UChar** src, UChar* end, else if (c == ':') { OnigOptionType prev = env->option; - env->option = option; + env->option = option; r = fetch_token(tok, &p, end, env); if (r < 0) return r; r = parse_subexp(&target, tok, term, &p, end, env); @@ -4185,6 +4358,14 @@ parse_effect(Node** np, OnigToken* tok, int term, UChar** src, UChar* end, return 0; } +static char* PopularQStr[] = { + "?", "*", "+", "??", "*?", "+?" +}; + +static char* ReduceQStr[] = { + "", "", "*", "*?", "??", "+ and ??", "+? and ?" +}; + static int set_qualifier(Node* qnode, Node* target, int group, ScanEnv* env) { @@ -4217,38 +4398,38 @@ set_qualifier(Node* qnode, Node* target, int group, ScanEnv* env) #ifdef USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR if (qn->by_number == 0 && qnt->by_number == 0 && IS_SYNTAX_BV(env->syntax, ONIG_SYN_WARN_REDUNDANT_NESTED_REPEAT)) { - if (IS_REPEAT_INFINITE(qn->upper)) { - if (qn->lower == 0) { /* '*' */ - redundant: - { - char buf[WARN_BUFSIZE]; - if (onig_verb_warn != onig_null_warn) { - onig_snprintf_with_pattern(buf, WARN_BUFSIZE, env->enc, - env->pattern, env->pattern_end, - "redundant nested repeat operator"); - (*onig_verb_warn)(buf); - } - goto warn_exit; - } - } - else if (qn->lower == 1) { /* '+' */ - /* (?:a?)+? only allowed. */ - if (qn->greedy || !(qnt->upper == 1 && qnt->greedy)) - goto redundant; - } - } - else if (qn->upper == 1 && qn->lower == 0) { - if (qn->greedy) { /* '?' */ - if (!(qnt->lower == 1 && qnt->greedy == 0)) /* not '+?' */ - goto redundant; - } - else { /* '??' */ - /* '(?:a+)?? only allowd. (?:a*)?? can be replaced to (?:a+)?? */ - if (!(qnt->greedy && qnt->lower == 1 && - IS_REPEAT_INFINITE(qnt->upper))) - goto redundant; - } - } + int nestq_num, targetq_num; + char buf[WARN_BUFSIZE]; + + nestq_num = popular_qualifier_num(qn); + targetq_num = popular_qualifier_num(qnt); + + switch(ReduceTypeTable[targetq_num][nestq_num]) { + case RQ_ASIS: + break; + + case RQ_DEL: + if (onig_verb_warn != onig_null_warn) { + onig_snprintf_with_pattern(buf, WARN_BUFSIZE, env->enc, + env->pattern, env->pattern_end, + "redundant nested repeat operator"); + (*onig_verb_warn)(buf); + } + goto warn_exit; + break; + + default: + if (onig_verb_warn != onig_null_warn) { + onig_snprintf_with_pattern(buf, WARN_BUFSIZE, env->enc, + env->pattern, env->pattern_end, + "nested repeat operator %s and %s was replaced with '%s'", + PopularQStr[targetq_num], PopularQStr[nestq_num], + ReduceQStr[ReduceTypeTable[targetq_num][nestq_num]]); + (*onig_verb_warn)(buf); + } + goto warn_exit; + break; + } } warn_exit: @@ -4269,74 +4450,151 @@ set_qualifier(Node* qnode, Node* target, int group, ScanEnv* env) return 0; } -#ifdef USE_FOLD_MATCH -static int -make_alt_node_from_fold_info(OnigEncFoldMatchInfo* info, Node** node) -{ - int i; - UChar *s, *end; - Node *root, **ptail, *snode; - - ptail = &root; - for (i = 0; i < info->target_num; i++) { - s = info->target_str[i]; - end = s + info->target_byte_len[i]; - /* ex. - U+00DF match "ss" and "SS, but not match "Ss". - So, string nodes must be raw. - */ - snode = node_new_str_raw(s, end); - CHECK_NULL_RETURN_VAL(snode, ONIGERR_MEMORY); - - *ptail = node_new_alt(snode, NULL_NODE); - CHECK_NULL_RETURN_VAL(*ptail, ONIGERR_MEMORY); - ptail = &(NCONS(*ptail).right); - } - *ptail = NULL_NODE; - *node = root; - return 0; -} - static int -make_fold_alt_node_from_cc(OnigEncoding enc, CClassNode* cc, Node** root) +make_compound_alt_node_from_cc(OnigAmbigType ambig_flag, OnigEncoding enc, + CClassNode* cc, Node** root) { - int i, j, flen, len, ncode, n; - UChar *s, *end, buf[ONIGENC_CODE_TO_MBC_MAXLEN]; - OnigCodePoint* codes; - Node **ptail, *snode; - OnigEncFoldMatchInfo* info; + int r, i, j, k, clen, len, ncode, n; + UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN]; + Node **ptail, *snode = NULL_NODE; + OnigCompAmbigCodes* ccs; + OnigCompAmbigCodeItem* ci; + OnigAmbigType amb; + n = 0; *root = NULL_NODE; ptail = root; - ncode = ONIGENC_GET_ALL_FOLD_MATCH_CODE(enc, &codes); - n = 0; - for (i = 0; i < ncode; i++) { - if (onig_is_code_in_cc(enc, codes[i], cc)) { - len = ONIGENC_CODE_TO_MBC(enc, codes[i], buf); - flen = ONIGENC_GET_FOLD_MATCH_INFO(enc, buf, buf + len, &info); - if (flen > 0) { /* fold */ - for (j = 0; j < info->target_num; j++) { - s = info->target_str[j]; - end = s + info->target_byte_len[j]; - if (onig_strncmp(s, buf, enc_len(enc, *s)) == 0) - continue; /* ignore single char. */ - - snode = node_new_str_raw(s, end); - CHECK_NULL_RETURN_VAL(snode, ONIGERR_MEMORY); - - *ptail = node_new_alt(snode, NULL_NODE); - CHECK_NULL_RETURN_VAL(*ptail, ONIGERR_MEMORY); - ptail = &(NCONS(*ptail).right); - n++; - } + + for (amb = 0x01; amb <= ONIGENC_AMBIGUOUS_MATCH_LIMIT; amb <<= 1) { + if ((amb & ambig_flag) == 0) continue; + + ncode = ONIGENC_GET_ALL_COMP_AMBIG_CODES(enc, amb, &ccs); + for (i = 0; i < ncode; i++) { + if (onig_is_code_in_cc(enc, ccs[i].code, cc)) { + for (j = 0; j < ccs[i].n; j++) { + ci = &(ccs[i].items[j]); + if (ci->len > 1) { /* compound only */ + if (IS_CCLASS_NOT(cc)) clear_not_flag_cclass(cc, enc); + + clen = ci->len; + for (k = 0; k < clen; k++) { + len = ONIGENC_CODE_TO_MBC(enc, ci->code[k], buf); + + if (k == 0) { + snode = node_new_str_raw(buf, buf + len); + CHECK_NULL_RETURN_VAL(snode, ONIGERR_MEMORY); + } + else { + r = onig_node_str_cat(snode, buf, buf + len); + if (r < 0) return r; + } + } + + *ptail = node_new_alt(snode, NULL_NODE); + CHECK_NULL_RETURN_VAL(*ptail, ONIGERR_MEMORY); + ptail = &(NCONS(*ptail).right); + n++; + } + } } } } return n; } -#endif + + +#ifdef USE_SHARED_CCLASS_TABLE + +#define THRESHOLD_RANGE_NUM_FOR_SHARE_CCLASS 8 + +/* for ctype node hash table */ + +typedef struct { + OnigEncoding enc; + int not; + int type; +} type_cclass_key; + +static int type_cclass_cmp(type_cclass_key* x, type_cclass_key* y) +{ + if (x->type != y->type) return 1; + if (x->enc != y->enc) return 1; + if (x->not != y->not) return 1; + return 0; +} + +static int type_cclass_hash(type_cclass_key* key) +{ + int i, val; + unsigned char *p; + + val = 0; + + p = (unsigned char* )&(key->enc); + for (i = 0; i < sizeof(key->enc); i++) { + val = val * 997 + (int )*p++; + } + + p = (unsigned char* )(&key->type); + for (i = 0; i < sizeof(key->type); i++) { + val = val * 997 + (int )*p++; + } + + val += key->not; + return val + (val >> 5); +} + +static int type_cclass_key_free(st_data_t x) +{ + xfree((void* )x); + return 0; +} + +static st_data_t type_cclass_key_clone(st_data_t x) +{ + type_cclass_key* new_key; + type_cclass_key* key = (type_cclass_key* )x; + + new_key = (type_cclass_key* )xmalloc(sizeof(type_cclass_key)); + *new_key = *key; + return (st_data_t )new_key; +} + +static struct st_hash_type type_type_cclass_hash = { + type_cclass_cmp, + type_cclass_hash, + type_cclass_key_free, + type_cclass_key_clone +}; + +static st_table* OnigTypeCClassTable; + + +static int +i_free_shared_class(type_cclass_key* key, Node* node, void* arg) +{ + if (IS_NOT_NULL(node)) { + CClassNode* cc = &(NCCLASS(node)); + if (IS_NOT_NULL(cc->mbuf)) xfree(cc->mbuf); + xfree(node); + } + return ST_DELETE; +} + +extern int +onig_free_shared_cclass_table() +{ + if (IS_NOT_NULL(OnigTypeCClassTable)) { + onig_st_foreach(OnigTypeCClassTable, i_free_shared_class, 0); + } + + return 0; +} + +#endif /* USE_SHARED_CCLASS_TABLE */ + static int parse_exp(Node** np, OnigToken* tok, int term, @@ -4346,7 +4604,6 @@ parse_exp(Node** np, OnigToken* tok, int term, Node* qn; Node** targetp; - start: *np = NULL; if (tok->type == term) goto end_of_token; @@ -4376,11 +4633,6 @@ parse_exp(Node** np, OnigToken* tok, int term, NEFFECT(*np).target = target; return tok->type; } - else if (r == 3) { /* comment */ - r = fetch_token(tok, src, end, env); - if (r < 0) return r; - goto start; - } break; case TK_SUBEXP_CLOSE: @@ -4391,76 +4643,22 @@ parse_exp(Node** np, OnigToken* tok, int term, else goto tk_byte; break; - case TK_BYTE: + case TK_STRING: tk_byte: { - *np = node_new_str_char((UChar )tok->u.c); + *np = node_new_str(tok->backp, *src); CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY); while (1) { - len = enc_len(env->enc, tok->u.c); - if (len > 1) { - r = onig_node_str_cat(*np, *src, *src + len - 1); - if (r < 0) return r; - *src += (len - 1); - } - r = fetch_token(tok, src, end, env); if (r < 0) return r; - if (r != TK_BYTE) break; + if (r != TK_STRING) break; - r = node_str_cat_char(*np, (UChar )tok->u.c); + r = onig_node_str_cat(*np, tok->backp, *src); if (r < 0) return r; } - fold_entry: -#ifdef USE_FOLD_MATCH - if (IS_IGNORECASE(env->option) && ONIGENC_IS_FOLD_MATCH(env->enc)) { - int flen, ret; - Node *root, **ptail, *work, *snode, *anode; - UChar *p, *pprev; - OnigEncFoldMatchInfo* fold_info; - StrNode* sn = &(NSTRING(*np)); - - ptail = &root; - pprev = sn->s; - for (p = sn->s; p < sn->end; ) { - flen = ONIGENC_GET_FOLD_MATCH_INFO(env->enc, p, sn->end, &fold_info); - if (flen > 0) { /* fold */ - ret = make_alt_node_from_fold_info(fold_info, &anode); - if (ret != 0) return ret; - work = node_new_list(anode, NULL); - CHECK_NULL_RETURN_VAL(work, ONIGERR_MEMORY); - - if (pprev < p) { - snode = node_new_str(pprev, p); - CHECK_NULL_RETURN_VAL(snode, ONIGERR_MEMORY); - *ptail = node_new_list(snode, work); - CHECK_NULL_RETURN_VAL(*ptail, ONIGERR_MEMORY); - } - else { - *ptail = work; - } - ptail = &(NCONS(work).right); - p += flen; - pprev = p; - } - else - p += enc_len(env->enc, *p); - } - *ptail = NULL_NODE; - if (IS_NOT_NULL(root)) { - if (pprev < sn->end) { - snode = node_new_str(pprev, sn->end); - CHECK_NULL_RETURN_VAL(snode, ONIGERR_MEMORY); - *ptail = node_new_list(snode, NULL_NODE); - CHECK_NULL_RETURN_VAL(*ptail, ONIGERR_MEMORY); - } - onig_node_free(*np); - *np = root; - } - } -#endif + string_end: targetp = np; goto repeat; } @@ -4469,22 +4667,19 @@ parse_exp(Node** np, OnigToken* tok, int term, case TK_RAW_BYTE: tk_raw_byte: { - int expect_len; - *np = node_new_str_raw_char((UChar )tok->u.c); CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY); - expect_len = enc_len(env->enc, tok->u.c); len = 1; while (1) { r = fetch_token(tok, src, end, env); if (r < 0) return r; if (r != TK_RAW_BYTE) { #ifndef NUMBERED_CHAR_IS_NOT_CASE_AMBIG - if (len >= expect_len) { + if (len >= enc_len(env->enc, NSTRING(*np).s)) { NSTRING_CLEAR_RAW(*np); } #endif - goto fold_entry; + goto string_end; } r = node_str_cat_char(*np, (UChar )tok->u.c); @@ -4510,9 +4705,11 @@ parse_exp(Node** np, OnigToken* tok, int term, case TK_QUOTE_OPEN: { - OnigCodePoint end_op[] = { (OnigCodePoint )MC_ESC, (OnigCodePoint )'E' }; + OnigCodePoint end_op[2]; UChar *qstart, *qend, *nextp; + end_op[0] = (OnigCodePoint )MC_ESC(env->enc); + end_op[1] = (OnigCodePoint )'E'; qstart = *src; qend = find_str_position(end_op, 2, qstart, end, &nextp, env->enc); if (IS_NULL(qend)) { @@ -4537,17 +4734,69 @@ parse_exp(Node** np, OnigToken* tok, int term, case CTYPE_NOT_WHITE_SPACE: case CTYPE_DIGIT: case CTYPE_NOT_DIGIT: + case CTYPE_XDIGIT: + case CTYPE_NOT_XDIGIT: { CClassNode* cc; int ctype, not; - ctype = parse_ctype_to_enc_ctype(tok->u.subtype, ¬); +#ifdef USE_SHARED_CCLASS_TABLE + OnigCodePoint *sbr, *mbr; - *np = node_new_cclass(); - CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY); - cc = &(NCCLASS(*np)); - add_ctype_to_cc(cc, ctype, 0, env); - if (not != 0) CCLASS_SET_NOT(cc); + ctype = parse_ctype_to_enc_ctype(tok->u.subtype, ¬); + r = ONIGENC_GET_CTYPE_CODE_RANGE(env->enc, ctype, &sbr, &mbr); + if (r == 0 && + ONIGENC_CODE_RANGE_NUM(mbr) + >= THRESHOLD_RANGE_NUM_FOR_SHARE_CCLASS) { + type_cclass_key key; + type_cclass_key* new_key; + + key.enc = env->enc; + key.not = not; + key.type = ctype; + + THREAD_ATOMIC_START; + + if (IS_NULL(OnigTypeCClassTable)) { + OnigTypeCClassTable + = onig_st_init_table_with_size(&type_type_cclass_hash, 10); + if (IS_NULL(OnigTypeCClassTable)) { + THREAD_ATOMIC_END; + return ONIGERR_MEMORY; + } + } + else { + if (onig_st_lookup(OnigTypeCClassTable, (st_data_t )&key, + (st_data_t* )np)) { + THREAD_ATOMIC_END; + break; + } + } + + *np = node_new_cclass_by_codepoint_range(not, sbr, mbr); + if (IS_NULL(*np)) { + THREAD_ATOMIC_END; + return ONIGERR_MEMORY; + } + + CCLASS_SET_SHARE(&(NCCLASS(*np))); + new_key = (type_cclass_key* )xmalloc(sizeof(type_cclass_key)); + onig_st_add_direct(OnigTypeCClassTable, (st_data_t )new_key, + (st_data_t )*np); + + THREAD_ATOMIC_END; + } + else { +#endif + ctype = parse_ctype_to_enc_ctype(tok->u.subtype, ¬); + *np = node_new_cclass(); + CHECK_NULL_RETURN_VAL(*np, ONIGERR_MEMORY); + cc = &(NCCLASS(*np)); + add_ctype_to_cc(cc, ctype, 0, env); + if (not != 0) CCLASS_SET_NOT(cc); +#ifdef USE_SHARED_CCLASS_TABLE + } +#endif } break; @@ -4564,27 +4813,66 @@ parse_exp(Node** np, OnigToken* tok, int term, break; case TK_CC_OPEN: - r = parse_char_class(np, tok, src, end, env); - if (r != 0) return r; + { + CClassNode* cc; -#ifdef USE_FOLD_MATCH - if (IS_IGNORECASE(env->option) && ONIGENC_IS_FOLD_MATCH(env->enc)) { - int res; - Node *alt_root, *work; - CClassNode* cc = &(NCCLASS(*np)); - - res = make_fold_alt_node_from_cc(env->enc, cc, &alt_root); - if (res < 0) return res; - if (res > 0) { - work = node_new_alt(*np, alt_root); - if (IS_NULL(work)) { - onig_node_free(alt_root); - return ONIGERR_MEMORY; - } - *np = work; + r = parse_char_class(np, tok, src, end, env); + if (r != 0) return r; + + cc = &(NCCLASS(*np)); + + if (IS_IGNORECASE(env->option)) { + int i, n, in_cc; + OnigPairAmbigCodes* ccs; + BitSetRef bs = cc->bs; + OnigAmbigType amb; + + for (amb = 0x01; amb <= ONIGENC_AMBIGUOUS_MATCH_LIMIT; amb <<= 1) { + if ((amb & env->ambig_flag) == 0) continue; + + n = ONIGENC_GET_ALL_PAIR_AMBIG_CODES(env->enc, amb, &ccs); + for (i = 0; i < n; i++) { + in_cc = onig_is_code_in_cc(env->enc, ccs[i].from, cc); + + if ((in_cc != 0 && !IS_CCLASS_NOT(cc)) || + (in_cc == 0 && IS_CCLASS_NOT(cc))) { + if (ONIGENC_MBC_MINLEN(env->enc) > 1 || + ccs[i].from >= SINGLE_BYTE_SIZE) { + /* if (cc->not) clear_not_flag_cclass(cc, env->enc); */ + add_code_range(&(cc->mbuf), env, ccs[i].to, ccs[i].to); + } + else { + if (BITSET_AT(bs, ccs[i].from)) { + /* /(?i:[^A-C])/.match("a") ==> fail. */ + BITSET_SET_BIT(bs, ccs[i].to); + } + if (BITSET_AT(bs, ccs[i].to)) { + BITSET_SET_BIT(bs, ccs[i].from); + } + } + } + } + } + } + + if (IS_IGNORECASE(env->option) && + (env->ambig_flag & ONIGENC_AMBIGUOUS_MATCH_COMPOUND) != 0) { + int res; + Node *alt_root, *work; + + res = make_compound_alt_node_from_cc(env->ambig_flag, env->enc, + cc, &alt_root); + if (res < 0) return res; + if (res > 0) { + work = node_new_alt(*np, alt_root); + if (IS_NULL(work)) { + onig_node_free(alt_root); + return ONIGERR_MEMORY; + } + *np = work; + } } } -#endif break; case TK_ANYCHAR: @@ -4630,7 +4918,6 @@ parse_exp(Node** np, OnigToken* tok, int term, *np = node_new_empty(); } else { - *src = tok->backp; goto tk_byte; } break; @@ -4781,7 +5068,7 @@ parse_regexp(Node** top, UChar** src, UChar* end, ScanEnv* env) } extern int -onig_parse_make_tree(Node** root, UChar* pattern, UChar* end, regex_t* reg, +onig_parse_make_tree(Node** root, const UChar* pattern, const UChar* end, regex_t* reg, ScanEnv* env) { int r; @@ -4793,15 +5080,16 @@ onig_parse_make_tree(Node** root, UChar* pattern, UChar* end, regex_t* reg, scan_env_clear(env); env->option = reg->options; + env->ambig_flag = reg->ambig_flag; env->enc = reg->enc; env->syntax = reg->syntax; - env->pattern = pattern; - env->pattern_end = end; + env->pattern = (UChar* )pattern; + env->pattern_end = (UChar* )end; env->reg = reg; *root = NULL; - p = pattern; - r = parse_regexp(root, &p, end, env); + p = (UChar* )pattern; + r = parse_regexp(root, &p, (UChar* )end, env); reg->num_mem = env->num_mem; return r; } diff --git a/ext/mbstring/oniguruma/regparse.h b/ext/mbstring/oniguruma/regparse.h index b2726becbdea..1a4ac7dea248 100644 --- a/ext/mbstring/oniguruma/regparse.h +++ b/ext/mbstring/oniguruma/regparse.h @@ -1,12 +1,33 @@ +#ifndef REGPARSE_H +#define REGPARSE_H /********************************************************************** - regparse.h - Oniguruma (regular expression library) - - Copyright (C) 2003-2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ -#ifndef REGPARSE_H -#define REGPARSE_H +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ #include "regint.h" @@ -43,7 +64,8 @@ #define CTYPE_NOT_WHITE_SPACE (1<<3) #define CTYPE_DIGIT (1<<4) #define CTYPE_NOT_DIGIT (1<<5) - +#define CTYPE_XDIGIT (1<<6) +#define CTYPE_NOT_XDIGIT (1<<7) #define ANCHOR_ANYCHAR_STAR_MASK (ANCHOR_ANYCHAR_STAR | ANCHOR_ANYCHAR_STAR_PL) #define ANCHOR_END_BUF_MASK (ANCHOR_END_BUF | ANCHOR_SEMI_END_BUF) @@ -52,29 +74,27 @@ #define EFFECT_OPTION (1<<1) #define EFFECT_STOP_BACKTRACK (1<<2) -#define REPEAT_INFINITE -1 -#define IS_REPEAT_INFINITE(n) ((n) == REPEAT_INFINITE) - #define NODE_STR_MARGIN 16 #define NODE_STR_BUF_SIZE 24 /* sizeof(CClassNode) - sizeof(int)*4 */ #define NODE_BACKREFS_SIZE 7 #define NSTR_RAW (1<<0) /* by backslashed number */ -#define NSTR_CASE_AMBIG (1<<1) - -#define NSTRING_LEN(node) ((node)->u.str.end - (node)->u.str.s) -#define NSTRING_SET_RAW(node) (node)->u.str.flag |= NSTR_RAW -#define NSTRING_CLEAR_RAW(node) (node)->u.str.flag &= ~NSTR_RAW -#define NSTRING_SET_CASE_AMBIG(node) (node)->u.str.flag |= NSTR_CASE_AMBIG -#define NSTRING_IS_RAW(node) (((node)->u.str.flag & NSTR_RAW) != 0) -#define NSTRING_IS_CASE_AMBIG(node) \ - (((node)->u.str.flag & NSTR_CASE_AMBIG) != 0) +#define NSTR_AMBIG (1<<1) +#define NSTR_AMBIG_REDUCE (1<<2) + +#define NSTRING_LEN(node) ((node)->u.str.end - (node)->u.str.s) +#define NSTRING_SET_RAW(node) (node)->u.str.flag |= NSTR_RAW +#define NSTRING_CLEAR_RAW(node) (node)->u.str.flag &= ~NSTR_RAW +#define NSTRING_SET_AMBIG(node) (node)->u.str.flag |= NSTR_AMBIG +#define NSTRING_SET_AMBIG_REDUCE(node) (node)->u.str.flag |= NSTR_AMBIG_REDUCE +#define NSTRING_IS_RAW(node) (((node)->u.str.flag & NSTR_RAW) != 0) +#define NSTRING_IS_AMBIG(node) (((node)->u.str.flag & NSTR_AMBIG) != 0) +#define NSTRING_IS_AMBIG_REDUCE(node) \ + (((node)->u.str.flag & NSTR_AMBIG_REDUCE) != 0) #define BACKREFS_P(br) \ (IS_NOT_NULL((br)->back_dynamic) ? (br)->back_dynamic : (br)->back_static); -#define CCLASS_SET_NOT(cc) (cc)->not = 1 - #define NQ_TARGET_ISNOT_EMPTY 0 #define NQ_TARGET_IS_EMPTY 1 #define NQ_TARGET_IS_EMPTY_MEM 2 @@ -89,13 +109,17 @@ typedef struct { UChar buf[NODE_STR_BUF_SIZE]; } StrNode; +/* move to regint.h */ +#if 0 typedef struct { - int not; + int flags; BitSet bs; BBuf* mbuf; /* multi-byte info or NULL */ } CClassNode; +#endif typedef struct { + int state; struct _Node* target; int lower; int upper; @@ -108,19 +132,19 @@ typedef struct { } QualifierNode; /* status bits */ -#define NST_MIN_FIXED (1<<0) -#define NST_MAX_FIXED (1<<1) -#define NST_CLEN_FIXED (1<<2) -#define NST_MARK1 (1<<3) -#define NST_MARK2 (1<<4) -#define NST_MEM_BACKREFED (1<<5) -#define NST_SIMPLE_REPEAT (1<<6) /* for stop backtrack optimization */ - -#define NST_RECURSION (1<<7) -#define NST_CALLED (1<<8) -#define NST_ADDR_FIXED (1<<9) -#define NST_NAMED_GROUP (1<<10) -#define NST_NAME_REF (1<<11) +#define NST_MIN_FIXED (1<<0) +#define NST_MAX_FIXED (1<<1) +#define NST_CLEN_FIXED (1<<2) +#define NST_MARK1 (1<<3) +#define NST_MARK2 (1<<4) +#define NST_MEM_BACKREFED (1<<5) +#define NST_STOP_BT_SIMPLE_REPEAT (1<<6) +#define NST_RECURSION (1<<7) +#define NST_CALLED (1<<8) +#define NST_ADDR_FIXED (1<<9) +#define NST_NAMED_GROUP (1<<10) +#define NST_NAME_REF (1<<11) +#define NST_IN_REPEAT (1<<12) /* STK_REPEAT is nested in stack. */ #define SET_EFFECT_STATUS(node,f) (node)->u.effect.state |= (f) #define CLEAR_EFFECT_STATUS(node,f) (node)->u.effect.state &= ~(f) @@ -133,13 +157,15 @@ typedef struct { #define IS_EFFECT_MIN_FIXED(en) (((en)->state & NST_MIN_FIXED) != 0) #define IS_EFFECT_MAX_FIXED(en) (((en)->state & NST_MAX_FIXED) != 0) #define IS_EFFECT_CLEN_FIXED(en) (((en)->state & NST_CLEN_FIXED) != 0) -#define IS_EFFECT_SIMPLE_REPEAT(en) (((en)->state & NST_SIMPLE_REPEAT) != 0) +#define IS_EFFECT_STOP_BT_SIMPLE_REPEAT(en) \ + (((en)->state & NST_STOP_BT_SIMPLE_REPEAT) != 0) #define IS_EFFECT_NAMED_GROUP(en) (((en)->state & NST_NAMED_GROUP) != 0) #define SET_CALL_RECURSION(node) (node)->u.call.state |= NST_RECURSION #define IS_CALL_RECURSION(cn) (((cn)->state & NST_RECURSION) != 0) #define IS_CALL_NAME_REF(cn) (((cn)->state & NST_NAME_REF) != 0) #define IS_BACKREF_NAME_REF(bn) (((bn)->state & NST_NAME_REF) != 0) +#define IS_QUALIFIER_IN_REPEAT(qn) (((qn)->state & NST_IN_REPEAT) != 0) typedef struct { int state; @@ -224,9 +250,10 @@ typedef struct _Node { (senv)->mem_nodes_dynamic : (senv)->mem_nodes_static) typedef struct { - OnigOptionType option; - OnigEncoding enc; - OnigSyntaxType* syntax; + OnigOptionType option; + OnigAmbigType ambig_flag; + OnigEncoding enc; + OnigSyntaxType* syntax; BitStatusType capture_history; BitStatusType bt_mem_start; BitStatusType bt_mem_end; @@ -254,19 +281,31 @@ typedef struct { #define IS_SYNTAX_OP2(syn, opm) (((syn)->op2 & (opm)) != 0) #define IS_SYNTAX_BV(syn, bvm) (((syn)->behavior & (bvm)) != 0) + +#ifdef USE_NAMED_GROUP +typedef struct { + int new_val; +} GroupNumRemap; + +extern int onig_renumber_name_table P_((regex_t* reg, GroupNumRemap* map)); +#endif + extern int onig_is_code_in_cc P_((OnigEncoding enc, OnigCodePoint code, CClassNode* cc)); -extern int onig_strncmp P_((UChar* s1, UChar* s2, int n)); +extern int onig_strncmp P_((const UChar* s1, const UChar* s2, int n)); extern void onig_scan_env_set_error_string P_((ScanEnv* env, int ecode, UChar* arg, UChar* arg_end)); -extern int onig_scan_unsigned_number P_((UChar** src, UChar* end, OnigEncoding enc)); +extern int onig_scan_unsigned_number P_((UChar** src, const UChar* end, OnigEncoding enc)); extern void onig_reduce_nested_qualifier P_((Node* pnode, Node* cnode)); extern void onig_node_conv_to_str_node P_((Node* node, int raw)); -extern int onig_node_str_cat P_((Node* node, UChar* s, UChar* end)); +extern int onig_node_str_cat P_((Node* node, const UChar* s, const UChar* end)); extern void onig_node_free P_((Node* node)); extern Node* onig_node_new_effect P_((int type)); extern Node* onig_node_new_anchor P_((int type)); +extern Node* onig_node_new_str P_((const UChar* s, const UChar* end)); +extern Node* onig_node_new_list P_((Node* left, Node* right)); +extern void onig_node_str_clear P_((Node* node)); extern int onig_free_node_list(); extern int onig_names_free P_((regex_t* reg)); -extern int onig_parse_make_tree P_((Node** root, UChar* pattern, UChar* end, regex_t* reg, ScanEnv* env)); +extern int onig_parse_make_tree P_((Node** root, const UChar* pattern, const UChar* end, regex_t* reg, ScanEnv* env)); #ifdef ONIG_DEBUG #ifdef USE_NAMED_GROUP diff --git a/ext/mbstring/oniguruma/regposerr.c b/ext/mbstring/oniguruma/regposerr.c index 533f813c0c45..e54b5c4089e6 100644 --- a/ext/mbstring/oniguruma/regposerr.c +++ b/ext/mbstring/oniguruma/regposerr.c @@ -1,10 +1,32 @@ /********************************************************************** - regposerr.c - Oniguruma (regular expression library) - - Copyright (C) 2003-2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include "config.h" #include "onigposix.h" @@ -58,7 +80,7 @@ regerror(int posix_ecode, const regex_t* reg, char* buf, size_t size) s = tbuf; } - len = strlen(s) + 1; + len = strlen(s) + 1; /* use strlen() because s is ascii encoding. */ if (buf != NULL && size > 0) { strncpy(buf, s, size - 1); diff --git a/ext/mbstring/oniguruma/regposix.c b/ext/mbstring/oniguruma/regposix.c index 4cb30cc56535..34cbeb9a46f0 100644 --- a/ext/mbstring/oniguruma/regposix.c +++ b/ext/mbstring/oniguruma/regposix.c @@ -1,10 +1,31 @@ /********************************************************************** - regposix.c - Oniguruma (regular expression library) - - Copyright (C) 2003-2004 K.Kosako (kosako@sofnec.co.jp) - **********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ #define regex_t onig_regex_t #include "regint.h" @@ -14,16 +35,17 @@ #define ONIG_C(reg) ((onig_regex_t* )((reg)->onig)) #define PONIG_C(reg) ((onig_regex_t** )(&(reg)->onig)) -#if 1 +/* #define ENC_STRING_LEN(enc,s,len) len = strlen(s) */ #define ENC_STRING_LEN(enc,s,len) do { \ - UChar* tmps = (UChar* )(s); \ - /* while (*tmps != 0) tmps += enc_len(enc,*tmps); */ \ - while (*tmps != 0) tmps++; /* OK for UTF-8, EUC-JP, Shift_JIS */ \ - len = tmps - (UChar* )(s); \ + if (ONIGENC_MBC_MINLEN(enc) == 1) { \ + UChar* tmps = (UChar* )(s); \ + while (*tmps != 0) tmps++; \ + len = tmps - (UChar* )(s); \ + } \ + else { \ + len = onigenc_str_bytelen_null(enc, (UChar* )s); \ + } \ } while(0) -#else -#define ENC_STRING_LEN(enc,s,len) len = strlen(s) -#endif typedef struct { int onig_err; @@ -50,7 +72,7 @@ onig2posix_error_code(int code) { ONIGERR_END_PATTERN_AT_LEFT_BRACKET, REG_EBRACK }, { ONIGERR_EMPTY_CHAR_CLASS, REG_ECTYPE }, { ONIGERR_PREMATURE_END_OF_CHAR_CLASS, REG_ECTYPE }, - { ONIGERR_END_PATTERN_AT_BACKSLASH, REG_EESCAPE }, + { ONIGERR_END_PATTERN_AT_ESCAPE, REG_EESCAPE }, { ONIGERR_END_PATTERN_AT_META, REG_EESCAPE }, { ONIGERR_END_PATTERN_AT_CONTROL, REG_EESCAPE }, { ONIGERR_META_CODE_SYNTAX, REG_BADPAT }, @@ -91,6 +113,7 @@ onig2posix_error_code(int code) { ONIGERR_NEVER_ENDING_RECURSION, REG_BADPAT }, { ONIGERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY, REG_BADPAT }, { ONIGERR_INVALID_CHAR_PROPERTY_NAME, REG_BADPAT }, + { ONIGERR_NOT_SUPPORTED_ENCODING_COMBINATION, REG_EONIG_BADARG }, { ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT, REG_EONIG_THREAD } }; @@ -145,24 +168,37 @@ regexec(regex_t* reg, const char* str, size_t nmatch, { int r, i, len; UChar* end; + regmatch_t* pm; OnigOptionType options; options = ONIG_OPTION_POSIX_REGION; if ((posix_options & REG_NOTBOL) != 0) options |= ONIG_OPTION_NOTBOL; if ((posix_options & REG_NOTEOL) != 0) options |= ONIG_OPTION_NOTEOL; - if ((reg->comp_options & REG_NOSUB) != 0) { - pmatch = (regmatch_t* )NULL; + if (nmatch == 0 || (reg->comp_options & REG_NOSUB) != 0) { + pm = (regmatch_t* )NULL; nmatch = 0; } + else if ((int )nmatch < ONIG_C(reg)->num_mem + 1) { + pm = (regmatch_t* )xmalloc(sizeof(regmatch_t) + * (ONIG_C(reg)->num_mem + 1)); + if (pm == NULL) + return REG_ESPACE; + } + else { + pm = pmatch; + } - ENC_STRING_LEN(ONIG_C(reg)->code,str,len); + ENC_STRING_LEN(ONIG_C(reg)->enc, str, len); end = (UChar* )(str + len); r = onig_search(ONIG_C(reg), (UChar* )str, end, (UChar* )str, end, (OnigRegion* )pmatch, options); if (r >= 0) { r = 0; /* Match */ + if (pm != pmatch && pm != NULL) { + xmemcpy(pmatch, pm, sizeof(regmatch_t) * nmatch); + } } else if (r == ONIG_MISMATCH) { r = REG_NOMATCH; @@ -173,6 +209,9 @@ regexec(regex_t* reg, const char* str, size_t nmatch, r = onig2posix_error_code(r); } + if (pm != pmatch && pm != NULL) + xfree(pm); + return r; } @@ -201,6 +240,13 @@ reg_set_encoding(int mb_code) case REG_POSIX_ENCODING_UTF8: enc = ONIG_ENCODING_UTF8; break; + case REG_POSIX_ENCODING_UTF16_BE: + enc = ONIG_ENCODING_UTF16_BE; + break; + case REG_POSIX_ENCODING_UTF16_LE: + enc = ONIG_ENCODING_UTF16_LE; + break; + default: return ; break; @@ -211,18 +257,18 @@ reg_set_encoding(int mb_code) extern int reg_name_to_group_numbers(regex_t* reg, - unsigned char* name, unsigned char* name_end, int** nums) + const unsigned char* name, const unsigned char* name_end, int** nums) { return onig_name_to_group_numbers(ONIG_C(reg), name, name_end, nums); } typedef struct { - int (*func)(unsigned char*,unsigned char*,int,int*,regex_t*,void*); + int (*func)(const unsigned char*, const unsigned char*,int,int*,regex_t*,void*); regex_t* reg; void* arg; } i_wrap; -static int i_wrapper(unsigned char* name, unsigned char* name_end, +static int i_wrapper(const unsigned char* name, const unsigned char* name_end, int ng, int* gs, onig_regex_t* reg, void* arg) { @@ -233,8 +279,8 @@ static int i_wrapper(unsigned char* name, unsigned char* name_end, extern int reg_foreach_name(regex_t* reg, - int (*func)(unsigned char*,unsigned char*,int,int*,regex_t*,void*), - void* arg) + int (*func)(const unsigned char*, const unsigned char*,int,int*,regex_t*,void*), + void* arg) { i_wrap warg; diff --git a/ext/mbstring/oniguruma/regsyntax.c b/ext/mbstring/oniguruma/regsyntax.c new file mode 100644 index 000000000000..a0f36b8c33dd --- /dev/null +++ b/ext/mbstring/oniguruma/regsyntax.c @@ -0,0 +1,207 @@ +/********************************************************************** + regsyntax.c - Oniguruma (regular expression library) +**********************************************************************/ +/*- + * Copyright (c) 2002-2004 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "regint.h" + +OnigSyntaxType OnigSyntaxPosixBasic = { + ( SYN_POSIX_COMMON_OP | ONIG_SYN_OP_ESC_LPAREN_SUBEXP | + ONIG_SYN_OP_ESC_BRACE_INTERVAL ) + , 0 + , 0 + , ( ONIG_OPTION_SINGLELINE | ONIG_OPTION_MULTILINE ) +}; + +OnigSyntaxType OnigSyntaxPosixExtended = { + ( SYN_POSIX_COMMON_OP | ONIG_SYN_OP_LPAREN_SUBEXP | + ONIG_SYN_OP_BRACE_INTERVAL | + ONIG_SYN_OP_PLUS_ONE_INF | ONIG_SYN_OP_QMARK_ZERO_ONE | ONIG_SYN_OP_VBAR_ALT ) + , 0 + , ( ONIG_SYN_CONTEXT_INDEP_ANCHORS | + ONIG_SYN_CONTEXT_INDEP_REPEAT_OPS | ONIG_SYN_CONTEXT_INVALID_REPEAT_OPS | + ONIG_SYN_ALLOW_UNMATCHED_CLOSE_SUBEXP | + ONIG_SYN_ALLOW_DOUBLE_RANGE_OP_IN_CC ) + , ( ONIG_OPTION_SINGLELINE | ONIG_OPTION_MULTILINE ) +}; + +OnigSyntaxType OnigSyntaxEmacs = { + ( ONIG_SYN_OP_DOT_ANYCHAR | ONIG_SYN_OP_BRACKET_CC | + ONIG_SYN_OP_ESC_BRACE_INTERVAL | + ONIG_SYN_OP_ESC_LPAREN_SUBEXP | ONIG_SYN_OP_ESC_VBAR_ALT | + ONIG_SYN_OP_ASTERISK_ZERO_INF | ONIG_SYN_OP_PLUS_ONE_INF | + ONIG_SYN_OP_QMARK_ZERO_ONE | ONIG_SYN_OP_DECIMAL_BACKREF | + ONIG_SYN_OP_LINE_ANCHOR | ONIG_SYN_OP_ESC_CONTROL_CHARS ) + , ONIG_SYN_OP2_ESC_GNU_BUF_ANCHOR + , ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC + , ONIG_OPTION_NONE +}; + +OnigSyntaxType OnigSyntaxGrep = { + ( ONIG_SYN_OP_DOT_ANYCHAR | ONIG_SYN_OP_BRACKET_CC | ONIG_SYN_OP_POSIX_BRACKET | + ONIG_SYN_OP_BRACE_INTERVAL | ONIG_SYN_OP_ESC_LPAREN_SUBEXP | + ONIG_SYN_OP_ESC_VBAR_ALT | + ONIG_SYN_OP_ASTERISK_ZERO_INF | ONIG_SYN_OP_ESC_PLUS_ONE_INF | + ONIG_SYN_OP_ESC_QMARK_ZERO_ONE | ONIG_SYN_OP_LINE_ANCHOR | + ONIG_SYN_OP_ESC_W_WORD | ONIG_SYN_OP_ESC_B_WORD_BOUND | + ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END | ONIG_SYN_OP_DECIMAL_BACKREF ) + , 0 + , ( ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC | ONIG_SYN_NOT_NEWLINE_IN_NEGATIVE_CC ) + , ONIG_OPTION_NONE +}; + +OnigSyntaxType OnigSyntaxGnuRegex = { + SYN_GNU_REGEX_OP + , 0 + , SYN_GNU_REGEX_BV + , ONIG_OPTION_NONE +}; + +OnigSyntaxType OnigSyntaxJava = { + (( SYN_GNU_REGEX_OP | ONIG_SYN_OP_QMARK_NON_GREEDY | + ONIG_SYN_OP_ESC_CONTROL_CHARS | ONIG_SYN_OP_ESC_C_CONTROL | + ONIG_SYN_OP_ESC_OCTAL3 | ONIG_SYN_OP_ESC_X_HEX2 ) + & ~ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END ) + , ( ONIG_SYN_OP2_ESC_CAPITAL_Q_QUOTE | ONIG_SYN_OP2_QMARK_GROUP_EFFECT | + ONIG_SYN_OP2_OPTION_PERL | ONIG_SYN_OP2_PLUS_POSSESSIVE_REPEAT | + ONIG_SYN_OP2_PLUS_POSSESSIVE_INTERVAL | ONIG_SYN_OP2_CCLASS_SET_OP | + ONIG_SYN_OP2_ESC_V_VTAB | ONIG_SYN_OP2_ESC_U_HEX4 | + ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY ) + , ( SYN_GNU_REGEX_BV | ONIG_SYN_DIFFERENT_LEN_ALT_LOOK_BEHIND ) + , ONIG_OPTION_SINGLELINE +}; + +OnigSyntaxType OnigSyntaxPerl = { + (( SYN_GNU_REGEX_OP | ONIG_SYN_OP_QMARK_NON_GREEDY | + ONIG_SYN_OP_ESC_OCTAL3 | ONIG_SYN_OP_ESC_X_HEX2 | + ONIG_SYN_OP_ESC_X_BRACE_HEX8 | ONIG_SYN_OP_ESC_CONTROL_CHARS | + ONIG_SYN_OP_ESC_C_CONTROL ) + & ~ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END ) + , ( ONIG_SYN_OP2_ESC_CAPITAL_Q_QUOTE | + ONIG_SYN_OP2_QMARK_GROUP_EFFECT | ONIG_SYN_OP2_OPTION_PERL | + ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY | + ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT | + ONIG_SYN_OP2_CHAR_PROPERTY_PREFIX_IS ) + , SYN_GNU_REGEX_BV + , ONIG_OPTION_SINGLELINE +}; + + +extern int +onig_set_default_syntax(OnigSyntaxType* syntax) +{ + if (IS_NULL(syntax)) + syntax = ONIG_SYNTAX_RUBY; + + OnigDefaultSyntax = syntax; + return 0; +} + +extern void +onig_copy_syntax(OnigSyntaxType* to, OnigSyntaxType* from) +{ + *to = *from; +} + +extern void +onig_set_syntax_op(OnigSyntaxType* syntax, unsigned int op) +{ + syntax->op = op; +} + +extern void +onig_set_syntax_op2(OnigSyntaxType* syntax, unsigned int op2) +{ + syntax->op2 = op2; +} + +extern void +onig_set_syntax_behavior(OnigSyntaxType* syntax, unsigned int behavior) +{ + syntax->behavior = behavior; +} + +extern void +onig_set_syntax_options(OnigSyntaxType* syntax, OnigOptionType options) +{ + syntax->options = options; +} + +extern unsigned int +onig_get_syntax_op(OnigSyntaxType* syntax) +{ + return syntax->op; +} + +extern unsigned int +onig_get_syntax_op2(OnigSyntaxType* syntax) +{ + return syntax->op2; +} + +extern unsigned int +onig_get_syntax_behavior(OnigSyntaxType* syntax) +{ + return syntax->behavior; +} + +extern OnigOptionType +onig_get_syntax_options(OnigSyntaxType* syntax) +{ + return syntax->options; +} + +#ifdef USE_VARIABLE_META_CHARS +extern int onig_set_meta_char(OnigEncoding enc, + unsigned int what, OnigCodePoint code) +{ + switch (what) { + case ONIG_META_CHAR_ESCAPE: + enc->meta_char_table.esc = code; + break; + case ONIG_META_CHAR_ANYCHAR: + enc->meta_char_table.anychar = code; + break; + case ONIG_META_CHAR_ANYTIME: + enc->meta_char_table.anytime = code; + break; + case ONIG_META_CHAR_ZERO_OR_ONE_TIME: + enc->meta_char_table.zero_or_one_time = code; + break; + case ONIG_META_CHAR_ONE_OR_MORE_TIME: + enc->meta_char_table.one_or_more_time = code; + break; + case ONIG_META_CHAR_ANYCHAR_ANYTIME: + enc->meta_char_table.anychar_anytime = code; + break; + default: + return ONIGERR_INVALID_ARGUMENT; + break; + } + return 0; +} +#endif /* USE_VARIABLE_META_CHARS */ diff --git a/ext/mbstring/oniguruma/regtrav.c b/ext/mbstring/oniguruma/regtrav.c new file mode 100644 index 000000000000..58a17f58b344 --- /dev/null +++ b/ext/mbstring/oniguruma/regtrav.c @@ -0,0 +1,76 @@ +/********************************************************************** + regtrav.c - Oniguruma (regular expression library) +**********************************************************************/ +/*- + * Copyright (c) 2002-2004 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "regint.h" + +#ifdef USE_CAPTURE_HISTORY + +static int +capture_tree_traverse(OnigCaptureTreeNode* node, int at, + int(*callback_func)(int,int,int,int,int,void*), + int level, void* arg) +{ + int r, i; + + if (node == (OnigCaptureTreeNode* )0) + return 0; + + if ((at & ONIG_TRAVERSE_CALLBACK_AT_FIRST) != 0) { + r = (*callback_func)(node->group, node->beg, node->end, + level, ONIG_TRAVERSE_CALLBACK_AT_FIRST, arg); + if (r != 0) return r; + } + + for (i = 0; i < node->num_childs; i++) { + r = capture_tree_traverse(node->childs[i], at, + callback_func, level + 1, arg); + if (r != 0) return r; + } + + if ((at & ONIG_TRAVERSE_CALLBACK_AT_LAST) != 0) { + r = (*callback_func)(node->group, node->beg, node->end, + level, ONIG_TRAVERSE_CALLBACK_AT_LAST, arg); + if (r != 0) return r; + } + + return 0; +} +#endif /* USE_CAPTURE_HISTORY */ + +extern int +onig_capture_tree_traverse(OnigRegion* region, int at, + int(*callback_func)(int,int,int,int,int,void*), void* arg) +{ +#ifdef USE_CAPTURE_HISTORY + return capture_tree_traverse(region->history_root, at, + callback_func, 0, arg); +#else + return ONIG_NO_SUPPORT_CONFIG; +#endif +} diff --git a/ext/mbstring/oniguruma/regversion.c b/ext/mbstring/oniguruma/regversion.c new file mode 100644 index 000000000000..5f15c10e6520 --- /dev/null +++ b/ext/mbstring/oniguruma/regversion.c @@ -0,0 +1,55 @@ +/********************************************************************** + regversion.c - Oniguruma (regular expression library) +**********************************************************************/ +/*- + * Copyright (c) 2002-2005 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "oniguruma.h" +#include + +extern const char* +onig_version(void) +{ + static char s[12]; + + sprintf(s, "%d.%d.%d", + ONIGURUMA_VERSION_MAJOR, + ONIGURUMA_VERSION_MINOR, + ONIGURUMA_VERSION_TEENY); + return s; +} + +extern const char* +onig_copyright(void) +{ + static char s[58]; + + sprintf(s, "Oniguruma %d.%d.%d : Copyright (C) 2002-2005 K.Kosako", + ONIGURUMA_VERSION_MAJOR, + ONIGURUMA_VERSION_MINOR, + ONIGURUMA_VERSION_TEENY); + return s; +} diff --git a/ext/mbstring/oniguruma/st.c b/ext/mbstring/oniguruma/st.c new file mode 100644 index 000000000000..65c2cc58bd79 --- /dev/null +++ b/ext/mbstring/oniguruma/st.c @@ -0,0 +1,717 @@ +/* This is a public domain general purpose hash table package written by Peter Moore @ UCB. */ + +/* static char sccsid[] = "@(#) st.c 5.1 89/12/14 Crucible"; */ + +#include "config.h" +#include +#include +#include + +#ifdef _WIN32 +#include +#endif + +#ifdef NOT_RUBY +#include "regint.h" +#else +#ifdef RUBY_PLATFORM +#define xmalloc ruby_xmalloc +#define xcalloc ruby_xcalloc +#define xrealloc ruby_xrealloc +#define xfree ruby_xfree + +void *xmalloc(long); +void *xcalloc(long, long); +void *xrealloc(void *, long); +void xfree(void *); +#endif +#endif + +#include "st.h" + +typedef struct st_table_entry st_table_entry; + +struct st_table_entry { + unsigned int hash; + st_data_t key; + st_data_t record; + st_table_entry *next; +}; + +#define ST_DEFAULT_MAX_DENSITY 5 +#define ST_DEFAULT_INIT_TABLE_SIZE 11 + + /* + * DEFAULT_MAX_DENSITY is the default for the largest we allow the + * average number of items per bin before increasing the number of + * bins + * + * DEFAULT_INIT_TABLE_SIZE is the default for the number of bins + * allocated initially + * + */ + +static int numcmp(long, long); +static int numhash(long); +static struct st_hash_type type_numhash = { + numcmp, + numhash, + st_nothing_key_free, + st_nothing_key_clone +}; + +/* extern int strcmp(const char *, const char *); */ +static int strhash(const char *); +static struct st_hash_type type_strhash = { + strcmp, + strhash, + st_nothing_key_free, + st_nothing_key_clone +}; + +static int strend_cmp(st_strend_key*, st_strend_key*); +static int strend_hash(st_strend_key*); +static int strend_key_free(st_data_t key); +static st_data_t strend_key_clone(st_data_t x); + +static struct st_hash_type type_strend_hash = { + strend_cmp, + strend_hash, + strend_key_free, + strend_key_clone +}; + +static void rehash(st_table *); + +#define alloc(type) (type*)xmalloc((unsigned)sizeof(type)) +#define Calloc(n,s) (char*)xcalloc((n),(s)) + +#define EQUAL(table,x,y) ((x)==(y) || (*table->type->compare)((x),(y)) == 0) + +#define do_hash(key,table) (unsigned int)(*(table)->type->hash)((key)) +#define do_hash_bin(key,table) (do_hash(key, table)%(table)->num_bins) + +/* + * MINSIZE is the minimum size of a dictionary. + */ + +#define MINSIZE 8 + +/* +Table of prime numbers 2^n+a, 2<=n<=30. +*/ +static long primes[] = { + 8 + 3, + 16 + 3, + 32 + 5, + 64 + 3, + 128 + 3, + 256 + 27, + 512 + 9, + 1024 + 9, + 2048 + 5, + 4096 + 3, + 8192 + 27, + 16384 + 43, + 32768 + 3, + 65536 + 45, + 131072 + 29, + 262144 + 3, + 524288 + 21, + 1048576 + 7, + 2097152 + 17, + 4194304 + 15, + 8388608 + 9, + 16777216 + 43, + 33554432 + 35, + 67108864 + 15, + 134217728 + 29, + 268435456 + 3, + 536870912 + 11, + 1073741824 + 85, + 0 +}; + +static int +new_size(size) + int size; +{ + int i; + +#if 0 + for (i=3; i<31; i++) { + if ((1< size) return 1< size) return primes[i]; + } + /* Ran out of polynomials */ + return -1; /* should raise exception */ +#endif +} + +#ifdef HASH_LOG +static int collision = 0; +static int init_st = 0; + +static void +stat_col() +{ + FILE *f = fopen("/tmp/col", "w"); + fprintf(f, "collision: %d\n", collision); + fclose(f); +} +#endif + +st_table* +st_init_table_with_size(type, size) + struct st_hash_type *type; + int size; +{ + st_table *tbl; + +#ifdef HASH_LOG + if (init_st == 0) { + init_st = 1; + atexit(stat_col); + } +#endif + + size = new_size(size); /* round up to prime number */ + + tbl = alloc(st_table); + tbl->type = type; + tbl->num_entries = 0; + tbl->num_bins = size; + tbl->bins = (st_table_entry **)Calloc(size, sizeof(st_table_entry*)); + + return tbl; +} + +st_table* +st_init_table(type) + struct st_hash_type *type; +{ + return st_init_table_with_size(type, 0); +} + +st_table* +st_init_numtable(void) +{ + return st_init_table(&type_numhash); +} + +st_table* +st_init_numtable_with_size(size) + int size; +{ + return st_init_table_with_size(&type_numhash, size); +} + +st_table* +st_init_strtable(void) +{ + return st_init_table(&type_strhash); +} + +st_table* +st_init_strtable_with_size(size) + int size; +{ + return st_init_table_with_size(&type_strhash, size); +} + +st_table* +st_init_strend_table_with_size(size) + int size; +{ + return st_init_table_with_size(&type_strend_hash, size); +} + +void +st_free_table(table) + st_table *table; +{ + register st_table_entry *ptr, *next; + int i; + + for(i = 0; i < table->num_bins; i++) { + ptr = table->bins[i]; + while (ptr != 0) { + next = ptr->next; + table->type->key_free(ptr->key); + free(ptr); + ptr = next; + } + } + free(table->bins); + free(table); +} + +#define PTR_NOT_EQUAL(table, ptr, hash_val, key) \ +((ptr) != 0 && (ptr->hash != (hash_val) || !EQUAL((table), (key), (ptr)->key))) + +#ifdef HASH_LOG +#define COLLISION collision++ +#else +#define COLLISION +#endif + +#define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\ + bin_pos = hash_val%(table)->num_bins;\ + ptr = (table)->bins[bin_pos];\ + if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) {\ + COLLISION;\ + while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) {\ + ptr = ptr->next;\ + }\ + ptr = ptr->next;\ + }\ +} while (0) + +int +st_lookup(table, key, value) + st_table *table; + register st_data_t key; + st_data_t *value; +{ + unsigned int hash_val, bin_pos; + register st_table_entry *ptr; + + hash_val = do_hash(key, table); + FIND_ENTRY(table, ptr, hash_val, bin_pos); + + if (ptr == 0) { + return 0; + } + else { + if (value != 0) *value = ptr->record; + return 1; + } +} + +int +st_lookup_strend(table, str_key, end_key, value) + st_table *table; + const unsigned char* str_key; + const unsigned char* end_key; + st_data_t *value; +{ + st_strend_key key; + + key.s = (unsigned char* )str_key; + key.end = (unsigned char* )end_key; + + return st_lookup(table, (st_data_t )(&key), value); +} + +#define ADD_DIRECT(table, key, value, hash_val, bin_pos)\ +do {\ + st_table_entry *entry;\ + if (table->num_entries/(table->num_bins) > ST_DEFAULT_MAX_DENSITY) {\ + rehash(table);\ + bin_pos = hash_val % table->num_bins;\ + }\ + \ + entry = alloc(st_table_entry);\ + \ + entry->hash = hash_val;\ + entry->key = key;\ + entry->record = value;\ + entry->next = table->bins[bin_pos];\ + table->bins[bin_pos] = entry;\ + table->num_entries++;\ +} while (0) + +int +st_insert(table, key, value) + register st_table *table; + register st_data_t key; + st_data_t value; +{ + unsigned int hash_val, bin_pos; + register st_table_entry *ptr; + + hash_val = do_hash(key, table); + FIND_ENTRY(table, ptr, hash_val, bin_pos); + + if (ptr == 0) { + ADD_DIRECT(table, key, value, hash_val, bin_pos); + return 0; + } + else { + ptr->record = value; + return 1; + } +} + +int +st_insert_strend(table, str_key, end_key, value) + st_table *table; + const unsigned char* str_key; + const unsigned char* end_key; + st_data_t value; +{ + st_strend_key* key; + + key = alloc(st_strend_key); + key->s = (unsigned char* )str_key; + key->end = (unsigned char* )end_key; + + return st_insert(table, (st_data_t )key, value); +} + +void +st_add_direct(table, key, value) + st_table *table; + st_data_t key; + st_data_t value; +{ + unsigned int hash_val, bin_pos; + + hash_val = do_hash(key, table); + bin_pos = hash_val % table->num_bins; + ADD_DIRECT(table, key, value, hash_val, bin_pos); +} + +void +st_add_direct_strend(table, str_key, end_key, value) + st_table *table; + const unsigned char* str_key; + const unsigned char* end_key; + st_data_t value; +{ + st_strend_key* key; + + key = alloc(st_strend_key); + key->s = (unsigned char* )str_key; + key->end = (unsigned char* )end_key; + st_add_direct(table, (st_data_t )key, value); +} + +static void +rehash(table) + register st_table *table; +{ + register st_table_entry *ptr, *next, **new_bins; + int i, old_num_bins = table->num_bins, new_num_bins; + unsigned int hash_val; + + new_num_bins = new_size(old_num_bins+1); + new_bins = (st_table_entry**)Calloc(new_num_bins, sizeof(st_table_entry*)); + + for(i = 0; i < old_num_bins; i++) { + ptr = table->bins[i]; + while (ptr != 0) { + next = ptr->next; + hash_val = ptr->hash % new_num_bins; + ptr->next = new_bins[hash_val]; + new_bins[hash_val] = ptr; + ptr = next; + } + } + free(table->bins); + table->num_bins = new_num_bins; + table->bins = new_bins; +} + +st_table* +st_copy(old_table) + st_table *old_table; +{ + st_table *new_table; + st_table_entry *ptr, *entry; + int i, num_bins = old_table->num_bins; + + new_table = alloc(st_table); + if (new_table == 0) { + return 0; + } + + *new_table = *old_table; + new_table->bins = (st_table_entry**) + Calloc((unsigned)num_bins, sizeof(st_table_entry*)); + + if (new_table->bins == 0) { + free(new_table); + return 0; + } + + for(i = 0; i < num_bins; i++) { + new_table->bins[i] = 0; + ptr = old_table->bins[i]; + while (ptr != 0) { + entry = alloc(st_table_entry); + if (entry == 0) { + free(new_table->bins); + free(new_table); + return 0; + } + *entry = *ptr; + entry->key = old_table->type->key_clone(ptr->key); + entry->next = new_table->bins[i]; + new_table->bins[i] = entry; + ptr = ptr->next; + } + } + return new_table; +} + +int +st_delete(table, key, value) + register st_table *table; + register st_data_t *key; + st_data_t *value; +{ + unsigned int hash_val; + st_table_entry *tmp; + register st_table_entry *ptr; + + hash_val = do_hash_bin(*key, table); + ptr = table->bins[hash_val]; + + if (ptr == 0) { + if (value != 0) *value = 0; + return 0; + } + + if (EQUAL(table, *key, ptr->key)) { + table->bins[hash_val] = ptr->next; + table->num_entries--; + if (value != 0) *value = ptr->record; + *key = ptr->key; + free(ptr); + return 1; + } + + for(; ptr->next != 0; ptr = ptr->next) { + if (EQUAL(table, ptr->next->key, *key)) { + tmp = ptr->next; + ptr->next = ptr->next->next; + table->num_entries--; + if (value != 0) *value = tmp->record; + *key = tmp->key; + free(tmp); + return 1; + } + } + + return 0; +} + +int +st_delete_safe(table, key, value, never) + register st_table *table; + register st_data_t *key; + st_data_t *value; + st_data_t never; +{ + unsigned int hash_val; + register st_table_entry *ptr; + + hash_val = do_hash_bin(*key, table); + ptr = table->bins[hash_val]; + + if (ptr == 0) { + if (value != 0) *value = 0; + return 0; + } + + for(; ptr != 0; ptr = ptr->next) { + if ((ptr->key != never) && EQUAL(table, ptr->key, *key)) { + table->num_entries--; + *key = ptr->key; + if (value != 0) *value = ptr->record; + ptr->key = ptr->record = never; + return 1; + } + } + + return 0; +} + +static int +delete_never(key, value, never) + st_data_t key, value, never; +{ + if (value == never) return ST_DELETE; + return ST_CONTINUE; +} + +void +st_cleanup_safe(table, never) + st_table *table; + st_data_t never; +{ + int num_entries = table->num_entries; + + st_foreach(table, delete_never, never); + table->num_entries = num_entries; +} + +void +st_foreach(table, func, arg) + st_table *table; + int (*func)(); + st_data_t arg; +{ + st_table_entry *ptr, *last, *tmp; + enum st_retval retval; + int i; + + for(i = 0; i < table->num_bins; i++) { + last = 0; + for(ptr = table->bins[i]; ptr != 0;) { + retval = (*func)(ptr->key, ptr->record, arg, 0); + switch (retval) { + case ST_CHECK: /* check if hash is modified during iteration */ + tmp = 0; + if (i < table->num_bins) { + for (tmp = table->bins[i]; tmp; tmp=tmp->next) { + if (tmp == ptr) break; + } + } + if (!tmp) { + /* call func with error notice */ + retval = (*func)(0, 0, arg, 1); + return; + } + /* fall through */ + case ST_CONTINUE: + last = ptr; + ptr = ptr->next; + break; + case ST_STOP: + return; + case ST_DELETE: + tmp = ptr; + if (last == 0) { + table->bins[i] = ptr->next; + } + else { + last->next = ptr->next; + } + ptr = ptr->next; + table->type->key_free(tmp->key); + free(tmp); + table->num_entries--; + } + } + } +} + +static int +strhash(string) + register const char *string; +{ + register int c; + +#ifdef HASH_ELFHASH + register unsigned int h = 0, g; + + while ((c = *string++) != '\0') { + h = ( h << 4 ) + c; + if ( g = h & 0xF0000000 ) + h ^= g >> 24; + h &= ~g; + } + return h; +#elif HASH_PERL + register int val = 0; + + while ((c = *string++) != '\0') { + val += c; + val += (val << 10); + val ^= (val >> 6); + } + val += (val << 3); + val ^= (val >> 11); + + return val + (val << 15); +#else + register int val = 0; + + while ((c = *string++) != '\0') { + val = val*997 + c; + } + + return val + (val>>5); +#endif +} + +static int +numcmp(x, y) + long x, y; +{ + return x != y; +} + +static int +numhash(n) + long n; +{ + return n; +} + +extern int +st_nothing_key_free(st_data_t key) { return 0; } + +extern st_data_t +st_nothing_key_clone(st_data_t x) { return x; } + +static int strend_cmp(st_strend_key* x, st_strend_key* y) +{ + unsigned char *p, *q; + int c; + + if ((x->end - x->s) != (y->end - y->s)) + return 1; + + p = x->s; + q = y->s; + while (p < x->end) { + c = (int )*p - (int )*q; + if (c != 0) return c; + + p++; q++; + } + + return 0; +} + +static int strend_hash(st_strend_key* x) +{ + int val; + unsigned char *p; + + val = 0; + p = x->s; + while (p < x->end) { + val = val * 997 + (int )*p++; + } + + return val + (val >> 5); +} + +static int strend_key_free(st_data_t x) +{ + xfree((void* )x); + return 0; +} + +static st_data_t strend_key_clone(st_data_t x) +{ + st_strend_key* new_key; + st_strend_key* key = (st_strend_key* )x; + + new_key = alloc(st_strend_key); + *new_key = *key; + return (st_data_t )new_key; +} diff --git a/ext/mbstring/oniguruma/st.h b/ext/mbstring/oniguruma/st.h new file mode 100644 index 000000000000..c5cc4e625e08 --- /dev/null +++ b/ext/mbstring/oniguruma/st.h @@ -0,0 +1,77 @@ +/* This is a public domain general purpose hash table package written by Peter Moore @ UCB. */ + +/* @(#) st.h 5.1 89/12/14 */ + +#ifndef ST_INCLUDED + +#define ST_INCLUDED + +typedef unsigned long st_data_t; +#define ST_DATA_T_DEFINED + +typedef struct st_table st_table; + +struct st_hash_type { + int (*compare)(); + int (*hash)(); + int (*key_free)(); + st_data_t (*key_clone)(); +}; + +struct st_table { + struct st_hash_type *type; + int num_bins; + int num_entries; + struct st_table_entry **bins; +}; + +typedef struct { + unsigned char* s; + unsigned char* end; +} st_strend_key; + +#define st_is_member(table,key) st_lookup(table,key,(st_data_t *)0) + +enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE, ST_CHECK}; + +#ifndef _ +# define _(args) args +#endif +#ifndef ANYARGS +# ifdef __cplusplus +# define ANYARGS ... +# else +# define ANYARGS +# endif +#endif + +st_table *st_init_table _((struct st_hash_type *)); +st_table *st_init_table_with_size _((struct st_hash_type *, int)); +st_table *st_init_numtable _((void)); +st_table *st_init_numtable_with_size _((int)); +st_table *st_init_strtable _((void)); +st_table *st_init_strtable_with_size _((int)); +st_table *st_init_strend_table_with_size _((int)); +int st_delete _((st_table *, st_data_t *, st_data_t *)); +int st_delete_safe _((st_table *, st_data_t *, st_data_t *, st_data_t)); +int st_insert _((st_table *, st_data_t, st_data_t)); +int st_insert_strend _((st_table *, const unsigned char*, const unsigned char*, st_data_t)); +int st_lookup _((st_table *, st_data_t, st_data_t *)); +int st_lookup_strend _((st_table *, const unsigned char*, const unsigned char*, st_data_t*)); +void st_foreach _((st_table *, int (*)(ANYARGS), st_data_t)); +void st_add_direct _((st_table *, st_data_t, st_data_t)); +void st_add_direct_strend _((st_table *, const unsigned char*, const unsigned char*, st_data_t)); +void st_free_table _((st_table *)); +void st_cleanup_safe _((st_table *, st_data_t)); +st_table *st_copy _((st_table *)); + +extern st_data_t st_nothing_key_clone _((st_data_t key)); +extern int st_nothing_key_free _((st_data_t key)); + +#define ST_NUMCMP ((int (*)()) 0) +#define ST_NUMHASH ((int (*)()) -2) + +#define st_numcmp ST_NUMCMP +#define st_numhash ST_NUMHASH + +#endif /* ST_INCLUDED */ diff --git a/ext/mbstring/oniguruma/testc.c b/ext/mbstring/oniguruma/testc.c deleted file mode 100644 index e4d197e21db3..000000000000 --- a/ext/mbstring/oniguruma/testc.c +++ /dev/null @@ -1,833 +0,0 @@ -/* - * This program was generated by testconv.rb. - */ -#include - -#ifdef POSIX_TEST -#include "onigposix.h" -#else -#include "oniguruma.h" -#endif - -static int nsucc = 0; -static int nfail = 0; -static int nerror = 0; - -static FILE* err_file; - -#ifndef POSIX_TEST -static OnigRegion* region; -#endif - -static void xx(char* pattern, char* str, int from, int to, int mem, int not) -{ - int r; - -#ifdef POSIX_TEST - regex_t reg; - char buf[200]; - regmatch_t pmatch[20]; - - r = regcomp(®, pattern, REG_EXTENDED | REG_NEWLINE); - if (r) { - regerror(r, ®, buf, sizeof(buf)); - fprintf(err_file, "ERROR: %s\n", buf); - nerror++; - return ; - } - - r = regexec(®, str, reg.re_nsub + 1, pmatch, 0); - if (r != 0 && r != REG_NOMATCH) { - regerror(r, ®, buf, sizeof(buf)); - fprintf(err_file, "ERROR: %s\n", buf); - nerror++; - return ; - } - - if (r == REG_NOMATCH) { - if (not) { - fprintf(stdout, "OK(N): /%s/ '%s'\n", pattern, str); - nsucc++; - } - else { - fprintf(stdout, "FAIL: /%s/ '%s'\n", pattern, str); - nfail++; - } - } - else { - if (not) { - fprintf(stdout, "FAIL(N): /%s/ '%s'\n", pattern, str); - nfail++; - } - else { - if (pmatch[mem].rm_so == from && pmatch[mem].rm_eo == to) { - fprintf(stdout, "OK: /%s/ '%s'\n", pattern, str); - nsucc++; - } - else { - fprintf(stdout, "FAIL: /%s/ '%s' %d-%d : %d-%d\n", pattern, str, - from, to, pmatch[mem].rm_so, pmatch[mem].rm_eo); - nfail++; - } - } - } - regfree(®); - -#else - regex_t* reg; - OnigErrorInfo einfo; - - r = onig_new(®, (UChar* )pattern, (UChar* )(pattern + strlen(pattern)), - ONIG_OPTION_DEFAULT, ONIG_ENCODING_EUC_JP, ONIG_SYNTAX_DEFAULT, &einfo); - if (r) { - char s[ONIG_MAX_ERROR_MESSAGE_LEN]; - onig_error_code_to_str(s, r, &einfo); - fprintf(err_file, "ERROR: %s\n", s); - nerror++; - return ; - } - - r = onig_search(reg, (UChar* )str, (UChar* )(str + strlen(str)), - (UChar* )str, (UChar* )(str + strlen(str)), - region, ONIG_OPTION_NONE); - if (r < ONIG_MISMATCH) { - char s[ONIG_MAX_ERROR_MESSAGE_LEN]; - onig_error_code_to_str(s, r); - fprintf(err_file, "ERROR: %s\n", s); - nerror++; - return ; - } - - if (r == ONIG_MISMATCH) { - if (not) { - fprintf(stdout, "OK(N): /%s/ '%s'\n", pattern, str); - nsucc++; - } - else { - fprintf(stdout, "FAIL: /%s/ '%s'\n", pattern, str); - nfail++; - } - } - else { - if (not) { - fprintf(stdout, "FAIL(N): /%s/ '%s'\n", pattern, str); - nfail++; - } - else { - if (region->beg[mem] == from && region->end[mem] == to) { - fprintf(stdout, "OK: /%s/ '%s'\n", pattern, str); - nsucc++; - } - else { - fprintf(stdout, "FAIL: /%s/ '%s' %d-%d : %d-%d\n", pattern, str, - from, to, region->beg[mem], region->end[mem]); - nfail++; - } - } - } - onig_free(reg); -#endif -} - -static void x2(char* pattern, char* str, int from, int to) -{ - xx(pattern, str, from, to, 0, 0); -} - -static void x3(char* pattern, char* str, int from, int to, int mem) -{ - xx(pattern, str, from, to, mem, 0); -} - -static void n(char* pattern, char* str) -{ - xx(pattern, str, 0, 0, 0, 1); -} - -extern int main(int argc, char* argv[]) -{ - err_file = stdout; - -#ifdef POSIX_TEST - reg_set_encoding(REG_POSIX_ENCODING_EUC_JP); -#else - region = onig_region_new(); -#endif - - x2("", "", 0, 0); - x2("^", "", 0, 0); - x2("$", "", 0, 0); - x2("\\G", "", 0, 0); - x2("\\A", "", 0, 0); - x2("\\Z", "", 0, 0); - x2("\\z", "", 0, 0); - x2("^$", "", 0, 0); - x2("\\ca", "\001", 0, 1); - x2("\\C-b", "\002", 0, 1); - x2("\\M-Z", "\xDA", 0, 1); - x2("", "a", 0, 0); - x2("a", "a", 0, 1); - x2("aa", "aa", 0, 2); - x2("aaa", "aaa", 0, 3); - x2("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0, 35); - x2("ab", "ab", 0, 2); - x2("b", "ab", 1, 2); - x2("bc", "abc", 1, 3); - x2("\\17", "\017", 0, 1); - x2("\\x1f", "\x1f", 0, 1); - x2("\\xFE", "\xfe", 0, 1); - x2("a(?#....\\\\JJJJ)b", "ab", 0, 2); - x2("(?x) G (o O(?-x)oO) g L", "GoOoOgLe", 0, 7); - x2(".", "a", 0, 1); - n(".", ""); - x2("..", "ab", 0, 2); - x2("\\w", "e", 0, 1); - n("\\W", "e"); - x2("\\s", " ", 0, 1); - x2("\\S", "b", 0, 1); - x2("\\d", "4", 0, 1); - n("\\D", "4"); - x2("\\b", "z ", 0, 0); - x2("\\b", " z", 1, 1); - x2("\\B", "zz ", 1, 1); - x2("\\B", "z ", 2, 2); - x2("\\B", " z", 0, 0); - x2("[ab]", "b", 0, 1); - n("[ab]", "c"); - x2("[a-z]", "t", 0, 1); - n("[^a]", "a"); - x2("[^a]", "\n", 0, 1); - x2("[]]", "]", 0, 1); - n("[^]]", "]"); - x2("[\\^]+", "0^^1", 1, 3); - x2("[b-]", "b", 0, 1); - x2("[b-]", "-", 0, 1); - x2("[\\w]", "z", 0, 1); - n("[\\w]", " "); - x2("[\\W]", "b$", 1, 2); - x2("[\\d]", "5", 0, 1); - n("[\\d]", "e"); - x2("[\\D]", "t", 0, 1); - n("[\\D]", "3"); - x2("[\\s]", " ", 0, 1); - n("[\\s]", "a"); - x2("[\\S]", "b", 0, 1); - n("[\\S]", " "); - x2("[\\w\\d]", "2", 0, 1); - n("[\\w\\d]", " "); - x2("[[:upper:]]", "B", 0, 1); - x2("[*[:xdigit:]+]", "+", 0, 1); - x2("[*[:xdigit:]+]", "GHIKK-9+*", 6, 7); - x2("[*[:xdigit:]+]", "-@^+", 3, 4); - n("[[:upper]]", "A"); - x2("[[:upper]]", ":", 0, 1); - x2("[\\044-\\047]", "\046", 0, 1); - x2("[\\x5a-\\x5c]", "\x5b", 0, 1); - x2("[\\x6A-\\x6D]", "\x6c", 0, 1); - n("[\\x6A-\\x6D]", "\x6E"); - n("^[0-9A-F]+ 0+ UNDEF ", "75F 00000000 SECT14A notype () External | _rb_apply"); - x2("[\\[]", "[", 0, 1); - x2("[\\]]", "]", 0, 1); - x2("[&]", "&", 0, 1); - x2("[[ab]]", "b", 0, 1); - x2("[[ab]c]", "c", 0, 1); - n("[[^a]]", "a"); - n("[^[a]]", "a"); - x2("[[ab]&&bc]", "b", 0, 1); - n("[[ab]&&bc]", "a"); - n("[[ab]&&bc]", "c"); - x2("[a-z&&b-y&&c-x]", "w", 0, 1); - n("[^a-z&&b-y&&c-x]", "w"); - x2("[[^a&&a]&&a-z]", "b", 0, 1); - n("[[^a&&a]&&a-z]", "a"); - x2("[[^a-z&&bcdef]&&[^c-g]]", "h", 0, 1); - n("[[^a-z&&bcdef]&&[^c-g]]", "c"); - x2("[^[^abc]&&[^cde]]", "c", 0, 1); - x2("[^[^abc]&&[^cde]]", "e", 0, 1); - n("[^[^abc]&&[^cde]]", "f"); - x2("[a-&&-a]", "-", 0, 1); - n("[a-&&-a]", "&"); - n("\\wabc", " abc"); - x2("a\\Wbc", "a bc", 0, 4); - x2("a.b.c", "aabbc", 0, 5); - x2(".\\wb\\W..c", "abb bcc", 0, 7); - x2("\\s\\wzzz", " zzzz", 0, 5); - x2("aa.b", "aabb", 0, 4); - n(".a", "ab"); - x2(".a", "aa", 0, 2); - x2("^a", "a", 0, 1); - x2("^a$", "a", 0, 1); - x2("^\\w$", "a", 0, 1); - n("^\\w$", " "); - x2("^\\wab$", "zab", 0, 3); - x2("^\\wabcdef$", "zabcdef", 0, 7); - x2("^\\w...def$", "zabcdef", 0, 7); - x2("\\w\\w\\s\\Waaa\\d", "aa aaa4", 0, 8); - x2("\\A\\Z", "", 0, 0); - x2("\\Axyz", "xyz", 0, 3); - x2("xyz\\Z", "xyz", 0, 3); - x2("xyz\\z", "xyz", 0, 3); - x2("\\Gaz", "az", 0, 2); - n("\\Gz", "bza"); - n("az\\G", "az"); - n("az\\A", "az"); - n("a\\Az", "az"); - x2("\\^\\$", "^$", 0, 2); - x2("^x?y", "xy", 0, 2); - x2("^(x?y)", "xy", 0, 2); - x2("\\w", "_", 0, 1); - n("\\W", "_"); - x2("(?=z)z", "z", 0, 1); - n("(?=z).", "a"); - x2("(?!z)a", "a", 0, 1); - n("(?!z)a", "z"); - x2("(?i:a)", "a", 0, 1); - x2("(?i:a)", "A", 0, 1); - x2("(?i:A)", "a", 0, 1); - n("(?i:A)", "b"); - x2("(?i:[A-Z])", "a", 0, 1); - x2("(?i:[f-m])", "H", 0, 1); - x2("(?i:[f-m])", "h", 0, 1); - n("(?i:[f-m])", "e"); - x2("(?i:[A-c])", "D", 0, 1); - x2("(?i:[!-k])", "Z", 0, 1); - x2("(?i:[!-k])", "7", 0, 1); - x2("(?i:[T-}])", "b", 0, 1); - x2("(?i:[T-}])", "{", 0, 1); - x2("(?i:\\?a)", "?A", 0, 2); - x2("(?i:\\*A)", "*a", 0, 2); - n(".", "\n"); - x2("(?m:.)", "\n", 0, 1); - x2("(?m:a.)", "a\n", 0, 2); - x2("(?m:.b)", "a\nb", 1, 3); - n("(?i)(?-i)a", "A"); - n("(?i)(?-i:a)", "A"); - x2("a?", "", 0, 0); - x2("a?", "b", 0, 0); - x2("a?", "a", 0, 1); - x2("a*", "", 0, 0); - x2("a*", "a", 0, 1); - x2("a*", "aaa", 0, 3); - x2("a*", "baaaa", 0, 0); - n("a+", ""); - x2("a+", "a", 0, 1); - x2("a+", "aaaa", 0, 4); - x2("a+", "aabbb", 0, 2); - x2("a+", "baaaa", 1, 5); - x2(".?", "", 0, 0); - x2(".?", "f", 0, 1); - x2(".?", "\n", 0, 0); - x2(".*", "", 0, 0); - x2(".*", "abcde", 0, 5); - x2(".+", "z", 0, 1); - x2(".+", "zdswer\n", 0, 6); - x2("a|b", "a", 0, 1); - x2("a|b", "b", 0, 1); - x2("|a", "a", 0, 0); - x2("(|a)", "a", 0, 0); - x2("ab|bc", "ab", 0, 2); - x2("ab|bc", "bc", 0, 2); - x2("z(?:ab|bc)", "zbc", 0, 3); - x2("a(?:ab|bc)c", "aabc", 0, 4); - x2("ab|(?:ac|az)", "az", 0, 2); - x2("a|b|c", "dc", 1, 2); - x2("a|b|cd|efg|h|ijk|lmn|o|pq|rstuvwx|yz", "pqr", 0, 2); - n("a|b|cd|efg|h|ijk|lmn|o|pq|rstuvwx|yz", "mn"); - x2("a|^z", "ba", 1, 2); - x2("a|^z", "za", 0, 1); - x2("a|\\Gz", "bza", 2, 3); - x2("a|\\Gz", "za", 0, 1); - x2("a|\\Az", "bza", 2, 3); - x2("a|\\Az", "za", 0, 1); - x2("a|b\\Z", "ba", 1, 2); - x2("a|b\\Z", "b", 0, 1); - x2("a|b\\z", "ba", 1, 2); - x2("a|b\\z", "b", 0, 1); - x2("\\w|\\s", " ", 0, 1); - n("\\w|\\w", " "); - x2("\\w|%", "%", 0, 1); - x2("\\w|[&$]", "&", 0, 1); - x2("[b-d]|[^e-z]", "a", 0, 1); - x2("(?:a|[c-f])|bz", "dz", 0, 1); - x2("(?:a|[c-f])|bz", "bz", 0, 2); - x2("abc|(?=zz)..f", "zzf", 0, 3); - x2("abc|(?!zz)..f", "abf", 0, 3); - x2("(?=za)..a|(?=zz)..a", "zza", 0, 3); - n("(?>a|abd)c", "abdc"); - x2("(?>abd|a)c", "abdc", 0, 4); - x2("a?|b", "a", 0, 1); - x2("a?|b", "b", 0, 0); - x2("a?|b", "", 0, 0); - x2("a*|b", "aa", 0, 2); - x2("a*|b*", "ba", 0, 0); - x2("a*|b*", "ab", 0, 1); - x2("a+|b*", "", 0, 0); - x2("a+|b*", "bbb", 0, 3); - x2("a+|b*", "abbb", 0, 1); - n("a+|b+", ""); - x2("(a|b)?", "b", 0, 1); - x2("(a|b)*", "ba", 0, 2); - x2("(a|b)+", "bab", 0, 3); - x2("(ab|ca)+", "caabbc", 0, 4); - x2("(ab|ca)+", "aabca", 1, 5); - x2("(ab|ca)+", "abzca", 0, 2); - x2("(a|bab)+", "ababa", 0, 5); - x2("(a|bab)+", "ba", 1, 2); - x2("(a|bab)+", "baaaba", 1, 4); - x2("(?:a|b)(?:a|b)", "ab", 0, 2); - x2("(?:a*|b*)(?:a*|b*)", "aaabbb", 0, 3); - x2("(?:a*|b*)(?:a+|b+)", "aaabbb", 0, 6); - x2("(?:a+|b+){2}", "aaabbb", 0, 6); - x2("h{0,}", "hhhh", 0, 4); - x2("(?:a+|b+){1,2}", "aaabbb", 0, 6); - n("ax{2}*a", "0axxxa1"); - n("a.{0,2}a", "0aXXXa0"); - n("a.{0,2}?a", "0aXXXa0"); - n("a.{0,2}?a", "0aXXXXa0"); - x2("(?:a+|\\Ab*)cc", "cc", 0, 2); - n("(?:a+|\\Ab*)cc", "abcc"); - x2("(?:^a+|b+)*c", "aabbbabc", 6, 8); - x2("(?:^a+|b+)*c", "aabbbbc", 0, 7); - x2("a|(?i)c", "C", 0, 1); - x2("(?i)c|a", "C", 0, 1); - x2("(?i)c|a", "A", 0, 1); - x2("(?i:c)|a", "C", 0, 1); - n("(?i:c)|a", "A"); - x2("[abc]?", "abc", 0, 1); - x2("[abc]*", "abc", 0, 3); - x2("[^abc]*", "abc", 0, 0); - n("[^abc]+", "abc"); - x2("a??", "aaa", 0, 0); - x2("ba??b", "bab", 0, 3); - x2("a*?", "aaa", 0, 0); - x2("ba*?", "baa", 0, 1); - x2("ba*?b", "baab", 0, 4); - x2("a+?", "aaa", 0, 1); - x2("ba+?", "baa", 0, 2); - x2("ba+?b", "baab", 0, 4); - x2("(?:a?)??", "a", 0, 0); - x2("(?:a??)?", "a", 0, 0); - x2("(?:a?)+?", "aaa", 0, 1); - x2("(?:a+)??", "aaa", 0, 0); - x2("(?:a+)??b", "aaab", 0, 4); - x2("(?:ab)?{2}", "", 0, 0); - x2("(?:ab)?{2}", "ababa", 0, 4); - x2("(?:ab)*{0}", "ababa", 0, 0); - x2("(?:ab){3,}", "abababab", 0, 8); - n("(?:ab){3,}", "abab"); - x2("(?:ab){2,4}", "ababab", 0, 6); - x2("(?:ab){2,4}", "ababababab", 0, 8); - x2("(?:ab){2,4}?", "ababababab", 0, 4); - x2("(?:ab){,}", "ab{,}", 0, 5); - x2("(?:abc)+?{2}", "abcabcabc", 0, 6); - x2("(?:X*)(?i:xa)", "XXXa", 0, 4); - x2("(d+)([^abc]z)", "dddz", 0, 4); - x2("([^abc]*)([^abc]z)", "dddz", 0, 4); - x2("(\\w+)(\\wz)", "dddz", 0, 4); - x3("(a)", "a", 0, 1, 1); - x3("(ab)", "ab", 0, 2, 1); - x2("((ab))", "ab", 0, 2); - x3("((ab))", "ab", 0, 2, 1); - x3("((ab))", "ab", 0, 2, 2); - x3("((((((((((((((((((((ab))))))))))))))))))))", "ab", 0, 2, 20); - x3("(ab)(cd)", "abcd", 0, 2, 1); - x3("(ab)(cd)", "abcd", 2, 4, 2); - x3("()(a)bc(def)ghijk", "abcdefghijk", 3, 6, 3); - x3("(()(a)bc(def)ghijk)", "abcdefghijk", 3, 6, 4); - x2("(^a)", "a", 0, 1); - x3("(a)|(a)", "ba", 1, 2, 1); - x3("(^a)|(a)", "ba", 1, 2, 2); - x3("(a?)", "aaa", 0, 1, 1); - x3("(a*)", "aaa", 0, 3, 1); - x3("(a*)", "", 0, 0, 1); - x3("(a+)", "aaaaaaa", 0, 7, 1); - x3("(a+|b*)", "bbbaa", 0, 3, 1); - x3("(a+|b?)", "bbbaa", 0, 1, 1); - x3("(abc)?", "abc", 0, 3, 1); - x3("(abc)*", "abc", 0, 3, 1); - x3("(abc)+", "abc", 0, 3, 1); - x3("(xyz|abc)+", "abc", 0, 3, 1); - x3("([xyz][abc]|abc)+", "abc", 0, 3, 1); - x3("((?i:abc))", "AbC", 0, 3, 1); - x2("(abc)(?i:\\1)", "abcABC", 0, 6); - x3("((?m:a.c))", "a\nc", 0, 3, 1); - x3("((?=az)a)", "azb", 0, 1, 1); - x3("abc|(.abd)", "zabd", 0, 4, 1); - x2("(?:abc)|(ABC)", "abc", 0, 3); - x3("(?i:(abc))|(zzz)", "ABC", 0, 3, 1); - x3("a*(.)", "aaaaz", 4, 5, 1); - x3("a*?(.)", "aaaaz", 0, 1, 1); - x3("a*?(c)", "aaaac", 4, 5, 1); - x3("[bcd]a*(.)", "caaaaz", 5, 6, 1); - x3("(\\Abb)cc", "bbcc", 0, 2, 1); - n("(\\Abb)cc", "zbbcc"); - x3("(^bb)cc", "bbcc", 0, 2, 1); - n("(^bb)cc", "zbbcc"); - x3("cc(bb$)", "ccbb", 2, 4, 1); - n("cc(bb$)", "ccbbb"); - n("(\\1)", ""); - n("\\1(a)", "aa"); - n("(a(b)\\1)\\2+", "ababb"); - n("(?:(?:\\1|z)(a))+$", "zaa"); - x2("(?:(?:\\1|z)(a))+$", "zaaa", 0, 4); - x2("(a)(?=\\1)", "aa", 0, 1); - n("(a)$|\\1", "az"); - x2("(a)\\1", "aa", 0, 2); - n("(a)\\1", "ab"); - x2("(a?)\\1", "aa", 0, 2); - x2("(a??)\\1", "aa", 0, 0); - x2("(a*)\\1", "aaaaa", 0, 4); - x3("(a*)\\1", "aaaaa", 0, 2, 1); - x2("a(b*)\\1", "abbbb", 0, 5); - x2("a(b*)\\1", "ab", 0, 1); - x2("(a*)(b*)\\1\\2", "aaabbaaabb", 0, 10); - x2("(a*)(b*)\\2", "aaabbbb", 0, 7); - x2("(((((((a*)b))))))c\\7", "aaabcaaa", 0, 8); - x3("(((((((a*)b))))))c\\7", "aaabcaaa", 0, 3, 7); - x2("(a)(b)(c)\\2\\1\\3", "abcbac", 0, 6); - x2("([a-d])\\1", "cc", 0, 2); - x2("(\\w\\d\\s)\\1", "f5 f5 ", 0, 6); - n("(\\w\\d\\s)\\1", "f5 f5"); - x2("(who|[a-c]{3})\\1", "whowho", 0, 6); - x2("...(who|[a-c]{3})\\1", "abcwhowho", 0, 9); - x2("(who|[a-c]{3})\\1", "cbccbc", 0, 6); - x2("(^a)\\1", "aa", 0, 2); - n("(^a)\\1", "baa"); - n("(a$)\\1", "aa"); - n("(ab\\Z)\\1", "ab"); - x2("(a*\\Z)\\1", "a", 1, 1); - x2(".(a*\\Z)\\1", "ba", 1, 2); - x3("(.(abc)\\2)", "zabcabc", 0, 7, 1); - x3("(.(..\\d.)\\2)", "z12341234", 0, 9, 1); - x2("((?i:az))\\1", "AzAz", 0, 4); - n("((?i:az))\\1", "Azaz"); - x2("(?<=a)b", "ab", 1, 2); - n("(?<=a)b", "bb"); - x2("(?<=a|b)b", "bb", 1, 2); - x2("(?<=a|bc)b", "bcb", 2, 3); - x2("(?<=a|bc)b", "ab", 1, 2); - x2("(?<=a|bc||defghij|klmnopq|r)z", "rz", 1, 2); - x2("(a)\\g<1>", "aa", 0, 2); - x2("(?a)", "a", 0, 1); - x2("(?ab)\\g", "abab", 0, 4); - x2("(?.zv.)\\k", "azvbazvb", 0, 8); - x2("(?<=\\g)|-\\zEND (?XyZ)", "XyZ", 3, 3); - x2("(?|a\\g)+", "", 0, 0); - x2("(?|\\(\\g\\))+$", "()(())", 0, 6); - x3("\\g(?.){0}", "X", 0, 1, 1); - x2("\\g(abc|df(?.YZ){2,8}){0}", "XYZ", 0, 3); - x2("\\A(?(a\\g)|)\\z", "aaaa", 0, 4); - x2("(?|\\g\\g)\\z|\\zEND (?a|(b)\\g)", "bbbbabba", 0, 8); - x2("(?\\w+\\sx)a+\\k", " fg xaaaaaaaafg x", 2, 18); - x3("(z)()()(?<_9>a)\\g<_9>", "zaa", 2, 3, 1); - x2("(.)(((?<_>a)))\\k<_>", "zaa", 0, 3); - x2("((?\\d)|(?\\w))(\\k|\\k)", "ff", 0, 2); - x2("(?:(?)|(?efg))\\k", "", 0, 0); - x2("(?:(?abc)|(?efg))\\k", "abcefgefg", 3, 9); - n("(?:(?abc)|(?efg))\\k", "abcefg"); - x2("(?:(?.)|(?..)|(?...)|(?....)|(?.....)|(?......)|(?.......)|(?........)|(?.........)|(?..........)|(?...........)|(?............)|(?.............)|(?..............))\\k$", "a-pyumpyum", 2, 10); - x3("(?:(?.)|(?..)|(?...)|(?....)|(?.....)|(?......)|(?.......)|(?........)|(?.........)|(?..........)|(?...........)|(?............)|(?.............)|(?..............))\\k$", "xxxxabcdefghijklmnabcdefghijklmn", 4, 18, 14); - x3("(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?aaa)(?)$", "aaa", 0, 3, 16); - x2("(?a|\\(\\g\\))", "a", 0, 1); - x2("(?a|\\(\\g\\))", "((((((a))))))", 0, 13); - x3("(?a|\\(\\g\\))", "((((((((a))))))))", 0, 17, 1); - x2("\\g|\\zEND(?.*abc$)", "abcxxxabc", 0, 9); - x2("\\g<1>|\\zEND(.a.)", "bac", 0, 3); - x3("\\g<_A>\\g<_A>|\\zEND(.a.)(?<_A>.b.)", "xbxyby", 3, 6, 1); - x2("\\A(?:\\g|\\g|\\zEND (?a|c\\gc)(?b|d\\gd))$", "cdcbcdc", 0, 7); - x2("\\A(?|a\\g)\\z|\\zEND (?\\g)", "aaaa", 0, 4); - x2("(?(a|b\\gc){3,5})", "baaaaca", 1, 5); - x2("(?(a|b\\gc){3,5})", "baaaacaaaaa", 0, 10); - x2("()*\\1", "", 0, 0); - x2("(?:()|())*\\1\\2", "", 0, 0); - x3("(?:\\1a|())*", "a", 0, 0, 1); - x2("x((.)*)*x", "0x1x2x3", 1, 6); - x2("x((.)*)*x(?i:\\1)\\Z", "0x1x2x1X2", 1, 9); - x2("(?:()|()|()|()|()|())*\\2\\5", "", 0, 0); - x2("(?:()|()|()|(x)|()|())*\\2b\\5", "b", 0, 1); - x2("", "¤¢", 0, 0); - x2("¤¢", "¤¢", 0, 2); - n("¤¤", "¤¢"); - x2("¤¦¤¦", "¤¦¤¦", 0, 4); - x2("¤¢¤¤¤¦", "¤¢¤¤¤¦", 0, 6); - x2("¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³", "¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³¤³", 0, 70); - x2("¤¢", "¤¤¤¢", 2, 4); - x2("¤¤¤¦", "¤¢¤¤¤¦", 2, 6); - x2("\\xca\\xb8", "\xca\xb8", 0, 2); - x2(".", "¤¢", 0, 2); - x2("..", "¤«¤­", 0, 4); - x2("\\w", "¤ª", 0, 2); - n("\\W", "¤¢"); - x2("[\\W]", "¤¦$", 2, 3); - x2("\\S", "¤½", 0, 2); - x2("\\S", "´Á", 0, 2); - x2("\\b", "µ¤ ", 0, 0); - x2("\\b", " ¤Û", 1, 1); - x2("\\B", "¤»¤½ ", 2, 2); - x2("\\B", "¤¦ ", 3, 3); - x2("\\B", " ¤¤", 0, 0); - x2("[¤¿¤Á]", "¤Á", 0, 2); - n("[¤Ê¤Ë]", "¤Ì"); - x2("[¤¦-¤ª]", "¤¨", 0, 2); - n("[^¤±]", "¤±"); - x2("[\\w]", "¤Í", 0, 2); - n("[\\d]", "¤Õ"); - x2("[\\D]", "¤Ï", 0, 2); - n("[\\s]", "¤¯"); - x2("[\\S]", "¤Ø", 0, 2); - x2("[\\w\\d]", "¤è", 0, 2); - x2("[\\w\\d]", " ¤è", 3, 5); - n("\\wµ´¼Ö", " µ´¼Ö"); - x2("µ´\\W¼Ö", "µ´ ¼Ö", 0, 5); - x2("¤¢.¤¤.¤¦", "¤¢¤¢¤¤¤¤¤¦", 0, 10); - x2(".\\w¤¦\\W..¤¾", "¤¨¤¦¤¦ ¤¦¤¾¤¾", 0, 13); - x2("\\s\\w¤³¤³¤³", " ¤³¤³¤³¤³", 0, 9); - x2("¤¢¤¢.¤±", "¤¢¤¢¤±¤±", 0, 8); - n(".¤¤", "¤¤¤¨"); - x2(".¤ª", "¤ª¤ª", 0, 4); - x2("^¤¢", "¤¢", 0, 2); - x2("^¤à$", "¤à", 0, 2); - x2("^\\w$", "¤Ë", 0, 2); - x2("^\\w¤«¤­¤¯¤±¤³$", "z¤«¤­¤¯¤±¤³", 0, 11); - x2("^\\w...¤¦¤¨¤ª$", "z¤¢¤¤¤¦¤¦¤¨¤ª", 0, 13); - x2("\\w\\w\\s\\W¤ª¤ª¤ª\\d", "a¤ª ¤ª¤ª¤ª4", 0, 12); - x2("\\A¤¿¤Á¤Ä", "¤¿¤Á¤Ä", 0, 6); - x2("¤à¤á¤â\\Z", "¤à¤á¤â", 0, 6); - x2("¤«¤­¤¯\\z", "¤«¤­¤¯", 0, 6); - x2("¤«¤­¤¯\\Z", "¤«¤­¤¯\n", 0, 6); - x2("\\G¤Ý¤Ô", "¤Ý¤Ô", 0, 4); - n("\\G¤¨", "¤¦¤¨¤ª"); - n("¤È¤Æ\\G", "¤È¤Æ"); - n("¤Þ¤ß\\A", "¤Þ¤ß"); - n("¤Þ\\A¤ß", "¤Þ¤ß"); - x2("(?=¤»)¤»", "¤»", 0, 2); - n("(?=¤¦).", "¤¤"); - x2("(?!¤¦)¤«", "¤«", 0, 2); - n("(?!¤È)¤¢", "¤È"); - x2("(?i:¤¢)", "¤¢", 0, 2); - x2("(?i:¤Ö¤Ù)", "¤Ö¤Ù", 0, 4); - n("(?i:¤¤)", "¤¦"); - x2("(?m:¤è.)", "¤è\n", 0, 3); - x2("(?m:.¤á)", "¤Þ\n¤á", 2, 5); - x2("¤¢?", "", 0, 0); - x2("ÊÑ?", "²½", 0, 0); - x2("ÊÑ?", "ÊÑ", 0, 2); - x2("ÎÌ*", "", 0, 0); - x2("ÎÌ*", "ÎÌ", 0, 2); - x2("»Ò*", "»Ò»Ò»Ò", 0, 6); - x2("ÇÏ*", "¼¯ÇÏÇÏÇÏÇÏ", 0, 0); - n("»³+", ""); - x2("²Ï+", "²Ï", 0, 2); - x2("»þ+", "»þ»þ»þ»þ", 0, 8); - x2("¤¨+", "¤¨¤¨¤¦¤¦¤¦", 0, 4); - x2("¤¦+", "¤ª¤¦¤¦¤¦¤¦", 2, 10); - x2(".?", "¤¿", 0, 2); - x2(".*", "¤Ñ¤Ô¤×¤Ú", 0, 8); - x2(".+", "¤í", 0, 2); - x2(".+", "¤¤¤¦¤¨¤«\n", 0, 8); - x2("¤¢|¤¤", "¤¢", 0, 2); - x2("¤¢|¤¤", "¤¤", 0, 2); - x2("¤¢¤¤|¤¤¤¦", "¤¢¤¤", 0, 4); - x2("¤¢¤¤|¤¤¤¦", "¤¤¤¦", 0, 4); - x2("¤ò(?:¤«¤­|¤­¤¯)", "¤ò¤«¤­", 0, 6); - x2("¤ò(?:¤«¤­|¤­¤¯)¤±", "¤ò¤­¤¯¤±", 0, 8); - x2("¤¢¤¤|(?:¤¢¤¦|¤¢¤ò)", "¤¢¤ò", 0, 4); - x2("¤¢|¤¤|¤¦", "¤¨¤¦", 2, 4); - x2("¤¢|¤¤|¤¦¤¨|¤ª¤«¤­|¤¯|¤±¤³¤µ|¤·¤¹¤»|¤½|¤¿¤Á|¤Ä¤Æ¤È¤Ê¤Ë|¤Ì¤Í", "¤·¤¹¤»", 0, 6); - n("¤¢|¤¤|¤¦¤¨|¤ª¤«¤­|¤¯|¤±¤³¤µ|¤·¤¹¤»|¤½|¤¿¤Á|¤Ä¤Æ¤È¤Ê¤Ë|¤Ì¤Í", "¤¹¤»"); - x2("¤¢|^¤ï", "¤Ö¤¢", 2, 4); - x2("¤¢|^¤ò", "¤ò¤¢", 0, 2); - x2("µ´|\\G¼Ö", "¤±¼Öµ´", 4, 6); - x2("µ´|\\G¼Ö", "¼Öµ´", 0, 2); - x2("µ´|\\A¼Ö", "b¼Öµ´", 3, 5); - x2("µ´|\\A¼Ö", "¼Ö", 0, 2); - x2("µ´|¼Ö\\Z", "¼Öµ´", 2, 4); - x2("µ´|¼Ö\\Z", "¼Ö", 0, 2); - x2("µ´|¼Ö\\Z", "¼Ö\n", 0, 2); - x2("µ´|¼Ö\\z", "¼Öµ´", 2, 4); - x2("µ´|¼Ö\\z", "¼Ö", 0, 2); - x2("\\w|\\s", "¤ª", 0, 2); - x2("\\w|%", "%¤ª", 0, 1); - x2("\\w|[&$]", "¤¦&", 0, 2); - x2("[¤¤-¤±]", "¤¦", 0, 2); - x2("[¤¤-¤±]|[^¤«-¤³]", "¤¢", 0, 2); - x2("[¤¤-¤±]|[^¤«-¤³]", "¤«", 0, 2); - x2("[^¤¢]", "\n", 0, 1); - x2("(?:¤¢|[¤¦-¤­])|¤¤¤ò", "¤¦¤ò", 0, 2); - x2("(?:¤¢|[¤¦-¤­])|¤¤¤ò", "¤¤¤ò", 0, 4); - x2("¤¢¤¤¤¦|(?=¤±¤±)..¤Û", "¤±¤±¤Û", 0, 6); - x2("¤¢¤¤¤¦|(?!¤±¤±)..¤Û", "¤¢¤¤¤Û", 0, 6); - x2("(?=¤ò¤¢)..¤¢|(?=¤ò¤ò)..¤¢", "¤ò¤ò¤¢", 0, 6); - x2("(?<=¤¢|¤¤¤¦)¤¤", "¤¤¤¦¤¤", 4, 6); - n("(?>¤¢|¤¢¤¤¤¨)¤¦", "¤¢¤¤¤¨¤¦"); - x2("(?>¤¢¤¤¤¨|¤¢)¤¦", "¤¢¤¤¤¨¤¦", 0, 8); - x2("¤¢?|¤¤", "¤¢", 0, 2); - x2("¤¢?|¤¤", "¤¤", 0, 0); - x2("¤¢?|¤¤", "", 0, 0); - x2("¤¢*|¤¤", "¤¢¤¢", 0, 4); - x2("¤¢*|¤¤*", "¤¤¤¢", 0, 0); - x2("¤¢*|¤¤*", "¤¢¤¤", 0, 2); - x2("[a¤¢]*|¤¤*", "a¤¢¤¤¤¤¤¤", 0, 3); - x2("¤¢+|¤¤*", "", 0, 0); - x2("¤¢+|¤¤*", "¤¤¤¤¤¤", 0, 6); - x2("¤¢+|¤¤*", "¤¢¤¤¤¤¤¤", 0, 2); - x2("¤¢+|¤¤*", "a¤¢¤¤¤¤¤¤", 0, 0); - n("¤¢+|¤¤+", ""); - x2("(¤¢|¤¤)?", "¤¤", 0, 2); - x2("(¤¢|¤¤)*", "¤¤¤¢", 0, 4); - x2("(¤¢|¤¤)+", "¤¤¤¢¤¤", 0, 6); - x2("(¤¢¤¤|¤¦¤¢)+", "¤¦¤¢¤¢¤¤¤¦¤¨", 0, 8); - x2("(¤¢¤¤|¤¦¤¨)+", "¤¦¤¢¤¢¤¤¤¦¤¨", 4, 12); - x2("(¤¢¤¤|¤¦¤¢)+", "¤¢¤¢¤¤¤¦¤¢", 2, 10); - x2("(¤¢¤¤|¤¦¤¢)+", "¤¢¤¤¤ò¤¦¤¢", 0, 4); - x2("(¤¢¤¤|¤¦¤¢)+", "$$zzzz¤¢¤¤¤ò¤¦¤¢", 6, 10); - x2("(¤¢|¤¤¤¢¤¤)+", "¤¢¤¤¤¢¤¤¤¢", 0, 10); - x2("(¤¢|¤¤¤¢¤¤)+", "¤¤¤¢", 2, 4); - x2("(¤¢|¤¤¤¢¤¤)+", "¤¤¤¢¤¢¤¢¤¤¤¢", 2, 8); - x2("(?:¤¢|¤¤)(?:¤¢|¤¤)", "¤¢¤¤", 0, 4); - x2("(?:¤¢*|¤¤*)(?:¤¢*|¤¤*)", "¤¢¤¢¤¢¤¤¤¤¤¤", 0, 6); - x2("(?:¤¢*|¤¤*)(?:¤¢+|¤¤+)", "¤¢¤¢¤¢¤¤¤¤¤¤", 0, 12); - x2("(?:¤¢+|¤¤+){2}", "¤¢¤¢¤¢¤¤¤¤¤¤", 0, 12); - x2("(?:¤¢+|¤¤+){1,2}", "¤¢¤¢¤¢¤¤¤¤¤¤", 0, 12); - x2("(?:¤¢+|\\A¤¤*)¤¦¤¦", "¤¦¤¦", 0, 4); - n("(?:¤¢+|\\A¤¤*)¤¦¤¦", "¤¢¤¤¤¦¤¦"); - x2("(?:^¤¢+|¤¤+)*¤¦", "¤¢¤¢¤¤¤¤¤¤¤¢¤¤¤¦", 12, 16); - x2("(?:^¤¢+|¤¤+)*¤¦", "¤¢¤¢¤¤¤¤¤¤¤¤¤¦", 0, 14); - x2("¤¦{0,}", "¤¦¤¦¤¦¤¦", 0, 8); - x2("¤¢|(?i)c", "C", 0, 1); - x2("(?i)c|¤¢", "C", 0, 1); - x2("(?i:¤¢)|a", "a", 0, 1); - n("(?i:¤¢)|a", "A"); - x2("[¤¢¤¤¤¦]?", "¤¢¤¤¤¦", 0, 2); - x2("[¤¢¤¤¤¦]*", "¤¢¤¤¤¦", 0, 6); - x2("[^¤¢¤¤¤¦]*", "¤¢¤¤¤¦", 0, 0); - n("[^¤¢¤¤¤¦]+", "¤¢¤¤¤¦"); - x2("¤¢??", "¤¢¤¢¤¢", 0, 0); - x2("¤¤¤¢??¤¤", "¤¤¤¢¤¤", 0, 6); - x2("¤¢*?", "¤¢¤¢¤¢", 0, 0); - x2("¤¤¤¢*?", "¤¤¤¢¤¢", 0, 2); - x2("¤¤¤¢*?¤¤", "¤¤¤¢¤¢¤¤", 0, 8); - x2("¤¢+?", "¤¢¤¢¤¢", 0, 2); - x2("¤¤¤¢+?", "¤¤¤¢¤¢", 0, 4); - x2("¤¤¤¢+?¤¤", "¤¤¤¢¤¢¤¤", 0, 8); - x2("(?:Å·?)??", "Å·", 0, 0); - x2("(?:Å·??)?", "Å·", 0, 0); - x2("(?:Ì´?)+?", "Ì´Ì´Ì´", 0, 2); - x2("(?:É÷+)??", "É÷É÷É÷", 0, 0); - x2("(?:Àã+)??Áú", "ÀãÀãÀãÁú", 0, 8); - x2("(?:¤¢¤¤)?{2}", "", 0, 0); - x2("(?:µ´¼Ö)?{2}", "µ´¼Öµ´¼Öµ´", 0, 8); - x2("(?:µ´¼Ö)*{0}", "µ´¼Öµ´¼Öµ´", 0, 0); - x2("(?:µ´¼Ö){3,}", "µ´¼Öµ´¼Öµ´¼Öµ´¼Ö", 0, 16); - n("(?:µ´¼Ö){3,}", "µ´¼Öµ´¼Ö"); - x2("(?:µ´¼Ö){2,4}", "µ´¼Öµ´¼Öµ´¼Ö", 0, 12); - x2("(?:µ´¼Ö){2,4}", "µ´¼Öµ´¼Öµ´¼Öµ´¼Öµ´¼Ö", 0, 16); - x2("(?:µ´¼Ö){2,4}?", "µ´¼Öµ´¼Öµ´¼Öµ´¼Öµ´¼Ö", 0, 8); - x2("(?:µ´¼Ö){,}", "µ´¼Ö{,}", 0, 7); - x2("(?:¤«¤­¤¯)+?{2}", "¤«¤­¤¯¤«¤­¤¯¤«¤­¤¯", 0, 12); - x3("(²Ð)", "²Ð", 0, 2, 1); - x3("(²Ð¿å)", "²Ð¿å", 0, 4, 1); - x2("((»þ´Ö))", "»þ´Ö", 0, 4); - x3("((É÷¿å))", "É÷¿å", 0, 4, 1); - x3("((ºòÆü))", "ºòÆü", 0, 4, 2); - x3("((((((((((((((((((((ÎÌ»Ò))))))))))))))))))))", "ÎÌ»Ò", 0, 4, 20); - x3("(¤¢¤¤)(¤¦¤¨)", "¤¢¤¤¤¦¤¨", 0, 4, 1); - x3("(¤¢¤¤)(¤¦¤¨)", "¤¢¤¤¤¦¤¨", 4, 8, 2); - x3("()(¤¢)¤¤¤¦(¤¨¤ª¤«)¤­¤¯¤±¤³", "¤¢¤¤¤¦¤¨¤ª¤«¤­¤¯¤±¤³", 6, 12, 3); - x3("(()(¤¢)¤¤¤¦(¤¨¤ª¤«)¤­¤¯¤±¤³)", "¤¢¤¤¤¦¤¨¤ª¤«¤­¤¯¤±¤³", 6, 12, 4); - x3(".*(¥Õ¥©)¥ó¡¦¥Þ(¥ó()¥·¥å¥¿)¥¤¥ó", "¥Õ¥©¥ó¡¦¥Þ¥ó¥·¥å¥¿¥¤¥ó", 10, 18, 2); - x2("(^¤¢)", "¤¢", 0, 2); - x3("(¤¢)|(¤¢)", "¤¤¤¢", 2, 4, 1); - x3("(^¤¢)|(¤¢)", "¤¤¤¢", 2, 4, 2); - x3("(¤¢?)", "¤¢¤¢¤¢", 0, 2, 1); - x3("(¤Þ*)", "¤Þ¤Þ¤Þ", 0, 6, 1); - x3("(¤È*)", "", 0, 0, 1); - x3("(¤ë+)", "¤ë¤ë¤ë¤ë¤ë¤ë¤ë", 0, 14, 1); - x3("(¤Õ+|¤Ø*)", "¤Õ¤Õ¤Õ¤Ø¤Ø", 0, 6, 1); - x3("(¤¢+|¤¤?)", "¤¤¤¤¤¤¤¢¤¢", 0, 2, 1); - x3("(¤¢¤¤¤¦)?", "¤¢¤¤¤¦", 0, 6, 1); - x3("(¤¢¤¤¤¦)*", "¤¢¤¤¤¦", 0, 6, 1); - x3("(¤¢¤¤¤¦)+", "¤¢¤¤¤¦", 0, 6, 1); - x3("(¤µ¤·¤¹|¤¢¤¤¤¦)+", "¤¢¤¤¤¦", 0, 6, 1); - x3("([¤Ê¤Ë¤Ì][¤«¤­¤¯]|¤«¤­¤¯)+", "¤«¤­¤¯", 0, 6, 1); - x3("((?i:¤¢¤¤¤¦))", "¤¢¤¤¤¦", 0, 6, 1); - x3("((?m:¤¢.¤¦))", "¤¢\n¤¦", 0, 5, 1); - x3("((?=¤¢¤ó)¤¢)", "¤¢¤ó¤¤", 0, 2, 1); - x3("¤¢¤¤¤¦|(.¤¢¤¤¤¨)", "¤ó¤¢¤¤¤¨", 0, 8, 1); - x3("¤¢*(.)", "¤¢¤¢¤¢¤¢¤ó", 8, 10, 1); - x3("¤¢*?(.)", "¤¢¤¢¤¢¤¢¤ó", 0, 2, 1); - x3("¤¢*?(¤ó)", "¤¢¤¢¤¢¤¢¤ó", 8, 10, 1); - x3("[¤¤¤¦¤¨]¤¢*(.)", "¤¨¤¢¤¢¤¢¤¢¤ó", 10, 12, 1); - x3("(\\A¤¤¤¤)¤¦¤¦", "¤¤¤¤¤¦¤¦", 0, 4, 1); - n("(\\A¤¤¤¤)¤¦¤¦", "¤ó¤¤¤¤¤¦¤¦"); - x3("(^¤¤¤¤)¤¦¤¦", "¤¤¤¤¤¦¤¦", 0, 4, 1); - n("(^¤¤¤¤)¤¦¤¦", "¤ó¤¤¤¤¤¦¤¦"); - x3("¤í¤í(¤ë¤ë$)", "¤í¤í¤ë¤ë", 4, 8, 1); - n("¤í¤í(¤ë¤ë$)", "¤í¤í¤ë¤ë¤ë"); - x2("(̵)\\1", "̵̵", 0, 4); - n("(̵)\\1", "̵Éð"); - x2("(¶õ?)\\1", "¶õ¶õ", 0, 4); - x2("(¶õ??)\\1", "¶õ¶õ", 0, 0); - x2("(¶õ*)\\1", "¶õ¶õ¶õ¶õ¶õ", 0, 8); - x3("(¶õ*)\\1", "¶õ¶õ¶õ¶õ¶õ", 0, 4, 1); - x2("¤¢(¤¤*)\\1", "¤¢¤¤¤¤¤¤¤¤", 0, 10); - x2("¤¢(¤¤*)\\1", "¤¢¤¤", 0, 2); - x2("(¤¢*)(¤¤*)\\1\\2", "¤¢¤¢¤¢¤¤¤¤¤¢¤¢¤¢¤¤¤¤", 0, 20); - x2("(¤¢*)(¤¤*)\\2", "¤¢¤¢¤¢¤¤¤¤¤¤¤¤", 0, 14); - x3("(¤¢*)(¤¤*)\\2", "¤¢¤¢¤¢¤¤¤¤¤¤¤¤", 6, 10, 2); - x2("(((((((¤Ý*)¤Ú))))))¤Ô\\7", "¤Ý¤Ý¤Ý¤Ú¤Ô¤Ý¤Ý¤Ý", 0, 16); - x3("(((((((¤Ý*)¤Ú))))))¤Ô\\7", "¤Ý¤Ý¤Ý¤Ú¤Ô¤Ý¤Ý¤Ý", 0, 6, 7); - x2("(¤Ï)(¤Ò)(¤Õ)\\2\\1\\3", "¤Ï¤Ò¤Õ¤Ò¤Ï¤Õ", 0, 12); - x2("([¤­-¤±])\\1", "¤¯¤¯", 0, 4); - x2("(\\w\\d\\s)\\1", "¤¢5 ¤¢5 ", 0, 8); - n("(\\w\\d\\s)\\1", "¤¢5 ¤¢5"); - x2("(ï¡©|[¤¢-¤¦]{3})\\1", "ï¡©", 0, 8); - x2("...(ï¡©|[¤¢-¤¦]{3})\\1", "¤¢a¤¢Ã¯¡©Ã¯¡©", 0, 13); - x2("(ï¡©|[¤¢-¤¦]{3})\\1", "¤¦¤¤¤¦¤¦¤¤¤¦", 0, 12); - x2("(^¤³)\\1", "¤³¤³", 0, 4); - n("(^¤à)\\1", "¤á¤à¤à"); - n("(¤¢$)\\1", "¤¢¤¢"); - n("(¤¢¤¤\\Z)\\1", "¤¢¤¤"); - x2("(¤¢*\\Z)\\1", "¤¢", 2, 2); - x2(".(¤¢*\\Z)\\1", "¤¤¤¢", 2, 4); - x3("(.(¤ä¤¤¤æ)\\2)", "z¤ä¤¤¤æ¤ä¤¤¤æ", 0, 13, 1); - x3("(.(..\\d.)\\2)", "¤¢12341234", 0, 10, 1); - x2("((?i:¤¢v¤º))\\1", "¤¢v¤º¤¢v¤º", 0, 10); - x2("(?<¶ò¤«>ÊÑ|\\(\\g<¶ò¤«>\\))", "((((((ÊÑ))))))", 0, 14); - x2("\\A(?:\\g<°¤_1>|\\g<±¾_2>|\\z½ªÎ» (?<°¤_1>´Ñ|¼«\\g<±¾_2>¼«)(?<±¾_2>ºß|Êî»§\\g<°¤_1>Êî»§))$", "Êî»§¼«Êî»§¼«ºß¼«Êî»§¼«Êî»§", 0, 26); - x2("[[¤Ò¤Õ]]", "¤Õ", 0, 2); - x2("[[¤¤¤ª¤¦]¤«]", "¤«", 0, 2); - n("[[^¤¢]]", "¤¢"); - n("[^[¤¢]]", "¤¢"); - x2("[^[^¤¢]]", "¤¢", 0, 2); - x2("[[¤«¤­¤¯]&&¤­¤¯]", "¤¯", 0, 2); - n("[[¤«¤­¤¯]&&¤­¤¯]", "¤«"); - n("[[¤«¤­¤¯]&&¤­¤¯]", "¤±"); - x2("[¤¢-¤ó&&¤¤-¤ò&&¤¦-¤ñ]", "¤ñ", 0, 2); - n("[^¤¢-¤ó&&¤¤-¤ò&&¤¦-¤ñ]", "¤ñ"); - x2("[[^¤¢&&¤¢]&&¤¢-¤ó]", "¤¤", 0, 2); - n("[[^¤¢&&¤¢]&&¤¢-¤ó]", "¤¢"); - x2("[[^¤¢-¤ó&&¤¤¤¦¤¨¤ª]&&[^¤¦-¤«]]", "¤­", 0, 2); - n("[[^¤¢-¤ó&&¤¤¤¦¤¨¤ª]&&[^¤¦-¤«]]", "¤¤"); - x2("[^[^¤¢¤¤¤¦]&&[^¤¦¤¨¤ª]]", "¤¦", 0, 2); - x2("[^[^¤¢¤¤¤¦]&&[^¤¦¤¨¤ª]]", "¤¨", 0, 2); - n("[^[^¤¢¤¤¤¦]&&[^¤¦¤¨¤ª]]", "¤«"); - x2("[¤¢-&&-¤¢]", "-", 0, 1); - x2("[^[^a-z¤¢¤¤¤¦]&&[^bcdefg¤¦¤¨¤ª]q-w]", "¤¨", 0, 2); - x2("[^[^a-z¤¢¤¤¤¦]&&[^bcdefg¤¦¤¨¤ª]g-w]", "f", 0, 1); - x2("[^[^a-z¤¢¤¤¤¦]&&[^bcdefg¤¦¤¨¤ª]g-w]", "g", 0, 1); - n("[^[^a-z¤¢¤¤¤¦]&&[^bcdefg¤¦¤¨¤ª]g-w]", "2"); - fprintf(stdout, "\nRESULT SUCC: %d, FAIL: %d, ERROR: %d\n", - nsucc, nfail, nerror); - -#ifndef POSIX_TEST - onig_region_free(region, 1); - onig_end(); -#endif - - return 0; -} diff --git a/ext/mbstring/php_mbregex.c b/ext/mbstring/php_mbregex.c index b1543f290928..14654dcec5e5 100644 --- a/ext/mbstring/php_mbregex.c +++ b/ext/mbstring/php_mbregex.c @@ -124,6 +124,22 @@ php_mb_regex_enc_name_map_t enc_name_map[] ={ "UTF-8\0UTF8\0", ONIG_ENCODING_UTF8 }, + { + "UTF-16\0UTF-16BE\0", + ONIG_ENCODING_UTF16_BE + }, + { + "UTF-16LE\0", + ONIG_ENCODING_UTF16_LE + }, + { + "UCS-4\0UTF-32\0UTF-32BE\0", + ONIG_ENCODING_UTF32_BE + }, + { + "UCS-4LE\0UTF-32LE\0", + ONIG_ENCODING_UTF32_LE + }, { "SJIS\0CP932\0MS932\0SHIFT_JIS\0SJIS-WIN\0WINDOWS-31J\0", ONIG_ENCODING_SJIS @@ -485,7 +501,7 @@ PHP_FUNCTION(mb_regex_encoding) zend_get_parameters_ex(1, &arg1) != FAILURE) { convert_to_string_ex(arg1); mbctype = php_mb_regex_name2mbctype(Z_STRVAL_PP(arg1)); - if (mbctype < 0) { + if (mbctype == ONIG_ENCODING_UNDEF) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", Z_STRVAL_PP(arg1)); RETVAL_FALSE; } else { diff --git a/ext/mbstring/tests/bug28220.phpt b/ext/mbstring/tests/bug28220.phpt new file mode 100644 index 000000000000..563e2da743e4 --- /dev/null +++ b/ext/mbstring/tests/bug28220.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #28220 (mb_strwidth() returns wrong width values for some Hangul characters) +--FILE-- + +--EXPECT-- +8101 +63 diff --git a/ext/mbstring/tests/bug30549.phpt b/ext/mbstring/tests/bug30549.phpt new file mode 100644 index 000000000000..dbd8e0bd1983 --- /dev/null +++ b/ext/mbstring/tests/bug30549.phpt @@ -0,0 +1,29 @@ +--TEST-- +Bug #30549 (incorrect character translations for some ISO8859 charsets) +--FILE-- + 0x20ac, 0xa5 => 0x20af, 0xaa => 0x037a)); +test('ISO-8859-8', array(0xaf => 0x00af, 0xfd => 0x200e, 0xfe => 0x200f)); +test('ISO-8859-10', array(0xa4 => 0x012a )); + +function test($enc, $map) { + print "$enc\n"; + + foreach($map as $fromc => $toc) { + $ustr = mb_convert_encoding(pack('C', $fromc), 'UCS-4BE', $enc); + foreach (unpack('Nc', $ustr) as $unic); + printf("0x%04x, 0x%04x\n", $toc, $unic); + } +} +?> +--EXPECT-- +ISO-8859-7 +0x20ac, 0x20ac +0x20af, 0x20af +0x037a, 0x037a +ISO-8859-8 +0x00af, 0x00af +0x200e, 0x200e +0x200f, 0x200f +ISO-8859-10 +0x012a, 0x012a diff --git a/ext/mbstring/tests/bug31911.phpt b/ext/mbstring/tests/bug31911.phpt new file mode 100644 index 000000000000..eb6438d4e7ac --- /dev/null +++ b/ext/mbstring/tests/bug31911.phpt @@ -0,0 +1,11 @@ +--TEST-- +Bug #31911 (mb_decode_mimeheader() is case-sensitive to hex escapes) +--FILE-- + +--EXPECT-- +Works: ??? +Fails: ??? diff --git a/ext/mbstring/tests/mb_send_mail05.phpt b/ext/mbstring/tests/mb_send_mail05.phpt index 7d1dc981d2ab..7033424b80e7 100644 --- a/ext/mbstring/tests/mb_send_mail05.phpt +++ b/ext/mbstring/tests/mb_send_mail05.phpt @@ -6,7 +6,7 @@ if (@mb_send_mail() === false || !mb_language("Simplified Chinese")) { die("skip mb_send_mail() not available"); } if (!@mb_internal_encoding('GB2312')) { - die("skip GB2312 encoding is not avaliable on this platform"); + die("skip GB2312 encoding is not available on this platform"); } ?> --INI-- diff --git a/ext/mbstring/tests/mb_send_mail06.phpt b/ext/mbstring/tests/mb_send_mail06.phpt index 92087f964907..2e8c15128484 100644 --- a/ext/mbstring/tests/mb_send_mail06.phpt +++ b/ext/mbstring/tests/mb_send_mail06.phpt @@ -6,7 +6,7 @@ if (@mb_send_mail() === false || !mb_language("Traditional Chinese")) { die("skip mb_send_mail() not available"); } if (!@mb_internal_encoding('BIG5')) { - die("skip BIG5 encoding is not avaliable on this platform"); + die("skip BIG5 encoding is not available on this platform"); } ?> --INI-- diff --git a/ext/mbstring/tests/mb_send_mail07.phpt b/ext/mbstring/tests/mb_send_mail07.phpt index ae429f3ced52..21fdaa597c5a 100644 --- a/ext/mbstring/tests/mb_send_mail07.phpt +++ b/ext/mbstring/tests/mb_send_mail07.phpt @@ -6,7 +6,7 @@ if (@mb_send_mail() === false || !mb_language("Korean")) { die("skip mb_send_mail() not available"); } if (!@mb_internal_encoding('ISO-2022-KR')) { - die("skip ISO-2022-KR encoding is not avaliable on this platform"); + die("skip ISO-2022-KR encoding is not available on this platform"); } ?> --INI-- diff --git a/ext/mbstring/tests/php_gr_jp_16242.phpt b/ext/mbstring/tests/php_gr_jp_16242.phpt index 774b4fb1e69f..f693cf8dd1a4 100644 --- a/ext/mbstring/tests/php_gr_jp_16242.phpt +++ b/ext/mbstring/tests/php_gr_jp_16242.phpt @@ -4,28 +4,16 @@ php-users@php.gr.jp #16242 ---FILE-- -" |'.getenv("TEST_PHP_EXECUTABLE").' -c '.$tmpfile; - -system($cmd); +var_dump(ini_get('mbstring.language')); +var_dump(ini_get('mbstring.internal_encoding')); +var_dump(mb_internal_encoding()); -unlink($tmpfile); ?> --EXPECT-- string(8) "Japanese" diff --git a/ext/mcrypt/config.m4 b/ext/mcrypt/config.m4 index 4d9cc3eb0687..c93e040bcac9 100644 --- a/ext/mcrypt/config.m4 +++ b/ext/mcrypt/config.m4 @@ -2,7 +2,7 @@ dnl dnl $Id$ dnl -AC_DEFUN(PHP_MCRYPT_CHECK_VERSION,[ +AC_DEFUN([PHP_MCRYPT_CHECK_VERSION],[ old_CPPFLAGS=$CPPFLAGS CPPFLAGS=-I$MCRYPT_DIR/include AC_MSG_CHECKING(for libmcrypt version) @@ -39,8 +39,6 @@ if test "$PHP_MCRYPT" != "no"; then PHP_ADD_LIBRARY(ltdl,, MCRYPT_SHARED_LIBADD) AC_DEFINE(HAVE_LIBMCRYPT,1,[ ]) ],[ - unset found - unset ac_cv_lib_mcrypt_mcrypt_module_open PHP_CHECK_LIBRARY(mcrypt, mcrypt_module_open, [ AC_DEFINE(HAVE_LIBMCRYPT,1,[ ]) diff --git a/ext/mcve/config.m4 b/ext/mcve/config.m4 index 7f104f876dd1..ae7b936c6aae 100644 --- a/ext/mcve/config.m4 +++ b/ext/mcve/config.m4 @@ -51,6 +51,20 @@ yes ],[ AC_MSG_ERROR([libmcve 3.2.2 or greater required.]) ]) + + AC_MSG_CHECKING([for correct libmonetra 4.2 or higher]) + AC_EGREP_CPP(yes,[ +#include "$MCVE_DIR/include/mcve.h" +#ifdef MCVE_SetSSL_CAfile +yes +#endif + ],[ + AC_MSG_RESULT([yes]) + ],[ + AC_DEFINE([LIBMONETRA_BELOW_4_2], 1, [Whether or not we're using libmonetra 4.2 or higher ]) + AC_MSG_RESULT([no]) + ]) + CPPFLAGS=$saved_CPPFLAGS PHP_ADD_INCLUDE($MCVE_DIR/include) diff --git a/ext/mcve/mcve.c b/ext/mcve/mcve.c index d7864abf4e72..f3f8e8f8b924 100644 --- a/ext/mcve/mcve.c +++ b/ext/mcve/mcve.c @@ -25,6 +25,12 @@ #include "php.h" +#if PHP_WIN32 +#include "config.w32.h" +#else +#include +#endif + #if HAVE_MCVE /* standard php include(s) */ @@ -54,6 +60,10 @@ function_entry mcve_functions[] = { PHP_FE(m_setdropfile, NULL) PHP_FE(m_setip, NULL) PHP_FE(m_setssl, NULL) +#if LIBMONETRA_VERSION >= 050000 + PHP_FE(m_setssl_cafile, NULL) + PHP_FE(m_responsekeys, NULL) +#endif PHP_FE(m_setssl_files, NULL) PHP_FE(m_settimeout, NULL) PHP_FE(m_setblocking, NULL) @@ -65,6 +75,10 @@ function_entry mcve_functions[] = { PHP_FE(m_connect, NULL) PHP_FE(m_transnew, NULL) PHP_FE(m_transparam, NULL) +#if LIBMONETRA_VERSION >= 050000 + PHP_FE(m_transkeyval, NULL) + PHP_FE(m_validateidentifier, NULL) +#endif PHP_FE(m_transsend, NULL) PHP_FE(m_ping, NULL) PHP_FE(m_responseparam, NULL) @@ -542,7 +556,7 @@ PHP_MINIT_FUNCTION(mcve) PHP_MINFO_FUNCTION(mcve) { php_info_print_table_start(); - php_info_print_table_row(2, "mcve support", "enabled"); + php_info_print_table_row(2, "mcve/monetra support", "enabled"); php_info_print_table_row(2, "version", PHP_MCVE_VERSION); php_info_print_table_end(); } @@ -581,6 +595,11 @@ PHP_FUNCTION(m_initconn) MCVE_InitConn(conn); +/* Since the identifiers are pointer addresses, we need to validate it by + * checking our linked list in PHP, since we don't want to cause segfaults */ +#if LIBMONETRA_VERSION >= 050000 + M_ValidateIdentifier(conn, 1); +#endif ZEND_REGISTER_RESOURCE(return_value, conn, le_conn); } /* }}} */ @@ -719,23 +738,59 @@ PHP_FUNCTION(m_setssl) } /* }}} */ -/* {{{ proto int m_setssl_files(string sslkeyfile, string sslcertfile) +#if LIBMONETRA_VERSION >= 050000 +/* {{{ proto int m_setssl_cafile(resource conn, string cafile) + Set SSL CA (Certificate Authority) file for verification of server + certificate +*/ +PHP_FUNCTION(m_setssl_cafile) +{ + MCVE_CONN *conn; + int retval; + zval **arg1, **arg2; + + if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) + WRONG_PARAM_COUNT; + + + ZEND_FETCH_RESOURCE(conn, MCVE_CONN *, arg1, -1, "mcve connection", le_conn); + convert_to_string_ex(arg2); + + retval = M_SetSSL_CAfile(conn, Z_STRVAL_PP(arg2)); + + RETURN_LONG(retval); +} +/* }}} */ +#endif + +/* {{{ proto int m_setssl_files(resource conn, string sslkeyfile, string sslcertfile) Set certificate key files and certificates if server requires client certificate verification */ PHP_FUNCTION(m_setssl_files) { + MCVE_CONN *conn; int retval; - zval **arg1, **arg2; + zval **arg1, **arg2, **arg3; +#ifndef LIBMONETRA_BELOW_4_2 + if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &arg1, &arg2, &arg3) == FAILURE) + WRONG_PARAM_COUNT; + ZEND_FETCH_RESOURCE(conn, MCVE_CONN *, arg1, -1, "mcve connection", le_conn); +#else if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) WRONG_PARAM_COUNT; +#endif - convert_to_string_ex(arg1); convert_to_string_ex(arg2); +#ifndef LIBMONETRA_BELOW_4_2 + convert_to_string_ex(arg3); + retval = MCVE_SetSSL_Files(conn, Z_STRVAL_PP(arg2), Z_STRVAL_PP(arg3)); +#else + convert_to_string_ex(arg1); retval = MCVE_SetSSL_Files(Z_STRVAL_PP(arg1), Z_STRVAL_PP(arg2)); - +#endif RETURN_LONG(retval); } /* }}} */ @@ -871,7 +926,7 @@ PHP_FUNCTION(m_connect) PHP_FUNCTION(m_connectionerror) { MCVE_CONN *conn; - char *retval; + const char *retval; zval **arg; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg) == FAILURE) @@ -884,7 +939,7 @@ PHP_FUNCTION(m_connectionerror) if (retval == NULL) { RETVAL_STRING("",1); } else { - RETVAL_STRING(retval, 1); + RETVAL_STRING(estrdup(retval), 0); } } /* }}} */ @@ -946,8 +1001,53 @@ PHP_FUNCTION(m_transnew) } /* }}} */ +#if LIBMONETRA_VERSION >= 050000 +/* {{{ proto int m_validateidentifier(resource conn, int tf) + Whether or not to validate the passed identifier on any transaction it is passed to +*/ +PHP_FUNCTION(m_validateidentifier) +{ + MCVE_CONN *conn; + int retval; + zval **arg1, **arg2; + + if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) + WRONG_PARAM_COUNT; + + ZEND_FETCH_RESOURCE(conn, MCVE_CONN *, arg1, -1, "mcve connection", le_conn); + + convert_to_long_ex(arg2); + retval = M_ValidateIdentifier(conn, (int)Z_LVAL_PP(arg2)); + RETURN_LONG(retval); +} +/* }}} */ + +/* {{{ proto int m_transkeyval(resource conn, long identifier, string key, string value) + Add key/value pair to a transaction. Replaces deprecated transparam() */ +PHP_FUNCTION(m_transkeyval) +{ + MCVE_CONN *conn; + int retval; + zval **arg1, **arg2, **arg3, **arg4; + + if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &arg1, &arg2, &arg3, &arg4) == FAILURE) + WRONG_PARAM_COUNT; + + ZEND_FETCH_RESOURCE(conn, MCVE_CONN *, arg1, -1, "mcve connection", le_conn); + + convert_to_long_ex(arg2); + convert_to_string_ex(arg3); + convert_to_string_ex(arg4); + + retval = M_TransKeyVal(conn, (long)Z_LVAL_PP(arg2), Z_STRVAL_PP(arg3), Z_STRVAL_PP(arg4)); + + RETURN_LONG(retval); +} +/* }}} */ +#endif + /* {{{ proto int m_transparam(resource conn, long identifier, int key, ...) - Add a parameter to a transaction */ + Add a parameter to a transaction (deprecated) */ PHP_FUNCTION(m_transparam) { MCVE_CONN *conn; @@ -1057,7 +1157,7 @@ PHP_FUNCTION(m_transsend) PHP_FUNCTION(m_responseparam) { MCVE_CONN *conn; - char *retval; + const char *retval; zval **arg1, **arg2, **arg3; if (ZEND_NUM_ARGS() != 3 || @@ -1074,17 +1174,47 @@ PHP_FUNCTION(m_responseparam) if (retval == NULL) { RETVAL_STRING("",1); } else { - RETVAL_STRING(retval, 1); + RETVAL_STRING(estrdup(retval), 0); + } +} +/* }}} */ + +#if LIBMONETRA_VERSION >= 050000 +/* {{{ proto array m_responsekeys(resource conn, long identifier) + Returns array of strings which represents the keys that can be used + for response parameters on this transaction +*/ +PHP_FUNCTION(m_responsekeys) +{ + MCVE_CONN *conn; + char **retval; + int num_keys, i; + zval **arg1, **arg2; + + if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) + WRONG_PARAM_COUNT; + + ZEND_FETCH_RESOURCE(conn, MCVE_CONN *, arg1, -1, "mcve connection", le_conn); + convert_to_long_ex(arg2); + + array_init(return_value); + + retval=M_ResponseKeys(conn, Z_LVAL_PP(arg2), &num_keys); + if (retval != NULL) { + for (i=0; i + +#ifndef LIBMONETRA_VERSION +#define LIBMONETRA_VERSION 040000 +#endif #define MCVE_CONST (CONST_CS | CONST_PERSISTENT) @@ -45,6 +51,10 @@ PHP_FUNCTION(m_destroyconn); PHP_FUNCTION(m_setdropfile); PHP_FUNCTION(m_setip); PHP_FUNCTION(m_setssl); +#if LIBMONETRA_VERSION >= 050000 +PHP_FUNCTION(m_setssl_cafile); +PHP_FUNCTION(m_responsekeys); +#endif PHP_FUNCTION(m_setssl_files); PHP_FUNCTION(m_setblocking); PHP_FUNCTION(m_settimeout); @@ -55,6 +65,10 @@ PHP_FUNCTION(m_connectionerror); PHP_FUNCTION(m_deletetrans); PHP_FUNCTION(m_connect); PHP_FUNCTION(m_transnew); +#if LIBMONETRA_VERSION >= 050000 +PHP_FUNCTION(m_transkeyval); +PHP_FUNCTION(m_validateidentifier); +#endif PHP_FUNCTION(m_transparam); PHP_FUNCTION(m_transsend); PHP_FUNCTION(m_ping); diff --git a/ext/mhash/tests/skip.inc b/ext/mhash/tests/skip.inc index 81912d21c84b..ff60bfff275b 100644 --- a/ext/mhash/tests/skip.inc +++ b/ext/mhash/tests/skip.inc @@ -1,5 +1,5 @@ \ No newline at end of file diff --git a/ext/mime_magic/mime_magic.c b/ext/mime_magic/mime_magic.c index d4df213f7255..f13b1e3bb545 100644 --- a/ext/mime_magic/mime_magic.c +++ b/ext/mime_magic/mime_magic.c @@ -345,12 +345,13 @@ PHP_FUNCTION(mime_content_type) /* fallthru if not a stream resource */ default: php_error_docref(NULL TSRMLS_CC, E_WARNING, "can only process string or stream arguments"); + RETURN_FALSE; break; } if (conf->magic == (struct magic *)-1) { if(MIME_MAGIC_G(debug)) - php_error_docref("http://www.php.net/mime_magic" TSRMLS_CC, E_ERROR, "mime_magic could not be initialized, magic file %s is not avaliable", conf->magicfile); + php_error_docref("http://www.php.net/mime_magic" TSRMLS_CC, E_ERROR, "mime_magic could not be initialized, magic file %s is not available", conf->magicfile); RETURN_FALSE; } diff --git a/ext/ming/config.m4 b/ext/ming/config.m4 index f6a80c52a1a8..15f50059636f 100644 --- a/ext/ming/config.m4 +++ b/ext/ming/config.m4 @@ -11,6 +11,7 @@ if test "$PHP_MING" != "no"; then for i in $PHP_MING /usr/local /usr; do if test -f $i/lib/libming.$SHLIB_SUFFIX_NAME -o -f $i/lib/libming.a; then MING_DIR=$i + break fi done @@ -57,7 +58,9 @@ int main() { AC_MSG_RESULT([unknown]) ]) - dnl Check Ming version (FIXME: if/when ming has some better way to detect the version..) + PHP_CHECK_LIBRARY(ming, SWFPrebuiltClip, [ AC_DEFINE(HAVE_SWFPREBUILTCLIP, 1, [ ]) ], [], []) + +dnl Check Ming version (FIXME: if/when ming has some better way to detect the version..) old_CPPFLAGS=$CPPFLAGS CPPFLAGS=-I$MING_INC_DIR AC_EGREP_CPP(yes, [ diff --git a/ext/ming/config.w32 b/ext/ming/config.w32 index 78baa2603d42..228e620a77a7 100644 --- a/ext/ming/config.w32 +++ b/ext/ming/config.w32 @@ -15,12 +15,13 @@ function ming_check_version() } c = file_get_contents(ming_h + "\\ming.h"); - if (c.match(/MING_VERSION\s+(0.[a-zA-Z0-9]+)/)) { + if (typeof(c) == "string" && c.match(/MING_VERSION\s+(0.[a-zA-Z0-9]+)/)) { v = RegExp.$1; if (v > "0.2") { if (CHECK_LIB("libungif.lib", "ming", PHP_MING) && CHECK_LIB("libpng.lib", "ming", PHP_MING)) { AC_DEFINE('HAVE_NEW_MING', 1); + AC_DEFINE('HAVE_SWFPREBUILTCLIP', 1); if (PHP_ZLIB != "no") { AC_DEFINE('HAVE_MING_ZLIB', 1); } diff --git a/ext/ming/ming.c b/ext/ming/ming.c index 9449f37ce66a..2fdc81da688b 100644 --- a/ext/ming/ming.c +++ b/ext/ming/ming.c @@ -72,6 +72,10 @@ static SWFSound getSound(zval *id TSRMLS_DC); #ifdef HAVE_NEW_MING static SWFFontCharacter getFontCharacter(zval *id TSRMLS_DC); static SWFSoundInstance getSoundInstance(zval *id TSRMLS_DC); +static SWFVideoStream getVideoStream(zval *id TSRMLS_DC); +#endif +#ifdef HAVE_SWFPREBUILTCLIP +static SWFPrebuiltClip getPrebuiltClip(zval *id TSRMLS_DC); #endif #define PHP_MING_FILE_CHK(file) \ @@ -156,6 +160,10 @@ static int le_swfsoundp; #ifdef HAVE_NEW_MING static int le_swffontcharp; static int le_swfsoundinstancep; +static int le_swfvideostreamp; +#endif +#ifdef HAVE_SWFPREBUILTCLIP +static int le_swfprebuiltclipp; #endif static zend_class_entry *movie_class_entry_ptr; @@ -175,6 +183,10 @@ static zend_class_entry *sound_class_entry_ptr; #ifdef HAVE_NEW_MING static zend_class_entry *fontchar_class_entry_ptr; static zend_class_entry *soundinstance_class_entry_ptr; +static zend_class_entry *videostream_class_entry_ptr; +#endif +#ifdef HAVE_SWFPREBUILTCLIP +static zend_class_entry *prebuiltclip_class_entry_ptr; #endif /* {{{ internal function SWFgetProperty @@ -232,10 +244,20 @@ static SWFCharacter getCharacter(zval *id TSRMLS_DC) return (SWFCharacter)getBitmap(id TSRMLS_CC); else if(Z_OBJCE_P(id) == sound_class_entry_ptr) return (SWFCharacter)getSound(id TSRMLS_CC); -/* +#ifdef HAVE_NEW_MING + + else if(Z_OBJCE_P(id) == fontchar_class_entry_ptr) + return (SWFCharacter)getFontCharacter(id TSRMLS_CC); else if(Z_OBJCE_P(id) == soundinstance_class_entry_ptr) return (SWFCharacter)getSoundInstance(id TSRMLS_CC); -*/ + + else if(Z_OBJCE_P(id) == videostream_class_entry_ptr) + return (SWFCharacter)getVideoStream(id TSRMLS_CC); +#endif +#ifdef HAVE_SWFPREBUILTCLIP + else if(Z_OBJCE_P(id) == prebuiltclip_class_entry_ptr) + return (SWFCharacter)getPrebuiltClip(id TSRMLS_CC); +#endif else php_error_docref(NULL TSRMLS_CC, E_ERROR, "Called object is not an SWFCharacter"); return NULL; @@ -603,6 +625,7 @@ PHP_METHOD(swfbutton, addSound) ret = zend_list_insert(item, le_swfsoundinstancep); object_init_ex(return_value, soundinstance_class_entry_ptr); add_property_resource(return_value, "soundinstance", ret); + zend_list_addref(ret); } } /* }}} */ @@ -1878,7 +1901,189 @@ static zend_function_entry swfsoundinstance_functions[] = { { NULL, NULL, NULL } }; +/* {{{ SWFVideoStream */ + +/* {{{ proto class swfvideostream_init([file]) + Returns a SWVideoStream object */ + +PHP_METHOD(swfvideostream, __construct) +{ + zval **zfile = NULL; + SWFVideoStream stream; + SWFInput input; + int ret; + + switch(ZEND_NUM_ARGS()) { + case 1: + if(zend_get_parameters_ex(1, &zfile) == FAILURE) + WRONG_PARAM_COUNT; + + if(Z_TYPE_PP(zfile) != IS_RESOURCE) + { + convert_to_string_ex(zfile); + input = newSWFInput_buffer(Z_STRVAL_PP(zfile), Z_STRLEN_PP(zfile)); + zend_list_addref(zend_list_insert(input, le_swfinputp)); + } + else + input = getInput(zfile TSRMLS_CC); + + stream = newSWFVideoStream_fromInput(input); + break; + case 0: + stream = newSWFVideoStream(); + break; + default: + WRONG_PARAM_COUNT; + break; + } + + if(stream) { + ret = zend_list_insert(stream, le_swfvideostreamp); + object_init_ex(getThis(), videostream_class_entry_ptr); + add_property_resource(getThis(), "videostream", ret); + zend_list_addref(ret); + } + +} + +static void destroy_SWFVideoStream_resource(zend_rsrc_list_entry *resource TSRMLS_DC) +{ + destroySWFVideoStream((SWFVideoStream)resource->ptr); +} +/* }}} */ + +/* {{{ internal function getVideoStream + Returns the SWFVideoStream object contained in zval *id */ + +static SWFVideoStream getVideoStream(zval *id TSRMLS_DC) +{ + void *stream = SWFgetProperty(id, "videostream", 11, le_swfvideostreamp TSRMLS_CC); + + if(!stream) + php_error(E_ERROR, "called object is not an SWFVideoStream!"); + + return (SWFVideoStream)stream; +} + +/* }}} */ + +/* {{{ setDimension */ + +PHP_METHOD(swfvideostream, setdimension) +{ + zval **x, **y; + SWFVideoStream stream = getVideoStream(getThis() TSRMLS_CC); + if(!stream) + php_error(E_ERROR, "getVideoSTream returned NULL"); + + if( ZEND_NUM_ARGS() != 2 + || zend_get_parameters_ex(2, &x, &y) == FAILURE ) + WRONG_PARAM_COUNT; + + convert_to_long_ex(x); + convert_to_long_ex(y); + + SWFVideoStream_setDimension(stream, Z_LVAL_PP(x), Z_LVAL_PP(y)); +} +/* }}} */ + +/* {{{ getNumFrames */ +PHP_METHOD(swfvideostream, getnumframes) +{ + if(ZEND_NUM_ARGS() != 0) + WRONG_PARAM_COUNT; + + RETURN_LONG(SWFVideoStream_getNumFrames(getVideoStream(getThis() TSRMLS_CC))); +} +/* }}} */ + + +static zend_function_entry swfvideostream_functions[] = { + PHP_ME(swfvideostream, __construct, NULL, 0) + PHP_ME(swfvideostream, setdimension, NULL, 0) + PHP_ME(swfvideostream, getnumframes, NULL, 0) + { NULL, NULL, NULL } +}; + +/* }}} */ +#endif + +#ifdef HAVE_SWFPREBUILTCLIP +/* {{{ SWFPrebuiltClip */ +/* {{{ proto class swfprebuiltclip_init([file]) + Returns a SWFPrebuiltClip object */ + +PHP_METHOD(swfprebuiltclip, __construct) +{ + zval **zfile = NULL; + SWFPrebuiltClip clip; + SWFInput input; + int ret; + + switch(ZEND_NUM_ARGS()) { + case 1: + if(zend_get_parameters_ex(1, &zfile) == FAILURE) + WRONG_PARAM_COUNT; + + if(Z_TYPE_PP(zfile) != IS_RESOURCE) + { + convert_to_string_ex(zfile); + input = newSWFInput_buffer(Z_STRVAL_PP(zfile), Z_STRLEN_PP(zfile)); + zend_list_addref(zend_list_insert(input, le_swfinputp)); + } + else + input = getInput(zfile TSRMLS_CC); + + clip = newSWFPrebuiltClip_fromInput(input); + break; +/* not sure whether this makes sense + there would have to be a function to add contents + case 0: + clip = newSWFPrebuiltClip(); + break; */ + default: + WRONG_PARAM_COUNT; + break; + } + + if(clip) { + ret = zend_list_insert(clip, le_swfprebuiltclipp); + object_init_ex(getThis(), prebuiltclip_class_entry_ptr); + add_property_resource(getThis(), "prebuiltclip", ret); + zend_list_addref(ret); + } +} +/* }}} */ + +/* {{{ internal function destroy_SWFPrebuiltClip */ +static void destroy_SWFPrebuiltClip_resource(zend_rsrc_list_entry *resource TSRMLS_DC) +{ + destroySWFPrebuiltClip((SWFPrebuiltClip)resource->ptr); +} +/* }}} */ + +/* {{{ internal function getPrebuiltClip + Returns the SWFPrebuiltClip object contained in zval *id */ + +static SWFPrebuiltClip getPrebuiltClip(zval *id TSRMLS_DC) +{ + void *clip = SWFgetProperty(id, "prebuiltclip", 12, le_swfprebuiltclipp TSRMLS_CC); + + if(!clip) + php_error(E_ERROR, "called object is not an SWFPrebuiltClip!"); + + return (SWFPrebuiltClip)clip; +} + +/* }}} */ +static zend_function_entry swfprebuiltclip_functions[] = { + PHP_ME(swfprebuiltclip, __construct, NULL, 0) + { NULL, NULL, NULL } +}; + +/* }}} */ #endif + /* }}} */ /* {{{ SWFMovie @@ -1979,6 +2184,7 @@ PHP_METHOD(swfmovie, add) ret = zend_list_insert(item, le_swfdisplayitemp); object_init_ex(return_value, displayitem_class_entry_ptr); add_property_resource(return_value, "displayitem", ret); + zend_list_addref(ret); } } /* }}} */ @@ -2012,28 +2218,55 @@ static void phpByteOutputMethod(byte b, void *data) PHP_METHOD(swfmovie, output) { SWFMovie movie = getMovie(getThis() TSRMLS_CC); -#ifdef HAVE_MING_ZLIB +#if defined(HAVE_MING_ZLIB) && !defined(HAVE_NEW_MING) zval **zlimit = NULL; int limit = -1; + int argc = ZEND_NUM_ARGS(); + int oldval = INT_MIN; + long out; - if (zend_get_parameters_ex(1, &zlimit) == FAILURE) { - WRONG_PARAM_COUNT; - } + if(argc) { + if (zend_get_parameters_ex(1, &zlimit) == FAILURE) { + WRONG_PARAM_COUNT; + } - convert_to_long_ex(zlimit); - limit = Z_LVAL_PP(zlimit); + convert_to_long_ex(zlimit); + limit = Z_LVAL_PP(zlimit); - if ((limit < 0) || (limit > 9)) { - php_error(E_WARNING,"compression level must be within 0..9"); - RETURN_FALSE; + if ((limit < 0) || (limit > 9)) { + php_error(E_WARNING,"compression level must be within 0..9"); + RETURN_FALSE; + } } -#endif + oldval = Ming_setSWFCompression(limit); + out = SWFMovie_output(movie, &phpByteOutputMethod, NULL); + if (oldval >= -1 && oldval <= 9) { + Ming_setSWFCompression(oldval); + } + RETURN_LONG(out); +#elif defined(HAVE_NEW_MING) + zval **zlimit = NULL; + int limit = -1; + int argc = ZEND_NUM_ARGS(); -#ifdef HAVE_NEW_MING + if(argc) { + if (zend_get_parameters_ex(1, &zlimit) == FAILURE) { + WRONG_PARAM_COUNT; + } + + convert_to_long_ex(zlimit); + limit = Z_LVAL_PP(zlimit); + + if ((limit < 0) || (limit > 9)) { + php_error(E_WARNING,"compression level must be within 0..9"); + RETURN_FALSE; + } + } RETURN_LONG(SWFMovie_output(movie, &phpByteOutputMethod, NULL, limit)); #else RETURN_LONG(SWFMovie_output(movie, &phpByteOutputMethod, NULL)); #endif + } /* }}} */ @@ -2049,9 +2282,13 @@ static void phpStreamOutputMethod(byte b, void * data) PHP_METHOD(swfmovie, saveToFile) { zval **x; -#ifdef HAVE_MING_ZLIB +#if defined(HAVE_MING_ZLIB) || defined(HAVE_NEW_MING) zval **zlimit = NULL; int limit = -1; +#endif +#if defined(HAVE_MING_ZLIB) && !defined(HAVE_NEW_MING) + int oldval = INT_MIN; + long out; #endif SWFMovie movie = getMovie(getThis() TSRMLS_CC); php_stream *what; @@ -2062,7 +2299,7 @@ PHP_METHOD(swfmovie, saveToFile) WRONG_PARAM_COUNT; break; case 2: -#ifdef HAVE_MING_ZLIB +#if defined(HAVE_MING_ZLIB) || defined(HAVE_NEW_MING) if (zend_get_parameters_ex(2, &x, &zlimit) == FAILURE) WRONG_PARAM_COUNT; convert_to_long_ex(zlimit); @@ -2071,6 +2308,9 @@ PHP_METHOD(swfmovie, saveToFile) php_error(E_WARNING,"compression level must be within 0..9"); RETURN_FALSE; } +#endif +#if defined(HAVE_MING_ZLIB) && !defined(HAVE_NEW_MING) + oldval = Ming_setSWFCompression(limit); #endif break; default: @@ -2078,7 +2318,12 @@ PHP_METHOD(swfmovie, saveToFile) } ZEND_FETCH_RESOURCE(what, php_stream *, x, -1,"File-Handle",php_file_le_stream()); -#ifdef HAVE_NEW_MING +#if defined(HAVE_MING_ZLIB) && !defined(HAVE_NEW_MING) + out = SWFMovie_output(getMovie(getThis() TSRMLS_CC), &phpStreamOutputMethod, what); + if (oldval >= -1 && oldval <=9) + Ming_setSWFCompression(oldval); + RETURN_LONG(out); +#elif defined(HAVE_NEW_MING) RETURN_LONG(SWFMovie_output(movie, &phpStreamOutputMethod, what, limit)); #else RETURN_LONG(SWFMovie_output(movie, &phpStreamOutputMethod, what)); @@ -2091,9 +2336,12 @@ PHP_METHOD(swfmovie, saveToFile) PHP_METHOD(swfmovie, save) { zval **x; -#ifdef HAVE_MING_ZLIB +#if defined(HAVE_MING_ZLIB) || defined(HAVE_NEW_MING) zval **zlimit = NULL; int limit = -1; +#endif +#if defined(HAVE_MING_ZLIB) && !defined(HAVE_NEW_MING) + int oldval = INT_MIN; #endif long retval; php_stream *stream; @@ -2105,7 +2353,7 @@ PHP_METHOD(swfmovie, save) } break; case 2: -#ifdef HAVE_MING_ZLIB +#if defined(HAVE_MING_ZLIB) || defined(HAVE_NEW_MING) if (zend_get_parameters_ex(2, &x, &zlimit) == FAILURE) { WRONG_PARAM_COUNT; } @@ -2115,6 +2363,9 @@ PHP_METHOD(swfmovie, save) php_error(E_WARNING,"compression level must be within 0..9"); RETURN_FALSE; } +#endif +#if defined(HAVE_MING_ZLIB) && !defined(HAVE_NEW_MING) + oldval = Ming_setSWFCompression(limit); #endif break; default: @@ -2123,10 +2374,15 @@ PHP_METHOD(swfmovie, save) if (Z_TYPE_PP(x) == IS_RESOURCE) { ZEND_FETCH_RESOURCE(stream, php_stream *, x, -1,"File-Handle",php_file_le_stream()); -#ifdef HAVE_NEW_MING +#if defined(HAVE_NEW_MING) RETURN_LONG(SWFMovie_output(getMovie(getThis() TSRMLS_CC), &phpStreamOutputMethod, stream, limit)); #else - RETURN_LONG(SWFMovie_output(getMovie(getThis() TSRMLS_CC), &phpStreamOutputMethod, stream)); + RETVAL_LONG(SWFMovie_output(getMovie(getThis() TSRMLS_CC), &phpStreamOutputMethod, stream)); +#if defined(HAVE_MING_ZLIB) && !defined(HAVE_NEW_MING) + if(oldval >= -1 && oldval <=9) + Ming_setSWFCompression(oldval); +#endif + return; #endif } @@ -2137,12 +2393,17 @@ PHP_METHOD(swfmovie, save) RETURN_FALSE; } -#ifdef HAVE_NEW_MING +#if defined(HAVE_NEW_MING) retval = SWFMovie_output(getMovie(getThis() TSRMLS_CC), &phpStreamOutputMethod, (void *)stream, limit); #else retval = SWFMovie_output(getMovie(getThis() TSRMLS_CC), &phpStreamOutputMethod, (void *)stream); #endif php_stream_close(stream); +#if defined(HAVE_MING_ZLIB) && !defined(HAVE_NEW_MING) + if(oldval >= -1 && oldval <=9) + Ming_setSWFCompression(oldval); +#endif + RETURN_LONG(retval); } /* }}} */ @@ -2296,6 +2557,7 @@ PHP_METHOD(swfmovie, startSound) ret = zend_list_insert(item, le_swfsoundinstancep); object_init_ex(return_value, soundinstance_class_entry_ptr); add_property_resource(return_value, "soundinstance", ret); + zend_list_addref(ret); } } /* }}} */ @@ -2340,6 +2602,7 @@ PHP_METHOD(swfmovie, importChar) ret = zend_list_insert(res, le_swfspritep); object_init_ex(return_value, sprite_class_entry_ptr); add_property_resource(return_value, "sprite", ret); + zend_list_addref(ret); } } /* }}} */ @@ -2367,6 +2630,7 @@ PHP_METHOD(swfmovie, importFont) ret = zend_list_insert(res, le_swffontcharp); object_init_ex(return_value, fontchar_class_entry_ptr); add_property_resource(return_value, "fontcharacter", ret); + zend_list_addref(ret); } } /* }}} */ @@ -2395,6 +2659,7 @@ PHP_METHOD(swfmovie, addFont) ret = zend_list_insert(res, le_swffontcharp); object_init_ex(return_value, fontchar_class_entry_ptr); add_property_resource(return_value, "fontcharacter", ret); + zend_list_addref(ret); } } /* }}} */ @@ -2579,6 +2844,7 @@ PHP_METHOD(swfshape, addFill) ret = zend_list_insert(fill, le_swffillp); object_init_ex(return_value, fill_class_entry_ptr); add_property_resource(return_value, "fill", ret); + zend_list_addref(ret); } /* }}} */ @@ -2865,7 +3131,7 @@ PHP_METHOD(swfshape, drawCircle) /* }}} */ /* {{{ proto void swfshape::drawarc(float r, float startAngle, float endAngle) - Draws an arc of radius r centered at the current location, from angle startAngle to angle endAngle measured counterclockwise from 12 o'clock */ + Draws an arc of radius r centered at the current location, from angle startAngle to angle endAngle measured clockwise from 12 o'clock */ PHP_METHOD(swfshape, drawArc) { zval **r, **start, **end; @@ -2878,7 +3144,7 @@ PHP_METHOD(swfshape, drawArc) convert_to_double_ex(end); /* convert angles to radians, since that's what php uses elsewhere */ - SWFShape_drawArc(getShape(getThis() TSRMLS_CC), FLOAT_Z_DVAL_PP(r), (float)(Z_DVAL_PP(start)*M_PI/180.0), (float)(Z_DVAL_PP(end)*M_PI/180.0)); + SWFShape_drawArc(getShape(getThis() TSRMLS_CC), FLOAT_Z_DVAL_PP(r), FLOAT_Z_DVAL_PP(start), FLOAT_Z_DVAL_PP(end)); } /* }}} */ @@ -3010,6 +3276,7 @@ PHP_METHOD(swfsprite, add) ret = zend_list_insert(item, le_swfdisplayitemp); object_init_ex(return_value, displayitem_class_entry_ptr); add_property_resource(return_value, "displayitem", ret); + zend_list_addref(ret); } } /* }}} */ @@ -3092,6 +3359,7 @@ PHP_METHOD(swfsprite, startSound) ret = zend_list_insert(item, le_swfsoundinstancep); object_init_ex(return_value, soundinstance_class_entry_ptr); add_property_resource(return_value, "soundinstance", ret); + zend_list_addref(ret); } } @@ -3790,12 +4058,26 @@ PHP_MINIT_FUNCTION(ming) #ifdef HAVE_NEW_MING zend_class_entry fontchar_class_entry; zend_class_entry soundinstance_class_entry; + zend_class_entry videostream_class_entry; +#endif +#ifdef HAVE_SWFPREBUILTCLIP + zend_class_entry prebuiltclip_class_entry; #endif Ming_setErrorFunction((void *) php_ming_error); #define CONSTANT(s,c) REGISTER_LONG_CONSTANT((s), (c), CONST_CS | CONST_PERSISTENT) +#ifdef HAVE_NEW_MING + CONSTANT("MING_NEW", 1); +#else + CONSTANT("MING_NEW", 0); +#endif +#ifdef HAVE_MING_ZLIB + CONSTANT("MING_ZLIB", 1); +#else + CONSTANT("MING_ZLIB", 0); +#endif /* flags for SWFButton_addShape */ CONSTANT("SWFBUTTON_HIT", SWFBUTTONRECORD_HITSTATE); CONSTANT("SWFBUTTON_DOWN", SWFBUTTONRECORD_DOWNSTATE); @@ -3863,6 +4145,10 @@ PHP_MINIT_FUNCTION(ming) #ifdef HAVE_NEW_MING le_swffontcharp = zend_register_list_destructors_ex(destroy_SWFFontCharacter_resource, NULL, "SWFFontCharacter", module_number); le_swfsoundinstancep = zend_register_list_destructors_ex(NULL, NULL, "SWFSoundInstance", module_number); + le_swfvideostreamp = zend_register_list_destructors_ex(destroy_SWFVideoStream_resource, NULL, "SWFVideoStream", module_number); +#endif +#ifdef HAVE_SWFPREBUILTCLIP + le_swfprebuiltclipp = zend_register_list_destructors_ex(destroy_SWFPrebuiltClip_resource, NULL, "SWFPrebuiltClip", module_number); #endif INIT_CLASS_ENTRY(shape_class_entry, "SWFShape", swfshape_functions); @@ -3882,6 +4168,10 @@ PHP_MINIT_FUNCTION(ming) #ifdef HAVE_NEW_MING INIT_CLASS_ENTRY(fontchar_class_entry, "SWFFontChar", swffontchar_functions); INIT_CLASS_ENTRY(soundinstance_class_entry, "SWFSoundInstance", swfsoundinstance_functions); + INIT_CLASS_ENTRY(videostream_class_entry, "SWFVideoStream", swfvideostream_functions); +#endif +#ifdef HAVE_SWFPREBUILTCLIP + INIT_CLASS_ENTRY(prebuiltclip_class_entry, "SWFPrebuiltClip", swfprebuiltclip_functions); #endif shape_class_entry_ptr = zend_register_internal_class(&shape_class_entry TSRMLS_CC); @@ -3901,6 +4191,10 @@ PHP_MINIT_FUNCTION(ming) #ifdef HAVE_NEW_MING fontchar_class_entry_ptr = zend_register_internal_class(&fontchar_class_entry TSRMLS_CC); soundinstance_class_entry_ptr = zend_register_internal_class(&soundinstance_class_entry TSRMLS_CC); + videostream_class_entry_ptr = zend_register_internal_class(&videostream_class_entry TSRMLS_CC); +#endif +#ifdef HAVE_SWFPREBUILTCLIP + prebuiltclip_class_entry_ptr = zend_register_internal_class(&prebuiltclip_class_entry TSRMLS_CC); #endif return SUCCESS; diff --git a/ext/ming/tests/swfaction-new.phpt b/ext/ming/tests/swfaction-new.phpt new file mode 100755 index 000000000000..43527100151d --- /dev/null +++ b/ext/ming/tests/swfaction-new.phpt @@ -0,0 +1,51 @@ +--TEST-- +Ming: Simple SWFAction() test +--SKIPIF-- + +--FILE-- +addFill(0xff, 0, 0); + $s->setRightFill($f); + + $s->movePenTo(-500,-500); + $s->drawLineTo(500,-500); + $s->drawLineTo(500,500); + $s->drawLineTo(-500,500); + $s->drawLineTo(-500,-500); + + $p = new SWFSprite(); + $i = $p->add($s); + $i->setDepth(1); + $p->nextFrame(); + + for($n=0; $n<5; ++$n) + { + $i->rotate(-15); + $p->nextFrame(); + } + + $m = new SWFMovie(); + $m->setBackground(0xff, 0xff, 0xff); + $m->setDimension(6000,4000); + + $i = $m->add($p); + $i->setDepth(1); + $i->moveTo(1000,2000); + $i->setName("box"); + + $m->add(new SWFAction("_root.box._x += 3;")); + $m->nextFrame(); + $m->add(new SWFAction("gotoFrame(0); play();")); + $m->nextFrame(); + + $m->save(dirname(__FILE__).'/test.swf'); + echo md5_file(dirname(__FILE__).'/test.swf'), "\n"; + unlink(dirname(__FILE__).'/test.swf'); +?> +--EXPECT-- +d0f09a7b6a14d3fe6d570367deb38633 diff --git a/ext/ming/tests/swfaction.phpt b/ext/ming/tests/swfaction.phpt index a99d4e24f61f..4717c7c998d7 100644 --- a/ext/ming/tests/swfaction.phpt +++ b/ext/ming/tests/swfaction.phpt @@ -1,7 +1,10 @@ --TEST-- Ming: Simple SWFAction() test --SKIPIF-- - + --FILE-- add(new SWFAction("gotoFrame(0); play();")); $m->nextFrame(); - $m->save('./test.swf'); - echo md5_file('./test.swf'), "\n"; - unlink('./test.swf'); + $m->save(dirname(__FILE__).'/test.swf'); + echo md5_file(dirname(__FILE__).'/test.swf'), "\n"; + unlink(dirname(__FILE__).'/test.swf'); ?> --EXPECT-- 9e47538692393b9915faf3fc7e686cd5 diff --git a/ext/mnogosearch/config.m4 b/ext/mnogosearch/config.m4 index d127ce670230..497838fbc47d 100644 --- a/ext/mnogosearch/config.m4 +++ b/ext/mnogosearch/config.m4 @@ -47,7 +47,7 @@ PHP_ARG_WITH(mnogosearch,for mnoGoSearch support, AC_DEFINE(HAVE_MNOGOSEARCH,1,[ ]) - PHP_SUBST(MNOGOSEARCH_SHARED_LIBADD) PHP_NEW_EXTENSION(mnogosearch, php_mnogo.c, $ext_shared) + PHP_SUBST(MNOGOSEARCH_SHARED_LIBADD) fi diff --git a/ext/mnogosearch/php_mnogo.c b/ext/mnogosearch/php_mnogo.c index 76f8e460be71..4e9e0f7bdc0e 100644 --- a/ext/mnogosearch/php_mnogo.c +++ b/ext/mnogosearch/php_mnogo.c @@ -3,9 +3,9 @@ /* +----------------------------------------------------------------------+ - | PHP Version 4 | + | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2003 The PHP Group | + | Copyright (c) 1997-2004 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -20,7 +20,7 @@ | and Ramil Kalimullin | | Further development by Sergey Kartashoff | +----------------------------------------------------------------------+ - */ +*/ #ifdef HAVE_CONFIG_H #include "config.h" @@ -430,7 +430,7 @@ DLEXPORT PHP_MINFO_FUNCTION(mnogosearch) static char* MyRemoveHiLightDup(const char *s){ size_t len=strlen(s)+1; - char *d, *res = (char*)UdmMalloc(len); + char *d, *res = (char*)emalloc(len); for(d=res; s[0]; s++) { @@ -1214,43 +1214,48 @@ DLEXPORT PHP_FUNCTION(udm_load_ispell_data) #endif case UDM_ISPELL_TYPE_AFFIX: -#if UDM_VERSION_ID < 30200 +#if UDM_VERSION_ID < 30200 Agent->Conf->ispell_mode &= ~UDM_ISPELL_MODE_DB; - #if UDM_VERSION_ID > 30111 Agent->Conf->ispell_mode &= ~UDM_ISPELL_MODE_SERVER; #endif - if (UdmImportAffixes(Agent->Conf,val1,val2,NULL,0)) { php_error_docref(NULL TSRMLS_CC, E_WARNING,"Cannot load affix file %s",val2); RETURN_FALSE; } -#else +#elif UDM_VERSION_ID < 30225 if (UdmImportAffixes(Agent->Conf,val1,charset,val2)) { php_error_docref(NULL TSRMLS_CC, E_WARNING,"Cannot load affix file %s",val2); RETURN_FALSE; } - +#else + if(UdmAffixListListAdd(&Agent->Conf->Affixes,val1,charset,val2)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING,"Cannot load affix file %s",val2); + RETURN_FALSE; + } #endif break; case UDM_ISPELL_TYPE_SPELL: #if UDM_VERSION_ID < 30200 Agent->Conf->ispell_mode &= ~UDM_ISPELL_MODE_DB; - #if UDM_VERSION_ID > 30111 Agent->Conf->ispell_mode &= ~UDM_ISPELL_MODE_SERVER; #endif - if (UdmImportDictionary(Agent->Conf,val1,val2,1,"")) { php_error_docref(NULL TSRMLS_CC, E_WARNING,"Cannot load spell file %s",val2); RETURN_FALSE; } -#else +#elif UDM_VERSION_ID < 30225 if (UdmImportDictionary(Agent->Conf,val1,charset,val2,0,"")) { php_error_docref(NULL TSRMLS_CC, E_WARNING,"Cannot load spell file %s",val2); RETURN_FALSE; } +#else + if(UdmSpellListListAdd(&Agent->Conf->Spells,val1,charset,val2)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING,"Cannot load spell file %s",val2); + RETURN_FALSE; + } #endif break; @@ -1262,6 +1267,7 @@ DLEXPORT PHP_FUNCTION(udm_load_ispell_data) } if (flag) { +#if UDM_VERSION_ID < 30225 #if UDM_VERSION_ID >= 30204 if(Agent->Conf->Spells.nspell) { UdmSortDictionary(&Agent->Conf->Spells); @@ -1272,6 +1278,19 @@ DLEXPORT PHP_FUNCTION(udm_load_ispell_data) UdmSortDictionary(Agent->Conf); UdmSortAffixes(Agent->Conf); } +#endif +#else + if(Agent->Conf->Spells.nitems && Agent->Conf->Affixes.nitems) { + char *err= Agent->Conf->errstr; + int flags= strcasecmp(UdmVarListFindStr(&Agent->Conf->Vars, + "IspellUsePrefixes","no"),"no"); + flags= flags ? 0 : UDM_SPELL_NOPREFIX; + if (UdmSpellListListLoad(&Agent->Conf->Spells, err, 128) || + UdmAffixListListLoad(&Agent->Conf->Affixes, flags, err, 128)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error loading ispell data"); + RETURN_FALSE; + } + } #endif } @@ -1297,8 +1316,11 @@ DLEXPORT PHP_FUNCTION(udm_free_ispell_data) break; } ZEND_FETCH_RESOURCE(Agent, UDM_AGENT *, yyagent, -1, "mnoGoSearch-Agent", le_link); - -#if UDM_VERSION_ID >= 30204 + +#if UDM_VERSION_ID >= 30225 + UdmSpellListListFree(&Agent->Conf->Spells); + UdmAffixListListFree(&Agent->Conf->Affixes); +#elif UDM_VERSION_ID >= 30204 UdmSpellListFree(&Agent->Conf->Spells); UdmAffixListFree(&Agent->Conf->Affixes); #elif UDM_VERSION_ID > 30111 @@ -1625,7 +1647,7 @@ DLEXPORT PHP_FUNCTION(udm_make_excerpt) al = (char *)MyRemoveHiLightDup((const char *)(UdmVarListFindStr(&(Res->Doc[row].Sections), "URL", ""))); UdmVarListReplaceInt(&(Res->Doc[row].Sections), "STORED_ID", UdmCRC32(al, strlen(al))); - free(al); + efree(al); #if UDM_VERSION_ID >= 30216 Excerpt = UdmExcerptDoc(Agent, Res, &(Res->Doc[row]), ExcerptSize, ExcerptPadding); @@ -1777,7 +1799,7 @@ DLEXPORT PHP_FUNCTION(udm_get_res_field_ex) char *al; al = (char *)MyRemoveHiLightDup((const char *)(UdmVarListFindStr(&(Res->Doc[row].Sections), field, ""))); UdmVarListReplaceStr(&Res->Doc[row].Sections,field,al); - free(al); + efree(al); } RETURN_STRING((char *)UdmVarListFindStr(&Res->Doc[row].Sections,field,""),1); } else { @@ -1826,6 +1848,7 @@ DLEXPORT PHP_FUNCTION(udm_store_doc_cgi) UdmPrepare(Agent,Res); UdmVarListReplaceStr(&Doc->Sections, "URL", UdmVarListFindStr(&Agent->Conf->Vars, "URL", "0")); + UdmVarListReplaceStr(&Doc->Sections, "dbnum", UdmVarListFindStr(&Agent->Conf->Vars, "dbnum", "0")); UdmURLAction(Agent, Doc, UDM_URL_ACTION_GET_CACHED_COPY); UdmVarListReplaceLst(&Agent->Conf->Vars, &Doc->Sections, NULL, "*"); @@ -1839,12 +1862,11 @@ DLEXPORT PHP_FUNCTION(udm_store_doc_cgi) if(!Doc->Buf.content) { UdmResultFree(Res); UdmDocFree(Doc); - UDM_FREE(HDoc); RETURN_FALSE; } - HEnd=HDoc = (char*)UdmMalloc(UDM_MAXDOCSIZE + 32); + HEnd=HDoc = (char*)emalloc(UDM_MAXDOCSIZE + 32); *HEnd='\0'; if (strncasecmp(content_type, "text/plain", 10) == 0) { @@ -1885,7 +1907,7 @@ DLEXPORT PHP_FUNCTION(udm_store_doc_cgi) UdmResultFree(Res); UdmDocFree(Doc); - UDM_FREE(HDoc); + efree(HDoc); RETURN_TRUE; } @@ -1990,7 +2012,7 @@ DLEXPORT PHP_FUNCTION(udm_hash32) Perform search */ DLEXPORT PHP_FUNCTION(udm_find) { - pval ** yyquery, ** yyagent; + pval ** yyquery=NULL, ** yyagent; UDM_RESULT * Res; UDM_AGENT * Agent; int id=-1; @@ -2021,6 +2043,9 @@ DLEXPORT PHP_FUNCTION(udm_find) if ((Res=UdmFind(Agent,UdmTolower(Z_STRVAL_PP(yyquery),Agent->charset)))) { #else #if UDM_VERSION_ID >= 30213 + if ((yyquery) && (strlen(Z_STRVAL_PP(yyquery)))) + UdmVarListReplaceStr(&Agent->Conf->Vars, "q", + Z_STRVAL_PP(yyquery)); if ((Res=UdmFind(Agent))) { #else if ((Res=UdmFind(Agent,Z_STRVAL_PP(yyquery)))) { @@ -2066,7 +2091,7 @@ DLEXPORT PHP_FUNCTION(udm_get_res_field) char *al; al = (char *)MyRemoveHiLightDup((const char *)(UdmVarListFindStr(&(Res->Doc[row].Sections), "URL", ""))); UdmVarListReplaceStr(&Res->Doc[row].Sections,"URL",al); - free(al); + efree(al); RETURN_STRING((char *)UdmVarListFindStr(&(Res->Doc[row].Sections),"URL",""),1); } @@ -2256,7 +2281,7 @@ DLEXPORT PHP_FUNCTION(udm_get_res_param) len += Res->WWList.Word[i].len + 64; { size_t wsize=(1+len)*sizeof(char); - char *wordinfo = (char*) malloc(wsize); + char *wordinfo = (char*) emalloc(wsize); *wordinfo = '\0'; @@ -2270,7 +2295,7 @@ DLEXPORT PHP_FUNCTION(udm_get_res_param) sprintf(UDM_STREND(wordinfo)," %s : stopword", Res->WWList.Word[i].word); } } - RETURN_STRING(wordinfo,1); + RETURN_STRING(wordinfo,0); } } #else @@ -2286,7 +2311,7 @@ DLEXPORT PHP_FUNCTION(udm_get_res_param) len += Res->WWList.Word[i].len + 64; { size_t wsize=(1+len)*sizeof(char); - char *wordinfo = (char*) malloc(wsize); + char *wordinfo = (char*) emalloc(wsize); int corder = (size_t)-1, ccount = 0; *wordinfo = '\0'; @@ -2305,7 +2330,7 @@ DLEXPORT PHP_FUNCTION(udm_get_res_param) sprintf(UDM_STREND(wordinfo),"%s%s : %d / %d", (*wordinfo) ? ", " : "", Res->WWList.Word[i].word, Res->WWList.Word[i].count, ccount); } else continue; } - RETURN_STRING(wordinfo,1); + RETURN_STRING(wordinfo,0); } } break; @@ -2489,7 +2514,7 @@ DLEXPORT PHP_FUNCTION(udm_cat_list) #endif array_init(return_value); - if (!(buf=calloc(1,UDMSTRSIZ+1))) { + if (!(buf=ecalloc(1,UDMSTRSIZ+1))) { RETURN_FALSE; } @@ -2513,7 +2538,7 @@ DLEXPORT PHP_FUNCTION(udm_cat_list) c++; } #endif - free(buf); + efree(buf); } else { RETURN_FALSE; } @@ -2563,7 +2588,7 @@ DLEXPORT PHP_FUNCTION(udm_cat_path) #endif array_init(return_value); - if (!(buf=calloc(1,UDMSTRSIZ+1))) { + if (!(buf=ecalloc(1,UDMSTRSIZ+1))) { RETURN_FALSE; } @@ -2587,7 +2612,7 @@ DLEXPORT PHP_FUNCTION(udm_cat_path) c++; } #endif - free(buf); + efree(buf); } else { RETURN_FALSE; } diff --git a/ext/mnogosearch/php_mnogo.h b/ext/mnogosearch/php_mnogo.h index f2a2ec5eb2f7..a26fb48cdd0e 100644 --- a/ext/mnogosearch/php_mnogo.h +++ b/ext/mnogosearch/php_mnogo.h @@ -3,14 +3,14 @@ /* +----------------------------------------------------------------------+ - | PHP Version 4 | + | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2003 The PHP Group | + | Copyright (c) 1997-2004 The PHP Group | +----------------------------------------------------------------------+ - | This source file is subject to version 2.02 of the PHP license, | + | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | - | available at through the world-wide-web at | - | http://www.php.net/license/2_02.txt. | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_0.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | @@ -20,7 +20,7 @@ | and Ramil Kalimullin | | Further development by Sergey Kartashoff | +----------------------------------------------------------------------+ - */ +*/ #ifndef _PHP_MNOGO_H #define _PHP_MNOGO_H diff --git a/ext/msql/config.m4 b/ext/msql/config.m4 index 093dfa54e980..f9a13d37583e 100644 --- a/ext/msql/config.m4 +++ b/ext/msql/config.m4 @@ -5,7 +5,7 @@ dnl dnl dnl Test mSQL version by checking if msql.h has "IDX_TYPE" defined. dnl -AC_DEFUN(PHP_MSQL_VERSION,[ +AC_DEFUN([PHP_MSQL_VERSION],[ AC_MSG_CHECKING([mSQL version]) ac_php_oldcppflags=$CPPFLAGS CPPFLAGS="$INCLUDES $CPPFLAGS" diff --git a/ext/msql/php_msql.c b/ext/msql/php_msql.c index f9a9e19feb17..841f0b59f676 100644 --- a/ext/msql/php_msql.c +++ b/ext/msql/php_msql.c @@ -958,9 +958,14 @@ static void php_msql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type) add_assoc_stringl(return_value, msql_field->name, data, data_len, should_copy); } } else { - /* - add_get_index_stringl(return_value, i, empty_string, 0, (void **) &pval_ptr, 1); - */ + /* NULL value. */ + if (result_type & MSQL_NUM) { + add_index_null(return_value, i); + } + + if (result_type & MSQL_ASSOC) { + add_assoc_null(return_value, msql_field->name); + } } } } diff --git a/ext/mssql/config.m4 b/ext/mssql/config.m4 index 7007b1b94c44..ead793553928 100644 --- a/ext/mssql/config.m4 +++ b/ext/mssql/config.m4 @@ -32,8 +32,8 @@ if test "$PHP_MSSQL" != "no"; then fi fi - if test ! -r "$FREETDS_INSTALLATION_DIR/lib/libtds.a"; then - AC_MSG_ERROR(Could not find $FREETDS_INSTALLATION_DIR/lib/libtds.a) + if test ! -r "$FREETDS_INSTALLATION_DIR/lib/libtds.a" && test ! -r "$FREETDS_INSTALLATION_DIR/lib/libtds.so"; then + AC_MSG_ERROR(Could not find $FREETDS_INSTALLATION_DIR/lib/libtds.[a|so]) fi MSSQL_INCDIR=$FREETDS_INSTALLATION_DIR/include diff --git a/ext/mssql/php_mssql.c b/ext/mssql/php_mssql.c index 9930d3d0e4ee..122d386de7fc 100644 --- a/ext/mssql/php_mssql.c +++ b/ext/mssql/php_mssql.c @@ -274,14 +274,11 @@ static void php_mssql_init_globals(zend_mssql_globals *mssql_globals) long compatability_mode; mssql_globals->num_persistent = 0; + mssql_globals->get_column_content = php_mssql_get_column_content_with_type; if (cfg_get_long("mssql.compatability_mode", &compatability_mode) == SUCCESS) { if (compatability_mode) { mssql_globals->get_column_content = php_mssql_get_column_content_without_type; - } else { - mssql_globals->get_column_content = php_mssql_get_column_content_with_type; } - } else { - mssql_globals->get_column_content = php_mssql_get_column_content_with_type; } } @@ -324,7 +321,11 @@ PHP_MINIT_FUNCTION(mssql) PHP_MSHUTDOWN_FUNCTION(mssql) { UNREGISTER_INI_ENTRIES(); +#ifndef HAVE_FREETDS + dbwinexit(); +#else dbexit(); +#endif return SUCCESS; } @@ -516,14 +517,17 @@ static void php_mssql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) RETURN_FALSE; } +#ifndef HAVE_FREETDS if (MS_SQL_G(textlimit) != -1) { sprintf(buffer, "%li", MS_SQL_G(textlimit)); if (DBSETOPT(mssql.link, DBTEXTLIMIT, buffer)==FAIL) { efree(hashed_details); dbfreelogin(mssql.login); + dbclose(mssql.link); RETURN_FALSE; } } +#endif if (MS_SQL_G(textsize) != -1) { sprintf(buffer, "SET TEXTSIZE %li", MS_SQL_G(textsize)); dbcmd(mssql.link, buffer); @@ -540,6 +544,7 @@ static void php_mssql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) free(mssql_ptr); efree(hashed_details); dbfreelogin(mssql.login); + dbclose(mssql.link); RETURN_FALSE; } MS_SQL_G(num_persistent)++; @@ -550,22 +555,25 @@ static void php_mssql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) log_error("PHP/MS SQL: Hashed persistent link is not a MS SQL link!",php_rqst->server); #endif php_error_docref(NULL TSRMLS_CC, E_WARNING, "Hashed persistent link is not a MS SQL link!"); + efree(hashed_details); RETURN_FALSE; } mssql_ptr = (mssql_link *) le->ptr; /* test that the link hasn't died */ if (DBDEAD(mssql_ptr->link) == TRUE) { + dbclose(mssql_ptr->link); #if BROKEN_MSSQL_PCONNECTS log_error("PHP/MS SQL: Persistent link died, trying to reconnect...",php_rqst->server); #endif - if ((mssql_ptr->link=dbopen(mssql_ptr->login,host))==FAIL) { + if ((mssql_ptr->link=dbopen(mssql_ptr->login,host))==NULL) { #if BROKEN_MSSQL_PCONNECTS log_error("PHP/MS SQL: Unable to reconnect!",php_rqst->server); #endif php_error_docref(NULL TSRMLS_CC, E_WARNING, "Link to server lost, unable to reconnect"); zend_hash_del(&EG(persistent_list), hashed_details, hashed_details_length+1); efree(hashed_details); + dbfreelogin(mssql_ptr->login); RETURN_FALSE; } #if BROKEN_MSSQL_PCONNECTS @@ -577,6 +585,8 @@ static void php_mssql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) #endif zend_hash_del(&EG(persistent_list), hashed_details, hashed_details_length + 1); efree(hashed_details); + dbfreelogin(mssql_ptr->login); + dbclose(mssql_ptr->link); RETURN_FALSE; } } @@ -595,6 +605,8 @@ static void php_mssql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) void *ptr; if (Z_TYPE_P(index_ptr) != le_index_ptr) { + efree(hashed_details); + dbfreelogin(mssql.login); RETURN_FALSE; } link = (int) index_ptr->ptr; @@ -604,6 +616,7 @@ static void php_mssql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) Z_LVAL_P(return_value) = link; php_mssql_set_default_link(link TSRMLS_CC); Z_TYPE_P(return_value) = IS_RESOURCE; + dbfreelogin(mssql.login); efree(hashed_details); return; } else { @@ -613,12 +626,14 @@ static void php_mssql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) if (MS_SQL_G(max_links) != -1 && MS_SQL_G(num_links) >= MS_SQL_G(max_links)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", MS_SQL_G(num_links)); efree(hashed_details); + dbfreelogin(mssql.login); RETURN_FALSE; } if ((mssql.link=dbopen(mssql.login, host))==NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to connect to server: %s", host); efree(hashed_details); + dbfreelogin(mssql.login); RETURN_FALSE; } @@ -629,14 +644,17 @@ static void php_mssql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) RETURN_FALSE; } +#ifndef HAVE_FREETDS if (MS_SQL_G(textlimit) != -1) { sprintf(buffer, "%li", MS_SQL_G(textlimit)); if (DBSETOPT(mssql.link, DBTEXTLIMIT, buffer)==FAIL) { efree(hashed_details); dbfreelogin(mssql.login); + dbclose(mssql.link); RETURN_FALSE; } } +#endif if (MS_SQL_G(textsize) != -1) { sprintf(buffer, "SET TEXTSIZE %li", MS_SQL_G(textsize)); dbcmd(mssql.link, buffer); @@ -862,6 +880,7 @@ static void php_mssql_get_column_content_with_type(mssql_link *mssql_ptr,int off res_buf = (unsigned char *) emalloc(res_length+1); res_length = dbconvert(NULL,coltype(offset),dbdata(mssql_ptr->link,offset), res_length, SQLCHAR,res_buf,-1); + res_buf[res_length] = '\0'; } else { if (column_type == SQLDATETIM4) { DBDATETIME temp; @@ -931,7 +950,7 @@ static void php_mssql_get_column_content_without_type(mssql_link *mssql_ptr,int res_buf = (unsigned char *) emalloc(res_length+1); res_length = dbconvert(NULL,coltype(offset),dbdata(mssql_ptr->link,offset), res_length, SQLCHAR, res_buf, -1); - + res_buf[res_length] = '\0'; } else { if (column_type == SQLDATETIM4) { DBDATETIME temp; @@ -976,6 +995,7 @@ static void _mssql_get_sp_result(mssql_link *mssql_ptr, mssql_statement *stateme case SQLINT2: case SQLINT4: convert_to_long_ex(&bind->zval); + /* FIXME this works only on little endian machine !!! */ Z_LVAL_P(bind->zval) = *((int *)(dbretdata(mssql_ptr->link,i))); break; @@ -996,6 +1016,7 @@ static void _mssql_get_sp_result(mssql_link *mssql_ptr, mssql_statement *stateme Z_STRLEN_P(bind->zval) = dbretlen(mssql_ptr->link,i); Z_STRVAL_P(bind->zval) = estrndup(dbretdata(mssql_ptr->link,i),Z_STRLEN_P(bind->zval)); break; + /* TODO binary */ } } else { @@ -1183,7 +1204,8 @@ PHP_FUNCTION(mssql_query) while ((num_fields = dbnumcols(mssql_ptr->link)) <= 0 && retvalue == SUCCEED) { retvalue = dbresults(mssql_ptr->link); } - if ((num_fields = dbnumcols(mssql_ptr->link)) <= 0) { + + if (num_fields <= 0) { RETURN_TRUE; } @@ -1203,12 +1225,8 @@ PHP_FUNCTION(mssql_query) result->mssql_ptr = mssql_ptr; result->cur_field=result->cur_row=result->num_rows=0; - if (num_fields > 0) { result->fields = (mssql_field *) safe_emalloc(sizeof(mssql_field), result->num_fields, 0); result->num_rows = _mssql_fetch_batch(mssql_ptr, result, retvalue TSRMLS_CC); - } - else - result->fields = NULL; ZEND_REGISTER_RESOURCE(return_value, result, le_result); } @@ -1794,7 +1812,7 @@ PHP_FUNCTION(mssql_result) } *return_value = result->data[Z_LVAL_PP(row)][field_offset]; - ZVAL_COPY_CTOR(return_value); + zval_copy_ctor(return_value); } /* }}} */ @@ -2217,7 +2235,7 @@ PHP_FUNCTION(mssql_guid_string) break; } - dbconvert(NULL, SQLBINARY, (BYTE*)Z_STRVAL_PP(binary), 16, SQLCHAR, buffer, -1); + dbconvert(NULL, SQLBINARY, (BYTE*)Z_STRVAL_PP(binary), MIN(16, Z_STRLEN_PP(binary)), SQLCHAR, buffer, -1); if (sf) { php_strtoupper(buffer, 32); @@ -2225,6 +2243,7 @@ PHP_FUNCTION(mssql_guid_string) } else { int i; + /* FIXME this works only on little endian machine */ for (i=0; i<4; i++) { buffer2[2*i] = buffer[6-2*i]; buffer2[2*i+1] = buffer[7-2*i]; diff --git a/ext/mysql/config.m4 b/ext/mysql/config.m4 index 8bf0a6a879f7..04b3db836f9c 100644 --- a/ext/mysql/config.m4 +++ b/ext/mysql/config.m4 @@ -2,8 +2,8 @@ dnl dnl $Id$ dnl -AC_DEFUN(MYSQL_LIB_CHK, [ - str="$MYSQL_DIR/$1/libmysqlclient.*" +AC_DEFUN([MYSQL_LIB_CHK], [ + str="$MYSQL_DIR/$1/lib$MY_LIBNAME.*" for j in `echo $str`; do if test -r $j; then MYSQL_LIB_DIR=$MYSQL_DIR/$1 @@ -12,7 +12,7 @@ AC_DEFUN(MYSQL_LIB_CHK, [ done ]) -AC_DEFUN(PHP_MYSQL_SOCKET_SEARCH, [ +AC_DEFUN([PHP_MYSQL_SOCKET_SEARCH], [ for i in \ /var/run/mysqld/mysqld.sock \ /var/tmp/mysql.sock \ @@ -83,7 +83,14 @@ if test "$PHP_MYSQL" != "no"; then Note that the MySQL client library is not bundled anymore.]) fi - for i in lib lib/mysql; do + MY_LIBNAME=mysqlclient + case $host_alias in + *netware*[)] + MY_LIBNAME=mysql + ;; + esac + + for i in lib lib/mysql lib64 lib64/mysql; do MYSQL_LIB_CHK($i) done @@ -92,11 +99,11 @@ Note that the MySQL client library is not bundled anymore.]) Note that the MySQL client library is not bundled anymore.]) fi - PHP_CHECK_LIBRARY(mysqlclient, mysql_close, [ ], + PHP_CHECK_LIBRARY($MY_LIBNAME, mysql_close, [ ], [ if test "$PHP_ZLIB_DIR" != "no"; then PHP_ADD_LIBRARY_WITH_PATH(z, $PHP_ZLIB_DIR, MYSQL_SHARED_LIBADD) - PHP_CHECK_LIBRARY(mysqlclient, mysql_error, [], [ + PHP_CHECK_LIBRARY($MY_LIBNAME, mysql_error, [], [ AC_MSG_ERROR([mysql configure failed. Please check config.log for more information.]) ], [ -L$PHP_ZLIB_DIR/lib -L$MYSQL_LIB_DIR @@ -104,7 +111,7 @@ Note that the MySQL client library is not bundled anymore.]) MYSQL_LIBS="-L$PHP_ZLIB_DIR/lib -lz" else PHP_ADD_LIBRARY(z,, MYSQL_SHARED_LIBADD) - PHP_CHECK_LIBRARY(mysqlclient, mysql_errno, [], [ + PHP_CHECK_LIBRARY($MY_LIBNAME, mysql_errno, [], [ AC_MSG_ERROR([Try adding --with-zlib-dir=. Please check config.log for more information.]) ], [ -L$MYSQL_LIB_DIR @@ -115,13 +122,13 @@ Note that the MySQL client library is not bundled anymore.]) -L$MYSQL_LIB_DIR ]) - PHP_ADD_LIBRARY_WITH_PATH(mysqlclient, $MYSQL_LIB_DIR, MYSQL_SHARED_LIBADD) + PHP_ADD_LIBRARY_WITH_PATH($MY_LIBNAME, $MYSQL_LIB_DIR, MYSQL_SHARED_LIBADD) PHP_ADD_INCLUDE($MYSQL_INC_DIR) PHP_NEW_EXTENSION(mysql, php_mysql.c, $ext_shared) MYSQL_MODULE_TYPE=external - MYSQL_LIBS="-L$MYSQL_LIB_DIR -lmysqlclient $MYSQL_LIBS" + MYSQL_LIBS="-L$MYSQL_LIB_DIR -l$MY_LIBNAME $MYSQL_LIBS" MYSQL_INCLUDE=-I$MYSQL_INC_DIR PHP_SUBST(MYSQL_SHARED_LIBADD) diff --git a/ext/mysql/php_mysql.c b/ext/mysql/php_mysql.c index 11dae416329d..d7c159e7dbad 100644 --- a/ext/mysql/php_mysql.c +++ b/ext/mysql/php_mysql.c @@ -52,6 +52,9 @@ # endif # include # include +# if HAVE_ARPA_INET_H +# include +# endif #endif #include @@ -2298,7 +2301,7 @@ static void php_mysql_field_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type) { zval **result, **field; MYSQL_RES *mysql_result; - MYSQL_FIELD *mysql_field; + MYSQL_FIELD *mysql_field = {0}; char buf[512]; int len; diff --git a/ext/mysqli/config.m4 b/ext/mysqli/config.m4 index 7f00915d0036..88c742a18f1d 100644 --- a/ext/mysqli/config.m4 +++ b/ext/mysqli/config.m4 @@ -46,8 +46,8 @@ if test "$PHP_MYSQLI" != "no"; then AC_DEFINE(HAVE_MYSQLILIB,1,[ ]) PHP_CHECK_LIBRARY(mysqlclient, mysql_stmt_field_count, [ ],[ - AC_MSG_ERROR([MySQLI doesn't support versions < 4.1.3 anymore. Please update your libraries.]) - ],[]) + AC_MSG_ERROR([MySQLI doesn't support versions < 4.1.3 (for MySQL 4.1.x) and < 5.0.1 for (MySQL 5.0.x) anymore. Please update your libraries.]) + ],[$MYSQLI_LIBLINE]) ],[ AC_MSG_ERROR([wrong mysql library version or lib not found. Check config.log for more information.]) ],[ diff --git a/ext/mysqli/config.w32 b/ext/mysqli/config.w32 index 2ced23e8b5cd..5b5c673f2239 100644 --- a/ext/mysqli/config.w32 +++ b/ext/mysqli/config.w32 @@ -4,8 +4,8 @@ ARG_WITH("mysqli", "MySQLi support", "no"); if (PHP_MYSQLI != "no") { - if (CHECK_LIB("libmysqli.lib", "mysqli", PHP_MYSQLI) && - CHECK_HEADER_ADD_INCLUDE("mysql.h", "CFLAGS_MYSQLI", PHP_PHP_BUILD + "\\include\\mysqli;" + PHP_MYSQLI)) { + if (CHECK_LIB("libmysql.lib", "mysqli", PHP_MYSQLI) && + CHECK_HEADER_ADD_INCLUDE("mysql.h", "CFLAGS_MYSQLI", PHP_PHP_BUILD + "\\include\\mysql;" + PHP_MYSQLI)) { EXTENSION("mysqli", "mysqli.c mysqli_api.c mysqli_fe.c mysqli_nonapi.c mysqli_prop.c mysqli_report.c mysqli_repl.c"); AC_DEFINE('HAVE_MYSQLILIB', 1, 'Have MySQLi library'); } else { diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c index 684e622ae8c1..45116f81578c 100644 --- a/ext/mysqli/mysqli.c +++ b/ext/mysqli/mysqli.c @@ -66,7 +66,7 @@ void php_free_stmt_bind_buffer(BIND_BUFFER bbuf, int type) for (i=0; i < bbuf.var_cnt; i++) { /* free temporary bind buffer */ - if (type == FETCH_RESULT) { + if (type == FETCH_RESULT && bbuf.buf[i].val) { efree(bbuf.buf[i].val); } @@ -107,16 +107,10 @@ void php_clear_stmt_bind(MY_STMT *stmt) /* {{{ php_clear_mysql */ void php_clear_mysql(MY_MYSQL *mysql) { - int i; - - for (i=0; i < 3; i++) { - if (&mysql->callback_func[i]) { - zval_dtor(&mysql->callback_func[i]); - } - } - - if (mysql->local_infile) { - zval_ptr_dtor(&mysql->local_infile); + if (mysql->li_read) { + efree(Z_STRVAL_P(mysql->li_read)); + FREE_ZVAL(mysql->li_read); + mysql->li_read = NULL; } } /* }}} */ @@ -124,21 +118,35 @@ void php_clear_mysql(MY_MYSQL *mysql) { /* {{{ mysqli_objects_free_storage */ static void mysqli_objects_free_storage(zend_object *object TSRMLS_DC) +{ + mysqli_object *intern = (mysqli_object *)object; + + zend_objects_free_object_storage(&(intern->zo) TSRMLS_CC); +} +/* }}} */ + +/* {{{ mysqli_objects_destroy_object + */ +static void mysqli_objects_destroy_object(void *object, zend_object_handle handle TSRMLS_DC) { mysqli_object *intern = (mysqli_object *)object; MYSQLI_RESOURCE *my_res = (MYSQLI_RESOURCE *)intern->ptr; - zend_hash_destroy(intern->zo.properties); - FREE_HASHTABLE(intern->zo.properties); + zend_objects_destroy_object(object, handle TSRMLS_CC); /* link object */ if (instanceof_function(intern->zo.ce, mysqli_link_class_entry TSRMLS_CC)) { if (my_res && my_res->ptr) { MY_MYSQL *mysql = (MY_MYSQL *)my_res->ptr; - mysql_close(mysql->mysql); + if (mysql->mysql) { + mysql_close(mysql->mysql); + } + + php_clear_mysql(mysql); + efree(mysql); - php_clear_mysql(mysql); + my_res->ptr = NULL; } } else if (intern->zo.ce == mysqli_stmt_class_entry) { /* stmt object */ if (my_res && my_res->ptr) { @@ -149,8 +157,8 @@ static void mysqli_objects_free_storage(zend_object *object TSRMLS_DC) mysql_free_result(my_res->ptr); } } + intern->ptr = NULL; my_efree(my_res); - efree(object); } /* }}} */ @@ -184,11 +192,6 @@ zval *mysqli_read_property(zval *object, zval *member, int type TSRMLS_DC) ret = FAILURE; obj = (mysqli_object *)zend_objects_get_address(object TSRMLS_CC); - if (!obj->valid) { - retval = EG(uninitialized_zval_ptr); - return(retval); - } - if (member->type != IS_STRING) { tmp_member = *member; zval_copy_ctor(&tmp_member); @@ -200,6 +203,24 @@ zval *mysqli_read_property(zval *object, zval *member, int type TSRMLS_DC) ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd); } if (ret == SUCCESS) { + + /* check if mysqli object is still valid */ + if (!strcmp(obj->zo.ce->name, "mysqli")) { + if (!obj->ptr || + !((MYSQL *)((MY_MYSQL *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr)->mysql)->thread_id) { + retval = EG(uninitialized_zval_ptr); + return(retval); + } + } else + /* check if stmt object is still valid */ + if (!strcmp(obj->zo.ce->name, "mysqli_stmt")) { + if (!obj->ptr || + !((MYSQL_STMT *)((MY_STMT *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr)->stmt)->mysql) { + retval = EG(uninitialized_zval_ptr); + return(retval); + } + } + ret = hnd->read_func(obj, &retval TSRMLS_CC); if (ret == SUCCESS) { /* ensure we're creating a temporary variable */ @@ -273,7 +294,7 @@ static union _zend_function *php_mysqli_constructor_get(zval *object TSRMLS_DC) { mysqli_object *obj = (mysqli_object *)zend_objects_get_address(object TSRMLS_CC); - if (obj->zo.ce != mysqli_link_class_entry && obj->zo.ce->constructor) { + if (obj->zo.ce != mysqli_link_class_entry) { return obj->zo.ce->constructor; } else { static zend_internal_function f; @@ -297,7 +318,7 @@ PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry *class_ zend_object_value retval; mysqli_object *intern; zval *tmp; - zend_class_entry *parent; + zend_class_entry *mysqli_base_class; intern = emalloc(sizeof(mysqli_object)); memset(intern, 0, sizeof(mysqli_object)); @@ -307,18 +328,21 @@ PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry *class_ intern->ptr = NULL; intern->valid = 0; intern->prop_handler = NULL; - if ((parent = class_type->parent)) + + mysqli_base_class = class_type; + while (mysqli_base_class->type != ZEND_INTERNAL_CLASS && mysqli_base_class->parent != NULL) { - zend_hash_find(&classes, parent->name, parent->name_length + 1, (void **) &intern->prop_handler); + mysqli_base_class = mysqli_base_class->parent; } - zend_hash_find(&classes, class_type->name, class_type->name_length + 1, (void **) &intern->prop_handler); + zend_hash_find(&classes, mysqli_base_class->name, mysqli_base_class->name_length + 1, + (void **) &intern->prop_handler); ALLOC_HASHTABLE(intern->zo.properties); zend_hash_init(intern->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0); zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); - retval.handle = zend_objects_store_put(intern, NULL, mysqli_objects_free_storage, NULL TSRMLS_CC); + retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t) mysqli_objects_destroy_object, (zend_objects_free_object_storage_t) mysqli_objects_free_storage, NULL TSRMLS_CC); retval.handlers = &mysqli_object_handlers; return retval; @@ -377,7 +401,6 @@ static void php_mysqli_init_globals(zend_mysqli_globals *mysqli_globals) mysqli_globals->reconnect = 0; mysqli_globals->report_mode = 0; mysqli_globals->report_ht = 0; - mysqli_globals->multi_query = 0; } /* }}} */ @@ -386,6 +409,7 @@ static void php_mysqli_init_globals(zend_mysqli_globals *mysqli_globals) PHP_MINIT_FUNCTION(mysqli) { zend_class_entry *ce; + zend_object_handlers *std_hnd = zend_get_std_object_handlers(); ZEND_INIT_MODULE_GLOBALS(mysqli, php_mysqli_init_globals, NULL); REGISTER_INI_ENTRIES(); @@ -394,7 +418,7 @@ PHP_MINIT_FUNCTION(mysqli) mysqli_object_handlers.clone_obj = NULL; mysqli_object_handlers.read_property = mysqli_read_property; mysqli_object_handlers.write_property = mysqli_write_property; - mysqli_object_handlers.get_property_ptr_ptr = NULL; + mysqli_object_handlers.get_property_ptr_ptr = std_hnd->get_property_ptr_ptr; mysqli_object_handlers.get_constructor = php_mysqli_constructor_get; zend_hash_init(&classes, 0, NULL, NULL, 1); @@ -431,6 +455,7 @@ PHP_MINIT_FUNCTION(mysqli) REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_INTERACTIVE", CLIENT_INTERACTIVE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_IGNORE_SPACE", CLIENT_IGNORE_SPACE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_NO_SCHEMA", CLIENT_NO_SCHEMA, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_FOUND_ROWS", CLIENT_FOUND_ROWS, CONST_CS | CONST_PERSISTENT); /* for mysqli_query */ REGISTER_LONG_CONSTANT("MYSQLI_STORE_RESULT", 0, CONST_CS | CONST_PERSISTENT); @@ -443,6 +468,14 @@ PHP_MINIT_FUNCTION(mysqli) /* for mysqli_stmt_set_attr */ REGISTER_LONG_CONSTANT("MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH", STMT_ATTR_UPDATE_MAX_LENGTH, CONST_CS | CONST_PERSISTENT); + +#if MYSQL_VERSION_ID > 50003 + REGISTER_LONG_CONSTANT("MYSQLI_STMT_ATTR_CURSOR_TYPE", STMT_ATTR_CURSOR_TYPE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MYSQLI_CURSOR_TYPE_NO_CURSOR", CURSOR_TYPE_NO_CURSOR, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MYSQLI_CURSOR_TYPE_READ_ONLY", CURSOR_TYPE_READ_ONLY, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MYSQLI_CURSOR_TYPE_FOR_UPDATE", CURSOR_TYPE_FOR_UPDATE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MYSQLI_CURSOR_TYPE_SCROLLABLE", CURSOR_TYPE_SCROLLABLE, CONST_CS | CONST_PERSISTENT); +#endif /* column information */ REGISTER_LONG_CONSTANT("MYSQLI_NOT_NULL_FLAG", NOT_NULL_FLAG, CONST_CS | CONST_PERSISTENT); @@ -493,6 +526,9 @@ PHP_MINIT_FUNCTION(mysqli) /* bind blob support */ REGISTER_LONG_CONSTANT("MYSQLI_NO_DATA", MYSQL_NO_DATA, CONST_CS | CONST_PERSISTENT); +#ifdef MYSQL_DATA_TRUNCATED + REGISTER_LONG_CONSTANT("MYSQLI_DATA_TRUNCATED", MYSQL_DATA_TRUNCATED, CONST_CS | CONST_PERSISTENT); +#endif /* reporting */ REGISTER_LONG_CONSTANT("MYSQLI_REPORT_INDEX", MYSQLI_REPORT_INDEX, CONST_CS | CONST_PERSISTENT); @@ -562,7 +598,7 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags { MYSQL_RES *result; zval *mysql_result; - int fetchtype; + long fetchtype; unsigned int i; MYSQL_FIELD *fields; MYSQL_ROW row; @@ -594,7 +630,7 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags } fetchtype = override_flags; } else { - fetchtype = MYSQLI_NUM; + fetchtype = MYSQLI_BOTH; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|l", &mysql_result, mysqli_result_class_entry, &fetchtype) == FAILURE) { return; } @@ -603,6 +639,11 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result"); + if ((fetchtype & MYSQLI_BOTH) == 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "The result type should be either MYSQLI_NUM, MYSQLI_ASSOC or MYSQLI_BOTH"); + RETURN_FALSE; + } + if (!(row = mysql_fetch_row(result))) { RETURN_NULL(); } @@ -747,15 +788,23 @@ if (a) {\ memset(source, 0, LOCAL_INFILE_ERROR_LEN);\ memcpy(source, dest, LOCAL_INFILE_ERROR_LEN-1); +/* {{{ void php_set_local_infile_handler_default +*/ +void php_set_local_infile_handler_default(MY_MYSQL *mysql) { + /* register internal callback functions */ + mysql_set_local_infile_handler(mysql->mysql, &php_local_infile_init, &php_local_infile_read, + &php_local_infile_end, &php_local_infile_error, (void *)mysql); + mysql->li_read = NULL; +} +/* }}} */ + /* {{{ php_local_infile_init */ int php_local_infile_init(void **ptr, const char *filename, void *userdata) { mysqli_local_infile *data; MY_MYSQL *mysql; - zval ***callback_args; - int argc = 2; - int i, rc = 0; + php_stream_context *context = NULL; TSRMLS_FETCH(); @@ -764,45 +813,28 @@ int php_local_infile_init(void **ptr, const char *filename, void *userdata) return 1; } - if (!(mysql = data->userdata = userdata)) { + if (!(mysql = (MY_MYSQL *)userdata)) { LOCAL_INFILE_ERROR_MSG(data->error_msg, ER(CR_UNKNOWN_ERROR)); return 1; } - ALLOC_CALLBACK_ARGS(callback_args, 0, argc); - - ZVAL_STRING(*callback_args[0], (char *)filename, 1); - ZVAL_STRING(*callback_args[1], "", 1); - - if (call_user_function_ex(EG(function_table), - NULL, - &mysql->callback_func[0], - &mysql->local_infile, - argc, - callback_args, - 0, - NULL TSRMLS_CC) == SUCCESS) { + /* check open_basedir */ + if (PG(open_basedir)) { + if (php_check_open_basedir_ex(filename, 0 TSRMLS_CC) == -1) { + LOCAL_INFILE_ERROR_MSG(data->error_msg, "open_basedir restriction in effect. Unable to open file"); + return 1; + } + } - /* check if user callback function returned a valid filehandle */ - convert_to_string_ex(callback_args[1]); + mysql->li_stream = php_stream_open_wrapper_ex((char *)filename, "r", 0, NULL, context); - if (Z_TYPE_P(mysql->local_infile) != IS_RESOURCE) { - if (!strlen(Z_STRVAL_P(*callback_args[1]))) { - LOCAL_INFILE_ERROR_MSG(data->error_msg, ER(CR_UNKNOWN_ERROR)); - } else { - LOCAL_INFILE_ERROR_MSG(data->error_msg, Z_STRVAL_P(*callback_args[1])); - } - rc = 1; - } else { - } - } else { - LOCAL_INFILE_ERROR_MSG(data->error_msg, "Can't execute load data local init callback function"); - rc = 1; + if (mysql->li_stream == NULL) { + return 1; } - FREE_CALLBACK_ARGS(callback_args, 0, argc); + data->userdata = mysql; - return rc; + return 0; } /* }}} */ @@ -811,7 +843,8 @@ int php_local_infile_read(void *ptr, char *buf, uint buf_len) mysqli_local_infile *data; MY_MYSQL *mysql; zval ***callback_args; - zval *retval; + zval *retval; + zval *fp; int argc = 4; int i; long rc; @@ -819,21 +852,35 @@ int php_local_infile_read(void *ptr, char *buf, uint buf_len) TSRMLS_FETCH(); data= (mysqli_local_infile *)ptr; - mysql = data->userdata; + /* default processing */ + if (!mysql->li_read) { + int count; + + count = (int)php_stream_read(mysql->li_stream, buf, buf_len); + + if (count < 0) { + LOCAL_INFILE_ERROR_MSG(data->error_msg, ER(2)); + } + + return count; + } + ALLOC_CALLBACK_ARGS(callback_args, 1, argc); /* set parameters: filepointer, buffer, buffer_len, errormsg */ - callback_args[0] = &mysql->local_infile; + MAKE_STD_ZVAL(fp); + php_stream_to_zval(mysql->li_stream, fp); + callback_args[0] = &fp; ZVAL_STRING(*callback_args[1], "", 1); ZVAL_LONG(*callback_args[2], buf_len); ZVAL_STRING(*callback_args[3], "", 1); if (call_user_function_ex(EG(function_table), NULL, - &mysql->callback_func[1], + mysql->li_read, &retval, argc, callback_args, @@ -861,6 +908,7 @@ int php_local_infile_read(void *ptr, char *buf, uint buf_len) } FREE_CALLBACK_ARGS(callback_args, 1, argc); + efree(fp); return rc; } @@ -869,6 +917,7 @@ int php_local_infile_read(void *ptr, char *buf, uint buf_len) int php_local_infile_error(void *ptr, char *error_msg, uint error_msg_len) { mysqli_local_infile *data = (mysqli_local_infile *) ptr; + if (data) { strcpy(error_msg, data->error_msg); return 2000; @@ -884,42 +933,17 @@ void php_local_infile_end(void *ptr) { mysqli_local_infile *data; MY_MYSQL *mysql; - zval ***callback_args; - zval *retval; - int argc = 1; - int i; TSRMLS_FETCH(); data= (mysqli_local_infile *)ptr; - mysql = data->userdata; - - ALLOC_CALLBACK_ARGS(callback_args, 1, argc); - - /* set parameters: filepointer, buffer, buffer_len, errormsg */ - - callback_args[0] = &mysql->local_infile; - - call_user_function_ex(EG(function_table), - NULL, - &mysql->callback_func[2], - &retval, - argc, - callback_args, - 0, - NULL TSRMLS_CC); - - if (retval) { - zval_ptr_dtor(&retval); - } - - if (mysql->local_infile) { - zval_ptr_dtor(&mysql->local_infile); + if (!(mysql = data->userdata)) { + return; } - FREE_CALLBACK_ARGS(callback_args, 1, argc); -// efree(data); + php_stream_close(mysql->li_stream); + return; } /* }}} */ diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index 231d231109a3..78844c78ab56 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -44,6 +44,9 @@ PHP_FUNCTION(mysqli_affected_rows) MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link"); rc = mysql_affected_rows(mysql->mysql); + if (rc == (my_ulonglong) -1) { + RETURN_LONG(-1); + } MYSQLI_RETURN_LONG_LONG(rc); } /* }}} */ @@ -54,7 +57,6 @@ PHP_FUNCTION(mysqli_autocommit) { MY_MYSQL *mysql; zval *mysql_link; - unsigned long rc; unsigned long automode; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ob", &mysql_link, mysqli_link_class_entry, &automode) == FAILURE) { @@ -62,9 +64,10 @@ PHP_FUNCTION(mysqli_autocommit) } MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link"); - rc = (long) mysql_autocommit(mysql->mysql, automode); - - RETURN_BOOL(rc); + if (mysql_autocommit(mysql->mysql, automode)) { + RETURN_FALSE; + } + RETURN_TRUE; } /* }}} */ @@ -106,12 +109,13 @@ PHP_FUNCTION(mysqli_stmt_bind_param) start = 1; } - if (strlen(types) != argc - start) { + if (typelen != argc - start) { /* number of bind variables doesn't match number of elements in type definition string */ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of elements in type definition string doesn't match number of bind variables"); + RETURN_FALSE; } - if (argc - start != stmt->stmt->param_count) { + if (typelen != stmt->stmt->param_count) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of variables doesn't match number of parameters in prepared statement"); RETURN_FALSE; } @@ -217,6 +221,16 @@ PHP_FUNCTION(mysqli_stmt_bind_result) zval *mysql_stmt; MYSQL_BIND *bind; + if (getThis()) { + start = 0; + } + + if (zend_parse_method_parameters((getThis()) ? 0:1 TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) { + return; + } + + MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt"); + if (argc < (getThis() ? 1 : 2)) { WRONG_PARAM_COUNT; } @@ -228,20 +242,11 @@ PHP_FUNCTION(mysqli_stmt_bind_result) WRONG_PARAM_COUNT; } - if (getThis()) { - start = 0; - } - - if (zend_parse_method_parameters((getThis()) ? 0:1 TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) { - return; - } - - MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt"); var_cnt = argc - start; if (var_cnt != mysql_stmt_field_count(stmt->stmt)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of bind variables doesn't match number of fields in prepared statmement."); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of bind variables doesn't match number of fields in prepared statement."); efree(args); RETURN_FALSE; } @@ -258,7 +263,6 @@ PHP_FUNCTION(mysqli_stmt_bind_result) for (i=start; i < var_cnt + start ; i++) { ofs = i - start; stmt->result.is_null[ofs] = 0; - col_type = (stmt->stmt->fields) ? stmt->stmt->fields[ofs].type : MYSQL_TYPE_STRING; switch (col_type) { @@ -298,7 +302,14 @@ PHP_FUNCTION(mysqli_stmt_bind_result) bind[ofs].is_null = &stmt->result.is_null[ofs]; bind[ofs].buffer_length = stmt->result.buf[ofs].buflen; break; - + case MYSQL_TYPE_NULL: + stmt->result.buf[ofs].type = IS_NULL; + stmt->result.buf[ofs].buflen = 0; + bind[ofs].buffer_type = MYSQL_TYPE_NULL; + bind[ofs].buffer = 0; + bind[ofs].is_null = &stmt->result.is_null[ofs]; + bind[ofs].buffer_length = 0; + break; case MYSQL_TYPE_DATE: case MYSQL_TYPE_TIME: case MYSQL_TYPE_DATETIME: @@ -308,9 +319,24 @@ PHP_FUNCTION(mysqli_stmt_bind_result) case MYSQL_TYPE_BLOB: case MYSQL_TYPE_TIMESTAMP: case MYSQL_TYPE_DECIMAL: +#ifdef FIELD_TYPE_NEWDECIMAL + case MYSQL_TYPE_NEWDECIMAL: +#endif stmt->result.buf[ofs].type = IS_STRING; - stmt->result.buf[ofs].buflen = - (stmt->stmt->fields) ? (stmt->stmt->fields[ofs].length) ? stmt->stmt->fields[ofs].length + 1: 256: 256; + /* + If the user has called $stmt->store_result() then we have asked + max_length to be updated. this is done only for BLOBS because we don't want to allocate + big chunkgs of memory 2^16 or 2^24 + */ + if (stmt->stmt->fields[ofs].max_length == 0) { + stmt->result.buf[ofs].buflen = + (stmt->stmt->fields) ? (stmt->stmt->fields[ofs].length) ? stmt->stmt->fields[ofs].length + 1: 256: 256; + } else { + /* + the user has called store_result(). if he does not there is no way to determine the + */ + stmt->result.buf[ofs].buflen = stmt->stmt->fields[ofs].max_length; + } stmt->result.buf[ofs].val = (char *)emalloc(stmt->result.buf[ofs].buflen); bind[ofs].buffer_type = MYSQL_TYPE_STRING; bind[ofs].buffer = stmt->result.buf[ofs].val; @@ -406,8 +432,10 @@ PHP_FUNCTION(mysqli_close) MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link"); mysql_close(mysql->mysql); - + php_clear_mysql(mysql); + efree(mysql); MYSQLI_CLEAR_RESOURCE(&mysql_link); + RETURN_TRUE; } /* }}} */ @@ -418,14 +446,15 @@ PHP_FUNCTION(mysqli_commit) { MY_MYSQL *mysql; zval *mysql_link; - ulong rc; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { return; } MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link"); - rc = mysql_commit(mysql->mysql); - RETURN_BOOL(rc); + if (mysql_commit(mysql->mysql)) { + RETURN_FALSE; + } + RETURN_TRUE; } /* }}} */ @@ -540,25 +569,25 @@ PHP_FUNCTION(mysqli_stmt_execute) for (i = 0; i < stmt->param.var_cnt; i++) { if (stmt->param.vars[i]) { - stmt->param.is_null[i] = (stmt->param.vars[i]->type == IS_NULL); - - switch (stmt->stmt->params[i].buffer_type) { - case MYSQL_TYPE_VAR_STRING: - convert_to_string_ex(&stmt->param.vars[i]); - stmt->stmt->params[i].buffer = Z_STRVAL_PP(&stmt->param.vars[i]); - stmt->stmt->params[i].buffer_length = strlen(Z_STRVAL_PP(&stmt->param.vars[i])); - break; - case MYSQL_TYPE_DOUBLE: - convert_to_double_ex(&stmt->param.vars[i]); - stmt->stmt->params[i].buffer = (gptr)&Z_LVAL_PP(&stmt->param.vars[i]); - break; - case MYSQL_TYPE_LONG: - convert_to_long_ex(&stmt->param.vars[i]); - stmt->stmt->params[i].buffer = (gptr)&Z_LVAL_PP(&stmt->param.vars[i]); - break; - default: - break; - } + if ( !(stmt->param.is_null[i] = (stmt->param.vars[i]->type == IS_NULL)) ) { + switch (stmt->stmt->params[i].buffer_type) { + case MYSQL_TYPE_VAR_STRING: + convert_to_string_ex(&stmt->param.vars[i]); + stmt->stmt->params[i].buffer = Z_STRVAL_PP(&stmt->param.vars[i]); + stmt->stmt->params[i].buffer_length = strlen(Z_STRVAL_PP(&stmt->param.vars[i])); + break; + case MYSQL_TYPE_DOUBLE: + convert_to_double_ex(&stmt->param.vars[i]); + stmt->stmt->params[i].buffer = (gptr)&Z_LVAL_PP(&stmt->param.vars[i]); + break; + case MYSQL_TYPE_LONG: + convert_to_long_ex(&stmt->param.vars[i]); + stmt->stmt->params[i].buffer = (gptr)&Z_LVAL_PP(&stmt->param.vars[i]); + break; + default: + break; + } + } } } if (mysql_stmt_execute(stmt->stmt)) { @@ -581,7 +610,7 @@ PHP_FUNCTION(mysqli_stmt_fetch) zval *mysql_stmt; unsigned int i; ulong ret; - long lval; + int lval; double dval; my_ulonglong llval; @@ -599,19 +628,24 @@ PHP_FUNCTION(mysqli_stmt_fetch) memset(stmt->result.buf[i].val, 0, stmt->result.buf[i].buflen); } } - if (!(ret = mysql_stmt_fetch(stmt->stmt))) { + ret = mysql_stmt_fetch(stmt->stmt); +#ifdef MYSQL_DATA_TRUNCATED + if (!ret || ret == MYSQL_DATA_TRUNCATED) { +#else + if (!ret) { +#endif for (i = 0; i < stmt->result.var_cnt; i++) { if (stmt->result.vars[i]->type == IS_STRING && stmt->result.vars[i]->value.str.len) { - efree(stmt->result.vars[i]->value.str.val); + efree(stmt->result.vars[i]->value.str.val); } if (!stmt->result.is_null[i]) { switch (stmt->result.buf[i].type) { case IS_LONG: - memcpy(&lval, stmt->result.buf[i].val, sizeof(long)); + memcpy(&lval, stmt->result.buf[i].val, sizeof(lval)); ZVAL_LONG(stmt->result.vars[i], lval); break; case IS_DOUBLE: - memcpy(&dval, stmt->result.buf[i].val, sizeof(double)); + memcpy(&dval, stmt->result.buf[i].val, sizeof(dval)); ZVAL_DOUBLE(stmt->result.vars[i], dval); break; case IS_STRING: @@ -629,7 +663,7 @@ PHP_FUNCTION(mysqli_stmt_fetch) ZVAL_LONG(stmt->result.vars[i], llval); } } else { - ZVAL_STRING(stmt->result.vars[i], stmt->result.buf[i].val, 1); + ZVAL_STRINGL(stmt->result.vars[i], stmt->result.buf[i].val, stmt->result.buf[i].buflen, 1); } break; default: @@ -683,6 +717,8 @@ PHP_FUNCTION(mysqli_fetch_field) add_property_string(return_value, "orgtable",(field->org_table ? field->org_table : ""), 1); add_property_string(return_value, "def",(field->def ? field->def : ""), 1); add_property_long(return_value, "max_length", field->max_length); + add_property_long(return_value, "length", field->length); + add_property_long(return_value, "charsetnr", field->charsetnr); add_property_long(return_value, "flags", field->flags); add_property_long(return_value, "type", field->type); add_property_long(return_value, "decimals", field->decimals); @@ -725,6 +761,8 @@ PHP_FUNCTION(mysqli_fetch_fields) add_property_string(obj, "orgtable",(field->org_table ? field->org_table : ""), 1); add_property_string(obj, "def",(field->def ? field->def : ""), 1); add_property_long(obj, "max_length", field->max_length); + add_property_long(obj, "length", field->length); + add_property_long(obj, "charsetnr", field->charsetnr); add_property_long(obj, "flags", field->flags); add_property_long(obj, "type", field->type); add_property_long(obj, "decimals", field->decimals); @@ -741,7 +779,7 @@ PHP_FUNCTION(mysqli_fetch_field_direct) MYSQL_RES *result; zval *mysql_result; MYSQL_FIELD *field; - int offset; + long offset; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &offset) == FAILURE) { return; @@ -749,6 +787,11 @@ PHP_FUNCTION(mysqli_fetch_field_direct) MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result"); + if (offset < 0 || offset >= mysql_num_fields(result)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field offset is invalid for resultset"); + RETURN_FALSE; + } + if (!(field = mysql_fetch_field_direct(result,offset))) { RETURN_FALSE; } @@ -826,7 +869,7 @@ PHP_FUNCTION(mysqli_field_seek) { MYSQL_RES *result; zval *mysql_result; - unsigned int fieldnr; + unsigned long fieldnr; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &fieldnr) == FAILURE) { return; @@ -906,7 +949,7 @@ PHP_FUNCTION(mysqli_get_host_info) } MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link"); - RETURN_STRING((mysql->mysql->host_info) ? mysql->mysql->host_info : empty_string, 1); + RETURN_STRING((mysql->mysql->host_info) ? mysql->mysql->host_info : "", 1); } /* }}} */ @@ -971,7 +1014,7 @@ PHP_FUNCTION(mysqli_info) } MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link"); - RETURN_STRING((mysql->mysql->info) ? mysql->mysql->info : empty_string, 1); + RETURN_STRING((mysql->mysql->info) ? mysql->mysql->info : "", 1); } /* }}} */ @@ -979,16 +1022,23 @@ PHP_FUNCTION(mysqli_info) Initialize mysqli and return a resource for use with mysql_real_connect */ PHP_FUNCTION(mysqli_init) { - MY_MYSQL *mysql = (MY_MYSQL *)calloc(1, sizeof(MY_MYSQL)); - - MYSQLI_RESOURCE *mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE)); + MYSQLI_RESOURCE *mysqli_resource; + MY_MYSQL *mysql = (MY_MYSQL *)ecalloc(1, sizeof(MY_MYSQL)); if (!(mysql->mysql = mysql_init(NULL))) { efree(mysql); RETURN_FALSE; } + + mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE)); mysqli_resource->ptr = (void *)mysql; - MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_link_class_entry); + + if (!getThis()) { + MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_link_class_entry); + } else { + ((mysqli_object *) zend_object_store_get_object(getThis() TSRMLS_CC))->ptr = mysqli_resource; + ((mysqli_object *) zend_object_store_get_object(getThis() TSRMLS_CC))->valid = 1; + } } /* }}} */ @@ -1015,7 +1065,7 @@ PHP_FUNCTION(mysqli_kill) { MY_MYSQL *mysql; zval *mysql_link; - int processid; + unsigned long processid; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_link, mysqli_link_class_entry, &processid) == FAILURE) { return; @@ -1030,13 +1080,12 @@ PHP_FUNCTION(mysqli_kill) } /* }}} */ -/* {{{ proto mysqli_set_local_infile_default(object link) +/* {{{ proto void mysqli_set_local_infile_default(object link) unsets user defined handler for load local infile command */ PHP_FUNCTION(mysqli_set_local_infile_default) { MY_MYSQL *mysql; zval *mysql_link; - int i; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { return; @@ -1044,52 +1093,41 @@ PHP_FUNCTION(mysqli_set_local_infile_default) MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link"); - for (i=0; i < 3; i++) { - if (&mysql->callback_func[i]) { - zval_dtor(&mysql->callback_func[i]); - } + if (mysql->li_read) { + efree(Z_STRVAL_P(mysql->li_read)); + zval_dtor(mysql->li_read); + mysql->li_read = NULL; } - - mysql_set_local_infile_default(mysql->mysql); } /* }}} */ -/* {{{ proto bool mysqli_set_local_infile_handler(object link, callback init_func, - callback read_func, callback end_func) +/* {{{ proto bool mysqli_set_local_infile_handler(object link, callback read_func) Set callback functions for LOAD DATA LOCAL INFILE */ PHP_FUNCTION(mysqli_set_local_infile_handler) { MY_MYSQL *mysql; zval *mysql_link; char *callback_name; - zval *callback_func[4]; - int i; + zval *callback_func; - if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ozzzz", &mysql_link, mysqli_link_class_entry, - &callback_func[0], &callback_func[1], &callback_func[2], &callback_func[3]) == FAILURE) { + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oz", &mysql_link, mysqli_link_class_entry, + &callback_func) == FAILURE) { return; } MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link"); - /* check callback functions */ - for (i=0; i < 3; i++) { - if (!zend_is_callable(callback_func[i], 0, &callback_name)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not a valid callback function %s", callback_name); - efree(callback_name); - RETURN_FALSE; - } + /* check callback function */ + if (!zend_is_callable(callback_func, 0, &callback_name)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not a valid callback function %s", callback_name); efree(callback_name); + RETURN_FALSE; } + efree(callback_name); - /* save callback functions */ - for (i=0; i < 3; i++) { - ZVAL_STRING(&mysql->callback_func[i], callback_func[i]->value.str.val, 1); - } - - /* register internal callback functions */ - mysql_set_local_infile_handler(mysql->mysql, &php_local_infile_init, &php_local_infile_read, - &php_local_infile_end, &php_local_infile_error, (void *)mysql); + /* save callback function */ + ALLOC_ZVAL(mysql->li_read); + ZVAL_STRING(mysql->li_read, callback_func->value.str.val, 1); } /* }}} */ @@ -1239,12 +1277,30 @@ PHP_FUNCTION(mysqli_prepare) } MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link"); + if (mysql->mysql->status == MYSQL_STATUS_GET_RESULT) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "All data must be fetched before a new preparing of a statement takes place"); + RETURN_FALSE; + } stmt = (MY_STMT *)ecalloc(1,sizeof(MY_STMT)); if ((stmt->stmt = mysql_stmt_init(mysql->mysql))) { if (mysql_stmt_prepare(stmt->stmt, query, query_len)) { + char last_error[MYSQL_ERRMSG_SIZE]; + char sqlstate[SQLSTATE_LENGTH+1]; + unsigned int last_errno; + + /* mysql_stmt_close clears errors, so we have to store them temporarily */ + last_errno = stmt->stmt->last_errno; + memcpy(last_error, stmt->stmt->last_error, MYSQL_ERRMSG_SIZE); + memcpy(sqlstate, mysql->mysql->net.sqlstate, SQLSTATE_LENGTH+1); + mysql_stmt_close(stmt->stmt); stmt->stmt = NULL; + + /* restore error messages */ + mysql->mysql->net.last_errno = last_errno; + memcpy(mysql->mysql->net.last_error, last_error, MYSQL_ERRMSG_SIZE); + memcpy(mysql->mysql->net.sqlstate, sqlstate, SQLSTATE_LENGTH+1); } } @@ -1268,8 +1324,8 @@ PHP_FUNCTION(mysqli_real_connect) { MY_MYSQL *mysql; char *hostname = NULL, *username=NULL, *passwd=NULL, *dbname=NULL, *socket=NULL; - unsigned int hostname_len, username_len, passwd_len, dbname_len, socket_len; - unsigned int port=0, flags=0; + unsigned int hostname_len = 0, username_len = 0, passwd_len = 0, dbname_len = 0, socket_len = 0; + unsigned long port=0, flags=0; zval *mysql_link; zval *object = getThis(); @@ -1318,6 +1374,9 @@ PHP_FUNCTION(mysqli_real_connect) php_mysqli_set_error(mysql_errno(mysql->mysql), (char *)mysql_error(mysql->mysql) TSRMLS_CC); mysql->mysql->reconnect = MyG(reconnect); + + /* set our own local_infile handler */ + php_set_local_infile_handler_default(mysql); if (object) { ((mysqli_object *) zend_object_store_get_object(object TSRMLS_CC))->valid = 1; @@ -1391,7 +1450,10 @@ PHP_FUNCTION(mysqli_rollback) } MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link"); - RETURN_BOOL(mysql_rollback(mysql->mysql)); + if (mysql_rollback(mysql->mysql)) { + RETURN_FALSE; + } + RETURN_TRUE; } /* }}} */ @@ -1402,7 +1464,8 @@ PHP_FUNCTION(mysqli_stmt_send_long_data) MY_STMT *stmt; zval *mysql_stmt; char *data; - long param_nr, data_len; + long param_nr; + int data_len; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ols", &mysql_stmt, mysqli_stmt_class_entry, ¶m_nr, &data, &data_len) == FAILURE) { @@ -1469,6 +1532,9 @@ PHP_FUNCTION(mysqli_stmt_affected_rows) MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt"); rc = mysql_stmt_affected_rows(stmt->stmt); + if (rc == (my_ulonglong) -1) { + RETURN_LONG(-1); + } MYSQLI_RETURN_LONG_LONG(rc) } /* }}} */ @@ -1504,6 +1570,10 @@ PHP_FUNCTION(mysqli_stmt_data_seek) if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_stmt, mysqli_stmt_class_entry, &offset) == FAILURE) { return; } + if (offset < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset must be positive"); + RETURN_FALSE; + } MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt"); @@ -1715,12 +1785,12 @@ PHP_FUNCTION(mysqli_stmt_attr_set) ulong attr; int rc; - if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Olb", &mysql_stmt, mysqli_stmt_class_entry, &attr, &mode) == FAILURE) { + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oll", &mysql_stmt, mysqli_stmt_class_entry, &attr, &mode) == FAILURE) { return; } MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt"); - if (rc = mysql_stmt_attr_set(stmt->stmt, attr, (void *)&mode)) { + if ((rc = mysql_stmt_attr_set(stmt->stmt, attr, (void *)&mode))) { RETURN_FALSE; } RETURN_TRUE; @@ -1742,7 +1812,7 @@ PHP_FUNCTION(mysqli_stmt_attr_get) } MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt"); - if (rc = mysql_stmt_attr_get(stmt->stmt, attr, &value)) { + if ((rc = mysql_stmt_attr_get(stmt->stmt, attr, &value))) { RETURN_FALSE; } RETURN_LONG(value); @@ -1863,11 +1933,27 @@ PHP_FUNCTION(mysqli_stmt_store_result) { MY_STMT *stmt; zval *mysql_stmt; - + int i; + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) { return; } MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt"); + + /* + If the user wants to store the data and we have BLOBs/TEXTs we try to allocate + not the maximal length of the type (which is 16MB even for LONGBLOB) but + the maximal length of the field in the result set. If he/she has quite big + BLOB/TEXT columns after calling store_result() the memory usage of PHP will + double - but this is a known problem of the simple MySQL API ;) + */ + for (i = mysql_stmt_field_count(stmt->stmt) - 1; i >=0; --i) { + if (stmt->stmt->fields && stmt->stmt->fields[i].type == MYSQL_TYPE_BLOB) { + my_bool tmp=1; + mysql_stmt_attr_set(stmt->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &tmp); + break; + } + } if (mysql_stmt_store_result(stmt->stmt)){ MYSQLI_REPORT_STMT_ERROR(stmt->stmt); diff --git a/ext/mysqli/mysqli_fe.c b/ext/mysqli/mysqli_fe.c index 2510e86432b3..b9d3470c513e 100644 --- a/ext/mysqli/mysqli_fe.c +++ b/ext/mysqli/mysqli_fe.c @@ -117,6 +117,9 @@ function_entry mysqli_functions[] = { PHP_FE(mysqli_rpl_probe, NULL) PHP_FE(mysqli_rpl_query_type, NULL) PHP_FE(mysqli_select_db, NULL) +#ifdef HAVE_MYSQLI_SET_CHARSET + PHP_FE(mysqli_set_charset, NULL) +#endif PHP_FE(mysqli_stmt_attr_get, NULL) PHP_FE(mysqli_stmt_attr_set, NULL) PHP_FE(mysqli_stmt_field_count, NULL) @@ -203,6 +206,7 @@ function_entry mysqli_link_methods[] = { PHP_FALIAS(master_query,mysqli_master_query,NULL) PHP_FALIAS(multi_query,mysqli_multi_query,NULL) PHP_FALIAS(more_results,mysqli_more_results, NULL) + PHP_FALIAS(mysqli, mysqli_connect, NULL) PHP_FALIAS(next_result, mysqli_next_result, NULL) PHP_FALIAS(options,mysqli_options,NULL) PHP_FALIAS(ping,mysqli_ping,NULL) @@ -217,6 +221,9 @@ function_entry mysqli_link_methods[] = { PHP_FALIAS(rpl_probe,mysqli_rpl_probe,NULL) PHP_FALIAS(rpl_query_type,mysqli_rpl_query_type,NULL) PHP_FALIAS(select_db,mysqli_select_db,NULL) +#ifdef HAVE_MYSQLI_SET_CHARSET + PHP_FALIAS(set_charset,mysqli_set_charset,NULL) +#endif PHP_FALIAS(set_opt, mysqli_options,NULL) PHP_FALIAS(slave_query,mysqli_slave_query,NULL) PHP_FALIAS(ssl_set,mysqli_ssl_set,NULL) diff --git a/ext/mysqli/mysqli_nonapi.c b/ext/mysqli/mysqli_nonapi.c index 053e1421e8cc..3c43fd071084 100644 --- a/ext/mysqli/mysqli_nonapi.c +++ b/ext/mysqli/mysqli_nonapi.c @@ -37,10 +37,9 @@ PHP_FUNCTION(mysqli_connect) MYSQLI_RESOURCE *mysqli_resource; zval *object = getThis(); char *hostname = NULL, *username=NULL, *passwd=NULL, *dbname=NULL, *socket=NULL; - unsigned int hostname_len, username_len, passwd_len, dbname_len, socket_len; + unsigned int hostname_len = 0, username_len = 0, passwd_len = 0, dbname_len = 0, socket_len = 0; long port=0; - if (getThis() && !ZEND_NUM_ARGS()) { RETURN_NULL(); } @@ -50,6 +49,10 @@ PHP_FUNCTION(mysqli_connect) return; } + if (!socket_len) { + socket = NULL; + } + /* TODO: safe mode handling */ if (PG(sql_safe_mode)){ } else { @@ -64,14 +67,18 @@ PHP_FUNCTION(mysqli_connect) } } - mysql = (MY_MYSQL *)calloc(1, sizeof(MY_MYSQL)); + mysql = (MY_MYSQL *)ecalloc(1, sizeof(MY_MYSQL)); if (!(mysql->mysql = mysql_init(NULL))) { efree(mysql); RETURN_FALSE; } - if (mysql_real_connect(mysql->mysql,hostname,username,passwd,dbname,port,socket,0) == NULL) { + if (!socket) { + socket = MyG(default_socket); + } + + if (mysql_real_connect(mysql->mysql,hostname,username,passwd,dbname,port,socket,CLIENT_MULTI_RESULTS) == NULL) { /* Save error messages */ MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql); @@ -82,6 +89,7 @@ PHP_FUNCTION(mysqli_connect) } /* free mysql structure */ mysql_close(mysql->mysql); + efree(mysql); RETURN_FALSE; } @@ -90,6 +98,9 @@ PHP_FUNCTION(mysqli_connect) mysql->mysql->reconnect = MyG(reconnect); + /* set our own local_infile handler */ + php_set_local_infile_handler_default(mysql); + mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE)); mysqli_resource->ptr = (void *)mysql; @@ -122,7 +133,7 @@ PHP_FUNCTION(mysqli_embedded_connect) return; } - mysql = (MY_MYSQL *) calloc(1, sizeof(MY_MYSQL)); + mysql = (MY_MYSQL *) ecalloc(1, sizeof(MY_MYSQL)); if (!(mysql = mysql_init(NULL))) { efree(mysql); @@ -207,7 +218,7 @@ PHP_FUNCTION(mysqli_multi_query) MY_MYSQL *mysql; zval *mysql_link; char *query = NULL; - unsigned int query_len; + unsigned long query_len; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) { return; @@ -216,8 +227,23 @@ PHP_FUNCTION(mysqli_multi_query) MYSQLI_ENABLE_MQ; if (mysql_real_query(mysql->mysql, query, query_len)) { - MYSQLI_DISABLE_MQ; + char s_error[MYSQL_ERRMSG_SIZE], s_sqlstate[SQLSTATE_LENGTH+1]; + unsigned int s_errno; MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql); + + /* we have to save error information, cause + MYSQLI_DISABLE_MQ will reset error information */ + strcpy(s_error, mysql_error(mysql->mysql)); + strcpy(s_sqlstate, mysql_sqlstate(mysql->mysql)); + s_errno = mysql_errno(mysql->mysql); + + MYSQLI_DISABLE_MQ; + + /* restore error information */ + strcpy(mysql->mysql->net.last_error, s_error); + strcpy(mysql->mysql->net.sqlstate, s_sqlstate); + mysql->mysql->net.last_errno = s_errno; + RETURN_FALSE; } RETURN_TRUE; @@ -233,11 +259,20 @@ PHP_FUNCTION(mysqli_query) MYSQL_RES *result; char *query = NULL; unsigned int query_len; - unsigned int resultmode = 0; + unsigned long resultmode = MYSQLI_STORE_RESULT; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|l", &mysql_link, mysqli_link_class_entry, &query, &query_len, &resultmode) == FAILURE) { return; } + if (!query_len) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty query"); + RETURN_FALSE; + } + if (resultmode != MYSQLI_USE_RESULT && resultmode != MYSQLI_STORE_RESULT) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for resultmode"); + RETURN_FALSE; + } + MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL*, &mysql_link, "mysqli_link"); MYSQLI_DISABLE_MQ; @@ -247,8 +282,8 @@ PHP_FUNCTION(mysqli_query) RETURN_FALSE; } - if (!mysql_field_count(mysql->mysql)) { + /* no result set - not a SELECT */ if (MyG(report_mode) & MYSQLI_REPORT_INDEX) { php_mysqli_report_index(query, mysql->mysql->server_status TSRMLS_CC); } @@ -271,6 +306,30 @@ PHP_FUNCTION(mysqli_query) } /* }}} */ +#ifdef HAVE_MYSQLI_SET_CHARSET +/* {{{ proto bool mysqli_set_charset(object link, string csname) + sets client character set */ +PHP_FUNCTION(mysqli_set_charset) +{ + MY_MYSQL *mysql; + zval *mysql_link; + char *cs_name = NULL; + unsigned int len; + + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &mysql_link, mysqli_link_class_entry, &cs_name, &len) == FAILURE) { + return; + } + MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL*, &mysql_link, "mysqli_link"); + + if (mysql_set_character_set(mysql->mysql, cs_name)) + { + RETURN_FALSE; + } + RETURN_TRUE; +} +/* }}} */ +#endif + /* * Local variables: * tab-width: 4 diff --git a/ext/mysqli/mysqli_prop.c b/ext/mysqli/mysqli_prop.c index c9d3f8d8ecbf..aace2c48494d 100644 --- a/ext/mysqli/mysqli_prop.c +++ b/ext/mysqli/mysqli_prop.c @@ -29,21 +29,38 @@ #include "ext/standard/info.h" #include "php_mysqli.h" +#define CHECK_OBJECT() \ + if (!obj->valid) { \ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Property access is not allowed yet. Call the default constructor of the object first"); \ + ZVAL_NULL(*retval); \ + return SUCCESS; \ + } \ + + + #define MYSQLI_GET_MYSQL() \ -MYSQL *p = (MYSQL *)((MY_MYSQL *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr)->mysql; +MYSQL *p; \ +ALLOC_ZVAL(*retval);\ +CHECK_OBJECT(); \ +p = (MYSQL *)((MY_MYSQL *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr)->mysql; #define MYSQLI_GET_RESULT() \ -MYSQL_RES *p = (MYSQL_RES *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr +MYSQL_RES *p; \ +ALLOC_ZVAL(*retval);\ +CHECK_OBJECT(); \ +p = (MYSQL_RES *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr #define MYSQLI_GET_STMT() \ -MYSQL_STMT *p = (MYSQL_STMT *)((MY_STMT *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr)->stmt +MYSQL_STMT *p; \ +ALLOC_ZVAL(*retval);\ +CHECK_OBJECT(); \ +p = (MYSQL_STMT *)((MY_STMT *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr)->stmt #define MYSQLI_MAP_PROPERTY_FUNC_LONG( __func, __int_func, __get_type, __ret_type)\ -int __func(mysqli_object *obj, zval **retval TSRMLS_DC) \ +static int __func(mysqli_object *obj, zval **retval TSRMLS_DC) \ {\ __ret_type l;\ __get_type;\ - ALLOC_ZVAL(*retval);\ if (!p) {\ ZVAL_NULL(*retval);\ } else {\ @@ -60,11 +77,10 @@ int __func(mysqli_object *obj, zval **retval TSRMLS_DC) \ } #define MYSQLI_MAP_PROPERTY_FUNC_STRING(__func, __int_func, __get_type)\ -int __func(mysqli_object *obj, zval **retval TSRMLS_DC)\ +static int __func(mysqli_object *obj, zval **retval TSRMLS_DC)\ {\ char *c;\ __get_type;\ - ALLOC_ZVAL(*retval);\ if (!p) {\ ZVAL_NULL(*retval);\ } else {\ @@ -79,29 +95,25 @@ int __func(mysqli_object *obj, zval **retval TSRMLS_DC)\ } /* {{{ property link_client_version_read */ -int link_client_version_read(mysqli_object *obj, zval **retval TSRMLS_DC) +static int link_client_version_read(mysqli_object *obj, zval **retval TSRMLS_DC) { ALLOC_ZVAL(*retval); - ZVAL_STRING(*retval, MYSQL_SERVER_VERSION, 1); + ZVAL_LONG(*retval, MYSQL_VERSION_ID); return SUCCESS; } /* }}} */ -/* {{{ property link_test_read */ -int link_test_read(mysqli_object *obj, zval **retval TSRMLS_DC) +/* {{{ property link_client_info_read */ +static int link_client_info_read(mysqli_object *obj, zval **retval TSRMLS_DC) { - long i; ALLOC_ZVAL(*retval); - array_init(*retval); - - for (i=0; i < 10; i++) - add_index_long(*retval, i, i + 10); + ZVAL_STRING(*retval, MYSQL_SERVER_VERSION, 1); return SUCCESS; } -/*i }}} */ +/* }}} */ /* {{{ property link_connect_errno_read */ -int link_connect_errno_read(mysqli_object *obj, zval **retval TSRMLS_DC) +static int link_connect_errno_read(mysqli_object *obj, zval **retval TSRMLS_DC) { ALLOC_ZVAL(*retval); ZVAL_LONG(*retval, (long)MyG(error_no)); @@ -110,7 +122,7 @@ int link_connect_errno_read(mysqli_object *obj, zval **retval TSRMLS_DC) /* }}} */ /* {{{ property link_connect_error_read */ -int link_connect_error_read(mysqli_object *obj, zval **retval TSRMLS_DC) +static int link_connect_error_read(mysqli_object *obj, zval **retval TSRMLS_DC) { ALLOC_ZVAL(*retval); ZVAL_STRING(*retval, MyG(error_msg), 1); @@ -118,9 +130,36 @@ int link_connect_error_read(mysqli_object *obj, zval **retval TSRMLS_DC) } /* }}} */ +/* {{{ property link_affected_rows_read */ +static int link_affected_rows_read(mysqli_object *obj, zval **retval TSRMLS_DC) +{ + MY_MYSQL *mysql; + my_ulonglong rc; + + ALLOC_ZVAL(*retval); + CHECK_OBJECT(); + + mysql = (MY_MYSQL *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr; + rc = mysql_affected_rows(mysql->mysql); + + if (rc == (my_ulonglong)-1) { + ZVAL_LONG(*retval, -1); + return SUCCESS; + } + + if (rc < LONG_MAX) { + ZVAL_LONG(*retval, rc); + } else { + char ret[40]; + sprintf(ret, "%llu", (my_ulonglong) rc); + ZVAL_STRING(*retval, ret, 1); + } + + return SUCCESS; +} +/* }}} */ /* link properties */ -MYSQLI_MAP_PROPERTY_FUNC_LONG(link_affected_rows_read, mysql_affected_rows, MYSQLI_GET_MYSQL(), my_ulonglong); MYSQLI_MAP_PROPERTY_FUNC_LONG(link_errno_read, mysql_errno, MYSQLI_GET_MYSQL(), ulong); MYSQLI_MAP_PROPERTY_FUNC_STRING(link_error_read, mysql_error, MYSQLI_GET_MYSQL()); MYSQLI_MAP_PROPERTY_FUNC_LONG(link_field_count_read, mysql_field_count, MYSQLI_GET_MYSQL(), ulong); @@ -136,11 +175,15 @@ MYSQLI_MAP_PROPERTY_FUNC_LONG(link_warning_count_read, mysql_warning_count, MYSQ /* result properties */ /* {{{ property result_type_read */ -int result_type_read(mysqli_object *obj, zval **retval TSRMLS_DC) +static int result_type_read(mysqli_object *obj, zval **retval TSRMLS_DC) { - MYSQL_RES *p = (MYSQL_RES *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr; + MYSQL_RES *p; + + ALLOC_ZVAL(*retval); + CHECK_OBJECT(); + + p = (MYSQL_RES *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr; - ALLOC_ZVAL(*retval); if (!p) { ZVAL_NULL(*retval); } else { @@ -151,11 +194,15 @@ int result_type_read(mysqli_object *obj, zval **retval TSRMLS_DC) /* }}} */ /* {{{ property result_lengths_read */ -int result_lengths_read(mysqli_object *obj, zval **retval TSRMLS_DC) +static int result_lengths_read(mysqli_object *obj, zval **retval TSRMLS_DC) { - MYSQL_RES *p = (MYSQL_RES *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr; + MYSQL_RES *p; + + ALLOC_ZVAL(*retval); + CHECK_OBJECT(); + + p = (MYSQL_RES *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr; - ALLOC_ZVAL(*retval); if (!p || !p->field_count) { ZVAL_NULL(*retval); } else { @@ -180,7 +227,55 @@ MYSQLI_MAP_PROPERTY_FUNC_LONG(result_field_count_read, mysql_num_fields, MYSQLI_ MYSQLI_MAP_PROPERTY_FUNC_LONG(result_num_rows_read, mysql_num_rows, MYSQLI_GET_RESULT(), my_ulonglong); /* statement properties */ -MYSQLI_MAP_PROPERTY_FUNC_LONG(stmt_affected_rows_read, mysql_stmt_affected_rows, MYSQLI_GET_STMT(), my_ulonglong); + +/* {{{ property stmt_id_read */ +static int stmt_id_read(mysqli_object *obj, zval **retval TSRMLS_DC) +{ + MY_STMT *p; + + ALLOC_ZVAL(*retval); + CHECK_OBJECT(); + + p = (MY_STMT*)((MYSQLI_RESOURCE *)(obj->ptr))->ptr; + + if (!p) { + ZVAL_NULL(*retval); + } else { + ZVAL_LONG(*retval, p->stmt->stmt_id); + } + return SUCCESS; +} +/* }}} */ + +/* {{{ property stmt_affected_rows_read */ +static int stmt_affected_rows_read(mysqli_object *obj, zval **retval TSRMLS_DC) +{ + MY_STMT *stmt; + my_ulonglong rc; + + ALLOC_ZVAL(*retval); + CHECK_OBJECT(); + + stmt = (MY_STMT *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr; + rc = mysql_stmt_affected_rows(stmt->stmt); + + if (rc == (my_ulonglong)-1) { + ZVAL_LONG(*retval, -1); + return SUCCESS; + } + + if (rc < LONG_MAX) { + ZVAL_LONG(*retval, rc); + } else { + char ret[40]; + sprintf(ret, "%llu", (my_ulonglong) rc); + ZVAL_STRING(*retval, ret, 1); + } + + return SUCCESS; +} +/* }}} */ + MYSQLI_MAP_PROPERTY_FUNC_LONG(stmt_insert_id_read, mysql_stmt_insert_id, MYSQLI_GET_STMT(), my_ulonglong); MYSQLI_MAP_PROPERTY_FUNC_LONG(stmt_num_rows_read, mysql_stmt_num_rows, MYSQLI_GET_STMT(), my_ulonglong); MYSQLI_MAP_PROPERTY_FUNC_LONG(stmt_param_count_read, mysql_stmt_param_count, MYSQLI_GET_STMT(), ulong); @@ -191,8 +286,8 @@ MYSQLI_MAP_PROPERTY_FUNC_STRING(stmt_sqlstate_read, mysql_stmt_sqlstate, MYSQLI_ mysqli_property_entry mysqli_link_property_entries[] = { {"affected_rows", link_affected_rows_read, NULL}, + {"client_info", link_client_info_read, NULL}, {"client_version", link_client_version_read, NULL}, - {"test", link_test_read, NULL}, {"connect_errno", link_connect_errno_read, NULL}, {"connect_error", link_connect_error_read, NULL}, {"errno", link_errno_read, NULL}, @@ -224,15 +319,11 @@ mysqli_property_entry mysqli_stmt_property_entries[] = { {"insert_id", stmt_insert_id_read, NULL}, {"num_rows", stmt_num_rows_read, NULL}, {"param_count", stmt_param_count_read, NULL}, - -/* TODO: stmt->field_count doesn't work currently, remove comments until mysqli_stmt_field_count - is implemented in client library -*/ {"field_count", stmt_field_count_read, NULL}, - {"errno", stmt_errno_read, NULL}, {"error", stmt_error_read, NULL}, {"sqlstate", stmt_sqlstate_read, NULL}, + {"id", stmt_id_read, NULL}, {NULL, NULL, NULL} }; diff --git a/ext/mysqli/php_mysqli.h b/ext/mysqli/php_mysqli.h index c5a090fa2e29..dc0e1dcb33c9 100644 --- a/ext/mysqli/php_mysqli.h +++ b/ext/mysqli/php_mysqli.h @@ -53,9 +53,9 @@ typedef struct { typedef struct { MYSQL *mysql; - /* callback functions for load data local infile support */ - zval callback_func[3]; - zval *local_infile; + zval *li_read; + php_stream *li_stream; + unsigned int multi_query; } MY_MYSQL; typedef struct { @@ -95,6 +95,10 @@ typedef struct { #define PHP_MYSQLI_API #endif +#if (MYSQL_VERSION_ID > 40112 && MYSQL_VERSION_ID < 50000) || MYSQL_VERSION_ID > 50005 +#define HAVE_MYSQLI_SET_CHARSET +#endif + #ifdef ZTS #include "TSRM.h" #endif @@ -112,6 +116,7 @@ extern mysqli_property_entry mysqli_stmt_property_entries[]; extern void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flag, int into_object); extern void php_clear_stmt_bind(MY_STMT *stmt); +void php_clear_mysql(MY_MYSQL *); extern void php_free_stmt_bind_buffer(BIND_BUFFER bbuf, int type); extern void php_mysqli_report_error(char *sqlstate, int errorno, char *error TSRMLS_DC); extern void php_mysqli_report_index(char *query, unsigned int status TSRMLS_DC); @@ -119,6 +124,7 @@ extern int php_local_infile_init(void **, const char *, void *); extern int php_local_infile_read(void *, char *, uint); extern void php_local_infile_end(void *); extern int php_local_infile_error(void *, char *, uint); +extern void php_set_local_infile_handler_default(MY_MYSQL *); zend_class_entry *mysqli_link_class_entry; zend_class_entry *mysqli_stmt_class_entry; @@ -130,14 +136,14 @@ zend_class_entry _mysqli_result_class_entry; PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry * TSRMLS_DC); -#define MYSQLI_DISABLE_MQ if (MyG(multi_query)) { \ +#define MYSQLI_DISABLE_MQ if (mysql->multi_query) { \ mysql_set_server_option(mysql->mysql, MYSQL_OPTION_MULTI_STATEMENTS_OFF); \ - MyG(multi_query) = 0; \ + mysql->multi_query = 0; \ } -#define MYSQLI_ENABLE_MQ if (!MyG(multi_query)) { \ +#define MYSQLI_ENABLE_MQ if (!mysql->multi_query) { \ mysql_set_server_option(mysql->mysql, MYSQL_OPTION_MULTI_STATEMENTS_ON); \ - MyG(multi_query) = 1; \ + mysql->multi_query = 1; \ } #define REGISTER_MYSQLI_CLASS_ENTRY(name, mysqli_entry, class_functions) { \ @@ -180,7 +186,7 @@ PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry * TSRML } \ __ptr = (__type)my_res->ptr; \ if (!strcmp((char *)__name, "mysqli_stmt")) {\ - if (!((MYSQL_STMT *)__ptr)->mysql) {\ + if (!((MY_STMT *)__ptr)->stmt->mysql) {\ php_error(E_WARNING, "Statement isn't valid anymore");\ RETURN_NULL();\ }\ @@ -271,6 +277,9 @@ PHP_FUNCTION(mysqli_affected_rows); PHP_FUNCTION(mysqli_autocommit); PHP_FUNCTION(mysqli_change_user); PHP_FUNCTION(mysqli_character_set_name); +#ifdef HAVE_MYSQLI_SET_CHARSET +PHP_FUNCTION(mysqli_set_charset); +#endif PHP_FUNCTION(mysqli_close); PHP_FUNCTION(mysqli_commit); PHP_FUNCTION(mysqli_connect); @@ -385,7 +394,6 @@ ZEND_BEGIN_MODULE_GLOBALS(mysqli) char *error_msg; int report_mode; HashTable *report_ht; - unsigned int multi_query; #ifdef HAVE_EMBEDDED_MYSQLI unsigned int embedded; #endif diff --git a/ext/mysqli/tests/001.phpt b/ext/mysqli/tests/001.phpt index 5e483aba8db5..880325bb5ae0 100644 --- a/ext/mysqli/tests/001.phpt +++ b/ext/mysqli/tests/001.phpt @@ -1,49 +1,40 @@ --TEST-- mysqli connect +--SKIPIF-- + --FILE-- --EXPECT-- -string(7) "1111111" +string(5) "11111" diff --git a/ext/mysqli/tests/002.phpt b/ext/mysqli/tests/002.phpt index 7925f84fa804..fa4e60e185d6 100644 --- a/ext/mysqli/tests/002.phpt +++ b/ext/mysqli/tests/002.phpt @@ -1,11 +1,13 @@ --TEST-- mysqli bind_result 1 +--SKIPIF-- + --FILE-- --FILE-- string(19) "2010-07-10 00:00:00" [5]=> - string(0) "" + string(19) "0000-00-00 00:00:00" [6]=> string(19) "1999-12-29 00:00:00" } diff --git a/ext/mysqli/tests/004.phpt b/ext/mysqli/tests/004.phpt index 179c4b64cfd0..c80c7214e326 100644 --- a/ext/mysqli/tests/004.phpt +++ b/ext/mysqli/tests/004.phpt @@ -1,11 +1,13 @@ --TEST-- mysqli fetch char/text +--SKIPIF-- + --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- +--SKIPIF-- + --FILE-- +--SKIPIF-- + --FILE-- --FILE-- --FILE-- - string(14) "root@localhost" + int(1) [1]=> string(4) "test" [2]=> diff --git a/ext/mysqli/tests/018.phpt b/ext/mysqli/tests/018.phpt index a0a247611dcb..4ba199d86654 100644 --- a/ext/mysqli/tests/018.phpt +++ b/ext/mysqli/tests/018.phpt @@ -1,11 +1,13 @@ --TEST-- mysqli fetch system variables +--SKIPIF-- + --FILE-- --FILE-- --FILE-- string(19) "2010-07-10 00:00:00" [5]=> - string(0) "" + string(19) "0000-00-00 00:00:00" [6]=> string(19) "1999-12-29 00:00:00" } diff --git a/ext/mysqli/tests/021.phpt b/ext/mysqli/tests/021.phpt index 614f978aafba..6f5bad32053e 100644 --- a/ext/mysqli/tests/021.phpt +++ b/ext/mysqli/tests/021.phpt @@ -1,11 +1,13 @@ --TEST-- mysqli bind_param+bind_result char/text +--SKIPIF-- + --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- ---EXPECT-- -string(25) "Localhost via UNIX socket" +--EXPECTF-- +string(%d) "%s via %s" \ No newline at end of file diff --git a/ext/mysqli/tests/034.phpt b/ext/mysqli/tests/034.phpt index e347586a36a5..47c99f07e5b2 100644 --- a/ext/mysqli/tests/034.phpt +++ b/ext/mysqli/tests/034.phpt @@ -1,13 +1,13 @@ --TEST-- function test: mysqli_get_proto_info +--SKIPIF-- + --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- close(); mysqli_close($link); ?> +--SKIPIF-- + --FILE-- --FILE-- --FILE-- - object(stdClass)#%d (9) { + object(stdClass)#4 (11) { ["name"]=> string(3) "foo" ["orgname"]=> @@ -42,6 +44,10 @@ array(2) { string(0) "" ["max_length"]=> int(0) + ["length"]=> + int(11) + ["charsetnr"]=> + int(63) ["flags"]=> int(32768) ["type"]=> @@ -50,7 +56,7 @@ array(2) { int(0) } [1]=> - object(stdClass)#%d (9) { + object(stdClass)#5 (11) { ["name"]=> string(3) "bar" ["orgname"]=> @@ -63,6 +69,10 @@ array(2) { string(0) "" ["max_length"]=> int(0) + ["length"]=> + int(10) + ["charsetnr"]=> + int(8) ["flags"]=> int(0) ["type"]=> diff --git a/ext/mysqli/tests/048.phpt b/ext/mysqli/tests/048.phpt index 102bcdfc26a5..1cf5b67894b9 100644 --- a/ext/mysqli/tests/048.phpt +++ b/ext/mysqli/tests/048.phpt @@ -1,11 +1,13 @@ --TEST-- mysqli bind_result (OO-Style) +--SKIPIF-- + --FILE-- select_db("test"); $mysql->query("DROP TABLE IF EXISTS test_fetch_null"); diff --git a/ext/mysqli/tests/049.phpt b/ext/mysqli/tests/049.phpt index 04e705de6ee6..13ea5594c31e 100644 --- a/ext/mysqli/tests/049.phpt +++ b/ext/mysqli/tests/049.phpt @@ -1,23 +1,23 @@ --TEST-- mysql_fetch_row (OO-Style) +--SKIPIF-- + --FILE-- select_db("test"); $result = $mysql->query("SELECT CURRENT_USER()"); $row = $result->fetch_row(); $result->close(); - - var_dump($row); + + $ok = ($row[0] == $user . "@" . $host); + var_dump($ok); $mysql->close(); ?> --EXPECT-- -array(1) { - [0]=> - string(14) "root@localhost" -} +bool(true) diff --git a/ext/mysqli/tests/050.phpt b/ext/mysqli/tests/050.phpt index 9ab5d346f89b..5f923ccf34bd 100644 --- a/ext/mysqli/tests/050.phpt +++ b/ext/mysqli/tests/050.phpt @@ -1,5 +1,7 @@ --TEST-- non freed statement test +--SKIPIF-- + --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- connect("localhost", $user, $passwd); + $foo->connect($host, $user, $passwd); $foo->close(); printf("%s\n", $foo->test()); ?> diff --git a/ext/mysqli/tests/057.phpt b/ext/mysqli/tests/057.phpt index 581201d8efd7..a987c72381c4 100644 --- a/ext/mysqli/tests/057.phpt +++ b/ext/mysqli/tests/057.phpt @@ -1,11 +1,13 @@ --TEST-- mysqli_get_metadata +--SKIPIF-- + --FILE-- --FILE-- --FILE-- --FILE-- +--FILE-- + +--EXPECT-- +foo-bar +rab-oof diff --git a/ext/mysqli/tests/064.phpt b/ext/mysqli/tests/064.phpt new file mode 100644 index 000000000000..1d6358e532ed --- /dev/null +++ b/ext/mysqli/tests/064.phpt @@ -0,0 +1,21 @@ +--TEST-- +NULL binding +--SKIPIF-- + +--FILE-- +prepare("SELECT NULL FROM DUAL"); + $stmt->execute(); + $stmt->bind_result($foo); + $stmt->fetch(); + $stmt->close(); + $mysql->close(); + + var_dump($foo); +?> +--EXPECT-- +NULL diff --git a/ext/mysqli/tests/065.phpt b/ext/mysqli/tests/065.phpt new file mode 100644 index 000000000000..950a10a437f5 --- /dev/null +++ b/ext/mysqli/tests/065.phpt @@ -0,0 +1,37 @@ +--TEST-- +set character set +--SKIPIF-- + +--FILE-- +set_charset("latin1")) { + /* 5C should be escaped */ + $len[0] = strlen($mysql->real_escape_string($esc_str)); + $charset[0] = $mysql->client_encoding(); + } + + if ($mysql->set_charset("gbk")) { + /* nothing should be escaped, it's a valid gbk character */ + $len[1] = strlen($mysql->real_escape_string($esc_str)); + $charset[1] = $mysql->client_encoding(); + } + + $mysql->close(); + var_dump($len[0]); + var_dump($len[1]); + var_dump($charset[0]); + var_dump($charset[1]); +?> +--EXPECT-- +int(3) +int(2) +string(6) "latin1" +string(3) "gbk" diff --git a/ext/mysqli/tests/bug29311.phpt b/ext/mysqli/tests/bug29311.phpt new file mode 100644 index 000000000000..b50de178b223 --- /dev/null +++ b/ext/mysqli/tests/bug29311.phpt @@ -0,0 +1,48 @@ +--TEST-- +constructor test +--SKIPIF-- + +--FILE-- +connect($host, $user, $passwd, "test"); + } + } + + /* class 3 has no constructor */ + class mysql3 extends mysqli { + + } + + $foo[0] = new mysql1(); + $foo[1] = new mysql2(); + $foo[2] = new mysql3($host, $user, $passwd, "test"); + + + for ($i=0; $i < 3; $i++) { + if (($result = $foo[$i]->query("SELECT DATABASE()"))) { + $row = $result->fetch_row(); + printf("%d: %s\n", $i, $row[0]); + $result->close(); + } + $foo[$i]->close(); + } +?> +--EXPECTF-- +0: test +1: test +2: test diff --git a/ext/mysqli/tests/bug30967.phpt b/ext/mysqli/tests/bug30967.phpt new file mode 100644 index 000000000000..0a82d0d43cd4 --- /dev/null +++ b/ext/mysqli/tests/bug30967.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #30967 testcase (properties) +--SKIPIF-- + +--FILE-- +query("THIS DOES NOT WORK"); + printf("%d\n", $mysql->errno); + + $mysql->close(); +?> +--EXPECTF-- +1064 diff --git a/ext/mysqli/tests/bug31141.phpt b/ext/mysqli/tests/bug31141.phpt new file mode 100644 index 000000000000..acad79f1f9e8 --- /dev/null +++ b/ext/mysqli/tests/bug31141.phpt @@ -0,0 +1,28 @@ +--TEST-- +Bug #31141 testcase (properties) +--SKIPIF-- + +--FILE-- +test = &$ar_test; + } +} + +$my_test = new Test; +$my_test->foo(); +var_dump($my_test->test); +?> +--EXPECTF-- +array(2) { + [0]=> + string(3) "foo" + [1]=> + string(3) "bar" +} diff --git a/ext/mysqli/tests/bug31668.phpt b/ext/mysqli/tests/bug31668.phpt new file mode 100644 index 000000000000..b813096a2a4b --- /dev/null +++ b/ext/mysqli/tests/bug31668.phpt @@ -0,0 +1,56 @@ +--TEST-- +Bug #31668 multi_query works exactly every other time (multi_query was global, now per connection) +--SKIPIF-- + +--FILE-- +multi_query('SELECT 1;SELECT 2'); + do { + $res = $mysql->store_result(); + if ($mysql->errno == 0) { + while ($arr = $res->fetch_assoc()) { + var_dump($arr); + } + $res->free(); + } + } while ($mysql->next_result()); + var_dump($mysql->error, __LINE__); + $mysql->close(); + + $mysql = new mysqli($host, $user, $passwd, "test"); + $mysql->multi_query('SELECT 1;SELECT 2'); + do { + $res = $mysql->store_result(); + if ($mysql->errno == 0) { + while ($arr = $res->fetch_assoc()) { + var_dump($arr); + } + $res->free(); + } + } while ($mysql->next_result()); + var_dump($mysql->error, __LINE__); +?> +--EXPECTF-- +array(1) { + [1]=> + string(1) "1" +} +array(1) { + [2]=> + string(1) "2" +} +string(0) "" +int(%d) +array(1) { + [1]=> + string(1) "1" +} +array(1) { + [2]=> + string(1) "2" +} +string(0) "" +int(%d) diff --git a/ext/mysqli/tests/bug32405.phpt b/ext/mysqli/tests/bug32405.phpt new file mode 100644 index 000000000000..9b58e3611bfc --- /dev/null +++ b/ext/mysqli/tests/bug32405.phpt @@ -0,0 +1,38 @@ +--TEST-- +Bug #32405 +--SKIPIF-- + +--FILE-- +query("CREATE TABLE test_users(user_id int(10) unsigned NOT NULL auto_increment, login varchar(50) default '', PRIMARY KEY (user_id))"); + $link->query('INSERT INTO test_users VALUES (NULL, "user1"), (NULL, "user2"), (NULL, "user3"), (NULL, "user4")'); + + + if ($stmt = $link->prepare("SELECT SQL_NO_CACHE user_id, login FROM test_users")) { + $stmt->execute(); + $stmt->bind_result($col1, $col2); + while ($stmt->fetch()) { + var_dump($col1, $col2); + } + $stmt->close(); + } + + mysqli_query($link,"DROP TABLE test_users"); + mysqli_close($link); +?> +--EXPECT-- +int(1) +string(5) "user1" +int(2) +string(5) "user2" +int(3) +string(5) "user3" +int(4) +string(5) "user4" diff --git a/ext/mysqli/tests/bug33090.phpt b/ext/mysqli/tests/bug33090.phpt new file mode 100644 index 000000000000..5c1cba961e48 --- /dev/null +++ b/ext/mysqli/tests/bug33090.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug #33090 +--SKIPIF-- + +--FILE-- +prepare("this makes no sense"))) { + printf("%d\n", $link->errno); + printf("%s\n", $link->sqlstate); + } + $link->close(); +?> +--EXPECT-- +1064 +42000 diff --git a/ext/mysqli/tests/bug33263.phpt b/ext/mysqli/tests/bug33263.phpt new file mode 100644 index 000000000000..44f9167c95dd --- /dev/null +++ b/ext/mysqli/tests/bug33263.phpt @@ -0,0 +1,31 @@ +--TEST-- +bug #33263 (mysqli_real_connect in __construct) +--SKIPIF-- + +--FILE-- +prepare("SELECT DATABASE()"); + $stmt->execute(); + $stmt->bind_result($db); + $stmt->fetch(); + $stmt->close(); + + var_dump($db); + + $mysql->close(); +?> +--EXPECT-- +string(4) "test" diff --git a/ext/mysqli/tests/skipif.inc b/ext/mysqli/tests/skipif.inc new file mode 100644 index 000000000000..68a9c7cf0ec3 --- /dev/null +++ b/ext/mysqli/tests/skipif.inc @@ -0,0 +1,4 @@ + diff --git a/ext/oci8/config.m4 b/ext/oci8/config.m4 index adb60f587c01..d3e7fc16a4b8 100644 --- a/ext/oci8/config.m4 +++ b/ext/oci8/config.m4 @@ -2,7 +2,7 @@ dnl dnl $Id$ dnl -AC_DEFUN(PHP_OCI_IF_DEFINED,[ +AC_DEFUN([PHP_OCI_IF_DEFINED],[ old_CPPFLAGS=$CPPFLAGS CPPFLAGS=$3 AC_EGREP_CPP(yes,[ @@ -18,7 +18,7 @@ AC_DEFUN(PHP_OCI_IF_DEFINED,[ ]) ]) -AC_DEFUN(AC_OCI8_VERSION,[ +AC_DEFUN([AC_OCI8_VERSION],[ AC_MSG_CHECKING([Oracle version]) if test -s "$OCI8_DIR/orainst/unix.rgs"; then OCI8_VERSION=`grep '"ocommon"' $OCI8_DIR/orainst/unix.rgs | sed 's/[ ][ ]*/:/g' | cut -d: -f 6 | cut -c 2-4` @@ -38,16 +38,51 @@ AC_DEFUN(AC_OCI8_VERSION,[ OCI8_VERSION=8.1 fi else - AC_MSG_ERROR(Oracle-OCI8 needed libraries not found) + AC_MSG_ERROR([Oracle (OCI8) required libraries not found]) fi AC_MSG_RESULT($OCI8_VERSION) ]) -PHP_ARG_WITH(oci8, for Oracle-OCI8 support, -[ --with-oci8[=DIR] Include Oracle-oci8 support. Default DIR is ORACLE_HOME.]) +AC_DEFUN([AC_OCI8IC_VERSION],[ + AC_MSG_CHECKING([Oracle Instant Client version]) + if test -f $PHP_OCI8_INSTANT_CLIENT/libociei.$SHLIB_SUFFIX_NAME; then + if test -f $PHP_OCI8_INSTANT_CLIENT/libclntsh.$SHLIB_SUFFIX_NAME.10.1; then + if test ! -f $PHP_OCI8_INSTANT_CLIENT/libclntsh.$SHLIB_SUFFIX_NAME; then + AC_MSG_ERROR([Link from $PHP_OCI8_INSTANT_CLIENT/libclntsh.$SHLIB_SUFFIX_NAME to libclntsh.$SHLIB_SUFFIX_NAME.10.1 not found]) + fi + OCI8_VERSION=10.1 + else + AC_MSG_ERROR([Oracle Instant Client library version not supported]) + fi + else + AC_MSG_ERROR([Oracle Instant Client libraries not found]) + fi + AC_MSG_RESULT([$OCI8_VERSION]) +]) + +PHP_ARG_WITH(oci8, for Oracle (OCI8) support using ORACLE_HOME installation, +[ --with-oci8[=DIR] Include Oracle (OCI8) support using an ORACLE_HOME + install. The default DIR is ORACLE_HOME]) + +if test "$PHP_OCI8" = "no"; then + PHP_ARG_WITH(oci8-instant-client, for Oracle (OCI8) support using Oracle Instant Client, + [ --with-oci8-instant-client[=DIR] + Include Oracle (OCI8) support using + Oracle Instant Client. DIR is the directory with the + Instant Client libraries. On Linux it will default to + /usr/lib/oracle//client/lib + Other platforms will need to have it explicitly specified.]) +else + PHP_OCI8_INSTANT_CLIENT="no"; +fi if test "$PHP_OCI8" != "no"; then - AC_MSG_CHECKING([Oracle Install-Dir]) + + if test "$PHP_OCI8_INSTANT_CLIENT" != "no"; then + AC_MSG_ERROR([--with-oci8 and --with-oci8-instant-client are mutually exclusive]) + fi + + AC_MSG_CHECKING([Oracle Install Directory]) if test "$PHP_OCI8" = "yes"; then OCI8_DIR=$ORACLE_HOME else @@ -116,15 +151,18 @@ if test "$PHP_OCI8" != "no"; then -L$OCI8_DIR/lib $OCI8_SHARED_LIBADD ]) ;; - + 10.1) PHP_ADD_LIBRARY(clntsh, 1, OCI8_SHARED_LIBADD) PHP_ADD_LIBPATH($OCI8_DIR/lib, OCI8_SHARED_LIBADD) AC_DEFINE(HAVE_OCI8_ATTR_STATEMENT,1,[ ]) AC_DEFINE(HAVE_OCI_9_2,1,[ ]) + AC_DEFINE(HAVE_OCI8_TEMP_LOB,1,[ ]) + AC_DEFINE(PHP_OCI8_HAVE_COLLECTIONS,1,[ ]) ;; + *) - AC_MSG_ERROR(Unsupported Oracle version!) + AC_MSG_ERROR([Unsupported Oracle version]) ;; esac @@ -163,5 +201,71 @@ if test "$PHP_OCI8" != "no"; then PHP_SUBST_OLD(OCI8_SHARED_LIBADD) PHP_SUBST_OLD(OCI8_DIR) PHP_SUBST_OLD(OCI8_VERSION) - + +elif test "$PHP_OCI8_INSTANT_CLIENT" != "no"; then + + AC_MSG_CHECKING([Oracle Instant Client directory]) + if test "$PHP_OCI8_INSTANT_CLIENT" = "yes"; then +dnl Generally the Instant Client can be anywhere so the user must pass in the +dnl directory to the libraries. But on Linux we default to the most recent +dnl version in /usr/lib + PHP_OCI8_INSTANT_CLIENT=`ls -d /usr/lib/oracle/*/client/lib 2> /dev/null | tail -1` + if test -z "$PHP_OCI8_INSTANT_CLIENT"; then + AC_MSG_ERROR([Oracle Instant Client directory not found. Try --with-oci8-instant-client=DIR]) + fi + fi + AC_MSG_RESULT($PHP_OCI8_INSTANT_CLIENT) + + OCI8_DIR=$PHP_OCI8_INSTANT_CLIENT + + AC_MSG_CHECKING([Oracle Instant Client SDK header directory]) + +dnl Header directory for Instant Client SDK RPM install + OCISDKRPMINC=`echo "$PHP_OCI8_INSTANT_CLIENT" | sed -e 's!^/usr/lib/oracle/\(.*\)/client/lib[[/]]*$!/usr/include/oracle/\1/client!'` + +dnl Header directory for Instant Client SDK zip file install + OCISDKZIPINC=$PHP_OCI8_INSTANT_CLIENT/sdk/include + + if test -f "$OCISDKRPMINC/oci.h"; then + AC_MSG_RESULT($OCISDKRPMINC) + PHP_ADD_INCLUDE($OCISDKRPMINC) + OCI8INCDIR=$OCISDKRPMINC + elif test -f "$OCISDKZIPINC/oci.h"; then + AC_MSG_RESULT($OCISDKZIPINC) + PHP_ADD_INCLUDE($OCISDKZIPINC) + OCI8INCDIR=$OCISDKZIPINC + else + AC_MSG_ERROR([Oracle Instant Client SDK header files not found]) + fi + + OCISYSLIBLIST=`echo "$OCI8INCDIR" | sed -e 's!\(.*\)/include$!\1/demo/sysliblist!'` + if test -f "$OCISYSLIBLIST"; then + PHP_EVAL_LIBLINE(`cat $OCISYSLIBLIST`, OCI8_SYSLIB) + fi + + AC_OCI8IC_VERSION($PHP_OCI8_INSTANT_CLIENT) + case $OCI8_VERSION in + 10.1) + PHP_ADD_LIBRARY(clntsh, 1, OCI8_SHARED_LIBADD) + PHP_ADD_LIBPATH($PHP_OCI8_INSTANT_CLIENT, OCI8_SHARED_LIBADD) + ;; + + *) + AC_MSG_ERROR([Unsupported Oracle Instant Client version]) + ;; + esac + + AC_DEFINE(HAVE_OCI8_ATTR_STATEMENT,1,[ ]) + AC_DEFINE(HAVE_OCI_9_2,1,[ ]) + AC_DEFINE(HAVE_OCI8_TEMP_LOB,1,[ ]) + AC_DEFINE(PHP_OCI8_HAVE_COLLECTIONS,1,[ ]) + AC_DEFINE(HAVE_OCI_INSTANT_CLIENT,1,[ ]) + + PHP_NEW_EXTENSION(oci8, oci8.c, $ext_shared) + AC_DEFINE(HAVE_OCI8,1,[ ]) + + PHP_SUBST_OLD(OCI8_SHARED_LIBADD) + PHP_SUBST_OLD(OCI8_DIR) + PHP_SUBST_OLD(OCI8_VERSION) + fi diff --git a/ext/oci8/oci8.c b/ext/oci8/oci8.c index 597b177a49b1..9169a53a19c4 100644 --- a/ext/oci8/oci8.c +++ b/ext/oci8/oci8.c @@ -1016,16 +1016,6 @@ static void _oci_conn_list_dtor(oci_connection *connection TSRMLS_DC) ); } - if (connection->session) { - /* close associated session when destructed */ - zend_list_delete(connection->session->num); - } - - if (connection->descriptors) { - zend_hash_destroy(connection->descriptors); - efree(connection->descriptors); - } - if (connection->pError) { CALL_OCI( OCIHandleFree( @@ -1035,6 +1025,16 @@ static void _oci_conn_list_dtor(oci_connection *connection TSRMLS_DC) ); } + if (connection->session && connection->session->exclusive) { + /* close associated session when destructed */ + zend_list_delete(connection->session->num); + } + + if (connection->descriptors) { + zend_hash_destroy(connection->descriptors); + efree(connection->descriptors); + } + oci_debug("END _oci_conn_list_dtor: id=%d",connection->id); efree(connection); @@ -2700,6 +2700,7 @@ static oci_session *_oci_open_session(oci_server* server,char *username,char *pa session->persistent = 1; } smart_str_free_ex(&hashed_details, 1); + mutex_unlock(mx_lock); return session; } else { _oci_close_session(session); @@ -2862,7 +2863,12 @@ static oci_session *_oci_open_session(oci_server* server,char *username,char *pa if (OCI(error) != OCI_SUCCESS) { oci_error(OCI(pError), "OCISessionBegin", OCI(error)); - goto CLEANUP; + /* OCISessionBegin returns OCI_SUCCESS_WITH_INFO when + * user's password has expired, but is still usable. + * */ + if (OCI(error) != OCI_SUCCESS_WITH_INFO) { + goto CLEANUP; + } } /* Free Temporary Service Context */ @@ -2906,7 +2912,7 @@ static int _session_compare(void *a, void *b) oci_session *sess1 = (oci_session*) a; oci_session *sess2 = (oci_session*) b; - return sess1->num = sess2->num; + return sess1->num == sess2->num; } static void _oci_close_session(oci_session *session) @@ -3009,6 +3015,16 @@ static void _oci_close_session(oci_session *session) } mutex_unlock(mx_lock); +#ifdef HAVE_OCI_9_2 + /* free environment handle (and fix bug #29652 with growing .msb FD number under weirdie Solarises) */ + CALL_OCI( + OCIHandleFree( + (dvoid *) session->pEnv, + OCI_HTYPE_ENV + ) + ); +#endif + if (session->exclusive) { efree(session); } @@ -3134,7 +3150,7 @@ static int _oci_session_cleanup(void *data TSRMLS_DC) if (le->type == le_session) { oci_server *server = ((oci_session*) le->ptr)->server; - if (server->is_open == 2) + if (server && server->is_open == 2) return 1; } return 0; @@ -3679,6 +3695,12 @@ break; } value_sz = sizeof(void*); break; + case SQLT_CHR: + break; + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or unsupported datatype given: %u", ocitype); + RETURN_FALSE; + break; } if ((ocitype == SQLT_CHR) && (value_sz == -1)) { @@ -5830,7 +5852,7 @@ PHP_FUNCTION(oci_new_connect) Connect to an Oracle database and log on. Returns a new session. */ PHP_FUNCTION(oci_connect) { - oci_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0); + oci_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1); } /* }}} */ diff --git a/ext/oci8/oci8.dsw b/ext/oci8/oci8.dsw deleted file mode 100644 index fc18fae34a1b..000000000000 --- a/ext/oci8/oci8.dsw +++ /dev/null @@ -1,29 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "oci8"=.\oci8.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/ext/odbc/birdstep.c b/ext/odbc/birdstep.c index 24b88d242b36..5a3e0441b5f5 100644 --- a/ext/odbc/birdstep.c +++ b/ext/odbc/birdstep.c @@ -39,7 +39,7 @@ # define PHPAPI __declspec(dllimport) # endif #else -# include "php_config.h" +# include # define PHPAPI # define THREAD_LS #endif diff --git a/ext/odbc/config.m4 b/ext/odbc/config.m4 index ce518dca5c07..8981799a249f 100644 --- a/ext/odbc/config.m4 +++ b/ext/odbc/config.m4 @@ -5,7 +5,7 @@ dnl dnl dnl Figure out which library file to link with for the Solid support. dnl -AC_DEFUN(AC_FIND_SOLID_LIBS,[ +AC_DEFUN([AC_FIND_SOLID_LIBS],[ AC_MSG_CHECKING([Solid library file]) ac_solid_uname_r=`uname -r 2>/dev/null` ac_solid_uname_s=`uname -s 2>/dev/null` @@ -71,7 +71,7 @@ fi dnl dnl Figure out which library file to link with for the Empress support. dnl -AC_DEFUN(AC_FIND_EMPRESS_LIBS,[ +AC_DEFUN([AC_FIND_EMPRESS_LIBS],[ AC_MSG_CHECKING([Empress library file]) ODBC_LIBS=`echo $1/libempodbccl.so | cut -d' ' -f1` if test ! -f $ODBC_LIBS; then @@ -80,7 +80,7 @@ AC_DEFUN(AC_FIND_EMPRESS_LIBS,[ AC_MSG_RESULT(`echo $ODBC_LIBS | sed -e 's!.*/!!'`) ]) -AC_DEFUN(AC_FIND_EMPRESS_BCS_LIBS,[ +AC_DEFUN([AC_FIND_EMPRESS_BCS_LIBS],[ AC_MSG_CHECKING([Empress local access library file]) ODBCBCS_LIBS=`echo $1/libempodbcbcs.a | cut -d' ' -f1` if test ! -f $ODBCBCS_LIBS; then @@ -194,13 +194,29 @@ AC_ARG_WITH(ibm-db2, ODBC_INCDIR=$withval/include ODBC_LIBDIR=$withval/lib fi + + if ! test -f "$ODBC_INCDIR/sqlcli1.h"; then + AC_MSG_ERROR([IBM DB2 header files not found]) + fi + ODBC_INCLUDE=-I$ODBC_INCDIR ODBC_LFLAGS=-L$ODBC_LIBDIR ODBC_TYPE=db2 ODBC_LIBS=-ldb2 - AC_DEFINE(HAVE_IBMDB2,1,[ ]) - AC_MSG_RESULT(yes) + PHP_TEST_BUILD(SQLExecute, [ + AC_DEFINE(HAVE_IBMDB2,1,[ ]) + AC_MSG_RESULT(yes) + ], [ + AC_MSG_RESULT(no) + AC_MSG_ERROR([ +build test failed. Please check the config.log for details. +You need to source your DB2 environment before running PHP configure: +# . \$IBM_DB2/db2profile +]) + ], [ + $ODBC_LFLAGS $ODBC_LIBS + ]) else AC_MSG_RESULT(no) fi @@ -304,10 +320,35 @@ AC_ARG_WITH(birdstep, ODBC_INCDIR=$withval/include ODBC_LIBDIR=$withval/lib fi + + case $host_alias in + *aix*[)] + AC_DEFINE(AIX,1,[ ]);; + *hpux*[)] + AC_DEFINE(HPUX,1,[ ]);; + *linux*[)] + AC_DEFINE(LINUX,1,[ ]);; + *qnx*[)] + AC_DEFINE(NEUTRINO,1,[ ]);; + i?86-*-solaris*[)] + AC_DEFINE(ISOLARIS,1,[ ]);; + sparc-*-solaris*[)] + AC_DEFINE(SOLARIS,1,[ ]);; + *unixware*[)] + AC_DEFINE(UNIXWARE,1,[ ]);; + esac + ODBC_INCLUDE=-I$ODBC_INCDIR ODBC_TYPE=birdstep ODBC_LFLAGS=-L$ODBC_LIBDIR ODBC_LIBS="-lCadm -lCdict -lCenc -lCrdm -lCrpc -lCrdbc -lCrm -lCuapi -lutil" + + if test -e "$ODBC_LIBDIR/libCrdbc32.$SHLIB_SUFFIX_NAME"; then + ODBC_LIBS="-lCrdbc32 -lCadm32 -lCncp32 -lCrm32 -lCsql32 -lCdict32 -lCrdm32 -lCrpc32 -lutil" + elif test -e "$ODBC_LIBDIR/libCrdbc.$SHLIB_SUFFIX_NAME"; then + ODBC_LIBS="-lCrdbc -lCadm -lCncp -lCrm -lCsql -lCdict -lCrdm -lCrpc -lutil" + fi + AC_DEFINE(HAVE_BIRDSTEP,1,[ ]) AC_MSG_RESULT(yes) @@ -505,7 +546,9 @@ if test -n "$ODBC_TYPE"; then if test "$ODBC_TYPE" != "dbmaker"; then ext_shared=$shared PHP_EVAL_LIBLINE([$ODBC_LFLAGS $ODBC_LIBS], ODBC_SHARED_LIBADD) - AC_DEFINE(HAVE_SQLDATASOURCES,1,[ ]) + if test "$ODBC_TYPE" != "birdstep"; then + AC_DEFINE(HAVE_SQLDATASOURCES,1,[ ]) + fi fi AC_DEFINE(HAVE_UODBC,1,[ ]) diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c index 0908ce6a5bda..5de280f7905b 100644 --- a/ext/odbc/php_odbc.c +++ b/ext/odbc/php_odbc.c @@ -246,7 +246,7 @@ static void _close_odbc_pconn(zend_rsrc_list_entry *rsrc TSRMLS_DC) odbc_result *res; odbc_connection *conn = (odbc_connection *)rsrc->ptr; - nument = zend_hash_next_free_element(&EG(regular_list)); + nument = zend_hash_next_free_element(&EG(persistent_list)); for(i = 1; i < nument; i++) { ptr = zend_list_find(i, &type); if (ptr && (type == le_result)) { @@ -1232,8 +1232,8 @@ PHP_FUNCTION(odbc_data_source) array_init(return_value); - add_assoc_stringl_ex(return_value, "server", sizeof("server"), server_name, len1, 1); - add_assoc_stringl_ex(return_value, "description", sizeof("description"), desc, len2, 1); + add_assoc_string_ex(return_value, "server", sizeof("server"), server_name, 1); + add_assoc_string_ex(return_value, "description", sizeof("description"), desc, 1); } /* }}} */ @@ -2423,10 +2423,7 @@ PHP_FUNCTION(odbc_next_result) result->fetched = 0; rc = SQLMoreResults(result->stmt); - if (rc == SQL_SUCCESS) { - RETURN_TRUE; - } - else if (rc == SQL_SUCCESS_WITH_INFO) { + if (rc == SQL_SUCCESS_WITH_INFO || rc == SQL_SUCCESS) { rc = SQLFreeStmt(result->stmt, SQL_UNBIND); SQLNumParams(result->stmt, &(result->numparams)); SQLNumResultCols(result->stmt, &(result->numcols)); @@ -2440,8 +2437,10 @@ PHP_FUNCTION(odbc_next_result) result->values = NULL; } RETURN_TRUE; - } - else { + } else if (rc == SQL_NO_DATA_FOUND) { + RETURN_FALSE; + } else { + odbc_sql_error(result->conn_ptr, result->stmt, "SQLMoreResults"); RETURN_FALSE; } } @@ -2670,15 +2669,17 @@ static void php_odbc_lasterror(INTERNAL_FUNCTION_PARAMETERS, int mode) } else { /* last error message */ len = SQL_MAX_MESSAGE_LENGTH; } - ptr = ecalloc(len + 1, 1); + if (argc == 1) { ZEND_FETCH_RESOURCE2(conn, odbc_connection *, pv_handle, -1, "ODBC-Link", le_conn, le_pconn); + ptr = ecalloc(len + 1, 1); if (mode == 0) { strlcpy(ptr, conn->laststate, len+1); } else { strlcpy(ptr, conn->lasterrormsg, len+1); } } else { + ptr = ecalloc(len + 1, 1); if (mode == 0) { strlcpy(ptr, ODBCG(laststate), len+1); } else { @@ -2765,7 +2766,7 @@ PHP_FUNCTION(odbc_setoption) * metadata functions */ -/* {{{ proto resource odbc_tables(resource connection_id [, string qualifier, string owner, string name, string table_types]) +/* {{{ proto resource odbc_tables(resource connection_id [, string qualifier [, string owner [, string name [, string table_types]]]]) Call the SQLTables function */ PHP_FUNCTION(odbc_tables) { @@ -2844,7 +2845,7 @@ PHP_FUNCTION(odbc_tables) } /* }}} */ -/* {{{ proto resource odbc_columns(resource connection_id, string qualifier, string owner, string table_name, string column_name) +/* {{{ proto resource odbc_columns(resource connection_id [, string qualifier [, string owner [, string table_name [, string column_name]]]]) Returns a result identifier that can be used to fetch a list of column names in specified tables */ PHP_FUNCTION(odbc_columns) { diff --git a/ext/odbc/php_odbc.h b/ext/odbc/php_odbc.h index 3eefbe06f45c..d9ef253e07b2 100644 --- a/ext/odbc/php_odbc.h +++ b/ext/odbc/php_odbc.h @@ -33,7 +33,7 @@ extern zend_module_entry odbc_module_entry; #define odbc_module_ptr &odbc_module_entry -#if defined(HAVE_DBMAKER) || defined(PHP_WIN32) || defined(HAVE_IBMDB2) || defined(HAVE_UNIXODBC) +#if defined(HAVE_DBMAKER) || defined(PHP_WIN32) || defined(HAVE_IBMDB2) || defined(HAVE_UNIXODBC) || defined(HAVE_BIRDSTEP) # define PHP_ODBC_HAVE_FETCH_HASH 1 #endif diff --git a/ext/odbc/php_odbc_includes.h b/ext/odbc/php_odbc_includes.h index 4a2f1ec1764a..36eedcec408a 100644 --- a/ext/odbc/php_odbc_includes.h +++ b/ext/odbc/php_odbc_includes.h @@ -216,7 +216,7 @@ typedef struct odbc_connection { typedef struct odbc_result_value { char name[32]; char *value; - long int vallen; + SDWORD vallen; SDWORD coltype; } odbc_result_value; diff --git a/ext/openssl/config0.m4 b/ext/openssl/config0.m4 index 157c35b66b5d..a51d9e193084 100644 --- a/ext/openssl/config0.m4 +++ b/ext/openssl/config0.m4 @@ -5,11 +5,19 @@ dnl PHP_ARG_WITH(openssl, for OpenSSL support, [ --with-openssl[=DIR] Include OpenSSL support (requires OpenSSL >= 0.9.6)]) +PHP_ARG_WITH(kerberos, for Kerberos support, +[ --with-kerberos[=DIR] OPENSSL: Include Kerberos support], no, no) + if test "$PHP_OPENSSL" != "no"; then + PHP_NEW_EXTENSION(openssl, openssl.c xp_ssl.c, $ext_shared) + PHP_SUBST(OPENSSL_SHARED_LIBADD) + + if test "$PHP_KERBEROS" != "no"; then + PHP_SETUP_KERBEROS(OPENSSL_SHARED_LIBADD) + fi + PHP_SETUP_OPENSSL(OPENSSL_SHARED_LIBADD, [ - PHP_NEW_EXTENSION(openssl, openssl.c xp_ssl.c, $ext_shared) - PHP_SUBST(OPENSSL_SHARED_LIBADD) AC_DEFINE(HAVE_OPENSSL_EXT,1,[ ]) ], [ AC_MSG_ERROR([OpenSSL check failed. Please check config.log for more information.]) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 002fd477481c..758e734f0187 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -135,7 +135,7 @@ zend_module_entry openssl_module_entry = { "openssl", openssl_functions, PHP_MINIT(openssl), - NULL, + PHP_MSHUTDOWN(openssl), NULL, NULL, PHP_MINFO(openssl), @@ -227,9 +227,9 @@ static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req static void add_assoc_name_entry(zval * val, char * key, X509_NAME * name, int shortname TSRMLS_DC) { - zval * subitem; - int i; - char * sn, * ln; + zval *subitem, *subentries; + int i, j = -1, last = -1, obj_cnt = 0; + char *sname; int nid; X509_NAME_ENTRY * ne; ASN1_STRING * str; @@ -241,14 +241,41 @@ static void add_assoc_name_entry(zval * val, char * key, X509_NAME * name, int s for (i = 0; i < X509_NAME_entry_count(name); i++) { ne = X509_NAME_get_entry(name, i); obj = X509_NAME_ENTRY_get_object(ne); - str = X509_NAME_ENTRY_get_data(ne); nid = OBJ_obj2nid(obj); + obj_cnt = 0; + if (shortname) { - sn = (char*)OBJ_nid2sn(nid); - add_assoc_stringl(subitem, sn, str->data, str->length, 1); + sname = (char *) OBJ_nid2sn(nid); + } else { + sname = (char *) OBJ_nid2ln(nid); + } + + MAKE_STD_ZVAL(subentries); + array_init(subentries); + + last = -1; + for (;;) { + j = X509_NAME_get_index_by_OBJ(name, obj, last); + if (j < 0) { + if (last != -1) break; + } else { + obj_cnt++; + ne = X509_NAME_get_entry(name, j); + str = X509_NAME_ENTRY_get_data(ne); + add_next_index_stringl(subentries, str->data, str->length, 1); + } + last = j; + } + i = last; + + if (obj_cnt > 1) { + add_assoc_zval_ex(subitem, sname, strlen(sname) + 1, subentries); } else { - ln = (char*)OBJ_nid2ln(nid); - add_assoc_stringl(subitem, ln, str->data, str->length, 1); + zval_dtor(subentries); + FREE_ZVAL(subentries); + if (obj_cnt) { + add_assoc_stringl(subitem, sname, str->data, str->length, 1); + } } } zend_hash_update(HASH_OF(val), key, strlen(key) + 1, (void *)&subitem, sizeof(subitem), NULL); @@ -632,6 +659,8 @@ PHP_MINIT_FUNCTION(openssl) } php_stream_xport_register("ssl", php_openssl_ssl_socket_factory TSRMLS_CC); + php_stream_xport_register("sslv3", php_openssl_ssl_socket_factory TSRMLS_CC); + php_stream_xport_register("sslv2", php_openssl_ssl_socket_factory TSRMLS_CC); php_stream_xport_register("tls", php_openssl_ssl_socket_factory TSRMLS_CC); /* override the default tcp socket provider */ @@ -665,6 +694,8 @@ PHP_MSHUTDOWN_FUNCTION(openssl) php_unregister_url_stream_wrapper("ftps" TSRMLS_CC); php_stream_xport_unregister("ssl" TSRMLS_CC); + php_stream_xport_unregister("sslv2" TSRMLS_CC); + php_stream_xport_unregister("sslv3" TSRMLS_CC); php_stream_xport_unregister("tls" TSRMLS_CC); /* reinstate the default tcp handler */ @@ -1666,11 +1697,18 @@ PHP_FUNCTION(openssl_csr_new) if (we_made_the_key) { /* and a resource for the private key */ ZVAL_RESOURCE(out_pkey, zend_list_insert(req.priv_key, le_key)); + req.priv_key = NULL; /* make sure the cleanup code doesn't zap it! */ } else if (key_resource != -1) { req.priv_key = NULL; /* make sure the cleanup code doesn't zap it! */ } } } + else { + if (!we_made_the_key) { + /* if we have not made the key we are not supposed to zap it by calling dispose! */ + req.priv_key = NULL; + } + } } } } @@ -2573,7 +2611,7 @@ PHP_FUNCTION(openssl_private_encrypt) cryptedlen = EVP_PKEY_size(pkey); cryptedbuf = emalloc(cryptedlen + 1); - switch (Z_TYPE_P(pkey)) { + switch (pkey->type) { case EVP_PKEY_RSA: case EVP_PKEY_RSA2: successful = (RSA_private_encrypt(data_len, @@ -2631,7 +2669,7 @@ PHP_FUNCTION(openssl_private_decrypt) cryptedlen = EVP_PKEY_size(pkey); crypttemp = emalloc(cryptedlen + 1); - switch (Z_TYPE_P(pkey)) { + switch (pkey->type) { case EVP_PKEY_RSA: case EVP_PKEY_RSA2: cryptedlen = RSA_private_decrypt(data_len, @@ -2696,7 +2734,7 @@ PHP_FUNCTION(openssl_public_encrypt) cryptedlen = EVP_PKEY_size(pkey); cryptedbuf = emalloc(cryptedlen + 1); - switch (Z_TYPE_P(pkey)) { + switch (pkey->type) { case EVP_PKEY_RSA: case EVP_PKEY_RSA2: successful = (RSA_public_encrypt(data_len, @@ -2755,7 +2793,7 @@ PHP_FUNCTION(openssl_public_decrypt) cryptedlen = EVP_PKEY_size(pkey); crypttemp = emalloc(cryptedlen + 1); - switch (Z_TYPE_P(pkey)) { + switch (pkey->type) { case EVP_PKEY_RSA: case EVP_PKEY_RSA2: cryptedlen = RSA_public_decrypt(data_len, diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 4171312907db..1cb3b401f154 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -235,9 +235,7 @@ static int php_openssl_sockop_close(php_stream *stream, int close_handle TSRMLS_ { php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract; #ifdef PHP_WIN32 - fd_set wrfds, efds; int n; - struct timeval timeout; #endif if (close_handle) { if (sslsock->ssl_active) { @@ -248,7 +246,7 @@ static int php_openssl_sockop_close(php_stream *stream, int close_handle TSRMLS_ SSL_free(sslsock->ssl_handle); sslsock->ssl_handle = NULL; } - if (sslsock->s.socket != -1) { + if (sslsock->s.socket != SOCK_ERR) { #ifdef PHP_WIN32 /* prevent more data from coming in */ shutdown(sslsock->s.socket, SHUT_RD); @@ -260,19 +258,11 @@ static int php_openssl_sockop_close(php_stream *stream, int close_handle TSRMLS_ * but at the same time avoid hanging indefintely. * */ do { - FD_ZERO(&wrfds); - FD_SET(sslsock->s.socket, &wrfds); - efds = wrfds; - - timeout.tv_sec = 0; - timeout.tv_usec = 5000; /* arbitrary */ - - n = select(sslsock->s.socket + 1, NULL, &wrfds, &efds, &timeout); + n = php_pollfd_for_ms(sslsock->s.socket, POLLOUT, 500); } while (n == -1 && php_socket_errno() == EINTR); #endif - closesocket(sslsock->s.socket); - sslsock->s.socket = -1; + sslsock->s.socket = SOCK_ERR; } } @@ -507,52 +497,52 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val switch (option) { case PHP_STREAM_OPTION_CHECK_LIVENESS: { - fd_set rfds; struct timeval tv; char buf; int alive = 1; - if (sslsock->s.timeout.tv_sec == -1) { - tv.tv_sec = FG(default_socket_timeout); + if (value == -1) { + if (sslsock->s.timeout.tv_sec == -1) { + tv.tv_sec = FG(default_socket_timeout); + tv.tv_usec = 0; + } else { + tv = sslsock->s.timeout; + } } else { - tv = sslsock->s.timeout; + tv.tv_sec = value; + tv.tv_usec = 0; } if (sslsock->s.socket == -1) { alive = 0; - } else { - FD_ZERO(&rfds); - FD_SET(sslsock->s.socket, &rfds); - - if (select(sslsock->s.socket + 1, &rfds, NULL, NULL, &tv) > 0 && FD_ISSET(sslsock->s.socket, &rfds)) { - if (sslsock->ssl_active) { - int n; - - do { - n = SSL_peek(sslsock->ssl_handle, &buf, sizeof(buf)); - if (n <= 0) { - int err = SSL_get_error(sslsock->ssl_handle, n); - - if (err == SSL_ERROR_SYSCALL) { - alive = php_socket_errno() == EAGAIN; - break; - } - - if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { - /* re-negotiate */ - continue; - } - - /* any other problem is a fatal error */ - alive = 0; + } else if (php_pollfd_for(sslsock->s.socket, PHP_POLLREADABLE|POLLPRI, &tv) > 0) { + if (sslsock->ssl_active) { + int n; + + do { + n = SSL_peek(sslsock->ssl_handle, &buf, sizeof(buf)); + if (n <= 0) { + int err = SSL_get_error(sslsock->ssl_handle, n); + + if (err == SSL_ERROR_SYSCALL) { + alive = php_socket_errno() == EAGAIN; + break; } - /* either peek succeeded or there was an error; we - * have set the alive flag appropriately */ - break; - } while (1); - } else if (0 == recv(sslsock->s.socket, &buf, sizeof(buf), MSG_PEEK) && php_socket_errno() != EAGAIN) { - alive = 0; - } + + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { + /* re-negotiate */ + continue; + } + + /* any other problem is a fatal error */ + alive = 0; + } + /* either peek succeeded or there was an error; we + * have set the alive flag appropriately */ + break; + } while (1); + } else if (0 == recv(sslsock->s.socket, &buf, sizeof(buf), MSG_PEEK) && php_socket_errno() != EAGAIN) { + alive = 0; } } return alive ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR; @@ -691,6 +681,12 @@ php_stream *php_openssl_ssl_socket_factory(const char *proto, long protolen, if (strncmp(proto, "ssl", protolen) == 0) { sslsock->enable_on_connect = 1; sslsock->method = STREAM_CRYPTO_METHOD_SSLv23_CLIENT; + } else if (strncmp(proto, "sslv2", protolen) == 0) { + sslsock->enable_on_connect = 1; + sslsock->method = STREAM_CRYPTO_METHOD_SSLv2_CLIENT; + } else if (strncmp(proto, "sslv3", protolen) == 0) { + sslsock->enable_on_connect = 1; + sslsock->method = STREAM_CRYPTO_METHOD_SSLv3_CLIENT; } else if (strncmp(proto, "tls", protolen) == 0) { sslsock->enable_on_connect = 1; sslsock->method = STREAM_CRYPTO_METHOD_TLS_CLIENT; diff --git a/ext/oracle/config.m4 b/ext/oracle/config.m4 index fdd5276ccde1..96895b44084f 100644 --- a/ext/oracle/config.m4 +++ b/ext/oracle/config.m4 @@ -2,7 +2,7 @@ dnl dnl $Id$ dnl -AC_DEFUN(AC_ORACLE_VERSION,[ +AC_DEFUN([AC_ORACLE_VERSION],[ AC_MSG_CHECKING([Oracle version]) if test -s "$ORACLE_DIR/orainst/unix.rgs"; then ORACLE_VERSION=`grep '"ocommon"' $ORACLE_DIR/orainst/unix.rgs | sed 's/[ ][ ]*/:/g' | cut -d: -f 6 | cut -c 2-4` diff --git a/ext/pcntl/pcntl.c b/ext/pcntl/pcntl.c index 8aa929001121..b3a0efb76843 100755 --- a/ext/pcntl/pcntl.c +++ b/ext/pcntl/pcntl.c @@ -56,8 +56,12 @@ function_entry pcntl_functions[] = { PHP_FE(pcntl_wstopsig, NULL) PHP_FE(pcntl_exec, NULL) PHP_FE(pcntl_alarm, NULL) +#ifdef HAVE_GETPRIORITY PHP_FE(pcntl_getpriority, NULL) +#endif +#ifdef HAVE_SETPRIORITY PHP_FE(pcntl_setpriority, NULL) +#endif {NULL, NULL, NULL} }; @@ -144,8 +148,10 @@ void php_register_signal_constants(INIT_FUNC_ARGS) #ifdef SIGPWR REGISTER_LONG_CONSTANT("SIGPWR", (long) SIGPWR, CONST_CS | CONST_PERSISTENT); #endif +#ifdef SIGSYS REGISTER_LONG_CONSTANT("SIGSYS", (long) SIGSYS, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SIGBABY", (long) SIGSYS, CONST_CS | CONST_PERSISTENT); +#endif #if HAVE_GETPRIORITY || HAVE_SETPRIORITY REGISTER_LONG_CONSTANT("PRIO_PGRP", PRIO_PGRP, CONST_CS | CONST_PERSISTENT); @@ -156,17 +162,13 @@ void php_register_signal_constants(INIT_FUNC_ARGS) static void php_pcntl_init_globals(zend_pcntl_globals *pcntl_globals) { - /* Just in case ... */ - memset(&pcntl_globals->php_signal_queue,0,sizeof(pcntl_globals->php_signal_queue)); - - zend_llist_init(&pcntl_globals->php_signal_queue, sizeof (long), NULL, 1); - pcntl_globals->signal_queue_ready = 0; - pcntl_globals->processing_signal_queue = 0; + memset(pcntl_globals, 0, sizeof(*pcntl_globals)); } PHP_RINIT_FUNCTION(pcntl) { - zend_hash_init(&PCNTL_G(php_signal_table), 16, NULL, ZVAL_PTR_DTOR, 1); + zend_hash_init(&PCNTL_G(php_signal_table), 16, NULL, ZVAL_PTR_DTOR, 0); + PCNTL_G(head) = PCNTL_G(tail) = PCNTL_G(spares) = NULL; return SUCCESS; } @@ -181,13 +183,26 @@ PHP_MINIT_FUNCTION(pcntl) PHP_MSHUTDOWN_FUNCTION(pcntl) { - zend_llist_destroy(&PCNTL_G(php_signal_queue)); return SUCCESS; } PHP_RSHUTDOWN_FUNCTION(pcntl) { + struct php_pcntl_pending_signal *sig; + + /* FIXME: if a signal is delivered after this point, things will go pear shaped; + * need to remove signal handlers */ zend_hash_destroy(&PCNTL_G(php_signal_table)); + while (PCNTL_G(head)) { + sig = PCNTL_G(head); + PCNTL_G(head) = sig->next; + efree(sig); + } + while (PCNTL_G(spares)) { + sig = PCNTL_G(spares); + PCNTL_G(spares) = sig->next; + efree(sig); + } return SUCCESS; } @@ -514,6 +529,19 @@ PHP_FUNCTION(pcntl_signal) return; } + if (!PCNTL_G(spares)) { + /* since calling malloc() from within a signal handler is not portable, + * pre-allocate a few records for recording signals */ + int i; + for (i = 0; i < 32; i++) { + struct php_pcntl_pending_signal *psig; + + psig = emalloc(sizeof(*psig)); + psig->next = PCNTL_G(spares); + PCNTL_G(spares) = psig; + } + } + /* Special long value case for SIG_DFL and SIG_IGN */ if (Z_TYPE_P(handle)==IS_LONG) { if (Z_LVAL_P(handle)!= (long) SIG_DFL && Z_LVAL_P(handle) != (long) SIG_IGN) { @@ -625,57 +653,63 @@ PHP_FUNCTION(pcntl_setpriority) /* Our custom signal handler that calls the appropriate php_function */ static void pcntl_signal_handler(int signo) { - long signal_num = signo; + struct php_pcntl_pending_signal *psig; TSRMLS_FETCH(); - IF_DEBUG(DEBUG_OUT("Caught signo %d\n", signo)); - if (! PCNTL_G(processing_signal_queue)) { - zend_llist_add_element(&PCNTL_G(php_signal_queue), &signal_num); - PCNTL_G(signal_queue_ready) = 1; - IF_DEBUG(DEBUG_OUT("Added queue entry\n")); + psig = PCNTL_G(spares); + if (!psig) { + /* oops, too many signals for us to track, so we'll forget about this one */ + return; } - return; + PCNTL_G(spares) = psig->next; + + psig->signo = signo; + psig->next = NULL; + + /* the head check is important, as the tick handler cannot atomically clear both + * the head and tail */ + if (PCNTL_G(head) && PCNTL_G(tail)) { + PCNTL_G(tail)->next = psig; + } else { + PCNTL_G(head) = psig; + } + PCNTL_G(tail) = psig; } void pcntl_tick_handler() { - zend_llist_element *element; zval *param, **handle, *retval; + struct php_pcntl_pending_signal *queue, *next; TSRMLS_FETCH(); /* Bail if the queue is empty or if we are already playing the queue*/ - if (! PCNTL_G(signal_queue_ready) || PCNTL_G(processing_signal_queue)) + if (! PCNTL_G(head) || PCNTL_G(processing_signal_queue)) return; - /* Mark our queue empty */ - PCNTL_G(signal_queue_ready) = 0; - - /* If for some reason our signal queue is empty then return */ - if (zend_llist_count(&PCNTL_G(php_signal_queue)) <= 0) { - return; - } - /* Prevent reentrant handler calls */ PCNTL_G(processing_signal_queue) = 1; + queue = PCNTL_G(head); + PCNTL_G(head) = NULL; /* simple stores are atomic */ + /* Allocate */ MAKE_STD_ZVAL(param); MAKE_STD_ZVAL(retval); - /* Traverse through our signal queue and call the appropriate php functions */ - for (element = (&PCNTL_G(php_signal_queue))->head; element; element = element->next) { - long *signal_num = (long *)&element->data; - if (zend_hash_index_find(&PCNTL_G(php_signal_table), *signal_num, (void **) &handle)==FAILURE) { - continue; + while (queue) { + if (zend_hash_index_find(&PCNTL_G(php_signal_table), queue->signo, (void **) &handle)==SUCCESS) { + ZVAL_LONG(param, queue->signo); + + /* Call php signal handler - Note that we do not report errors, and we ignore the return value */ + /* FIXME: this is probably broken when multiple signals are handled in this while loop (retval) */ + call_user_function(EG(function_table), NULL, *handle, retval, 1, ¶m TSRMLS_CC); } - ZVAL_LONG(param, *signal_num); - - /* Call php signal handler - Note that we do not report errors, and we ignore the return value */ - call_user_function(EG(function_table), NULL, *handle, retval, 1, ¶m TSRMLS_CC); + next = queue->next; + queue->next = PCNTL_G(spares); + PCNTL_G(spares) = queue; + queue = next; } - /* Clear */ - zend_llist_clean(&PCNTL_G(php_signal_queue)); /* Re-enable queue */ PCNTL_G(processing_signal_queue) = 0; @@ -685,6 +719,8 @@ void pcntl_tick_handler() efree(retval); } + + /* * Local variables: * tab-width: 4 diff --git a/ext/pcntl/php_pcntl.h b/ext/pcntl/php_pcntl.h index b9ac364f856a..762d2498681b 100644 --- a/ext/pcntl/php_pcntl.h +++ b/ext/pcntl/php_pcntl.h @@ -51,15 +51,24 @@ PHP_FUNCTION(pcntl_wtermsig); PHP_FUNCTION(pcntl_wstopsig); PHP_FUNCTION(pcntl_signal); PHP_FUNCTION(pcntl_exec); +#ifdef HAVE_GETPRIORITY PHP_FUNCTION(pcntl_getpriority); +#endif +#ifdef HAVE_SETPRIORITY PHP_FUNCTION(pcntl_setpriority); +#endif + +struct php_pcntl_pending_signal { + struct php_pcntl_pending_signal *next; + long signo; +}; ZEND_BEGIN_MODULE_GLOBALS(pcntl) HashTable php_signal_table; - zend_llist php_signal_queue; - int signal_queue_ready; int processing_signal_queue; + struct php_pcntl_pending_signal *head, *tail, *spares; ZEND_END_MODULE_GLOBALS(pcntl) + #ifdef ZTS #define PCNTL_G(v) TSRMG(pcntl_globals_id, zend_pcntl_globals *, v) #else diff --git a/ext/pcntl/test-pcntl.php b/ext/pcntl/test-pcntl.php index 6b3ee5649ef9..01d44fcad45c 100755 --- a/ext/pcntl/test-pcntl.php +++ b/ext/pcntl/test-pcntl.php @@ -4,11 +4,11 @@ declare(ticks=1); function alarm_handle($signal){ - if ($signal==SIGALRM) print "Caught SIGALRM!!!\n"; + if ($signal==SIGALRM) print "Child: Caught SIGALRM!!!\n"; } function usr1_handle($signal){ - if ($signal==SIGUSR1) print "Caught SIGUSR1!!!\n"; + if ($signal==SIGUSR1) print "Child: Caught SIGUSR1!!!\n"; } print "This test will demonstrate a fork followed by ipc via signals.\n"; @@ -23,6 +23,7 @@ function usr1_handle($signal){ sleep(100); print "Child: Resetting Alarm handler to Ignore....\n"; pcntl_signal(SIGALRM, SIG_IGN); + print "Child: sleeping for 10 seconds....\n"; sleep(10); print "Done\n"; } else { @@ -33,7 +34,7 @@ function usr1_handle($signal){ sleep(1); print "Parent: Senging SIGUSR1 to Child\n"; posix_kill($pid,SIGUSR1); - sleep(1); + sleep(2); print "Parent: Sending SIGALRM to Child\n"; pcntl_waitpid($pid, &$status, $options); } diff --git a/ext/pcntl/tests/001.phpt b/ext/pcntl/tests/001.phpt index 0c8e77ec6c0b..74c529124bf7 100644 --- a/ext/pcntl/tests/001.phpt +++ b/ext/pcntl/tests/001.phpt @@ -3,7 +3,7 @@ Test pcntl wait functionality --SKIPIF-- --FILE-- = 2.08]) - fi - - PHP_ADD_LIBRARY_WITH_PATH(pcre, $PCRE_LIBDIR, PCRE_SHARED_LIBADD) - - AC_DEFINE(HAVE_PCRE, 1, [ ]) - PHP_ADD_INCLUDE($PCRE_INCDIR) - PHP_NEW_EXTENSION(pcre, php_pcre.c, $ext_shared,,-DSUPPORT_UTF8 -DLINK_SIZE=2 -DPOSIX_MALLOC_THRESHOLD=10) - fi - PHP_SUBST(PCRE_SHARED_LIBADD) -fi diff --git a/ext/pcre/pcrelib/AUTHORS b/ext/pcre/pcrelib/AUTHORS index 622ba1c9a921..33df90f8df3e 100644 --- a/ext/pcre/pcrelib/AUTHORS +++ b/ext/pcre/pcrelib/AUTHORS @@ -1,6 +1,23 @@ -Written by: Philip Hazel +THE MAIN PCRE LIBRARY +--------------------- + +Written by: Philip Hazel +Email local part: ph10 +Email domain: cam.ac.uk University of Cambridge Computing Service, Cambridge, England. Phone: +44 1223 334714. -Copyright (c) 1997-2003 University of Cambridge +Copyright (c) 1997-2005 University of Cambridge +All rights reserved + + +THE C++ WRAPPER LIBRARY +----------------------- + +Written by: Google Inc. + +Copyright (c) 2005 Google Inc +All rights reserved + +#### diff --git a/ext/pcre/pcrelib/COPYING b/ext/pcre/pcrelib/COPYING index 09a242c10113..e8eb0d937032 100644 --- a/ext/pcre/pcrelib/COPYING +++ b/ext/pcre/pcrelib/COPYING @@ -4,51 +4,65 @@ PCRE LICENCE PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. -Written by: Philip Hazel +Release 6 of PCRE is distributed under the terms of the "BSD" licence, as +specified below. The documentation for PCRE, supplied in the "doc" +directory, is distributed under the same terms as the software itself. + +The basic library functions are written in C and are freestanding. Also +included in the distribution is a set of C++ wrapper functions. + + +THE BASIC LIBRARY FUNCTIONS +--------------------------- + +Written by: Philip Hazel +Email local part: ph10 +Email domain: cam.ac.uk University of Cambridge Computing Service, Cambridge, England. Phone: +44 1223 334714. -Copyright (c) 1997-2003 University of Cambridge +Copyright (c) 1997-2005 University of Cambridge +All rights reserved. + -Permission is granted to anyone to use this software for any purpose on any -computer system, and to redistribute it freely, subject to the following -restrictions: +THE C++ WRAPPER FUNCTIONS +------------------------- -1. This software is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +Contributed by: Google Inc. -2. The origin of this software must not be misrepresented, either by - explicit claim or by omission. In practice, this means that if you use - PCRE in software that you distribute to others, commercially or - otherwise, you must put a sentence like this +Copyright (c) 2005, Google Inc. +All rights reserved. - Regular expression support is provided by the PCRE library package, - which is open source software, written by Philip Hazel, and copyright - by the University of Cambridge, England. - somewhere reasonably visible in your documentation and in any relevant - files or online help data or similar. A reference to the ftp site for - the source, that is, to +THE "BSD" LICENCE +----------------- - ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/ +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: - should also be given in the documentation. However, this condition is not - intended to apply to whole chains of software. If package A includes PCRE, - it must acknowledge it, but if package B is software that includes package - A, the condition is not imposed on package B (unless it uses PCRE - independently). + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. -3. Altered versions must be plainly marked as such, and must not be - misrepresented as being the original software. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. -4. If PCRE is embedded in any software that is released under the GNU - General Purpose Licence (GPL), or Lesser General Purpose Licence (LGPL), - then the terms of that licence shall supersede any condition above with - which it is incompatible. + * Neither the name of the University of Cambridge nor the name of Google + Inc. nor the names of their contributors may be used to endorse or + promote products derived from this software without specific prior + written permission. -The documentation for PCRE, supplied in the "doc" directory, is distributed -under the same terms as the software itself. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. End diff --git a/ext/pcre/pcrelib/ChangeLog b/ext/pcre/pcrelib/ChangeLog index edc4aea49e84..b9d74d393f71 100644 --- a/ext/pcre/pcrelib/ChangeLog +++ b/ext/pcre/pcrelib/ChangeLog @@ -1,6 +1,357 @@ ChangeLog for PCRE ------------------ +Version 6.2 01-Aug-05 +--------------------- + + 1. There was no test for integer overflow of quantifier values. A construction + such as {1111111111111111} would give undefined results. What is worse, if + a minimum quantifier for a parenthesized subpattern overflowed and became + negative, the calculation of the memory size went wrong. This could have + led to memory overwriting. + + 2. Building PCRE using VPATH was broken. Hopefully it is now fixed. + + 3. Added "b" to the 2nd argument of fopen() in dftables.c, for non-Unix-like + operating environments where this matters. + + 4. Applied Giuseppe Maxia's patch to add additional features for controlling + PCRE options from within the C++ wrapper. + + 5. Named capturing subpatterns were not being correctly counted when a pattern + was compiled. This caused two problems: (a) If there were more than 100 + such subpatterns, the calculation of the memory needed for the whole + compiled pattern went wrong, leading to an overflow error. (b) Numerical + back references of the form \12, where the number was greater than 9, were + not recognized as back references, even though there were sufficient + previous subpatterns. + + 6. Two minor patches to pcrecpp.cc in order to allow it to compile on older + versions of gcc, e.g. 2.95.4. + + +Version 6.1 21-Jun-05 +--------------------- + + 1. There was one reference to the variable "posix" in pcretest.c that was not + surrounded by "#if !defined NOPOSIX". + + 2. Make it possible to compile pcretest without DFA support, UTF8 support, or + the cross-check on the old pcre_info() function, for the benefit of the + cut-down version of PCRE that is currently imported into Exim. + + 3. A (silly) pattern starting with (?i)(?-i) caused an internal space + allocation error. I've done the easy fix, which wastes 2 bytes for sensible + patterns that start (?i) but I don't think that matters. The use of (?i) is + just an example; this all applies to the other options as well. + + 4. Since libtool seems to echo the compile commands it is issuing, the output + from "make" can be reduced a bit by putting "@" in front of each libtool + compile command. + + 5. Patch from the folks at Google for configure.in to be a bit more thorough + in checking for a suitable C++ installation before trying to compile the + C++ stuff. This should fix a reported problem when a compiler was present, + but no suitable headers. + + 6. The man pages all had just "PCRE" as their title. I have changed them to + be the relevant file name. I have also arranged that these names are + retained in the file doc/pcre.txt, which is a concatenation in text format + of all the man pages except the little individual ones for each function. + + 7. The NON-UNIX-USE file had not been updated for the different set of source + files that come with release 6. I also added a few comments about the C++ + wrapper. + + +Version 6.0 07-Jun-05 +--------------------- + + 1. Some minor internal re-organization to help with my DFA experiments. + + 2. Some missing #ifdef SUPPORT_UCP conditionals in pcretest and printint that + didn't matter for the library itself when fully configured, but did matter + when compiling without UCP support, or within Exim, where the ucp files are + not imported. + + 3. Refactoring of the library code to split up the various functions into + different source modules. The addition of the new DFA matching code (see + below) to a single monolithic source would have made it really too + unwieldy, quite apart from causing all the code to be include in a + statically linked application, when only some functions are used. This is + relevant even without the DFA addition now that patterns can be compiled in + one application and matched in another. + + The downside of splitting up is that there have to be some external + functions and data tables that are used internally in different modules of + the library but which are not part of the API. These have all had their + names changed to start with "_pcre_" so that they are unlikely to clash + with other external names. + + 4. Added an alternate matching function, pcre_dfa_exec(), which matches using + a different (DFA) algorithm. Although it is slower than the original + function, it does have some advantages for certain types of matching + problem. + + 5. Upgrades to pcretest in order to test the features of pcre_dfa_exec(), + including restarting after a partial match. + + 6. A patch for pcregrep that defines INVALID_FILE_ATTRIBUTES if it is not + defined when compiling for Windows was sent to me. I have put it into the + code, though I have no means of testing or verifying it. + + 7. Added the pcre_refcount() auxiliary function. + + 8. Added the PCRE_FIRSTLINE option. This constrains an unanchored pattern to + match before or at the first newline in the subject string. In pcretest, + the /f option on a pattern can be used to set this. + + 9. A repeated \w when used in UTF-8 mode with characters greater than 256 + would behave wrongly. This has been present in PCRE since release 4.0. + +10. A number of changes to the pcregrep command: + + (a) Refactored how -x works; insert ^(...)$ instead of setting + PCRE_ANCHORED and checking the length, in preparation for adding + something similar for -w. + + (b) Added the -w (match as a word) option. + + (c) Refactored the way lines are read and buffered so as to have more + than one at a time available. + + (d) Implemented a pcregrep test script. + + (e) Added the -M (multiline match) option. This allows patterns to match + over several lines of the subject. The buffering ensures that at least + 8K, or the rest of the document (whichever is the shorter) is available + for matching (and similarly the previous 8K for lookbehind assertions). + + (f) Changed the --help output so that it now says + + -w, --word-regex(p) + + instead of two lines, one with "regex" and the other with "regexp" + because that confused at least one person since the short forms are the + same. (This required a bit of code, as the output is generated + automatically from a table. It wasn't just a text change.) + + (g) -- can be used to terminate pcregrep options if the next thing isn't an + option but starts with a hyphen. Could be a pattern or a path name + starting with a hyphen, for instance. + + (h) "-" can be given as a file name to represent stdin. + + (i) When file names are being printed, "(standard input)" is used for + the standard input, for compatibility with GNU grep. Previously + "" was used. + + (j) The option --label=xxx can be used to supply a name to be used for + stdin when file names are being printed. There is no short form. + + (k) Re-factored the options decoding logic because we are going to add + two more options that take data. Such options can now be given in four + different ways, e.g. "-fname", "-f name", "--file=name", "--file name". + + (l) Added the -A, -B, and -C options for requesting that lines of context + around matches be printed. + + (m) Added the -L option to print the names of files that do not contain + any matching lines, that is, the complement of -l. + + (n) The return code is 2 if any file cannot be opened, but pcregrep does + continue to scan other files. + + (o) The -s option was incorrectly implemented. For compatibility with other + greps, it now suppresses the error message for a non-existent or non- + accessible file (but not the return code). There is a new option called + -q that suppresses the output of matching lines, which was what -s was + previously doing. + + (p) Added --include and --exclude options to specify files for inclusion + and exclusion when recursing. + +11. The Makefile was not using the Autoconf-supported LDFLAGS macro properly. + Hopefully, it now does. + +12. Missing cast in pcre_study(). + +13. Added an "uninstall" target to the makefile. + +14. Replaced "extern" in the function prototypes in Makefile.in with + "PCRE_DATA_SCOPE", which defaults to 'extern' or 'extern "C"' in the Unix + world, but is set differently for Windows. + +15. Added a second compiling function called pcre_compile2(). The only + difference is that it has an extra argument, which is a pointer to an + integer error code. When there is a compile-time failure, this is set + non-zero, in addition to the error test pointer being set to point to an + error message. The new argument may be NULL if no error number is required + (but then you may as well call pcre_compile(), which is now just a + wrapper). This facility is provided because some applications need a + numeric error indication, but it has also enabled me to tidy up the way + compile-time errors are handled in the POSIX wrapper. + +16. Added VPATH=.libs to the makefile; this should help when building with one + prefix path and installing with another. (Or so I'm told by someone who + knows more about this stuff than I do.) + +17. Added a new option, REG_DOTALL, to the POSIX function regcomp(). This + passes PCRE_DOTALL to the pcre_compile() function, making the "." character + match everything, including newlines. This is not POSIX-compatible, but + somebody wanted the feature. From pcretest it can be activated by using + both the P and the s flags. + +18. AC_PROG_LIBTOOL appeared twice in Makefile.in. Removed one. + +19. libpcre.pc was being incorrectly installed as executable. + +20. A couple of places in pcretest check for end-of-line by looking for '\n'; + it now also looks for '\r' so that it will work unmodified on Windows. + +21. Added Google's contributed C++ wrapper to the distribution. + +22. Added some untidy missing memory free() calls in pcretest, to keep + Electric Fence happy when testing. + + + +Version 5.0 13-Sep-04 +--------------------- + + 1. Internal change: literal characters are no longer packed up into items + containing multiple characters in a single byte-string. Each character + is now matched using a separate opcode. However, there may be more than one + byte in the character in UTF-8 mode. + + 2. The pcre_callout_block structure has two new fields: pattern_position and + next_item_length. These contain the offset in the pattern to the next match + item, and its length, respectively. + + 3. The PCRE_AUTO_CALLOUT option for pcre_compile() requests the automatic + insertion of callouts before each pattern item. Added the /C option to + pcretest to make use of this. + + 4. On the advice of a Windows user, the lines + + #if defined(_WIN32) || defined(WIN32) + _setmode( _fileno( stdout ), 0x8000 ); + #endif /* defined(_WIN32) || defined(WIN32) */ + + have been added to the source of pcretest. This apparently does useful + magic in relation to line terminators. + + 5. Changed "r" and "w" in the calls to fopen() in pcretest to "rb" and "wb" + for the benefit of those environments where the "b" makes a difference. + + 6. The icc compiler has the same options as gcc, but "configure" doesn't seem + to know about it. I have put a hack into configure.in that adds in code + to set GCC=yes if CC=icc. This seems to end up at a point in the + generated configure script that is early enough to affect the setting of + compiler options, which is what is needed, but I have no means of testing + whether it really works. (The user who reported this had patched the + generated configure script, which of course I cannot do.) + + LATER: After change 22 below (new libtool files), the configure script + seems to know about icc (and also ecc). Therefore, I have commented out + this hack in configure.in. + + 7. Added support for pkg-config (2 patches were sent in). + + 8. Negated POSIX character classes that used a combination of internal tables + were completely broken. These were [[:^alpha:]], [[:^alnum:]], and + [[:^ascii]]. Typically, they would match almost any characters. The other + POSIX classes were not broken in this way. + + 9. Matching the pattern "\b.*?" against "ab cd", starting at offset 1, failed + to find the match, as PCRE was deluded into thinking that the match had to + start at the start point or following a newline. The same bug applied to + patterns with negative forward assertions or any backward assertions + preceding ".*" at the start, unless the pattern required a fixed first + character. This was a failing pattern: "(?!.bcd).*". The bug is now fixed. + +10. In UTF-8 mode, when moving forwards in the subject after a failed match + starting at the last subject character, bytes beyond the end of the subject + string were read. + +11. Renamed the variable "class" as "classbits" to make life easier for C++ + users. (Previously there was a macro definition, but it apparently wasn't + enough.) + +12. Added the new field "tables" to the extra data so that tables can be passed + in at exec time, or the internal tables can be re-selected. This allows + a compiled regex to be saved and re-used at a later time by a different + program that might have everything at different addresses. + +13. Modified the pcre-config script so that, when run on Solaris, it shows a + -R library as well as a -L library. + +14. The debugging options of pcretest (-d on the command line or D on a + pattern) showed incorrect output for anything following an extended class + that contained multibyte characters and which was followed by a quantifier. + +15. Added optional support for general category Unicode character properties + via the \p, \P, and \X escapes. Unicode property support implies UTF-8 + support. It adds about 90K to the size of the library. The meanings of the + inbuilt class escapes such as \d and \s have NOT been changed. + +16. Updated pcredemo.c to include calls to free() to release the memory for the + compiled pattern. + +17. The generated file chartables.c was being created in the source directory + instead of in the building directory. This caused the build to fail if the + source directory was different from the building directory, and was + read-only. + +18. Added some sample Win commands from Mark Tetrode into the NON-UNIX-USE + file. No doubt somebody will tell me if they don't make sense... Also added + Dan Mooney's comments about building on OpenVMS. + +19. Added support for partial matching via the PCRE_PARTIAL option for + pcre_exec() and the \P data escape in pcretest. + +20. Extended pcretest with 3 new pattern features: + + (i) A pattern option of the form ">rest-of-line" causes pcretest to + write the compiled pattern to the file whose name is "rest-of-line". + This is a straight binary dump of the data, with the saved pointer to + the character tables forced to be NULL. The study data, if any, is + written too. After writing, pcretest reads a new pattern. + + (ii) If, instead of a pattern, " +Release 6 of PCRE is distributed under the terms of the "BSD" licence, as +specified below. The documentation for PCRE, supplied in the "doc" +directory, is distributed under the same terms as the software itself. + +The basic library functions are written in C and are freestanding. Also +included in the distribution is a set of C++ wrapper functions. + + +THE BASIC LIBRARY FUNCTIONS +--------------------------- + +Written by: Philip Hazel +Email local part: ph10 +Email domain: cam.ac.uk University of Cambridge Computing Service, Cambridge, England. Phone: +44 1223 334714. -Copyright (c) 1997-2003 University of Cambridge +Copyright (c) 1997-2005 University of Cambridge +All rights reserved. + -Permission is granted to anyone to use this software for any purpose on any -computer system, and to redistribute it freely, subject to the following -restrictions: +THE C++ WRAPPER FUNCTIONS +------------------------- -1. This software is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +Contributed by: Google Inc. -2. The origin of this software must not be misrepresented, either by - explicit claim or by omission. In practice, this means that if you use - PCRE in software that you distribute to others, commercially or - otherwise, you must put a sentence like this +Copyright (c) 2005, Google Inc. +All rights reserved. - Regular expression support is provided by the PCRE library package, - which is open source software, written by Philip Hazel, and copyright - by the University of Cambridge, England. - somewhere reasonably visible in your documentation and in any relevant - files or online help data or similar. A reference to the ftp site for - the source, that is, to +THE "BSD" LICENCE +----------------- - ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/ +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: - should also be given in the documentation. However, this condition is not - intended to apply to whole chains of software. If package A includes PCRE, - it must acknowledge it, but if package B is software that includes package - A, the condition is not imposed on package B (unless it uses PCRE - independently). + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. -3. Altered versions must be plainly marked as such, and must not be - misrepresented as being the original software. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. -4. If PCRE is embedded in any software that is released under the GNU - General Purpose Licence (GPL), or Lesser General Purpose Licence (LGPL), - then the terms of that licence shall supersede any condition above with - which it is incompatible. + * Neither the name of the University of Cambridge nor the name of Google + Inc. nor the names of their contributors may be used to endorse or + promote products derived from this software without specific prior + written permission. -The documentation for PCRE, supplied in the "doc" directory, is distributed -under the same terms as the software itself. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. End diff --git a/ext/pcre/pcrelib/NEWS b/ext/pcre/pcrelib/NEWS index 26219749e945..a6113e08996a 100644 --- a/ext/pcre/pcrelib/NEWS +++ b/ext/pcre/pcrelib/NEWS @@ -1,6 +1,85 @@ News about PCRE releases ------------------------ +Release 6.0 07-Jun-05 +--------------------- + +The release number has been increased to 6.0 because of the addition of several +major new pieces of functionality. + +A new function, pcre_dfa_exec(), which implements pattern matching using a DFA +algorithm, has been added. This has a number of advantages for certain cases, +though it does run more slowly, and lacks the ability to capture substrings. On +the other hand, it does find all matches, not just the first, and it works +better for partial matching. The pcrematching man page discusses the +differences. + +The pcretest program has been enhanced so that it can make use of the new +pcre_dfa_exec() matching function and the extra features it provides. + +The distribution now includes a C++ wrapper library. This is built +automatically if a C++ compiler is found. The pcrecpp man page discusses this +interface. + +The code itself has been re-organized into many more files, one for each +function, so it no longer requires everything to be linked in when static +linkage is used. As a consequence, some internal functions have had to have +their names exposed. These functions all have names starting with _pcre_. They +are undocumented, and are not intended for use by outside callers. + +The pcregrep program has been enhanced with new functionality such as +multiline-matching and options for output more matching context. See the +ChangeLog for a complete list of changes to the library and the utility +programs. + + +Release 5.0 13-Sep-04 +--------------------- + +The licence under which PCRE is released has been changed to the more +conventional "BSD" licence. + +In the code, some bugs have been fixed, and there are also some major changes +in this release (which is why I've increased the number to 5.0). Some changes +are internal rearrangements, and some provide a number of new facilities. The +new features are: + +1. There's an "automatic callout" feature that inserts callouts before every + item in the regex, and there's a new callout field that gives the position + in the pattern - useful for debugging and tracing. + +2. The extra_data structure can now be used to pass in a set of character + tables at exec time. This is useful if compiled regex are saved and re-used + at a later time when the tables may not be at the same address. If the + default internal tables are used, the pointer saved with the compiled + pattern is now set to NULL, which means that you don't need to do anything + special unless you are using custom tables. + +3. It is possible, with some restrictions on the content of the regex, to + request "partial" matching. A special return code is given if all of the + subject string matched part of the regex. This could be useful for testing + an input field as it is being typed. + +4. There is now some optional support for Unicode character properties, which + means that the patterns items such as \p{Lu} and \X can now be used. Only + the general category properties are supported. If PCRE is compiled with this + support, an additional 90K data structure is include, which increases the + size of the library dramatically. + +5. There is support for saving compiled patterns and re-using them later. + +6. There is support for running regular expressions that were compiled on a + different host with the opposite endianness. + +7. The pcretest program has been extended to accommodate the new features. + +The main internal rearrangement is that sequences of literal characters are no +longer handled as strings. Instead, each character is handled on its own. This +makes some UTF-8 handling easier, and makes the support of partial matching +possible. Compiled patterns containing long literal strings will be larger as a +result of this change; I hope that performance will not be much affected. + + Release 4.5 01-Dec-03 --------------------- diff --git a/ext/pcre/pcrelib/NON-UNIX-USE b/ext/pcre/pcrelib/NON-UNIX-USE index c015b214bdd7..b7fe4301a6de 100644 --- a/ext/pcre/pcrelib/NON-UNIX-USE +++ b/ext/pcre/pcrelib/NON-UNIX-USE @@ -1,19 +1,25 @@ Compiling PCRE on non-Unix systems ---------------------------------- -See below for comments on Cygwin or MinGW usage. I (Philip Hazel) have no -knowledge of Windows sytems and how their libraries work. The items in the -PCRE Makefile that relate to anything other than Unix-like systems have been -contributed by PCRE users. There are some other comments and files in the -Contrib directory on the ftp site that you may find useful. +See below for comments on Cygwin or MinGW and OpenVMS usage. I (Philip Hazel) +have no knowledge of Windows or VMS sytems and how their libraries work. The +items in the PCRE Makefile that relate to anything other than Unix-like systems +have been contributed by PCRE users. There are some other comments and files in +the Contrib directory on the ftp site that you may find useful. See -The following are generic comments about building PCRE: + ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/Contrib If you want to compile PCRE for a non-Unix system (or perhaps, more strictly, -for a system that does not support "configure" and make files), note that PCRE -consists entirely of code written in Standard C, and so should compile -successfully on any machine with a Standard C compiler and library, using -normal compiling commands to do the following: +for a system that does not support "configure" and "make" files), note that +PCRE consists entirely of code written in Standard C, and so should compile +successfully on any system that has a Standard C compiler and library. + + +GENERIC INSTRUCTIONS FOR THE C LIBRARY + +The following are generic comments about building PCRE. The interspersed +indented commands are suggestions from Mark Tetrode as to which commands you +might use on a Windows system to build a static library. (1) Copy or rename the file config.in as config.h, and change the macros that define HAVE_STRERROR and HAVE_MEMMOVE to define them as 1 rather than 0. @@ -23,32 +29,116 @@ particular, if you want to force a specific value for newline, you can define the NEWLINE macro. The default is to use '\n', thereby using whatever value your compiler gives to '\n'. + rem Mark Tetrode's commands + copy config.in config.h + rem Use write, because notepad cannot handle UNIX files. Change values. + write config.h + (2) Copy or rename the file pcre.in as pcre.h, and change the macro definitions for PCRE_MAJOR, PCRE_MINOR, and PCRE_DATE near its start to the values set in configure.in. + rem Mark Tetrode's commands + copy pcre.in pcre.h + rem Read values from configure.in + write configure.in + rem Change values + write pcre.h + (3) Compile dftables.c as a stand-alone program, and then run it with the single argument "chartables.c". This generates a set of standard character tables and writes them to that file. -(4) Compile maketables.c, get.c, study.c and pcre.c and link them all -together into an object library in whichever form your system keeps such -libraries. This is the pcre library (chartables.c is included by means of an -#include directive). If your system has static and shared libraries, you may -have to do this once for each type. + rem Mark Tetrode's commands + rem Compile & run + cl -DSUPPORT_UTF8 -DSUPPORT_UCP dftables.c + dftables.exe chartables.c + +(4) Compile the following source files: + + pcre_chartables.c + pcre_compile.c + pcre_config.c + pcre_dfa_exec.c + pcre_exec.c + pcre_fullinfo.c + pcre_get.c + pcre_globals.c + pcre_info.c + pcre_maketables.c + pcre_ord2utf8.c + pcre_printint.c + pcre_refcount.c + pcre_study.c + pcre_tables.c + pcre_try_flipped.c + pcre_ucp_findchar.c + pcre_valid_utf8.c + pcre_version.c + pcre_xclass.c + +and link them all together into an object library in whichever form your system +keeps such libraries. This is the pcre C library. If your system has static and +shared libraries, you may have to do this once for each type. + + rem These comments are out-of-date, referring to a previous release which + rem had fewer source files. Replace with the file names from above. + rem Mark Tetrode's commands, for a static library + rem Compile & lib + cl -DSUPPORT_UTF8 -DSUPPORT_UCP -DPOSIX_MALLOC_THRESHOLD=10 /c maketables.c get.c study.c pcre.c + lib /OUT:pcre.lib maketables.obj get.obj study.obj pcre.obj (5) Similarly, compile pcreposix.c and link it (on its own) as the pcreposix library. + rem Mark Tetrode's commands, for a static library + rem Compile & lib + cl -DSUPPORT_UTF8 -DSUPPORT_UCP -DPOSIX_MALLOC_THRESHOLD=10 /c pcreposix.c + lib /OUT:pcreposix.lib pcreposix.obj + (6) Compile the test program pcretest.c. This needs the functions in the pcre and pcreposix libraries when linking. + rem Mark Tetrode's commands + rem compile & link + cl /F0x400000 pcretest.c pcre.lib pcreposix.lib + (7) Run pcretest on the testinput files in the testdata directory, and check that the output matches the corresponding testoutput files. You must use the -i option when checking testinput2. Note that the supplied files are in Unix format, with just LF characters as line terminators. You may need to edit them to change this if your system uses a different convention. + rem Mark Tetrode's commands + pcretest testdata\testinput1 testdata\myoutput1 + windiff testdata\testoutput1 testdata\myoutput1 + pcretest -i testdata\testinput2 testdata\myoutput2 + windiff testdata\testoutput2 testdata\myoutput2 + pcretest testdata\testinput3 testdata\myoutput3 + windiff testdata\testoutput3 testdata\myoutput3 + pcretest testdata\testinput4 testdata\myoutput4 + windiff testdata\testoutput4 testdata\myoutput4 + pcretest testdata\testinput5 testdata\myoutput5 + windiff testdata\testoutput5 testdata\myoutput5 + pcretest testdata\testinput6 testdata\myoutput6 + windiff testdata\testoutput6 testdata\myoutput6 + +Note that there are now three more tests (7, 8, 9) that did not exist when Mark +wrote those comments. The test the new pcre_dfa_exec() function. + + +THE C++ WRAPPER FUNCTIONS + +The PCRE distribution now contains some C++ wrapper functions and tests, +contributed by Google Inc. On a system that can use "configure" and "make", +the functions are automatically built into a library called pcrecpp. It should +be straightforward to compile the .cc files manually on other systems. The +files called xxx_unittest.cc are test programs for each of the corresponding +xxx.cc files. + + +FURTHER REMARKS + If you have a system without "configure" but where you can use a Makefile, edit Makefile.in to create Makefile, substituting suitable values for the variables at the head of the file. @@ -119,4 +209,69 @@ void (*pcre_free)(void *) = free; #endif ========================= + +BUILDING PCRE ON OPENVMS + +Dan Mooney sent the following comments about building PCRE on OpenVMS. They +relate to an older version of PCRE that used fewer source files, so the exact +commands will need changing. See the current list of source files above. + +"It was quite easy to compile and link the library. I don't have a formal +make file but the attached file [reproduced below] contains the OpenVMS DCL +commands I used to build the library. I had to add #define +POSIX_MALLOC_THRESHOLD 10 to pcre.h since it was not defined anywhere. + +The library was built on: +O/S: HP OpenVMS v7.3-1 +Compiler: Compaq C v6.5-001-48BCD +Linker: vA13-01 + +The test results did not match 100% due to the issues you mention in your +documentation regarding isprint(), iscntrl(), isgraph() and ispunct(). I +modified some of the character tables temporarily and was able to get the +results to match. Tests using the fr locale did not match since I don't have +that locale loaded. The study size was always reported to be 3 less than the +value in the standard test output files." + +========================= +$! This DCL procedure builds PCRE on OpenVMS +$! +$! I followed the instructions in the non-unix-use file in the distribution. +$! +$ COMPILE == "CC/LIST/NOMEMBER_ALIGNMENT/PREFIX_LIBRARY_ENTRIES=ALL_ENTRIES +$ COMPILE DFTABLES.C +$ LINK/EXE=DFTABLES.EXE DFTABLES.OBJ +$ RUN DFTABLES.EXE/OUTPUT=CHARTABLES.C +$ COMPILE MAKETABLES.C +$ COMPILE GET.C +$ COMPILE STUDY.C +$! I had to set POSIX_MALLOC_THRESHOLD to 10 in PCRE.H since the symbol +$! did not seem to be defined anywhere. +$! I edited pcre.h and added #DEFINE SUPPORT_UTF8 to enable UTF8 support. +$ COMPILE PCRE.C +$ LIB/CREATE PCRE MAKETABLES.OBJ, GET.OBJ, STUDY.OBJ, PCRE.OBJ +$! I had to set POSIX_MALLOC_THRESHOLD to 10 in PCRE.H since the symbol +$! did not seem to be defined anywhere. +$ COMPILE PCREPOSIX.C +$ LIB/CREATE PCREPOSIX PCREPOSIX.OBJ +$ COMPILE PCRETEST.C +$ LINK/EXE=PCRETEST.EXE PCRETEST.OBJ, PCRE/LIB, PCREPOSIX/LIB +$! C programs that want access to command line arguments must be +$! defined as a symbol +$ PCRETEST :== "$ SYS$ROADSUSERS:[DMOONEY.REGEXP]PCRETEST.EXE" +$! Arguments must be enclosed in quotes. +$ PCRETEST "-C" +$! Test results: +$! +$! The test results did not match 100%. The functions isprint(), iscntrl(), +$! isgraph() and ispunct() on OpenVMS must not produce the same results +$! as the system that built the test output files provided with the +$! distribution. +$! +$! The study size did not match and was always 3 less on OpenVMS. +$! +$! Locale could not be set to fr +$! +========================= + **** diff --git a/ext/pcre/pcrelib/README b/ext/pcre/pcrelib/README index 879ba04f48db..f8d63bbd34c9 100644 --- a/ext/pcre/pcrelib/README +++ b/ext/pcre/pcrelib/README @@ -7,14 +7,22 @@ The latest release of PCRE is always available from Please read the NEWS file if you are upgrading from a previous release. -PCRE has its own native API, but a set of "wrapper" functions that are based on -the POSIX API are also supplied in the library libpcreposix. Note that this -just provides a POSIX calling interface to PCRE: the regular expressions -themselves still follow Perl syntax and semantics. The header file -for the POSIX-style functions is called pcreposix.h. The official POSIX name is -regex.h, but I didn't want to risk possible problems with existing files of -that name by distributing it that way. To use it with an existing program that -uses the POSIX API, it will have to be renamed or pointed at by a link. + +The PCRE APIs +------------- + +PCRE is written in C, and it has its own API. The distribution now includes a +set of C++ wrapper functions, courtesy of Google Inc. (see the pcrecpp man page +for details). + +Also included are a set of C wrapper functions that are based on the POSIX +API. These end up in the library called libpcreposix. Note that this just +provides a POSIX calling interface to PCRE: the regular expressions themselves +still follow Perl syntax and semantics. The header file for the POSIX-style +functions is called pcreposix.h. The official POSIX name is regex.h, but I +didn't want to risk possible problems with existing files of that name by +distributing it that way. To use it with an existing program that uses the +POSIX API, it will have to be renamed or pointed at by a link. If you are using the POSIX interface to PCRE and there is already a POSIX regex library installed on your system, you must take care when linking programs to @@ -22,6 +30,28 @@ ensure that they link with PCRE's libpcreposix library. Otherwise they may pick up the "real" POSIX functions of the same name. +Documentation for PCRE +---------------------- + +If you install PCRE in the normal way, you will end up with an installed set of +man pages whose names all start with "pcre". The one that is called "pcre" +lists all the others. In addition to these man pages, the PCRE documentation is +supplied in two other forms; however, as there is no standard place to install +them, they are left in the doc directory of the unpacked source distribution. +These forms are: + + 1. Files called doc/pcre.txt, doc/pcregrep.txt, and doc/pcretest.txt. The + first of these is a concatenation of the text forms of all the section 3 + man pages except those that summarize individual functions. The other two + are the text forms of the section 1 man pages for the pcregrep and + pcretest commands. Text forms are provided for ease of scanning with text + editors or similar tools. + + 2. A subdirectory called doc/html contains all the documentation in HTML + form, hyperlinked in various ways, and rooted in a file called + doc/index.html. + + Contributions by users of PCRE ------------------------------ @@ -46,7 +76,7 @@ INSTALL. Most commonly, people build PCRE within its own distribution directory, and in this case, on many systems, just running "./configure" is sufficient, but the -usual methods of changing standard defaults are available. For example, +usual methods of changing standard defaults are available. For example: CFLAGS='-O2 -Wall' ./configure --prefix=/opt/local @@ -69,6 +99,13 @@ library. You can read more about them in the pcrebuild man page. for handling UTF-8 is not included in the library. (Even when included, it still has to be enabled by an option at run time.) +. If, in addition to support for UTF-8 character strings, you want to include + support for the \P, \p, and \X sequences that recognize Unicode character + properties, you must add --enable-unicode-properties to the "configure" + command. This adds about 90K to the size of the library (in the form of a + property table); only the basic two-letter properties such as Lu are + supported. + . You can build PCRE to recognized CR or NL as the newline character, instead of whatever your compiler uses for "\n", by adding --newline-is-cr or --newline-is-nl to the "configure" command, respectively. Only do this if you @@ -83,7 +120,7 @@ library. You can read more about them in the pcrebuild man page. on the "configure" command. -. PCRE has a counter which can be set to limit the amount of resources it uses. +. PCRE has a counter that can be set to limit the amount of resources it uses. If the limit is exceeded during a match, the match fails. The default is ten million. You can change the default by setting, for example, @@ -101,51 +138,91 @@ library. You can read more about them in the pcrebuild man page. is a representation of the compiled pattern, and this changes with the link size. -. You can build PCRE so that its match() function does not call itself - recursively. Instead, it uses blocks of data from the heap via special - functions pcre_stack_malloc() and pcre_stack_free() to save data that would - otherwise be saved on the stack. To build PCRE like this, use +. You can build PCRE so that its internal match() function that is called from + pcre_exec() does not call itself recursively. Instead, it uses blocks of data + from the heap via special functions pcre_stack_malloc() and pcre_stack_free() + to save data that would otherwise be saved on the stack. To build PCRE like + this, use --disable-stack-for-recursion on the "configure" command. PCRE runs more slowly in this mode, but it may be - necessary in environments with limited stack sizes. + necessary in environments with limited stack sizes. This applies only to the + pcre_exec() function; it does not apply to pcre_dfa_exec(), which does not + use deeply nested recursion. -The "configure" script builds five files: +The "configure" script builds eight files for the basic C library: +. pcre.h is the header file for C programs that call PCRE +. Makefile is the makefile that builds the library +. config.h contains build-time configuration options for the library +. pcre-config is a script that shows the settings of "configure" options +. libpcre.pc is data for the pkg-config command . libtool is a script that builds shared and/or static libraries -. Makefile is built by copying Makefile.in and making substitutions. -. config.h is built by copying config.in and making substitutions. -. pcre-config is built by copying pcre-config.in and making substitutions. -. RunTest is a script for running tests +. RunTest is a script for running tests on the library +. RunGrepTest is a script for running tests on the pcregrep command + +In addition, if a C++ compiler is found, the following are also built: + +. pcrecpp.h is the header file for programs that call PCRE via the C++ wrapper +. pcre_stringpiece.h is the header for the C++ "stringpiece" functions -Once "configure" has run, you can run "make". It builds two libraries called +The "configure" script also creates config.status, which is an executable +script that can be run to recreate the configuration, and config.log, which +contains compiler output from tests that "configure" runs. + +Once "configure" has run, you can run "make". It builds two libraries, called libpcre and libpcreposix, a test program called pcretest, and the pcregrep -command. You can use "make install" to copy these, the public header files -pcre.h and pcreposix.h, and the man pages to appropriate live directories on -your system, in the normal way. +command. If a C++ compiler was found on your system, it also builds the C++ +wrapper library, which is called libpcrecpp, and some test programs called +pcrecpp_unittest, pcre_scanner_unittest, and pcre_stringpiece_unittest. + +The command "make test" runs all the appropriate tests. Details of the PCRE +tests are given in a separate section of this document, below. + +You can use "make install" to copy the libraries, the public header files +pcre.h, pcreposix.h, pcrecpp.h, and pcre_stringpiece.h (the last two only if +the C++ wrapper was built), and the man pages to appropriate live directories +on your system, in the normal way. + +If you want to remove PCRE from your system, you can run "make uninstall". +This removes all the files that "make install" installed. However, it does not +remove any directories, because these are often shared with other programs. + + +Retrieving configuration information on Unix-like systems +--------------------------------------------------------- Running "make install" also installs the command pcre-config, which can be used to recall information about the PCRE configuration and installation. For -example, +example: pcre-config --version prints the version number, and - pcre-config --libs + pcre-config --libs outputs information about where the library is installed. This command can be included in makefiles for programs that use PCRE, saving the programmer from having to remember too many details. +The pkg-config command is another system for saving and retrieving information +about installed libraries. Instead of separate commands for each library, a +single command is used. For example: + + pkg-config --cflags pcre + +The data is held in *.pc files that are installed in a directory called +pkgconfig. + Shared libraries on Unix-like systems ------------------------------------- -The default distribution builds PCRE as two shared libraries and two static -libraries, as long as the operating system supports shared libraries. Shared -library support relies on the "libtool" script which is built as part of the +The default distribution builds PCRE as shared libraries and static libraries, +as long as the operating system supports shared libraries. Shared library +support relies on the "libtool" script which is built as part of the "configure" process. The libtool script is used to compile and link both shared and static @@ -158,7 +235,7 @@ installed themselves. However, the versions left in the source directory still use the uninstalled libraries. To build PCRE using static libraries only you must use --disable-shared when -configuring it. For example +configuring it. For example: ./configure --prefix=/usr/gnu --disable-shared @@ -174,7 +251,8 @@ order to cross-compile PCRE for some other host. However, during the building process, the dftables.c source file is compiled *and run* on the local host, in order to generate the default character tables (the chartables.c file). It therefore needs to be compiled with the local compiler, not the cross compiler. -You can do this by specifying CC_FOR_BUILD (and if necessary CFLAGS_FOR_BUILD) +You can do this by specifying CC_FOR_BUILD (and if necessary CFLAGS_FOR_BUILD; +there are also CXX_FOR_BUILD and CXXFLAGS_FOR_BUILD for the C++ wrapper) when calling the "configure" command. If they are not specified, they default to the values of CC and CFLAGS. @@ -196,15 +274,21 @@ Testing PCRE ------------ To test PCRE on a Unix system, run the RunTest script that is created by the -configuring process. (This can also be run by "make runtest", "make check", or -"make test".) For other systems, see the instructions in NON-UNIX-USE. - -The script runs the pcretest test program (which is documented in its own man -page) on each of the testinput files (in the testdata directory) in turn, -and compares the output with the contents of the corresponding testoutput file. -A file called testtry is used to hold the output from pcretest. To run pcretest -on just one of the test files, give its number as an argument to RunTest, for -example: +configuring process. There is also a script called RunGrepTest that tests the +options of the pcregrep command. If the C++ wrapper library is build, three +test programs called pcrecpp_unittest, pcre_scanner_unittest, and +pcre_stringpiece_unittest are provided. + +Both the scripts and all the program tests are run if you obey "make runtest", +"make check", or "make test". For other systems, see the instructions in +NON-UNIX-USE. + +The RunTest script runs the pcretest test program (which is documented in its +own man page) on each of the testinput files (in the testdata directory) in +turn, and compares the output with the contents of the corresponding testoutput +file. A file called testtry is used to hold the main output from pcretest +(testsavedregex is also used as a working file). To run pcretest on just one of +the test files, give its number as an argument to RunTest, for example: RunTest 2 @@ -247,19 +331,28 @@ running "configure". This file can be also fed directly to the perltest script, provided you are running Perl 5.8 or higher. (For Perl 5.6, a small patch, commented in the script, can be be used.) -The fifth and final file tests error handling with UTF-8 encoding, and internal -UTF-8 features of PCRE that are not relevant to Perl. +The fifth test checks error handling with UTF-8 encoding, and internal UTF-8 +features of PCRE that are not relevant to Perl. + +The sixth and test checks the support for Unicode character properties. It it +not run automatically unless PCRE is built with Unicode property support. To to +this you must set --enable-unicode-properties when running "configure". + +The seventh, eighth, and ninth tests check the pcre_dfa_exec() alternative +matching function, in non-UTF-8 mode, UTF-8 mode, and UTF-8 mode with Unicode +property support, respectively. The eighth and ninth tests are not run +automatically unless PCRE is build with the relevant support. Character tables ---------------- -PCRE uses four tables for manipulating and identifying characters. The final -argument of the pcre_compile() function is a pointer to a block of memory -containing the concatenated tables. A call to pcre_maketables() can be used to -generate a set of tables in the current locale. If the final argument for -pcre_compile() is passed as NULL, a set of default tables that is built into -the binary is used. +PCRE uses four tables for manipulating and identifying characters whose values +are less than 256. The final argument of the pcre_compile() function is a +pointer to a block of memory containing the concatenated tables. A call to +pcre_maketables() can be used to generate a set of tables in the current +locale. If the final argument for pcre_compile() is passed as NULL, a set of +default tables that is built into the binary is used. The source file called chartables.c contains the default set of tables. This is not supplied in the distribution, but is built by the program dftables @@ -299,18 +392,47 @@ The distribution should contain the following files: headers: dftables.c auxiliary program for building chartables.c - get.c ) - maketables.c ) - study.c ) source of - pcre.c ) the functions + pcreposix.c ) - printint.c ) + pcre_compile.c ) + pcre_config.c ) + pcre_dfa_exec.c ) + pcre_exec.c ) + pcre_fullinfo.c ) + pcre_get.c ) sources for the functions in the library, + pcre_globals.c ) and some internal functions that they use + pcre_info.c ) + pcre_maketables.c ) + pcre_ord2utf8.c ) + pcre_printint.c ) + pcre_study.c ) + pcre_tables.c ) + pcre_try_flipped.c ) + pcre_ucp_findchar.c ) + pcre_valid_utf8.c ) + pcre_version.c ) + pcre_xclass.c ) + + ucp_findchar.c ) + ucp.h ) source for the code that is used for + ucpinternal.h ) Unicode property handling + ucptable.c ) + ucptypetable.c ) + pcre.in "source" for the header for the external API; pcre.h is built from this by "configure" pcreposix.h header for the external POSIX wrapper API - internal.h header for internal use + pcre_internal.h header for internal use config.in template for config.h, which is built by configure + pcrecpp.h.in "source" for the header file for the C++ wrapper + pcrecpp.cc ) + pcre_scanner.cc ) source for the C++ wrapper library + + pcre_stringpiece.h.in "source" for pcre_stringpiece.h, the header for the + C++ stringpiece functions + pcre_stringpiece.cc source for the C++ stringpiece functions + (B) Auxiliary files: AUTHORS information about the author of PCRE @@ -323,6 +445,7 @@ The distribution should contain the following files: NON-UNIX-USE notes on building PCRE on non-Unix systems README this file RunTest.in template for a Unix shell script for running tests + RunGrepTest.in template for a Unix shell script for pcregrep tests config.guess ) files used by libtool, config.sub ) used only when building a shared library configure a configuring shell script (built by autoconf) @@ -335,31 +458,32 @@ The distribution should contain the following files: doc/pcretest.txt plain text documentation of test program doc/perltest.txt plain text documentation of Perl test program install-sh a shell script for installing files + libpcre.pc.in "source" for libpcre.pc for pkg-config ltmain.sh file used to build a libtool script + mkinstalldirs script for making install directories pcretest.c comprehensive test program pcredemo.c simple demonstration of coding calls to PCRE perltest Perl test program pcregrep.c source of a grep utility that uses PCRE pcre-config.in source of script which retains PCRE information - testdata/testinput1 test data, compatible with Perl - testdata/testinput2 test data for error messages and non-Perl things - testdata/testinput3 test data for locale-specific tests - testdata/testinput4 test data for UTF-8 tests compatible with Perl - testdata/testinput5 test data for other UTF-8 tests - testdata/testoutput1 test results corresponding to testinput1 - testdata/testoutput2 test results corresponding to testinput2 - testdata/testoutput3 test results corresponding to testinput3 - testdata/testoutput4 test results corresponding to testinput4 - testdata/testoutput5 test results corresponding to testinput5 + pcrecpp_unittest.c ) + pcre_scanner_unittest.c ) test programs for the C++ wrapper + pcre_stringpiece_unittest.c ) + testdata/testinput* test data for main library tests + testdata/testoutput* expected test results + testdata/grep* input and output for pcregrep tests (C) Auxiliary files for Win32 DLL - dll.mk + libpcre.def + libpcreposix.def pcre.def (D) Auxiliary file for VPASCAL makevp.bat -Philip Hazel -December 2003 +Philip Hazel +Email local part: ph10 +Email domain: cam.ac.uk +June 2005 diff --git a/ext/pcre/pcrelib/dftables.c b/ext/pcre/pcrelib/dftables.c index ea66e09054c3..480753887ed5 100644 --- a/ext/pcre/pcrelib/dftables.c +++ b/ext/pcre/pcrelib/dftables.c @@ -2,52 +2,55 @@ * Perl-Compatible Regular Expressions * *************************************************/ -/* -PCRE is a library of functions to support regular expressions whose syntax +/* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. -Written by: Philip Hazel - - Copyright (c) 1997-2004 University of Cambridge + Written by Philip Hazel + Copyright (c) 1997-2005 University of Cambridge ----------------------------------------------------------------------------- -Permission is granted to anyone to use this software for any purpose on any -computer system, and to redistribute it freely, subject to the following -restrictions: - -1. This software is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -2. The origin of this software must not be misrepresented, either by - explicit claim or by omission. - -3. Altered versions must be plainly marked as such, and must not be - misrepresented as being the original software. - -4. If PCRE is embedded in any software that is released under the GNU - General Purpose Licence (GPL), then the terms of that licence shall - supersede any condition above with which it is incompatible. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------------------- - -See the file Tech.Notes for some information on the internals. */ -/* This is a support program to generate the file chartables.c, containing -character tables of various kinds. They are built according to the default C -locale and used as the default tables by PCRE. Now that pcre_maketables is -a function visible to the outside world, we make use of its code from here in -order to be consistent. */ +/* This is a freestanding support program to generate a file containing default +character tables for PCRE. The tables are built according to the default C +locale. Now that pcre_maketables is a function visible to the outside world, we +make use of its code from here in order to be consistent. */ #include #include #include -#include "internal.h" +#include "pcre_internal.h" -#define DFTABLES /* maketables.c notices this */ -#include "maketables.c" +#define DFTABLES /* pcre_maketables.c notices this */ +#include "pcre_maketables.c" int main(int argc, char **argv) @@ -55,6 +58,7 @@ int main(int argc, char **argv) int i; FILE *f; const unsigned char *tables = pcre_maketables(); +const unsigned char *base_of_tables = tables; if (argc != 2) { @@ -62,7 +66,7 @@ if (argc != 2) return 1; } -f = fopen(argv[1], "w"); +f = fopen(argv[1], "wb"); if (f == NULL) { fprintf(stderr, "dftables: failed to open %s for writing\n", argv[1]); @@ -80,10 +84,10 @@ fprintf(f, "program. If you edit it by hand, you might like to edit the Makefile to \n" "prevent its ever being regenerated.\n\n"); fprintf(f, - "This file is #included in the compilation of pcre.c to build the default\n" - "character tables which are used when no tables are passed to the compile\n" - "function. */\n\n" - "static unsigned char pcre_default_tables[] = {\n\n" + "This file contains the default tables for characters with codes less than\n" + "128 (ASCII characters). These tables are used when no external tables are\n" + "passed to PCRE. */\n\n" + "const unsigned char _pcre_default_tables[] = {\n\n" "/* This table is a lower casing table. */\n\n"); fprintf(f, " "); @@ -161,6 +165,7 @@ if (isprint(i-1)) fprintf(f, " %c ", i-1); fprintf(f, " */\n\n/* End of chartables.c */\n"); fclose(f); +free((void *)base_of_tables); return 0; } diff --git a/ext/pcre/pcrelib/doc/Tech.Notes b/ext/pcre/pcrelib/doc/Tech.Notes index 73c31c7ca18c..322cc2de131e 100644 --- a/ext/pcre/pcrelib/doc/Tech.Notes +++ b/ext/pcre/pcrelib/doc/Tech.Notes @@ -1,6 +1,9 @@ Technical Notes about PCRE -------------------------- +Historical note 1 +----------------- + Many years ago I implemented some regular expression functions to an algorithm suggested by Martin Richards. These were not Unix-like in form, and were quite restricted in what they could do by comparison with Perl. The interesting part @@ -9,12 +12,15 @@ form of an expression was known in advance. The code to apply an expression did not operate by backtracking, as the original Henry Spencer code and current Perl code does, but instead checked all possibilities simultaneously by keeping a list of current states and checking all of them as it advanced through the -subject string. (In the terminology of Jeffrey Friedl's book, it was a "DFA -algorithm".) When the pattern was all used up, all remaining states were +subject string. In the terminology of Jeffrey Friedl's book, it was a "DFA +algorithm". When the pattern was all used up, all remaining states were possible matches, and the one matching the longest subset of the subject string was chosen. This did not necessarily maximize the individual wild portions of the pattern, as is expected in Unix and Perl-style regular expressions. +Historical note 2 +----------------- + By contrast, the code originally written by Henry Spencer and subsequently heavily modified for Perl actually compiles the expression twice: once in a dummy mode in order to find out how much store will be needed, and then for @@ -23,23 +29,58 @@ optionally, minimizing in Perl) the amount of the subject that matches individual wild portions of the pattern. This is an "NFA algorithm" in Friedl's terminology. -For the set of functions that forms PCRE (which are unrelated to those -mentioned above), I tried at first to invent an algorithm that used an amount -of store bounded by a multiple of the number of characters in the pattern, to -save on compiling time. However, because of the greater complexity in Perl -regular expressions, I couldn't do this. In any case, a first pass through the -pattern is needed, for a number of reasons. PCRE works by running a very -degenerate first pass to calculate a maximum store size, and then a second pass -to do the real compile - which may use a bit less than the predicted amount of -store. The idea is that this is going to turn out faster because the first pass -is degenerate and the second pass can just store stuff straight into the -vector. It does make the compiling functions bigger, of course, but they have -got quite big anyway to handle all the Perl stuff. +OK, here's the real stuff +------------------------- + +For the set of functions that form the "basic" PCRE library (which are +unrelated to those mentioned above), I tried at first to invent an algorithm +that used an amount of store bounded by a multiple of the number of characters +in the pattern, to save on compiling time. However, because of the greater +complexity in Perl regular expressions, I couldn't do this. In any case, a +first pass through the pattern is needed, for a number of reasons. PCRE works +by running a very degenerate first pass to calculate a maximum store size, and +then a second pass to do the real compile - which may use a bit less than the +predicted amount of store. The idea is that this is going to turn out faster +because the first pass is degenerate and the second pass can just store stuff +straight into the vector, which it knows is big enough. It does make the +compiling functions bigger, of course, but they have got quite big anyway to +handle all the Perl stuff. + +Traditional matching function +----------------------------- + +The "traditional", and original, matching function is called pcre_exec(), and +it implements an NFA algorithm, similar to the original Henry Spencer algorithm +and the way that Perl works. Not surprising, since it is intended to be as +compatible with Perl as possible. This is the function most users of PCRE will +use most of the time. + +Supplementary matching function +------------------------------- + +From PCRE 6.0, there is also a supplementary matching function called +pcre_dfa_exec(). This implements a DFA matching algorithm that searches +simultaneously for all possible matches that start at one point in the subject +string. (Going back to my roots: see Historical Note 1 above.) This function +intreprets the same compiled pattern data as pcre_exec(); however, not all the +facilities are available, and those that are don't always work in quite the +same way. See the user documentation for details. + +Format of compiled patterns +--------------------------- The compiled form of a pattern is a vector of bytes, containing items of variable length. The first byte in an item is an opcode, and the length of the -item is either implicit in the opcode or contained in the data bytes which -follow it. A list of all the opcodes follows: +item is either implicit in the opcode or contained in the data bytes that +follow it. + +In many cases below "two-byte" data values are specified. This is in fact just +a default. PCRE can be compiled to use 3-byte or 4-byte values (impairing the +performance). This is necessary only when patterns whose compiled length is +greater than 64K are going to be processed. In this description, we assume the +"normal" compilation options. + +A list of all the opcodes follows: Opcodes with no following data ------------------------------ @@ -48,7 +89,7 @@ These items are all just one byte long OP_END end of pattern OP_ANY match any character - OP_ANYBYTE match any single byte, even in UTF-8 mode + OP_ANYBYTE match any single byte, even in UTF-8 mode OP_SOD match start of data: \A OP_SOM, start of match (subject + offset): \G OP_CIRC ^ (start of data, or after \n in multiline) @@ -63,13 +104,14 @@ These items are all just one byte long OP_EODN match end of data or \n at end: \Z OP_EOD match end of data: \z OP_DOLL $ (end of data, or before \n in multiline) - + OP_EXTUNI match an extended Unicode character + Repeating single characters --------------------------- -The common repeats (*, +, ?) when applied to a single character appear as -two-byte items using the following opcodes: +The common repeats (*, +, ?) when applied to a single character use the +following opcodes: OP_STAR OP_MINSTAR @@ -78,6 +120,7 @@ two-byte items using the following opcodes: OP_QUERY OP_MINQUERY +In ASCII mode, these are two-byte items; in UTF-8 mode, the length is variable. Those with "MIN" in their name are the minimizing versions. Each is followed by the character that is to be repeated. Other repeats make use of @@ -109,39 +152,52 @@ byte. The opcodes are: OP_TYPEEXACT -Matching a character string +Match by Unicode property +------------------------- + +OP_PROP and OP_NOTPROP are used for positive and negative matches of a +character by testing its Unicode property (the \p and \P escape sequences). +Each is followed by a single byte that encodes the desired property value. + +Repeats of these items use the OP_TYPESTAR etc. set of opcodes, followed by two +bytes: OP_PROP or OP_NOTPROP and then the desired property value. + + +Matching literal characters --------------------------- -The OP_CHARS opcode is followed by a one-byte count and then that number of -characters. If there are more than 255 characters in sequence, successive -instances of OP_CHARS are used. +The OP_CHAR opcode is followed by a single character that is to be matched +casefully. For caseless matching, OP_CHARNC is used. In UTF-8 mode, the +character may be more than one byte long. (Earlier versions of PCRE used +multi-character strings, but this was changed to allow some new features to be +added.) Character classes ----------------- -If there is only one character, OP_CHARS is used for a positive class, -and OP_NOT for a negative one (that is, for something like [^a]). However, in -UTF-8 mode, this applies only to characters with values < 128, because OP_NOT -is confined to single bytes. +If there is only one character, OP_CHAR or OP_CHARNC is used for a positive +class, and OP_NOT for a negative one (that is, for something like [^a]). +However, in UTF-8 mode, the use of OP_NOT applies only to characters with +values < 128, because OP_NOT is confined to single bytes. Another set of repeating opcodes (OP_NOTSTAR etc.) are used for a repeated, negated, single-character class. The normal ones (OP_STAR etc.) are used for a repeated positive single-character class. When there's more than one character in a class and all the characters are less -than 256, OP_CLASS is used for a positive class, and OP_NCLASS for a negative +than 256, OP_CLASS is used for a positive class, and OP_NCLASS for a negative one. In either case, the opcode is followed by a 32-byte bit map containing a 1 bit for every character that is acceptable. The bits are counted from the least significant end of each byte. -The reason for having both OP_CLASS and OP_NCLASS is so that, in UTF-8 mode, -subject characters with values greater than 256 can be handled correctly. For +The reason for having both OP_CLASS and OP_NCLASS is so that, in UTF-8 mode, +subject characters with values greater than 256 can be handled correctly. For OP_CLASS they don't match, whereas for OP_NCLASS they do. For classes containing characters with values > 255, OP_XCLASS is used. It optionally uses a bit map (if any characters lie within it), followed by a list -of pairs and single characters. There is a flag character than indicates +of pairs and single characters. There is a flag character than indicates whether it's a positive or a negative class. @@ -191,15 +247,15 @@ number. This opcode is ignored while matching, but is fished out when handling the bracket itself. (They could have all been done like this, but I was making minimal changes.) -A bracket opcode is followed by two bytes which give the offset to the next -alternative OP_ALT or, if there aren't any branches, to the matching KET -opcode. Each OP_ALT is followed by two bytes giving the offset to the next one, -or to the KET opcode. +A bracket opcode is followed by LINK_SIZE bytes which give the offset to the +next alternative OP_ALT or, if there aren't any branches, to the matching +OP_KET opcode. Each OP_ALT is followed by LINK_SIZE bytes giving the offset to +the next one, or to the OP_KET opcode. OP_KET is used for subpatterns that do not repeat indefinitely, while OP_KETRMIN and OP_KETRMAX are used for indefinite repetitions, minimally or -maximally respectively. All three are followed by two bytes giving (as a -positive number) the offset back to the matching BRA opcode. +maximally respectively. All three are followed by LINK_SIZE bytes giving (as a +positive number) the offset back to the matching OP_BRA opcode. If a subpattern is quantified such that it is permitted to match zero times, it is preceded by one of OP_BRAZERO or OP_BRAMINZERO. These are single-byte @@ -207,15 +263,14 @@ opcodes which tell the matcher that skipping this subpattern entirely is a valid branch. A subpattern with an indefinite maximum repetition is replicated in the -compiled data its minimum number of times (or once with a BRAZERO if the -minimum is zero), with the final copy terminating with a KETRMIN or KETRMAX as -appropriate. +compiled data its minimum number of times (or once with OP_BRAZERO if the +minimum is zero), with the final copy terminating with OP_KETRMIN or OP_KETRMAX +as appropriate. A subpattern with a bounded maximum repetition is replicated in a nested -fashion up to the maximum number of times, with BRAZERO or BRAMINZERO before -each replication after the minimum, so that, for example, (abc){2,5} is -compiled as (abc)(abc)((abc)((abc)(abc)?)?)?. The 99 and 200 bracket limits do -not apply to these internally generated brackets. +fashion up to the maximum number of times, with OP_BRAZERO or OP_BRAMINZERO +before each replication after the minimum, so that, for example, (abc){2,5} is +compiled as (abc)(abc)((abc)((abc)(abc)?)?)?. Assertions @@ -260,8 +315,11 @@ from the start of the whole pattern. Callout ------- -OP_CALLOUT is followed by one byte of data that holds a callout number in the -range 0 to 255. +OP_CALLOUT is followed by one byte of data that holds a callout number in the +range 0 to 254 for manual callouts, or 255 for an automatic callout. In both +cases there follows a two-byte value giving the offset in the pattern to the +start of the following item, and another two-byte item giving the length of the +next item. Changing options @@ -278,4 +336,4 @@ at compile time, and so does not cause anything to be put into the compiled data. Philip Hazel -August 2003 +March 2005 diff --git a/ext/pcre/pcrelib/doc/pcre.txt b/ext/pcre/pcrelib/doc/pcre.txt index 698baa52e19f..801bde279b9b 100644 --- a/ext/pcre/pcrelib/doc/pcre.txt +++ b/ext/pcre/pcrelib/doc/pcre.txt @@ -1,3 +1,4 @@ +----------------------------------------------------------------------------- This file contains a concatenation of the PCRE man pages, converted to plain text format for ease of searching with a text editor, or for use on systems that do not have a man page processor. The small individual files that give @@ -5,25 +6,34 @@ synopses of each function in the library have not been included. There are separate text files for the pcregrep and pcretest commands. ----------------------------------------------------------------------------- -PCRE(3) PCRE(3) +PCRE(3) PCRE(3) NAME PCRE - Perl-compatible regular expressions -DESCRIPTION + +INTRODUCTION The PCRE library is a set of functions that implement regular expres- sion pattern matching using the same syntax and semantics as Perl, with just a few differences. The current implementation of PCRE (release - 4.x) corresponds approximately with Perl 5.8, including support for - UTF-8 encoded strings. However, this support has to be explicitly - enabled; it is not the default. - - PCRE is written in C and released as a C library. However, a number of - people have written wrappers and interfaces of various kinds. A C++ - class is included in these contributions, which can be found in the + 6.x) corresponds approximately with Perl 5.8, including support for + UTF-8 encoded strings and Unicode general category properties. However, + this support has to be explicitly enabled; it is not the default. + + In addition to the Perl-compatible matching function, PCRE also con- + tains an alternative matching function that matches the same compiled + patterns in a different way. In certain circumstances, the alternative + function has some advantages. For a discussion of the two matching + algorithms, see the pcrematching page. + + PCRE is written in C and released as a C library. A number of people + have written wrappers and interfaces of various kinds. In particular, + Google Inc. have provided a comprehensive C++ wrapper. This is now + included as part of the PCRE distribution. The pcrecpp page has details + of this interface. Other people's contributions can be found in the Contrib directory at the primary FTP site, which is: ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre @@ -34,34 +44,45 @@ DESCRIPTION Some features of PCRE can be included, excluded, or changed when the library is built. The pcre_config() function makes it possible for a - client to discover which features are available. Documentation about - building PCRE for various operating systems can be found in the README - file in the source distribution. + client to discover which features are available. The features them- + selves are described in the pcrebuild page. Documentation about build- + ing PCRE for various operating systems can be found in the README file + in the source distribution. + + The library contains a number of undocumented internal functions and + data tables that are used by more than one of the exported external + functions, but which are not intended for use by external callers. + Their names all begin with "_pcre_", which hopefully will not provoke + any name clashes. USER DOCUMENTATION - The user documentation for PCRE has been split up into a number of dif- - ferent sections. In the "man" format, each of these is a separate "man - page". In the HTML format, each is a separate page, linked from the - index page. In the plain text format, all the sections are concate- - nated, for ease of searching. The sections are as follows: + The user documentation for PCRE comprises a number of different sec- + tions. In the "man" format, each of these is a separate "man page". In + the HTML format, each is a separate page, linked from the index page. + In the plain text format, all the sections are concatenated, for ease + of searching. The sections are as follows: pcre this document - pcreapi details of PCRE's native API + pcreapi details of PCRE's native C API pcrebuild options for building PCRE pcrecallout details of the callout feature pcrecompat discussion of Perl compatibility + pcrecpp details of the C++ wrapper pcregrep description of the pcregrep command + pcrematching discussion of the two matching algorithms + pcrepartial details of the partial matching facility pcrepattern syntax and semantics of supported regular expressions pcreperform discussion of performance issues - pcreposix the POSIX-compatible API + pcreposix the POSIX-compatible C API + pcreprecompile details of saving and re-using precompiled patterns pcresample discussion of the sample program - pcretest the pcretest testing command + pcretest description of the pcretest testing command In addition, in the "man" and HTML formats, there is a short page for - each library function, listing its arguments and results. + each C library function, listing its arguments and results. LIMITATIONS @@ -74,7 +95,7 @@ LIMITATIONS process regular expressions that are truly enormous, you can compile PCRE with an internal linkage size of 3 or 4 (see the README file in the source distribution and the pcrebuild documentation for details). - If these cases the limit is substantially larger. However, the speed + In these cases the limit is substantially larger. However, the speed of execution will be slower. All values in repeating quantifiers must be less than 65536. The maxi- @@ -86,17 +107,18 @@ LIMITATIONS tern, is 200. The maximum length of a subject string is the largest positive number - that an integer variable can hold. However, PCRE uses recursion to han- - dle subpatterns and indefinite repetition. This means that the avail- - able stack space may limit the size of a subject string that can be - processed by certain patterns. + that an integer variable can hold. However, when using the traditional + matching function, PCRE uses recursion to handle subpatterns and indef- + inite repetition. This means that the available stack space may limit + the size of a subject string that can be processed by certain patterns. -UTF-8 SUPPORT +UTF-8 AND UNICODE PROPERTY SUPPORT - Starting at release 3.3, PCRE has had some support for character - strings encoded in the UTF-8 format. For release 4.0 this has been - greatly extended to cover most common requirements. + From release 3.3, PCRE has had some support for character strings + encoded in the UTF-8 format. For release 4.0 this was greatly extended + to cover most common requirements, and in release 5.0 additional sup- + port for Unicode general category properties was added. In order process UTF-8 strings, you must build PCRE to include UTF-8 support in the code, and, in addition, you must call pcre_compile() @@ -109,6 +131,14 @@ UTF-8 SUPPORT is limited to testing the PCRE_UTF8 flag in several places, so should not be very large. + If PCRE is built with Unicode character property support (which implies + UTF-8 support), the escape sequences \p{..}, \P{..}, and \X are sup- + ported. The available properties that can be tested are limited to the + general category properties such as Lu for an upper case letter or Nd + for a decimal number. A full list is given in the pcrepattern documen- + tation. The PCRE library is increased in size by about 90K when Unicode + property support is included. + The following comments apply when PCRE is running in UTF-8 mode: 1. When you set the PCRE_UTF8 flag, the strings passed as patterns and @@ -136,51 +166,63 @@ UTF-8 SUPPORT 4. Repeat quantifiers apply to complete UTF-8 characters, not to indi- vidual bytes, for example: \x{100}{3}. - 5. The dot metacharacter matches one UTF-8 character instead of a - single byte. + 5. The dot metacharacter matches one UTF-8 character instead of a sin- + gle byte. 6. The escape sequence \C can be used to match a single byte in UTF-8 - mode, but its use can lead to some strange effects. + mode, but its use can lead to some strange effects. This facility is + not available in the alternative matching function, pcre_dfa_exec(). - 7. The character escapes \b, \B, \d, \D, \s, \S, \w, and \W correctly - test characters of any code value, but the characters that PCRE recog- - nizes as digits, spaces, or word characters remain the same set as - before, all with values less than 256. + 7. The character escapes \b, \B, \d, \D, \s, \S, \w, and \W correctly + test characters of any code value, but the characters that PCRE recog- + nizes as digits, spaces, or word characters remain the same set as + before, all with values less than 256. This remains true even when PCRE + includes Unicode property support, because to do otherwise would slow + down PCRE in many common cases. If you really want to test for a wider + sense of, say, "digit", you must use Unicode property tests such as + \p{Nd}. - 8. Case-insensitive matching applies only to characters whose values - are less than 256. PCRE does not support the notion of "case" for - higher-valued characters. + 8. Similarly, characters that match the POSIX named character classes + are all low-valued characters. - 9. PCRE does not support the use of Unicode tables and properties or - the Perl escapes \p, \P, and \X. + 9. Case-insensitive matching applies only to characters whose values + are less than 128, unless PCRE is built with Unicode property support. + Even when Unicode property support is available, PCRE still uses its + own character tables when checking the case of low-valued characters, + so as not to degrade performance. The Unicode property information is + used only for characters with higher values. AUTHOR - Philip Hazel + Philip Hazel University Computing Service, Cambridge CB2 3QG, England. - Phone: +44 1223 334714 -Last updated: 20 August 2003 -Copyright (c) 1997-2003 University of Cambridge. ------------------------------------------------------------------------------ + Putting an actual email address here seems to have been a spam magnet, + so I've taken it away. If you want to email me, use my initial and sur- + name, separated by a dot, at the domain ucs.cam.ac.uk. + +Last updated: 07 March 2005 +Copyright (c) 1997-2005 University of Cambridge. +------------------------------------------------------------------------------ -PCRE(3) PCRE(3) +PCREBUILD(3) PCREBUILD(3) NAME PCRE - Perl-compatible regular expressions + PCRE BUILD-TIME OPTIONS This document describes the optional features of PCRE that can be selected when the library is compiled. They are all selected, or dese- - lected, by providing options to the configure script which is run - before the make command. The complete list of options for configure - (which includes the standard ones such as the selection of the instal- - lation directory) can be obtained by running + lected, by providing options to the configure script that is run before + the make command. The complete list of options for configure (which + includes the standard ones such as the selection of the installation + directory) can be obtained by running ./configure --help @@ -204,6 +246,25 @@ UTF-8 SUPPORT function. +UNICODE CHARACTER PROPERTY SUPPORT + + UTF-8 support allows PCRE to process character values greater than 255 + in the strings that it handles. On its own, however, it does not pro- + vide any facilities for accessing the properties of such characters. If + you want to be able to use the pattern escapes \P, \p, and \X, which + refer to Unicode character properties, you must add + + --enable-unicode-properties + + to the configure command. This implies UTF-8 support, even if you have + not explicitly requested it. + + Including Unicode property support adds around 90K of tables to the + PCRE library, approximately doubling its size. Only the general cate- + gory properties such as Lu and Nd are supported. Details are given in + the pcrepattern documentation. + + CODE VALUE OF NEWLINE By default, PCRE treats character 10 (linefeed) as the newline charac- @@ -231,9 +292,9 @@ BUILDING SHARED AND STATIC LIBRARIES POSIX MALLOC USAGE - When PCRE is called through the POSIX interface (see the pcreposix - documentation), additional working storage is required for holding the - pointers to capturing substrings because PCRE requires three integers + When PCRE is called through the POSIX interface (see the pcreposix doc- + umentation), additional working storage is required for holding the + pointers to capturing substrings, because PCRE requires three integers per substring, whereas the POSIX interface provides only two. If the number of expected substrings is small, the wrapper function uses space on the stack, because this is faster than using malloc() for each call. @@ -247,24 +308,26 @@ POSIX MALLOC USAGE LIMITING PCRE RESOURCE USAGE - Internally, PCRE has a function called match() which it calls repeat- - edly (possibly recursively) when performing a matching operation. By - limiting the number of times this function may be called, a limit can - be placed on the resources used by a single call to pcre_exec(). The - limit can be changed at run time, as described in the pcreapi documen- - tation. The default is 10 million, but this can be changed by adding a + Internally, PCRE has a function called match(), which it calls repeat- + edly (possibly recursively) when matching a pattern with the + pcre_exec() function. By controlling the maximum number of times this + function may be called during a single matching operation, a limit can + be placed on the resources used by a single call to pcre_exec(). The + limit can be changed at run time, as described in the pcreapi documen- + tation. The default is 10 million, but this can be changed by adding a setting such as --with-match-limit=500000 - to the configure command. + to the configure command. This setting has no effect on the + pcre_dfa_exec() matching function. HANDLING VERY LARGE PATTERNS Within a compiled pattern, offset values are used to point from one part to another (for example, from an opening parenthesis to an alter- - nation metacharacter). By default two-byte values are used for these + nation metacharacter). By default, two-byte values are used for these offsets, leading to a maximum size for a compiled pattern of around 64K. This is sufficient to handle all but the most gigantic patterns. Nevertheless, some people do want to process enormous patterns, so it @@ -285,49 +348,220 @@ HANDLING VERY LARGE PATTERNS AVOIDING EXCESSIVE STACK USAGE - PCRE implements backtracking while matching by making recursive calls - to an internal function called match(). In environments where the size - of the stack is limited, this can severely limit PCRE's operation. (The - Unix environment does not usually suffer from this problem.) An alter- - native approach that uses memory from the heap to remember data, - instead of using recursive function calls, has been implemented to work - round this problem. If you want to build a version of PCRE that works - this way, add + When matching with the pcre_exec() function, PCRE implements backtrack- + ing by making recursive calls to an internal function called match(). + In environments where the size of the stack is limited, this can se- + verely limit PCRE's operation. (The Unix environment does not usually + suffer from this problem.) An alternative approach that uses memory + from the heap to remember data, instead of using recursive function + calls, has been implemented to work round this problem. If you want to + build a version of PCRE that works this way, add --disable-stack-for-recursion to the configure command. With this configuration, PCRE will use the - pcre_stack_malloc and pcre_stack_free variables to call memory - management functions. Separate functions are provided because the usage - is very predictable: the block sizes requested are always the same, and + pcre_stack_malloc and pcre_stack_free variables to call memory manage- + ment functions. Separate functions are provided because the usage is + very predictable: the block sizes requested are always the same, and the blocks are always freed in reverse order. A calling program might be able to implement optimized functions that perform better than the standard malloc() and free() functions. PCRE runs noticeably more - slowly when built in this way. + slowly when built in this way. This option affects only the pcre_exec() + function; it is not relevant for the the pcre_dfa_exec() function. USING EBCDIC CODE - PCRE assumes by default that it will run in an environment where the - character code is ASCII (or UTF-8, which is a superset of ASCII). PCRE - can, however, be compiled to run in an EBCDIC environment by adding + PCRE assumes by default that it will run in an environment where the + character code is ASCII (or Unicode, which is a superset of ASCII). + PCRE can, however, be compiled to run in an EBCDIC environment by + adding --enable-ebcdic to the configure command. -Last updated: 09 December 2003 -Copyright (c) 1997-2003 University of Cambridge. ------------------------------------------------------------------------------ +Last updated: 28 February 2005 +Copyright (c) 1997-2005 University of Cambridge. +------------------------------------------------------------------------------ -PCRE(3) PCRE(3) +PCREMATCHING(3) PCREMATCHING(3) + + +NAME + PCRE - Perl-compatible regular expressions + + +PCRE MATCHING ALGORITHMS + + This document describes the two different algorithms that are available + in PCRE for matching a compiled regular expression against a given sub- + ject string. The "standard" algorithm is the one provided by the + pcre_exec() function. This works in the same was as Perl's matching + function, and provides a Perl-compatible matching operation. + + An alternative algorithm is provided by the pcre_dfa_exec() function; + this operates in a different way, and is not Perl-compatible. It has + advantages and disadvantages compared with the standard algorithm, and + these are described below. + + When there is only one possible way in which a given subject string can + match a pattern, the two algorithms give the same answer. A difference + arises, however, when there are multiple possibilities. For example, if + the pattern + + ^<.*> + + is matched against the string + + + + there are three possible answers. The standard algorithm finds only one + of them, whereas the DFA algorithm finds all three. + + +REGULAR EXPRESSIONS AS TREES + + The set of strings that are matched by a regular expression can be rep- + resented as a tree structure. An unlimited repetition in the pattern + makes the tree of infinite size, but it is still a tree. Matching the + pattern to a given subject string (from a given starting point) can be + thought of as a search of the tree. There are two standard ways to + search a tree: depth-first and breadth-first, and these correspond to + the two matching algorithms provided by PCRE. + + +THE STANDARD MATCHING ALGORITHM + + In the terminology of Jeffrey Friedl's book Mastering Regular Expres- + sions, the standard algorithm is an "NFA algorithm". It conducts a + depth-first search of the pattern tree. That is, it proceeds along a + single path through the tree, checking that the subject matches what is + required. When there is a mismatch, the algorithm tries any alterna- + tives at the current point, and if they all fail, it backs up to the + previous branch point in the tree, and tries the next alternative + branch at that level. This often involves backing up (moving to the + left) in the subject string as well. The order in which repetition + branches are tried is controlled by the greedy or ungreedy nature of + the quantifier. + + If a leaf node is reached, a matching string has been found, and at + that point the algorithm stops. Thus, if there is more than one possi- + ble match, this algorithm returns the first one that it finds. Whether + this is the shortest, the longest, or some intermediate length depends + on the way the greedy and ungreedy repetition quantifiers are specified + in the pattern. + + Because it ends up with a single path through the tree, it is rela- + tively straightforward for this algorithm to keep track of the sub- + strings that are matched by portions of the pattern in parentheses. + This provides support for capturing parentheses and back references. + + +THE DFA MATCHING ALGORITHM + + DFA stands for "deterministic finite automaton", but you do not need to + understand the origins of that name. This algorithm conducts a breadth- + first search of the tree. Starting from the first matching point in the + subject, it scans the subject string from left to right, once, charac- + ter by character, and as it does this, it remembers all the paths + through the tree that represent valid matches. + + The scan continues until either the end of the subject is reached, or + there are no more unterminated paths. At this point, terminated paths + represent the different matching possibilities (if there are none, the + match has failed). Thus, if there is more than one possible match, + this algorithm finds all of them, and in particular, it finds the long- + est. In PCRE, there is an option to stop the algorithm after the first + match (which is necessarily the shortest) has been found. + + Note that all the matches that are found start at the same point in the + subject. If the pattern + + cat(er(pillar)?) + + is matched against the string "the caterpillar catchment", the result + will be the three strings "cat", "cater", and "caterpillar" that start + at the fourth character of the subject. The algorithm does not automat- + ically move on to find matches that start at later positions. + + There are a number of features of PCRE regular expressions that are not + supported by the DFA matching algorithm. They are as follows: + + 1. Because the algorithm finds all possible matches, the greedy or + ungreedy nature of repetition quantifiers is not relevant. Greedy and + ungreedy quantifiers are treated in exactly the same way. + + 2. When dealing with multiple paths through the tree simultaneously, it + is not straightforward to keep track of captured substrings for the + different matching possibilities, and PCRE's implementation of this + algorithm does not attempt to do this. This means that no captured sub- + strings are available. + + 3. Because no substrings are captured, back references within the pat- + tern are not supported, and cause errors if encountered. + + 4. For the same reason, conditional expressions that use a backrefer- + ence as the condition are not supported. + + 5. Callouts are supported, but the value of the capture_top field is + always 1, and the value of the capture_last field is always -1. + + 6. The \C escape sequence, which (in the standard algorithm) matches a + single byte, even in UTF-8 mode, is not supported because the DFA algo- + rithm moves through the subject string one character at a time, for all + active paths through the tree. + + +ADVANTAGES OF THE DFA ALGORITHM + + Using the DFA matching algorithm provides the following advantages: + + 1. All possible matches (at a single point in the subject) are automat- + ically found, and in particular, the longest match is found. To find + more than one match using the standard algorithm, you have to do kludgy + things with callouts. + + 2. There is much better support for partial matching. The restrictions + on the content of the pattern that apply when using the standard algo- + rithm for partial matching do not apply to the DFA algorithm. For non- + anchored patterns, the starting position of a partial match is avail- + able. + + 3. Because the DFA algorithm scans the subject string just once, and + never needs to backtrack, it is possible to pass very long subject + strings to the matching function in several pieces, checking for par- + tial matching each time. + + +DISADVANTAGES OF THE DFA ALGORITHM + + The DFA algorithm suffers from a number of disadvantages: + + 1. It is substantially slower than the standard algorithm. This is + partly because it has to search for all possible matches, but is also + because it is less susceptible to optimization. + + 2. Capturing parentheses and back references are not supported. + + 3. The "atomic group" feature of PCRE regular expressions is supported, + but does not provide the advantage that it does for the standard algo- + rithm. + +Last updated: 28 February 2005 +Copyright (c) 1997-2005 University of Cambridge. +------------------------------------------------------------------------------ + + +PCREAPI(3) PCREAPI(3) NAME PCRE - Perl-compatible regular expressions -SYNOPSIS OF PCRE API + +PCRE NATIVE API #include @@ -335,6 +569,11 @@ SYNOPSIS OF PCRE API const char **errptr, int *erroffset, const unsigned char *tableptr); + pcre *pcre_compile2(const char *pattern, int options, + int *errorcodeptr, + const char **errptr, int *erroffset, + const unsigned char *tableptr); + pcre_extra *pcre_study(const pcre *code, int options, const char **errptr); @@ -342,6 +581,11 @@ SYNOPSIS OF PCRE API const char *subject, int length, int startoffset, int options, int *ovector, int ovecsize); + int pcre_dfa_exec(const pcre *code, const pcre_extra *extra, + const char *subject, int length, int startoffset, + int options, int *ovector, int ovecsize, + int *workspace, int wscount); + int pcre_copy_named_substring(const pcre *code, const char *subject, int *ovector, int stringcount, const char *stringname, @@ -377,6 +621,8 @@ SYNOPSIS OF PCRE API int pcre_info(const pcre *code, int *optptr, int *firstcharptr); + int pcre_refcount(pcre *code, int adjust); + int pcre_config(int what, void *where); char *pcre_version(void); @@ -392,62 +638,84 @@ SYNOPSIS OF PCRE API int (*pcre_callout)(pcre_callout_block *); -PCRE API +PCRE API OVERVIEW PCRE has its own native API, which is described in this document. There is also a set of wrapper functions that correspond to the POSIX regular - expression API. These are described in the pcreposix documentation. - - The native API function prototypes are defined in the header file - pcre.h, and on Unix systems the library itself is called libpcre.a, so - can be accessed by adding -lpcre to the command for linking an applica- - tion which calls it. The header file defines the macros PCRE_MAJOR and - PCRE_MINOR to contain the major and minor release numbers for the - library. Applications can use these to include support for different - releases. - - The functions pcre_compile(), pcre_study(), and pcre_exec() are used - for compiling and matching regular expressions. A sample program that - demonstrates the simplest way of using them is given in the file pcre- - demo.c. The pcresample documentation describes how to run it. - - There are convenience functions for extracting captured substrings from - a matched subject string. They are: + expression API. These are described in the pcreposix documentation. + Both of these APIs define a set of C function calls. A C++ wrapper is + distributed with PCRE. It is documented in the pcrecpp page. + + The native API C function prototypes are defined in the header file + pcre.h, and on Unix systems the library itself is called libpcre. It + can normally be accessed by adding -lpcre to the command for linking an + application that uses PCRE. The header file defines the macros + PCRE_MAJOR and PCRE_MINOR to contain the major and minor release num- + bers for the library. Applications can use these to include support + for different releases of PCRE. + + The functions pcre_compile(), pcre_compile2(), pcre_study(), and + pcre_exec() are used for compiling and matching regular expressions in + a Perl-compatible manner. A sample program that demonstrates the sim- + plest way of using them is provided in the file called pcredemo.c in + the source distribution. The pcresample documentation describes how to + run it. + + A second matching function, pcre_dfa_exec(), which is not Perl-compati- + ble, is also provided. This uses a different algorithm for the match- + ing. This allows it to find all possible matches (at a given point in + the subject), not just one. However, this algorithm does not return + captured substrings. A description of the two matching algorithms and + their advantages and disadvantages is given in the pcrematching docu- + mentation. + + In addition to the main compiling and matching functions, there are + convenience functions for extracting captured substrings from a subject + string that is matched by pcre_exec(). They are: pcre_copy_substring() pcre_copy_named_substring() pcre_get_substring() pcre_get_named_substring() pcre_get_substring_list() + pcre_get_stringnumber() pcre_free_substring() and pcre_free_substring_list() are also provided, to free the memory used for extracted strings. - The function pcre_maketables() is used (optionally) to build a set of - character tables in the current locale for passing to pcre_compile(). - - The function pcre_fullinfo() is used to find out information about a - compiled pattern; pcre_info() is an obsolete version which returns only - some of the available information, but is retained for backwards com- - patibility. The function pcre_version() returns a pointer to a string + The function pcre_maketables() is used to build a set of character + tables in the current locale for passing to pcre_compile(), + pcre_exec(), or pcre_dfa_exec(). This is an optional facility that is + provided for specialist use. Most commonly, no special tables are + passed, in which case internal tables that are generated when PCRE is + built are used. + + The function pcre_fullinfo() is used to find out information about a + compiled pattern; pcre_info() is an obsolete version that returns only + some of the available information, but is retained for backwards com- + patibility. The function pcre_version() returns a pointer to a string containing the version of PCRE and its date of release. - The global variables pcre_malloc and pcre_free initially contain the - entry points of the standard malloc() and free() functions respec- + The function pcre_refcount() maintains a reference count in a data + block containing a compiled pattern. This is provided for the benefit + of object-oriented applications. + + The global variables pcre_malloc and pcre_free initially contain the + entry points of the standard malloc() and free() functions, respec- tively. PCRE calls the memory management functions via these variables, - so a calling program can replace them if it wishes to intercept the + so a calling program can replace them if it wishes to intercept the calls. This should be done before calling any PCRE functions. - The global variables pcre_stack_malloc and pcre_stack_free are also - indirections to memory management functions. These special functions - are used only when PCRE is compiled to use the heap for remembering - data, instead of recursive function calls. This is a non-standard way - of building PCRE, for use in environments that have limited stacks. - Because of the greater use of memory management, it runs more slowly. - Separate functions are provided so that special-purpose external code - can be used for this case. When used, these functions are always called - in a stack-like manner (last obtained, first freed), and always for - memory blocks of the same size. + The global variables pcre_stack_malloc and pcre_stack_free are also + indirections to memory management functions. These special functions + are used only when PCRE is compiled to use the heap for remembering + data, instead of recursive function calls, when running the pcre_exec() + function. This is a non-standard way of building PCRE, for use in envi- + ronments that have limited stacks. Because of the greater use of memory + management, it runs more slowly. Separate functions are provided so + that special-purpose external code can be used for this case. When + used, these functions are always called in a stack-like manner (last + obtained, first freed), and always for memory blocks of the same size. The global variable pcre_callout initially contains NULL. It can be set by the caller to a "callout" function, which PCRE will then call at @@ -467,25 +735,38 @@ MULTITHREADING at once. +SAVING PRECOMPILED PATTERNS FOR LATER USE + + The compiled form of a regular expression can be saved and re-used at a + later time, possibly by a different program, and even on a host other + than the one on which it was compiled. Details are given in the + pcreprecompile documentation. + + CHECKING BUILD-TIME OPTIONS int pcre_config(int what, void *where); - The function pcre_config() makes it possible for a PCRE client to dis- + The function pcre_config() makes it possible for a PCRE client to dis- cover which optional features have been compiled into the PCRE library. - The pcrebuild documentation has more details about these optional fea- + The pcrebuild documentation has more details about these optional fea- tures. - The first argument for pcre_config() is an integer, specifying which + The first argument for pcre_config() is an integer, specifying which information is required; the second argument is a pointer to a variable - into which the information is placed. The following information is + into which the information is placed. The following information is available: PCRE_CONFIG_UTF8 - The output is an integer that is set to one if UTF-8 support is avail- + The output is an integer that is set to one if UTF-8 support is avail- able; otherwise it is set to zero. + PCRE_CONFIG_UNICODE_PROPERTIES + + The output is an integer that is set to one if support for Unicode + character properties is available; otherwise it is set to zero. + PCRE_CONFIG_NEWLINE The output is an integer that is set to the value of the code that is @@ -516,13 +797,13 @@ CHECKING BUILD-TIME OPTIONS PCRE_CONFIG_STACKRECURSE - The output is an integer that is set to one if internal recursion is - implemented by recursive function calls that use the stack to remember - their state. This is the usual way that PCRE is compiled. The output is - zero if PCRE was compiled to use blocks of data on the heap instead of - recursive function calls. In this case, pcre_stack_malloc and - pcre_stack_free are called to manage memory blocks on the heap, thus - avoiding the use of the stack. + The output is an integer that is set to one if internal recursion when + running pcre_exec() is implemented by recursive function calls that use + the stack to remember their state. This is the usual way that PCRE is + compiled. The output is zero if PCRE was compiled to use blocks of data + on the heap instead of recursive function calls. In this case, + pcre_stack_malloc and pcre_stack_free are called to manage memory + blocks on the heap, thus avoiding the use of the stack. COMPILING A PATTERN @@ -531,44 +812,61 @@ COMPILING A PATTERN const char **errptr, int *erroffset, const unsigned char *tableptr); + pcre *pcre_compile2(const char *pattern, int options, + int *errorcodeptr, + const char **errptr, int *erroffset, + const unsigned char *tableptr); + + Either of the functions pcre_compile() or pcre_compile2() can be called + to compile a pattern into an internal form. The only difference between + the two interfaces is that pcre_compile2() has an additional argument, + errorcodeptr, via which a numerical error code can be returned. - The function pcre_compile() is called to compile a pattern into an - internal form. The pattern is a C string terminated by a binary zero, - and is passed in the argument pattern. A pointer to a single block of - memory that is obtained via pcre_malloc is returned. This contains the - compiled code and related data. The pcre type is defined for the - returned block; this is a typedef for a structure whose contents are - not externally defined. It is up to the caller to free the memory when - it is no longer required. + The pattern is a C string terminated by a binary zero, and is passed in + the pattern argument. A pointer to a single block of memory that is + obtained via pcre_malloc is returned. This contains the compiled code + and related data. The pcre type is defined for the returned block; this + is a typedef for a structure whose contents are not externally defined. + It is up to the caller to free the memory when it is no longer + required. Although the compiled code of a PCRE regex is relocatable, that is, it does not depend on memory location, the complete pcre data block is not - fully relocatable, because it contains a copy of the tableptr argument, - which is an address (see below). + fully relocatable, because it may contain a copy of the tableptr argu- + ment, which is an address (see below). The options argument contains independent bits that affect the compila- - tion. It should be zero if no options are required. Some of the - options, in particular, those that are compatible with Perl, can also - be set and unset from within the pattern (see the detailed description - of regular expressions in the pcrepattern documentation). For these - options, the contents of the options argument specifies their initial - settings at the start of compilation and execution. The PCRE_ANCHORED - option can be set at the time of matching as well as at compile time. + tion. It should be zero if no options are required. The available + options are described below. Some of them, in particular, those that + are compatible with Perl, can also be set and unset from within the + pattern (see the detailed description in the pcrepattern documenta- + tion). For these options, the contents of the options argument speci- + fies their initial settings at the start of compilation and execution. + The PCRE_ANCHORED option can be set at the time of matching as well as + at compile time. If errptr is NULL, pcre_compile() returns NULL immediately. Otherwise, - if compilation of a pattern fails, pcre_compile() returns NULL, and + if compilation of a pattern fails, pcre_compile() returns NULL, and sets the variable pointed to by errptr to point to a textual error mes- - sage. The offset from the start of the pattern to the character where - the error was discovered is placed in the variable pointed to by - erroffset, which must not be NULL. If it is, an immediate error is + sage. The offset from the start of the pattern to the character where + the error was discovered is placed in the variable pointed to by + erroffset, which must not be NULL. If it is, an immediate error is given. - If the final argument, tableptr, is NULL, PCRE uses a default set of - character tables which are built when it is compiled, using the default - C locale. Otherwise, tableptr must be the result of a call to - pcre_maketables(). See the section on locale support below. + If pcre_compile2() is used instead of pcre_compile(), and the error- + codeptr argument is not NULL, a non-zero error code number is returned + via this argument in the event of an error. This is in addition to the + textual error message. Error codes and messages are listed below. - This code fragment shows a typical straightforward call to pcre_com- + If the final argument, tableptr, is NULL, PCRE uses a default set of + character tables that are built when PCRE is compiled, using the + default C locale. Otherwise, tableptr must be an address that is the + result of a call to pcre_maketables(). This value is stored with the + compiled pattern, and used again by pcre_exec(), unless another table + pointer is passed to it. For more discussion, see the section on locale + support below. + + This code fragment shows a typical straightforward call to pcre_com- pile(): pcre *re; @@ -581,144 +879,222 @@ COMPILING A PATTERN &erroffset, /* for error offset */ NULL); /* use default character tables */ - The following option bits are defined: + The following names for option bits are defined in the pcre.h header + file: PCRE_ANCHORED If this bit is set, the pattern is forced to be "anchored", that is, it is constrained to match only at the first matching point in the string - which is being searched (the "subject string"). This effect can also be + that is being searched (the "subject string"). This effect can also be achieved by appropriate constructs in the pattern itself, which is the only way to do it in Perl. + PCRE_AUTO_CALLOUT + + If this bit is set, pcre_compile() automatically inserts callout items, + all with number 255, before each pattern item. For discussion of the + callout facility, see the pcrecallout documentation. + PCRE_CASELESS If this bit is set, letters in the pattern match both upper and lower case letters. It is equivalent to Perl's /i option, and it can be - changed within a pattern by a (?i) option setting. + changed within a pattern by a (?i) option setting. In UTF-8 mode, PCRE + always understands the concept of case for characters whose values are + less than 128, so caseless matching is always possible. For characters + with higher values, the concept of case is supported if PCRE is com- + piled with Unicode property support, but not otherwise. If you want to + use caseless matching for characters 128 and above, you must ensure + that PCRE is compiled with Unicode property support as well as with + UTF-8 support. PCRE_DOLLAR_ENDONLY - If this bit is set, a dollar metacharacter in the pattern matches only - at the end of the subject string. Without this option, a dollar also - matches immediately before the final character if it is a newline (but - not before any other newlines). The PCRE_DOLLAR_ENDONLY option is + If this bit is set, a dollar metacharacter in the pattern matches only + at the end of the subject string. Without this option, a dollar also + matches immediately before the final character if it is a newline (but + not before any other newlines). The PCRE_DOLLAR_ENDONLY option is ignored if PCRE_MULTILINE is set. There is no equivalent to this option in Perl, and no way to set it within a pattern. PCRE_DOTALL If this bit is set, a dot metacharater in the pattern matches all char- - acters, including newlines. Without it, newlines are excluded. This - option is equivalent to Perl's /s option, and it can be changed within - a pattern by a (?s) option setting. A negative class such as [^a] - always matches a newline character, independent of the setting of this + acters, including newlines. Without it, newlines are excluded. This + option is equivalent to Perl's /s option, and it can be changed within + a pattern by a (?s) option setting. A negative class such as [^a] + always matches a newline character, independent of the setting of this option. PCRE_EXTENDED - If this bit is set, whitespace data characters in the pattern are - totally ignored except when escaped or inside a character class. - Whitespace does not include the VT character (code 11). In addition, - characters between an unescaped # outside a character class and the - next newline character, inclusive, are also ignored. This is equivalent - to Perl's /x option, and it can be changed within a pattern by a (?x) + If this bit is set, whitespace data characters in the pattern are + totally ignored except when escaped or inside a character class. White- + space does not include the VT character (code 11). In addition, charac- + ters between an unescaped # outside a character class and the next new- + line character, inclusive, are also ignored. This is equivalent to + Perl's /x option, and it can be changed within a pattern by a (?x) option setting. - This option makes it possible to include comments inside complicated - patterns. Note, however, that this applies only to data characters. - Whitespace characters may never appear within special character - sequences in a pattern, for example within the sequence (?( which + This option makes it possible to include comments inside complicated + patterns. Note, however, that this applies only to data characters. + Whitespace characters may never appear within special character + sequences in a pattern, for example within the sequence (?( which introduces a conditional subpattern. PCRE_EXTRA - This option was invented in order to turn on additional functionality - of PCRE that is incompatible with Perl, but it is currently of very - little use. When set, any backslash in a pattern that is followed by a - letter that has no special meaning causes an error, thus reserving - these combinations for future expansion. By default, as in Perl, a - backslash followed by a letter with no special meaning is treated as a - literal. There are at present no other features controlled by this + This option was invented in order to turn on additional functionality + of PCRE that is incompatible with Perl, but it is currently of very + little use. When set, any backslash in a pattern that is followed by a + letter that has no special meaning causes an error, thus reserving + these combinations for future expansion. By default, as in Perl, a + backslash followed by a letter with no special meaning is treated as a + literal. There are at present no other features controlled by this option. It can also be set by a (?X) option setting within a pattern. + PCRE_FIRSTLINE + + If this option is set, an unanchored pattern is required to match + before or at the first newline character in the subject string, though + the matched text may continue over the newline. + PCRE_MULTILINE - By default, PCRE treats the subject string as consisting of a single - "line" of characters (even if it actually contains several newlines). - The "start of line" metacharacter (^) matches only at the start of the - string, while the "end of line" metacharacter ($) matches only at the - end of the string, or before a terminating newline (unless PCRE_DOL- - LAR_ENDONLY is set). This is the same as Perl. - - When PCRE_MULTILINE it is set, the "start of line" and "end of line" - constructs match immediately following or immediately before any new- - line in the subject string, respectively, as well as at the very start - and end. This is equivalent to Perl's /m option, and it can be changed + By default, PCRE treats the subject string as consisting of a single + line of characters (even if it actually contains newlines). The "start + of line" metacharacter (^) matches only at the start of the string, + while the "end of line" metacharacter ($) matches only at the end of + the string, or before a terminating newline (unless PCRE_DOLLAR_ENDONLY + is set). This is the same as Perl. + + When PCRE_MULTILINE it is set, the "start of line" and "end of line" + constructs match immediately following or immediately before any new- + line in the subject string, respectively, as well as at the very start + and end. This is equivalent to Perl's /m option, and it can be changed within a pattern by a (?m) option setting. If there are no "\n" charac- - ters in a subject string, or no occurrences of ^ or $ in a pattern, + ters in a subject string, or no occurrences of ^ or $ in a pattern, setting PCRE_MULTILINE has no effect. PCRE_NO_AUTO_CAPTURE If this option is set, it disables the use of numbered capturing paren- - theses in the pattern. Any opening parenthesis that is not followed by - ? behaves as if it were followed by ?: but named parentheses can still - be used for capturing (and they acquire numbers in the usual way). + theses in the pattern. Any opening parenthesis that is not followed by + ? behaves as if it were followed by ?: but named parentheses can still + be used for capturing (and they acquire numbers in the usual way). There is no equivalent of this option in Perl. PCRE_UNGREEDY - This option inverts the "greediness" of the quantifiers so that they - are not greedy by default, but become greedy if followed by "?". It is - not compatible with Perl. It can also be set by a (?U) option setting + This option inverts the "greediness" of the quantifiers so that they + are not greedy by default, but become greedy if followed by "?". It is + not compatible with Perl. It can also be set by a (?U) option setting within the pattern. PCRE_UTF8 - This option causes PCRE to regard both the pattern and the subject as - strings of UTF-8 characters instead of single-byte character strings. - However, it is available only if PCRE has been built to include UTF-8 - support. If not, the use of this option provokes an error. Details of - how this option changes the behaviour of PCRE are given in the section - on UTF-8 support in the main pcre page. + This option causes PCRE to regard both the pattern and the subject as + strings of UTF-8 characters instead of single-byte character strings. + However, it is available only when PCRE is built to include UTF-8 sup- + port. If not, the use of this option provokes an error. Details of how + this option changes the behaviour of PCRE are given in the section on + UTF-8 support in the main pcre page. PCRE_NO_UTF8_CHECK When PCRE_UTF8 is set, the validity of the pattern as a UTF-8 string is - automatically checked. If an invalid UTF-8 sequence of bytes is found, - pcre_compile() returns an error. If you already know that your pattern - is valid, and you want to skip this check for performance reasons, you - can set the PCRE_NO_UTF8_CHECK option. When it is set, the effect of + automatically checked. If an invalid UTF-8 sequence of bytes is found, + pcre_compile() returns an error. If you already know that your pattern + is valid, and you want to skip this check for performance reasons, you + can set the PCRE_NO_UTF8_CHECK option. When it is set, the effect of passing an invalid UTF-8 string as a pattern is undefined. It may cause - your program to crash. Note that there is a similar option for sup- - pressing the checking of subject strings passed to pcre_exec(). - + your program to crash. Note that this option can also be passed to + pcre_exec() and pcre_dfa_exec(), to suppress the UTF-8 validity check- + ing of subject strings. + + +COMPILATION ERROR CODES + + The following table lists the error codes than may be returned by + pcre_compile2(), along with the error messages that may be returned by + both compiling functions. + + 0 no error + 1 \ at end of pattern + 2 \c at end of pattern + 3 unrecognized character follows \ + 4 numbers out of order in {} quantifier + 5 number too big in {} quantifier + 6 missing terminating ] for character class + 7 invalid escape sequence in character class + 8 range out of order in character class + 9 nothing to repeat + 10 operand of unlimited repeat could match the empty string + 11 internal error: unexpected repeat + 12 unrecognized character after (? + 13 POSIX named classes are supported only within a class + 14 missing ) + 15 reference to non-existent subpattern + 16 erroffset passed as NULL + 17 unknown option bit(s) set + 18 missing ) after comment + 19 parentheses nested too deeply + 20 regular expression too large + 21 failed to get memory + 22 unmatched parentheses + 23 internal error: code overflow + 24 unrecognized character after (?< + 25 lookbehind assertion is not fixed length + 26 malformed number after (?( + 27 conditional group contains more than two branches + 28 assertion expected after (?( + 29 (?R or (?digits must be followed by ) + 30 unknown POSIX class name + 31 POSIX collating elements are not supported + 32 this version of PCRE is not compiled with PCRE_UTF8 support + 33 spare error + 34 character value in \x{...} sequence is too large + 35 invalid condition (?(0) + 36 \C not allowed in lookbehind assertion + 37 PCRE does not support \L, \l, \N, \U, or \u + 38 number after (?C is > 255 + 39 closing ) for (?C expected + 40 recursive call could loop indefinitely + 41 unrecognized character after (?P + 42 syntax error after (?P + 43 two named groups have the same name + 44 invalid UTF-8 string + 45 support for \P, \p, and \X has not been compiled + 46 malformed \P or \p sequence + 47 unknown property name after \P or \p STUDYING A PATTERN - pcre_extra *pcre_study(const pcre *code, int options, + pcre_extra *pcre_study(const pcre *code, int options const char **errptr); - When a pattern is going to be used several times, it is worth spending - more time analyzing it in order to speed up the time taken for match- - ing. The function pcre_study() takes a pointer to a compiled pattern as - its first argument. If studing the pattern produces additional informa- - tion that will help speed up matching, pcre_study() returns a pointer - to a pcre_extra block, in which the study_data field points to the - results of the study. + If a compiled pattern is going to be used several times, it is worth + spending more time analyzing it in order to speed up the time taken for + matching. The function pcre_study() takes a pointer to a compiled pat- + tern as its first argument. If studying the pattern produces additional + information that will help speed up matching, pcre_study() returns a + pointer to a pcre_extra block, in which the study_data field points to + the results of the study. - The returned value from a pcre_study() can be passed directly to - pcre_exec(). However, the pcre_extra block also contains other fields + The returned value from pcre_study() can be passed directly to + pcre_exec(). However, a pcre_extra block also contains other fields that can be set by the caller before the block is passed; these are - described below. If studying the pattern does not produce any addi- - tional information, pcre_study() returns NULL. In that circumstance, if - the calling program wants to pass some of the other fields to - pcre_exec(), it must set up its own pcre_extra block. + described below in the section on matching a pattern. + + If studying the pattern does not produce any additional information + pcre_study() returns NULL. In that circumstance, if the calling program + wants to pass any of the other fields to pcre_exec(), it must set up + its own pcre_extra block. - The second argument contains option bits. At present, no options are - defined for pcre_study(), and this argument should always be zero. + The second argument of pcre_study() contains option bits. At present, + no options are defined, and this argument should always be zero. The third argument for pcre_study() is a pointer for an error message. If studying succeeds (even if no data is returned), the variable it @@ -736,39 +1112,52 @@ STUDYING A PATTERN At present, studying a pattern is useful only for non-anchored patterns that do not have a single fixed starting character. A bitmap of possi- - ble starting characters is created. + ble starting bytes is created. LOCALE SUPPORT PCRE handles caseless matching, and determines whether characters are - letters, digits, or whatever, by reference to a set of tables. When - running in UTF-8 mode, this applies only to characters with codes less - than 256. The library contains a default set of tables that is created - in the default C locale when PCRE is compiled. This is used when the - final argument of pcre_compile() is NULL, and is sufficient for many - applications. - - An alternative set of tables can, however, be supplied. Such tables are - built by calling the pcre_maketables() function, which has no argu- - ments, in the relevant locale. The result can then be passed to - pcre_compile() as often as necessary. For example, to build and use - tables that are appropriate for the French locale (where accented char- - acters with codes greater than 128 are treated as letters), the follow- - ing code could be used: - - setlocale(LC_CTYPE, "fr"); + letters digits, or whatever, by reference to a set of tables, indexed + by character value. When running in UTF-8 mode, this applies only to + characters with codes less than 128. Higher-valued codes never match + escapes such as \w or \d, but can be tested with \p if PCRE is built + with Unicode character property support. + + An internal set of tables is created in the default C locale when PCRE + is built. This is used when the final argument of pcre_compile() is + NULL, and is sufficient for many applications. An alternative set of + tables can, however, be supplied. These may be created in a different + locale from the default. As more and more applications change to using + Unicode, the need for this locale support is expected to die away. + + External tables are built by calling the pcre_maketables() function, + which has no arguments, in the relevant locale. The result can then be + passed to pcre_compile() or pcre_exec() as often as necessary. For + example, to build and use tables that are appropriate for the French + locale (where accented characters with values greater than 128 are + treated as letters), the following code could be used: + + setlocale(LC_CTYPE, "fr_FR"); tables = pcre_maketables(); re = pcre_compile(..., tables); - The tables are built in memory that is obtained via pcre_malloc. The - pointer that is passed to pcre_compile is saved with the compiled pat- - tern, and the same tables are used via this pointer by pcre_study() and - pcre_exec(). Thus, for any single pattern, compilation, studying and - matching all happen in the same locale, but different patterns can be - compiled in different locales. It is the caller's responsibility to - ensure that the memory containing the tables remains available for as - long as it is needed. + When pcre_maketables() runs, the tables are built in memory that is + obtained via pcre_malloc. It is the caller's responsibility to ensure + that the memory containing the tables remains available for as long as + it is needed. + + The pointer that is passed to pcre_compile() is saved with the compiled + pattern, and the same tables are used via this pointer by pcre_study() + and normally also by pcre_exec(). Thus, by default, for any single pat- + tern, compilation, studying and matching all happen in the same locale, + but different patterns can be compiled in different locales. + + It is possible to pass a table pointer or NULL (indicating the use of + the internal tables) to pcre_exec(). Although not intended for this + purpose, this facility could be used to match a pattern in a different + locale from the one in which it was compiled. Passing table pointers at + run time is discussed below in the section on matching a pattern. INFORMATION ABOUT A PATTERN @@ -776,15 +1165,15 @@ INFORMATION ABOUT A PATTERN int pcre_fullinfo(const pcre *code, const pcre_extra *extra, int what, void *where); - The pcre_fullinfo() function returns information about a compiled pat- + The pcre_fullinfo() function returns information about a compiled pat- tern. It replaces the obsolete pcre_info() function, which is neverthe- less retained for backwards compability (and is documented below). - The first argument for pcre_fullinfo() is a pointer to the compiled - pattern. The second argument is the result of pcre_study(), or NULL if - the pattern was not studied. The third argument specifies which piece - of information is required, and the fourth argument is a pointer to a - variable to receive the data. The yield of the function is zero for + The first argument for pcre_fullinfo() is a pointer to the compiled + pattern. The second argument is the result of pcre_study(), or NULL if + the pattern was not studied. The third argument specifies which piece + of information is required, and the fourth argument is a pointer to a + variable to receive the data. The yield of the function is zero for success, or one of the following negative numbers: PCRE_ERROR_NULL the argument code was NULL @@ -792,8 +1181,10 @@ INFORMATION ABOUT A PATTERN PCRE_ERROR_BADMAGIC the "magic number" was not found PCRE_ERROR_BADOPTION the value of what was invalid - Here is a typical call of pcre_fullinfo(), to obtain the length of the - compiled pattern: + The "magic number" is placed at the start of each compiled pattern as + an simple check against passing an arbitrary memory pointer. Here is a + typical call of pcre_fullinfo(), to obtain the length of the compiled + pattern: int rc; unsigned long int length; @@ -803,56 +1194,64 @@ INFORMATION ABOUT A PATTERN PCRE_INFO_SIZE, /* what is required */ &length); /* where to put the data */ - The possible values for the third argument are defined in pcre.h, and + The possible values for the third argument are defined in pcre.h, and are as follows: PCRE_INFO_BACKREFMAX - Return the number of the highest back reference in the pattern. The - fourth argument should point to an int variable. Zero is returned if + Return the number of the highest back reference in the pattern. The + fourth argument should point to an int variable. Zero is returned if there are no back references. PCRE_INFO_CAPTURECOUNT - Return the number of capturing subpatterns in the pattern. The fourth + Return the number of capturing subpatterns in the pattern. The fourth argument should point to an int variable. + PCRE_INFO_DEFAULT_TABLES + + Return a pointer to the internal default character tables within PCRE. + The fourth argument should point to an unsigned char * variable. This + information call is provided for internal use by the pcre_study() func- + tion. External callers can cause PCRE to use its internal tables by + passing a NULL table pointer. + PCRE_INFO_FIRSTBYTE - Return information about the first byte of any matched string, for a - non-anchored pattern. (This option used to be called - PCRE_INFO_FIRSTCHAR; the old name is still recognized for backwards + Return information about the first byte of any matched string, for a + non-anchored pattern. (This option used to be called + PCRE_INFO_FIRSTCHAR; the old name is still recognized for backwards compatibility.) - If there is a fixed first byte, e.g. from a pattern such as - (cat|cow|coyote), it is returned in the integer pointed to by where. + If there is a fixed first byte, for example, from a pattern such as + (cat|cow|coyote), it is returned in the integer pointed to by where. Otherwise, if either - (a) the pattern was compiled with the PCRE_MULTILINE option, and every + (a) the pattern was compiled with the PCRE_MULTILINE option, and every branch starts with "^", or (b) every branch of the pattern starts with ".*" and PCRE_DOTALL is not set (if it were set, the pattern would be anchored), - -1 is returned, indicating that the pattern matches only at the start - of a subject string or after any newline within the string. Otherwise + -1 is returned, indicating that the pattern matches only at the start + of a subject string or after any newline within the string. Otherwise -2 is returned. For anchored patterns, -2 is returned. PCRE_INFO_FIRSTTABLE - If the pattern was studied, and this resulted in the construction of a + If the pattern was studied, and this resulted in the construction of a 256-bit table indicating a fixed set of bytes for the first byte in any - matching string, a pointer to the table is returned. Otherwise NULL is - returned. The fourth argument should point to an unsigned char * vari- + matching string, a pointer to the table is returned. Otherwise NULL is + returned. The fourth argument should point to an unsigned char * vari- able. PCRE_INFO_LASTLITERAL - Return the value of the rightmost literal byte that must exist in any - matched string, other than at its start, if such a byte has been + Return the value of the rightmost literal byte that must exist in any + matched string, other than at its start, if such a byte has been recorded. The fourth argument should point to an int variable. If there - is no such byte, -1 is returned. For anchored patterns, a last literal - byte is recorded only if it follows something of variable length. For + is no such byte, -1 is returned. For anchored patterns, a last literal + byte is recorded only if it follows something of variable length. For example, for the pattern /^a\d+z\d+/ the returned value is "z", but for /^a\dz\d/ the returned value is -1. @@ -860,48 +1259,52 @@ INFORMATION ABOUT A PATTERN PCRE_INFO_NAMEENTRYSIZE PCRE_INFO_NAMETABLE - PCRE supports the use of named as well as numbered capturing parenthe- - ses. The names are just an additional way of identifying the parenthe- - ses, which still acquire a number. A caller that wants to extract data - from a named subpattern must convert the name to a number in order to - access the correct pointers in the output vector (described with - pcre_exec() below). In order to do this, it must first use these three - values to obtain the name-to-number mapping table for the pattern. + PCRE supports the use of named as well as numbered capturing parenthe- + ses. The names are just an additional way of identifying the parenthe- + ses, which still acquire numbers. A convenience function called + pcre_get_named_substring() is provided for extracting an individual + captured substring by name. It is also possible to extract the data + directly, by first converting the name to a number in order to access + the correct pointers in the output vector (described with pcre_exec() + below). To do the conversion, you need to use the name-to-number map, + which is described by these three values. The map consists of a number of fixed-size entries. PCRE_INFO_NAMECOUNT gives the number of entries, and PCRE_INFO_NAMEENTRYSIZE gives the size - of each entry; both of these return an int value. The entry size - depends on the length of the longest name. PCRE_INFO_NAMETABLE returns - a pointer to the first entry of the table (a pointer to char). The + of each entry; both of these return an int value. The entry size + depends on the length of the longest name. PCRE_INFO_NAMETABLE returns + a pointer to the first entry of the table (a pointer to char). The first two bytes of each entry are the number of the capturing parenthe- - sis, most significant byte first. The rest of the entry is the corre- - sponding name, zero terminated. The names are in alphabetical order. - For example, consider the following pattern (assume PCRE_EXTENDED is + sis, most significant byte first. The rest of the entry is the corre- + sponding name, zero terminated. The names are in alphabetical order. + For example, consider the following pattern (assume PCRE_EXTENDED is set, so white space - including newlines - is ignored): (?P (?P(\d\d)?\d\d) - (?P\d\d) - (?P\d\d) ) - There are four named subpatterns, so the table has four entries, and - each entry in the table is eight bytes long. The table is as follows, - with non-printing bytes shows in hex, and undefined bytes shown as ??: + There are four named subpatterns, so the table has four entries, and + each entry in the table is eight bytes long. The table is as follows, + with non-printing bytes shows in hexadecimal, and undefined bytes shown + as ??: 00 01 d a t e 00 ?? 00 05 d a y 00 ?? ?? 00 04 m o n t h 00 00 02 y e a r 00 ?? - When writing code to extract data from named subpatterns, remember that - the length of each entry may be different for each compiled pattern. + When writing code to extract data from named subpatterns using the + name-to-number map, remember that the length of each entry is likely to + be different for each compiled pattern. PCRE_INFO_OPTIONS - Return a copy of the options with which the pattern was compiled. The - fourth argument should point to an unsigned long int variable. These + Return a copy of the options with which the pattern was compiled. The + fourth argument should point to an unsigned long int variable. These option bits are those specified in the call to pcre_compile(), modified by any top-level option settings within the pattern itself. - A pattern is automatically anchored by PCRE if all of its top-level + A pattern is automatically anchored by PCRE if all of its top-level alternatives begin with one of the following: ^ unless PCRE_MULTILINE is set @@ -915,17 +1318,17 @@ INFORMATION ABOUT A PATTERN PCRE_INFO_SIZE - Return the size of the compiled pattern, that is, the value that was + Return the size of the compiled pattern, that is, the value that was passed as the argument to pcre_malloc() when PCRE was getting memory in which to place the compiled data. The fourth argument should point to a size_t variable. PCRE_INFO_STUDYSIZE - Returns the size of the data block pointed to by the study_data field - in a pcre_extra block. That is, it is the value that was passed to + Return the size of the data block pointed to by the study_data field in + a pcre_extra block. That is, it is the value that was passed to pcre_malloc() when PCRE was getting memory into which to place the data - created by pcre_study(). The fourth argument should point to a size_t + created by pcre_study(). The fourth argument should point to a size_t variable. @@ -933,34 +1336,65 @@ OBSOLETE INFO FUNCTION int pcre_info(const pcre *code, int *optptr, int *firstcharptr); - The pcre_info() function is now obsolete because its interface is too - restrictive to return all the available data about a compiled pattern. - New programs should use pcre_fullinfo() instead. The yield of - pcre_info() is the number of capturing subpatterns, or one of the fol- + The pcre_info() function is now obsolete because its interface is too + restrictive to return all the available data about a compiled pattern. + New programs should use pcre_fullinfo() instead. The yield of + pcre_info() is the number of capturing subpatterns, or one of the fol- lowing negative numbers: PCRE_ERROR_NULL the argument code was NULL PCRE_ERROR_BADMAGIC the "magic number" was not found - If the optptr argument is not NULL, a copy of the options with which - the pattern was compiled is placed in the integer it points to (see + If the optptr argument is not NULL, a copy of the options with which + the pattern was compiled is placed in the integer it points to (see PCRE_INFO_OPTIONS above). - If the pattern is not anchored and the firstcharptr argument is not - NULL, it is used to pass back information about the first character of + If the pattern is not anchored and the firstcharptr argument is not + NULL, it is used to pass back information about the first character of any matched string (see PCRE_INFO_FIRSTBYTE above). -MATCHING A PATTERN +REFERENCE COUNTS + + int pcre_refcount(pcre *code, int adjust); + + The pcre_refcount() function is used to maintain a reference count in + the data block that contains a compiled pattern. It is provided for the + benefit of applications that operate in an object-oriented manner, + where different parts of the application may be using the same compiled + pattern, but you want to free the block when they are all done. + + When a pattern is compiled, the reference count field is initialized to + zero. It is changed only by calling this function, whose action is to + add the adjust value (which may be positive or negative) to it. The + yield of the function is the new value. However, the value of the count + is constrained to lie between 0 and 65535, inclusive. If the new value + is outside these limits, it is forced to the appropriate limit value. + + Except when it is zero, the reference count is not correctly preserved + if a pattern is compiled on one host and then transferred to a host + whose byte-order is different. (This seems a highly unlikely scenario.) + + +MATCHING A PATTERN: THE TRADITIONAL FUNCTION int pcre_exec(const pcre *code, const pcre_extra *extra, const char *subject, int length, int startoffset, int options, int *ovector, int ovecsize); - The function pcre_exec() is called to match a subject string against a - pre-compiled pattern, which is passed in the code argument. If the pat- - tern has been studied, the result of the study should be passed in the - extra argument. + The function pcre_exec() is called to match a subject string against a + compiled pattern, which is passed in the code argument. If the pattern + has been studied, the result of the study should be passed in the extra + argument. This function is the main matching facility of the library, + and it operates in a Perl-like manner. For specialist use there is also + an alternative matching function, which is described below in the sec- + tion about the pcre_dfa_exec() function. + + In most applications, the pattern will have been compiled (and option- + ally studied) in the same process that calls pcre_exec(). However, it + is possible to save compiled patterns and study data, and then use them + later in different processes, possibly even on different hosts. For a + discussion about this, see the pcreprecompile documentation. Here is an example of a simple call to pcre_exec(): @@ -973,41 +1407,49 @@ MATCHING A PATTERN 11, /* the length of the subject string */ 0, /* start at offset 0 in the subject */ 0, /* default options */ - ovector, /* vector for substring information */ - 30); /* number of elements in the vector */ + ovector, /* vector of integers for substring information */ + 30); /* number of elements (NOT size in bytes) */ + + Extra data for pcre_exec() If the extra argument is not NULL, it must point to a pcre_extra data block. The pcre_study() function returns such a block (when it doesn't return NULL), but you can also create one for yourself, and pass addi- - tional information in it. The fields in the block are as follows: + tional information in it. The fields in a pcre_extra block are as fol- + lows: unsigned long int flags; void *study_data; unsigned long int match_limit; void *callout_data; + const unsigned char *tables; - The flags field is a bitmap that specifies which of the other fields + The flags field is a bitmap that specifies which of the other fields are set. The flag bits are: PCRE_EXTRA_STUDY_DATA PCRE_EXTRA_MATCH_LIMIT PCRE_EXTRA_CALLOUT_DATA + PCRE_EXTRA_TABLES - Other flag bits should be set to zero. The study_data field is set in - the pcre_extra block that is returned by pcre_study(), together with - the appropriate flag bit. You should not set this yourself, but you can - add to the block by setting the other fields. + Other flag bits should be set to zero. The study_data field is set in + the pcre_extra block that is returned by pcre_study(), together with + the appropriate flag bit. You should not set this yourself, but you may + add to the block by setting the other fields and their corresponding + flag bits. The match_limit field provides a means of preventing PCRE from using up a vast amount of resources when running patterns that are not going to match, but which have a very large number of possibilities in their search trees. The classic example is the use of nested unlimited - repeats. Internally, PCRE uses a function called match() which it calls - repeatedly (sometimes recursively). The limit is imposed on the number - of times this function is called during a match, which has the effect - of limiting the amount of recursion and backtracking that can take - place. For patterns that are not anchored, the count starts from zero - for each position in the subject string. + repeats. + + Internally, PCRE uses a function called match() which it calls repeat- + edly (sometimes recursively). The limit is imposed on the number of + times this function is called during a match, which has the effect of + limiting the amount of recursion and backtracking that can take place. + For patterns that are not anchored, the count starts from zero for each + position in the subject string. The default limit for the library can be set when PCRE is built; the default default is 10 million, which handles all but the most extreme @@ -1019,46 +1461,46 @@ MATCHING A PATTERN The pcre_callout field is used in conjunction with the "callout" fea- ture, which is described in the pcrecallout documentation. - The PCRE_ANCHORED option can be passed in the options argument, whose - unused bits must be zero. This limits pcre_exec() to matching at the - first matching position. However, if a pattern was compiled with - PCRE_ANCHORED, or turned out to be anchored by virtue of its contents, - it cannot be made unachored at matching time. - - When PCRE_UTF8 was set at compile time, the validity of the subject as - a UTF-8 string is automatically checked, and the value of startoffset - is also checked to ensure that it points to the start of a UTF-8 char- - acter. If an invalid UTF-8 sequence of bytes is found, pcre_exec() - returns the error PCRE_ERROR_BADUTF8. If startoffset contains an - invalid value, PCRE_ERROR_BADUTF8_OFFSET is returned. - - If you already know that your subject is valid, and you want to skip - these checks for performance reasons, you can set the - PCRE_NO_UTF8_CHECK option when calling pcre_exec(). You might want to - do this for the second and subsequent calls to pcre_exec() if you are - making repeated calls to find all the matches in a single subject - string. However, you should be sure that the value of startoffset - points to the start of a UTF-8 character. When PCRE_NO_UTF8_CHECK is - set, the effect of passing an invalid UTF-8 string as a subject, or a - value of startoffset that does not point to the start of a UTF-8 char- - acter, is undefined. Your program may crash. + The tables field is used to pass a character tables pointer to + pcre_exec(); this overrides the value that is stored with the compiled + pattern. A non-NULL value is stored with the compiled pattern only if + custom tables were supplied to pcre_compile() via its tableptr argu- + ment. If NULL is passed to pcre_exec() using this mechanism, it forces + PCRE's internal tables to be used. This facility is helpful when re- + using patterns that have been saved after compiling with an external + set of tables, because the external tables might be at a different + address when pcre_exec() is called. See the pcreprecompile documenta- + tion for a discussion of saving compiled patterns for later use. + + Option bits for pcre_exec() + + The unused bits of the options argument for pcre_exec() must be zero. + The only bits that may be set are PCRE_ANCHORED, PCRE_NOTBOL, + PCRE_NOTEOL, PCRE_NOTEMPTY, PCRE_NO_UTF8_CHECK and PCRE_PARTIAL. - There are also three further options that can be set only at matching - time: + PCRE_ANCHORED + + The PCRE_ANCHORED option limits pcre_exec() to matching at the first + matching position. If a pattern was compiled with PCRE_ANCHORED, or + turned out to be anchored by virtue of its contents, it cannot be made + unachored at matching time. PCRE_NOTBOL - The first character of the string is not the beginning of a line, so - the circumflex metacharacter should not match before it. Setting this - without PCRE_MULTILINE (at compile time) causes circumflex never to - match. + This option specifies that first character of the subject string is not + the beginning of a line, so the circumflex metacharacter should not + match before it. Setting this without PCRE_MULTILINE (at compile time) + causes circumflex never to match. This option affects only the behav- + iour of the circumflex metacharacter. It does not affect \A. PCRE_NOTEOL - The end of the string is not the end of a line, so the dollar metachar- - acter should not match it nor (except in multiline mode) a newline - immediately before it. Setting this without PCRE_MULTILINE (at compile - time) causes dollar never to match. + This option specifies that the end of the subject string is not the end + of a line, so the dollar metacharacter should not match it nor (except + in multiline mode) a newline immediately before it. Setting this with- + out PCRE_MULTILINE (at compile time) causes dollar never to match. This + option affects only the behaviour of the dollar metacharacter. It does + not affect \Z or \z. PCRE_NOTEMPTY @@ -1078,23 +1520,51 @@ MATCHING A PATTERN cial case of a pattern match of the empty string within its split() function, and when using the /g modifier. It is possible to emulate Perl's behaviour after matching a null string by first trying the match - again at the same offset with PCRE_NOTEMPTY set, and then if that fails - by advancing the starting offset (see below) and trying an ordinary - match again. - - The subject string is passed to pcre_exec() as a pointer in subject, a - length in length, and a starting byte offset in startoffset. Unlike the - pattern string, the subject may contain binary zero bytes. When the - starting offset is zero, the search for a match starts at the beginning - of the subject, and this is by far the most common case. - - If the pattern was compiled with the PCRE_UTF8 option, the subject must - be a sequence of bytes that is a valid UTF-8 string, and the starting - offset must point to the beginning of a UTF-8 character. If an invalid - UTF-8 string or offset is passed, an error (either PCRE_ERROR_BADUTF8 - or PCRE_ERROR_BADUTF8_OFFSET) is returned, unless the option - PCRE_NO_UTF8_CHECK is set, in which case PCRE's behaviour is not - defined. + again at the same offset with PCRE_NOTEMPTY and PCRE_ANCHORED, and then + if that fails by advancing the starting offset (see below) and trying + an ordinary match again. There is some code that demonstrates how to do + this in the pcredemo.c sample program. + + PCRE_NO_UTF8_CHECK + + When PCRE_UTF8 is set at compile time, the validity of the subject as a + UTF-8 string is automatically checked when pcre_exec() is subsequently + called. The value of startoffset is also checked to ensure that it + points to the start of a UTF-8 character. If an invalid UTF-8 sequence + of bytes is found, pcre_exec() returns the error PCRE_ERROR_BADUTF8. If + startoffset contains an invalid value, PCRE_ERROR_BADUTF8_OFFSET is + returned. + + If you already know that your subject is valid, and you want to skip + these checks for performance reasons, you can set the + PCRE_NO_UTF8_CHECK option when calling pcre_exec(). You might want to + do this for the second and subsequent calls to pcre_exec() if you are + making repeated calls to find all the matches in a single subject + string. However, you should be sure that the value of startoffset + points to the start of a UTF-8 character. When PCRE_NO_UTF8_CHECK is + set, the effect of passing an invalid UTF-8 string as a subject, or a + value of startoffset that does not point to the start of a UTF-8 char- + acter, is undefined. Your program may crash. + + PCRE_PARTIAL + + This option turns on the partial matching feature. If the subject + string fails to match the pattern, but at some point during the match- + ing process the end of the subject was reached (that is, the subject + partially matches the pattern and the failure to match occurred only + because there were not enough subject characters), pcre_exec() returns + PCRE_ERROR_PARTIAL instead of PCRE_ERROR_NOMATCH. When PCRE_PARTIAL is + used, there are restrictions on what may appear in the pattern. These + are discussed in the pcrepartial documentation. + + The string to be matched by pcre_exec() + + The subject string is passed to pcre_exec() as a pointer in subject, a + length in length, and a starting byte offset in startoffset. In UTF-8 + mode, the byte offset must point to the start of a UTF-8 character. + Unlike the pattern string, the subject may contain binary zero bytes. + When the starting offset is zero, the search for a match starts at the + beginning of the subject, and this is by far the most common case. A non-zero starting offset is useful when searching for another match in the same subject by calling pcre_exec() again after a previous suc- @@ -1111,14 +1581,16 @@ MATCHING A PATTERN the remainder of the subject, namely "issipi", it does not match, because \B is always false at the start of the subject, which is deemed to be a word boundary. However, if pcre_exec() is passed the entire - string again, but with startoffset set to 4, it finds the second - occurrence of "iss" because it is able to look behind the starting - point to discover that it is preceded by a letter. + string again, but with startoffset set to 4, it finds the second occur- + rence of "iss" because it is able to look behind the starting point to + discover that it is preceded by a letter. If a non-zero starting offset is passed when the pattern is anchored, - one attempt to match at the given offset is tried. This can only suc- - ceed if the pattern does not require the match to be at the start of - the subject. + one attempt to match at the given offset is made. This can only succeed + if the pattern does not require the match to be at the start of the + subject. + + How pcre_exec() returns captured substrings In general, a pattern matches a certain portion of the subject, and in addition, further substrings from the subject may be picked out by @@ -1130,54 +1602,59 @@ MATCHING A PATTERN Captured substrings are returned to the caller via a vector of integer offsets whose address is passed in ovector. The number of elements in - the vector is passed in ovecsize. The first two-thirds of the vector is - used to pass back captured substrings, each substring using a pair of - integers. The remaining third of the vector is used as workspace by - pcre_exec() while matching capturing subpatterns, and is not available - for passing back information. The length passed in ovecsize should - always be a multiple of three. If it is not, it is rounded down. - - When a match has been successful, information about captured substrings - is returned in pairs of integers, starting at the beginning of ovector, - and continuing up to two-thirds of its length at the most. The first + the vector is passed in ovecsize, which must be a non-negative number. + Note: this argument is NOT the size of ovector in bytes. + + The first two-thirds of the vector is used to pass back captured sub- + strings, each substring using a pair of integers. The remaining third + of the vector is used as workspace by pcre_exec() while matching cap- + turing subpatterns, and is not available for passing back information. + The length passed in ovecsize should always be a multiple of three. If + it is not, it is rounded down. + + When a match is successful, information about captured substrings is + returned in pairs of integers, starting at the beginning of ovector, + and continuing up to two-thirds of its length at the most. The first element of a pair is set to the offset of the first character in a sub- - string, and the second is set to the offset of the first character - after the end of a substring. The first pair, ovector[0] and ovec- - tor[1], identify the portion of the subject string matched by the - entire pattern. The next pair is used for the first capturing subpat- - tern, and so on. The value returned by pcre_exec() is the number of - pairs that have been set. If there are no capturing subpatterns, the - return value from a successful match is 1, indicating that just the + string, and the second is set to the offset of the first character + after the end of a substring. The first pair, ovector[0] and ovec- + tor[1], identify the portion of the subject string matched by the + entire pattern. The next pair is used for the first capturing subpat- + tern, and so on. The value returned by pcre_exec() is the number of + pairs that have been set. If there are no capturing subpatterns, the + return value from a successful match is 1, indicating that just the first pair of offsets has been set. - Some convenience functions are provided for extracting the captured - substrings as separate strings. These are described in the following + Some convenience functions are provided for extracting the captured + substrings as separate strings. These are described in the following section. - It is possible for an capturing subpattern number n+1 to match some - part of the subject when subpattern n has not been used at all. For + It is possible for an capturing subpattern number n+1 to match some + part of the subject when subpattern n has not been used at all. For example, if the string "abc" is matched against the pattern (a|(z))(bc) - subpatterns 1 and 3 are matched, but 2 is not. When this happens, both + subpatterns 1 and 3 are matched, but 2 is not. When this happens, both offset values corresponding to the unused subpattern are set to -1. If a capturing subpattern is matched repeatedly, it is the last portion - of the string that it matched that gets returned. - - If the vector is too small to hold all the captured substrings, it is - used as far as possible (up to two-thirds of its length), and the func- - tion returns a value of zero. In particular, if the substring offsets - are not of interest, pcre_exec() may be called with ovector passed as - NULL and ovecsize as zero. However, if the pattern contains back refer- - ences and the ovector isn't big enough to remember the related sub- - strings, PCRE has to get additional memory for use during matching. + of the string that it matched that is returned. + + If the vector is too small to hold all the captured substring offsets, + it is used as far as possible (up to two-thirds of its length), and the + function returns a value of zero. In particular, if the substring off- + sets are not of interest, pcre_exec() may be called with ovector passed + as NULL and ovecsize as zero. However, if the pattern contains back + references and the ovector is not big enough to remember the related + substrings, PCRE has to get additional memory for use during matching. Thus it is usually advisable to supply an ovector. - Note that pcre_info() can be used to find out how many capturing sub- + Note that pcre_info() can be used to find out how many capturing sub- patterns there are in a compiled pattern. The smallest size for ovector - that will allow for n captured substrings, in addition to the offsets + that will allow for n captured substrings, in addition to the offsets of the substring matched by the whole pattern, is (n+1)*3. - If pcre_exec() fails, it returns a negative number. The following are + Return values from pcre_exec() + + If pcre_exec() fails, it returns a negative number. The following are defined in the header file: PCRE_ERROR_NOMATCH (-1) @@ -1186,7 +1663,7 @@ MATCHING A PATTERN PCRE_ERROR_NULL (-2) - Either code or subject was passed as NULL, or ovector was NULL and + Either code or subject was passed as NULL, or ovector was NULL and ovecsize was not zero. PCRE_ERROR_BADOPTION (-3) @@ -1195,53 +1672,75 @@ MATCHING A PATTERN PCRE_ERROR_BADMAGIC (-4) - PCRE stores a 4-byte "magic number" at the start of the compiled code, - to catch the case when it is passed a junk pointer. This is the error - it gives when the magic number isn't present. + PCRE stores a 4-byte "magic number" at the start of the compiled code, + to catch the case when it is passed a junk pointer and to detect when a + pattern that was compiled in an environment of one endianness is run in + an environment with the other endianness. This is the error that PCRE + gives when the magic number is not present. PCRE_ERROR_UNKNOWN_NODE (-5) While running the pattern match, an unknown item was encountered in the - compiled pattern. This error could be caused by a bug in PCRE or by + compiled pattern. This error could be caused by a bug in PCRE or by overwriting of the compiled pattern. PCRE_ERROR_NOMEMORY (-6) - If a pattern contains back references, but the ovector that is passed + If a pattern contains back references, but the ovector that is passed to pcre_exec() is not big enough to remember the referenced substrings, - PCRE gets a block of memory at the start of matching to use for this - purpose. If the call via pcre_malloc() fails, this error is given. The - memory is freed at the end of matching. + PCRE gets a block of memory at the start of matching to use for this + purpose. If the call via pcre_malloc() fails, this error is given. The + memory is automatically freed at the end of matching. PCRE_ERROR_NOSUBSTRING (-7) - This error is used by the pcre_copy_substring(), pcre_get_substring(), + This error is used by the pcre_copy_substring(), pcre_get_substring(), and pcre_get_substring_list() functions (see below). It is never returned by pcre_exec(). PCRE_ERROR_MATCHLIMIT (-8) - The recursion and backtracking limit, as specified by the match_limit - field in a pcre_extra structure (or defaulted) was reached. See the + The recursion and backtracking limit, as specified by the match_limit + field in a pcre_extra structure (or defaulted) was reached. See the description above. PCRE_ERROR_CALLOUT (-9) This error is never generated by pcre_exec() itself. It is provided for - use by callout functions that want to yield a distinctive error code. + use by callout functions that want to yield a distinctive error code. See the pcrecallout documentation for details. PCRE_ERROR_BADUTF8 (-10) - A string that contains an invalid UTF-8 byte sequence was passed as a + A string that contains an invalid UTF-8 byte sequence was passed as a subject. PCRE_ERROR_BADUTF8_OFFSET (-11) The UTF-8 byte sequence that was passed as a subject was valid, but the - value of startoffset did not point to the beginning of a UTF-8 charac- + value of startoffset did not point to the beginning of a UTF-8 charac- ter. + PCRE_ERROR_PARTIAL (-12) + + The subject string did not match, but it did match partially. See the + pcrepartial documentation for details of partial matching. + + PCRE_ERROR_BADPARTIAL (-13) + + The PCRE_PARTIAL option was used with a compiled pattern containing + items that are not supported for partial matching. See the pcrepartial + documentation for details of partial matching. + + PCRE_ERROR_INTERNAL (-14) + + An unexpected internal error has occurred. This error could be caused + by a bug in PCRE or by overwriting of the compiled pattern. + + PCRE_ERROR_BADCOUNT (-15) + + This error is given if the value of the ovecsize argument is negative. + EXTRACTING CAPTURED SUBSTRINGS BY NUMBER @@ -1267,18 +1766,18 @@ EXTRACTING CAPTURED SUBSTRINGS BY NUMBER not, of course, a C string. The first three arguments are the same for all three of these func- - tions: subject is the subject string which has just been successfully + tions: subject is the subject string that has just been successfully matched, ovector is a pointer to the vector of integer offsets that was passed to pcre_exec(), and stringcount is the number of substrings that were captured by the match, including the substring that matched the - entire regular expression. This is the value returned by pcre_exec if + entire regular expression. This is the value returned by pcre_exec() if it is greater than zero. If pcre_exec() returned zero, indicating that it ran out of space in ovector, the value passed as stringcount should - be the size of the vector divided by three. + be the number of elements in the vector divided by three. The functions pcre_copy_substring() and pcre_get_substring() extract a single substring, whose number is given as stringnumber. A value of - zero extracts the substring that matched the entire pattern, while + zero extracts the substring that matched the entire pattern, whereas higher values extract the captured substrings. For pcre_copy_sub- string(), the string is placed in buffer, whose length is given by buffersize, while for pcre_get_substring() a new block of memory is @@ -1297,8 +1796,8 @@ EXTRACTING CAPTURED SUBSTRINGS BY NUMBER The pcre_get_substring_list() function extracts all available sub- strings and builds a list of pointers to them. All this is done in a - single block of memory which is obtained via pcre_malloc. The address - of the memory block is returned via listptr, which is also the start of + single block of memory that is obtained via pcre_malloc. The address of + the memory block is returned via listptr, which is also the start of the list of string pointers. The end of the list is marked by a NULL pointer. The yield of the function is zero if all went well, or @@ -1313,10 +1812,10 @@ EXTRACTING CAPTURED SUBSTRINGS BY NUMBER string by inspecting the appropriate offset in ovector, which is nega- tive for unset substrings. - The two convenience functions pcre_free_substring() and - pcre_free_substring_list() can be used to free the memory returned by a - previous call of pcre_get_substring() or pcre_get_substring_list(), - respectively. They do nothing more than call the function pointed to by + The two convenience functions pcre_free_substring() and pcre_free_sub- + string_list() can be used to free the memory returned by a previous + call of pcre_get_substring() or pcre_get_substring_list(), respec- + tively. They do nothing more than call the function pointed to by pcre_free, which of course could be called directly from a C program. However, PCRE is used in some situations where it is linked via a spe- cial interface to another programming language which cannot use @@ -1326,35 +1825,39 @@ EXTRACTING CAPTURED SUBSTRINGS BY NUMBER EXTRACTING CAPTURED SUBSTRINGS BY NAME + int pcre_get_stringnumber(const pcre *code, + const char *name); + int pcre_copy_named_substring(const pcre *code, const char *subject, int *ovector, int stringcount, const char *stringname, char *buffer, int buffersize); - int pcre_get_stringnumber(const pcre *code, - const char *name); - int pcre_get_named_substring(const pcre *code, const char *subject, int *ovector, int stringcount, const char *stringname, const char **stringptr); To extract a substring by name, you first have to find associated num- - ber. This can be done by calling pcre_get_stringnumber(). The first - argument is the compiled pattern, and the second is the name. For exam- - ple, for this pattern + ber. For example, for this pattern - ab(?\d+)... + (a+)b(?P\d+)... - the number of the subpattern called "xxx" is 1. Given the number, you - can then extract the substring directly, or use one of the functions - described in the previous section. For convenience, there are also two - functions that do the whole job. + the number of the subpattern called "xxx" is 2. You can find the number + from the name by calling pcre_get_stringnumber(). The first argument is + the compiled pattern, and the second is the name. The yield of the + function is the subpattern number, or PCRE_ERROR_NOSUBSTRING (-7) if + there is no subpattern of that name. - Most of the arguments of pcre_copy_named_substring() and - pcre_get_named_substring() are the same as those for the functions that - extract by number, and so are not re-described here. There are just two - differences. + Given the number, you can extract the substring directly, or use one of + the functions described in the previous section. For convenience, there + are also two functions that do the whole job. + + Most of the arguments of pcre_copy_named_substring() and + pcre_get_named_substring() are the same as those for the similarly + named functions that extract by number. As these are described in the + previous section, they are not re-described here. There are just two + differences: First, instead of a substring number, a substring name is given. Sec- ond, there is an extra argument, given at the start, which is a pointer @@ -1365,17 +1868,189 @@ EXTRACTING CAPTURED SUBSTRINGS BY NAME then call pcre_copy_substring() or pcre_get_substring(), as appropri- ate. -Last updated: 09 December 2003 -Copyright (c) 1997-2003 University of Cambridge. ------------------------------------------------------------------------------ -PCRE(3) PCRE(3) +FINDING ALL POSSIBLE MATCHES + + The traditional matching function uses a similar algorithm to Perl, + which stops when it finds the first match, starting at a given point in + the subject. If you want to find all possible matches, or the longest + possible match, consider using the alternative matching function (see + below) instead. If you cannot use the alternative function, but still + need to find all possible matches, you can kludge it up by making use + of the callout facility, which is described in the pcrecallout documen- + tation. + + What you have to do is to insert a callout right at the end of the pat- + tern. When your callout function is called, extract and save the cur- + rent matched substring. Then return 1, which forces pcre_exec() to + backtrack and try other alternatives. Ultimately, when it runs out of + matches, pcre_exec() will yield PCRE_ERROR_NOMATCH. + + +MATCHING A PATTERN: THE ALTERNATIVE FUNCTION + + int pcre_dfa_exec(const pcre *code, const pcre_extra *extra, + const char *subject, int length, int startoffset, + int options, int *ovector, int ovecsize, + int *workspace, int wscount); + + The function pcre_dfa_exec() is called to match a subject string + against a compiled pattern, using a "DFA" matching algorithm. This has + different characteristics to the normal algorithm, and is not compati- + ble with Perl. Some of the features of PCRE patterns are not supported. + Nevertheless, there are times when this kind of matching can be useful. + For a discussion of the two matching algorithms, see the pcrematching + documentation. + + The arguments for the pcre_dfa_exec() function are the same as for + pcre_exec(), plus two extras. The ovector argument is used in a differ- + ent way, and this is described below. The other common arguments are + used in the same way as for pcre_exec(), so their description is not + repeated here. + + The two additional arguments provide workspace for the function. The + workspace vector should contain at least 20 elements. It is used for + keeping track of multiple paths through the pattern tree. More + workspace will be needed for patterns and subjects where there are a + lot of possible matches. + + Here is an example of a simple call to pcre_exec(): + + int rc; + int ovector[10]; + int wspace[20]; + rc = pcre_exec( + re, /* result of pcre_compile() */ + NULL, /* we didn't study the pattern */ + "some string", /* the subject string */ + 11, /* the length of the subject string */ + 0, /* start at offset 0 in the subject */ + 0, /* default options */ + ovector, /* vector of integers for substring information */ + 10, /* number of elements (NOT size in bytes) */ + wspace, /* working space vector */ + 20); /* number of elements (NOT size in bytes) */ + + Option bits for pcre_dfa_exec() + + The unused bits of the options argument for pcre_dfa_exec() must be + zero. The only bits that may be set are PCRE_ANCHORED, PCRE_NOTBOL, + PCRE_NOTEOL, PCRE_NOTEMPTY, PCRE_NO_UTF8_CHECK, PCRE_PARTIAL, + PCRE_DFA_SHORTEST, and PCRE_DFA_RESTART. All but the last three of + these are the same as for pcre_exec(), so their description is not + repeated here. + + PCRE_PARTIAL + + This has the same general effect as it does for pcre_exec(), but the + details are slightly different. When PCRE_PARTIAL is set for + pcre_dfa_exec(), the return code PCRE_ERROR_NOMATCH is converted into + PCRE_ERROR_PARTIAL if the end of the subject is reached, there have + been no complete matches, but there is still at least one matching pos- + sibility. The portion of the string that provided the partial match is + set as the first matching string. + + PCRE_DFA_SHORTEST + + Setting the PCRE_DFA_SHORTEST option causes the matching algorithm to + stop as soon as it has found one match. Because of the way the DFA + algorithm works, this is necessarily the shortest possible match at the + first possible matching point in the subject string. + + PCRE_DFA_RESTART + + When pcre_dfa_exec() is called with the PCRE_PARTIAL option, and + returns a partial match, it is possible to call it again, with addi- + tional subject characters, and have it continue with the same match. + The PCRE_DFA_RESTART option requests this action; when it is set, the + workspace and wscount options must reference the same vector as before + because data about the match so far is left in them after a partial + match. There is more discussion of this facility in the pcrepartial + documentation. + + Successful returns from pcre_dfa_exec() + + When pcre_dfa_exec() succeeds, it may have matched more than one sub- + string in the subject. Note, however, that all the matches from one run + of the function start at the same point in the subject. The shorter + matches are all initial substrings of the longer matches. For example, + if the pattern + + <.*> + + is matched against the string + + This is no more + + the three matched strings are + + + + + + On success, the yield of the function is a number greater than zero, + which is the number of matched substrings. The substrings themselves + are returned in ovector. Each string uses two elements; the first is + the offset to the start, and the second is the offset to the end. All + the strings have the same start offset. (Space could have been saved by + giving this only once, but it was decided to retain some compatibility + with the way pcre_exec() returns data, even though the meaning of the + strings is different.) + + The strings are returned in reverse order of length; that is, the long- + est matching string is given first. If there were too many matches to + fit into ovector, the yield of the function is zero, and the vector is + filled with the longest matches. + + Error returns from pcre_dfa_exec() + + The pcre_dfa_exec() function returns a negative number when it fails. + Many of the errors are the same as for pcre_exec(), and these are + described above. There are in addition the following errors that are + specific to pcre_dfa_exec(): + + PCRE_ERROR_DFA_UITEM (-16) + + This return is given if pcre_dfa_exec() encounters an item in the pat- + tern that it does not support, for instance, the use of \C or a back + reference. + + PCRE_ERROR_DFA_UCOND (-17) + + This return is given if pcre_dfa_exec() encounters a condition item in + a pattern that uses a back reference for the condition. This is not + supported. + + PCRE_ERROR_DFA_UMLIMIT (-18) + + This return is given if pcre_dfa_exec() is called with an extra block + that contains a setting of the match_limit field. This is not supported + (it is meaningless). + + PCRE_ERROR_DFA_WSSIZE (-19) + + This return is given if pcre_dfa_exec() runs out of space in the + workspace vector. + + PCRE_ERROR_DFA_RECURSE (-20) + + When a recursive subpattern is processed, the matching function calls + itself recursively, using private vectors for ovector and workspace. + This error is given if the output vector is not large enough. This + should be extremely rare, as a vector of size 1000 is used. + +Last updated: 16 May 2005 +Copyright (c) 1997-2005 University of Cambridge. +------------------------------------------------------------------------------ + +PCRECALLOUT(3) PCRECALLOUT(3) NAME PCRE - Perl-compatible regular expressions + PCRE CALLOUTS int (*pcre_callout)(pcre_callout_block *); @@ -1392,11 +2067,48 @@ PCRE CALLOUTS default value is zero. For example, this pattern has two callout points: - (?C1)abc(?C2)def + (?C1)eabc(?C2)def + + If the PCRE_AUTO_CALLOUT option bit is set when pcre_compile() is + called, PCRE automatically inserts callouts, all with number 255, + before each item in the pattern. For example, if PCRE_AUTO_CALLOUT is + used with the pattern + + A(\d{2}|--) + + it is processed as if it were + + (?C255)A(?C255)((?C255)\d{2}(?C255)|(?C255)-(?C255)-(?C255))(?C255) + + Notice that there is a callout before and after each parenthesis and + alternation bar. Automatic callouts can be used for tracking the + progress of pattern matching. The pcretest command has an option that + sets automatic callouts; when it is used, the output indicates how the + pattern is matched. This is useful information when you are trying to + optimize the performance of a particular pattern. + + +MISSING CALLOUTS + + You should be aware that, because of optimizations in the way PCRE + matches patterns, callouts sometimes do not happen. For example, if the + pattern is + + ab(?C4)cd + + PCRE knows that any matching string must contain the letter "d". If the + subject string is "abyz", the lack of "d" means that matching doesn't + ever start, and the callout is never reached. However, with "abyd", + though the result is still no match, the callout is obeyed. - During matching, when PCRE reaches a callout point (and pcre_callout is - set), the external function is called. Its only argument is a pointer - to a pcre_callout block. This contains the following variables: + +THE CALLOUT INTERFACE + + During matching, when PCRE reaches a callout point, the external func- + tion defined by pcre_callout is called (if it is set). This applies to + both the pcre_exec() and the pcre_dfa_exec() matching functions. The + only argument to the callout function is a pointer to a pcre_callout + block. This structure contains the following fields: int version; int callout_number; @@ -1408,74 +2120,97 @@ PCRE CALLOUTS int capture_top; int capture_last; void *callout_data; + int pattern_position; + int next_item_length; - The version field is an integer containing the version number of the - block format. The current version is zero. The version number may - change in future if additional fields are added, but the intention is - never to remove any of the existing fields. + The version field is an integer containing the version number of the + block format. The initial version was 0; the current version is 1. The + version number will change again in future if additional fields are + added, but the intention is never to remove any of the existing fields. The callout_number field contains the number of the callout, as com- - piled into the pattern (that is, the number after ?C). + piled into the pattern (that is, the number after ?C for manual call- + outs, and 255 for automatically generated callouts). - The offset_vector field is a pointer to the vector of offsets that was - passed by the caller to pcre_exec(). The contents can be inspected in - order to extract substrings that have been matched so far, in the same - way as for extracting substrings after a match has completed. + The offset_vector field is a pointer to the vector of offsets that was + passed by the caller to pcre_exec() or pcre_dfa_exec(). When + pcre_exec() is used, the contents can be inspected in order to extract + substrings that have been matched so far, in the same way as for + extracting substrings after a match has completed. For pcre_dfa_exec() + this field is not useful. - The subject and subject_length fields contain copies the values that + The subject and subject_length fields contain copies of the values that were passed to pcre_exec(). - The start_match field contains the offset within the subject at which - the current match attempt started. If the pattern is not anchored, the - callout function may be called several times for different starting - points. + The start_match field contains the offset within the subject at which + the current match attempt started. If the pattern is not anchored, the + callout function may be called several times from the same point in the + pattern for different starting points in the subject. - The current_position field contains the offset within the subject of + The current_position field contains the offset within the subject of the current match pointer. - The capture_top field contains one more than the number of the highest - numbered captured substring so far. If no substrings have been - captured, the value of capture_top is one. + When the pcre_exec() function is used, the capture_top field contains + one more than the number of the highest numbered captured substring so + far. If no substrings have been captured, the value of capture_top is + one. This is always the case when pcre_dfa_exec() is used, because it + does not support captured substrings. - The capture_last field contains the number of the most recently cap- - tured substring. + The capture_last field contains the number of the most recently cap- + tured substring. If no substrings have been captured, its value is -1. + This is always the case when pcre_dfa_exec() is used. The callout_data field contains a value that is passed to pcre_exec() - by the caller specifically so that it can be passed back in callouts. - It is passed in the pcre_callout field of the pcre_extra data struc- - ture. If no such data was passed, the value of callout_data in a + or pcre_dfa_exec() specifically so that it can be passed back in call- + outs. It is passed in the pcre_callout field of the pcre_extra data + structure. If no such data was passed, the value of callout_data in a pcre_callout block is NULL. There is a description of the pcre_extra structure in the pcreapi documentation. + The pattern_position field is present from version 1 of the pcre_call- + out structure. It contains the offset to the next item to be matched in + the pattern string. + + The next_item_length field is present from version 1 of the pcre_call- + out structure. It contains the length of the next item to be matched in + the pattern string. When the callout immediately precedes an alterna- + tion bar, a closing parenthesis, or the end of the pattern, the length + is zero. When the callout precedes an opening parenthesis, the length + is that of the entire subpattern. + + The pattern_position and next_item_length fields are intended to help + in distinguishing between different automatic callouts, which all have + the same callout number. However, they are set for all callouts. RETURN VALUES - The callout function returns an integer. If the value is zero, matching - proceeds as normal. If the value is greater than zero, matching fails - at the current point, but backtracking to test other possibilities goes - ahead, just as if a lookahead assertion had failed. If the value is - less than zero, the match is abandoned, and pcre_exec() returns the - value. + The external callout function returns an integer to PCRE. If the value + is zero, matching proceeds as normal. If the value is greater than + zero, matching fails at the current point, but the testing of other + matching possibilities goes ahead, just as if a lookahead assertion had + failed. If the value is less than zero, the match is abandoned, and + pcre_exec() (or pcre_dfa_exec()) returns the negative value. - Negative values should normally be chosen from the set of + Negative values should normally be chosen from the set of PCRE_ERROR_xxx values. In particular, PCRE_ERROR_NOMATCH forces a stan- - dard "no match" failure. The error number PCRE_ERROR_CALLOUT is - reserved for use by callout functions; it will never be used by PCRE + dard "no match" failure. The error number PCRE_ERROR_CALLOUT is + reserved for use by callout functions; it will never be used by PCRE itself. -Last updated: 21 January 2003 -Copyright (c) 1997-2003 University of Cambridge. ------------------------------------------------------------------------------ +Last updated: 28 February 2005 +Copyright (c) 1997-2005 University of Cambridge. +------------------------------------------------------------------------------ -PCRE(3) PCRE(3) +PCRECOMPAT(3) PCRECOMPAT(3) NAME PCRE - Perl-compatible regular expressions -DIFFERENCES FROM PERL + +DIFFERENCES BETWEEN PCRE AND PERL This document describes the differences in the ways that PCRE and Perl handle regular expressions. The differences described here are with @@ -1498,18 +2233,23 @@ DIFFERENCES FROM PERL 4. Though binary zero characters are supported in the subject string, they are not allowed in a pattern string because it is passed as a nor- - mal C string, terminated by zero. The escape sequence "\0" can be used - in the pattern to represent a binary zero. + mal C string, terminated by zero. The escape sequence \0 can be used in + the pattern to represent a binary zero. 5. The following Perl escape sequences are not supported: \l, \u, \L, - \U, \P, \p, \N, and \X. In fact these are implemented by Perl's general - string-handling and are not part of its pattern matching engine. If any - of these are encountered by PCRE, an error is generated. - - 6. PCRE does support the \Q...\E escape for quoting substrings. Charac- - ters in between are treated as literals. This is slightly different - from Perl in that $ and @ are also handled as literals inside the - quotes. In Perl, they cause variable interpolation (but of course PCRE + \U, and \N. In fact these are implemented by Perl's general string-han- + dling and are not part of its pattern matching engine. If any of these + are encountered by PCRE, an error is generated. + + 6. The Perl escape sequences \p, \P, and \X are supported only if PCRE + is built with Unicode character property support. The properties that + can be tested with \p and \P are limited to the general category prop- + erties such as Lu and Nd. + + 7. PCRE does support the \Q...\E escape for quoting substrings. Charac- + ters in between are treated as literals. This is slightly different + from Perl in that $ and @ are also handled as literals inside the + quotes. In Perl, they cause variable interpolation (but of course PCRE does not have variables). Note the following examples: Pattern PCRE matches Perl matches @@ -1519,100 +2259,127 @@ DIFFERENCES FROM PERL \Qabc\$xyz\E abc\$xyz abc\$xyz \Qabc\E\$\Qxyz\E abc$xyz abc$xyz - The \Q...\E sequence is recognized both inside and outside character + The \Q...\E sequence is recognized both inside and outside character classes. - 7. Fairly obviously, PCRE does not support the (?{code}) and (?p{code}) - constructions. However, there is some experimental support for recur- - sive patterns using the non-Perl items (?R), (?number) and (?P>name). - Also, the PCRE "callout" feature allows an external function to be - called during pattern matching. + 8. Fairly obviously, PCRE does not support the (?{code}) and (?p{code}) + constructions. However, there is support for recursive patterns using + the non-Perl items (?R), (?number), and (?P>name). Also, the PCRE + "callout" feature allows an external function to be called during pat- + tern matching. See the pcrecallout documentation for details. - 8. There are some differences that are concerned with the settings of - captured strings when part of a pattern is repeated. For example, - matching "aba" against the pattern /^(a(b)?)+$/ in Perl leaves $2 + 9. There are some differences that are concerned with the settings of + captured strings when part of a pattern is repeated. For example, + matching "aba" against the pattern /^(a(b)?)+$/ in Perl leaves $2 unset, but in PCRE it is set to "b". - 9. PCRE provides some extensions to the Perl regular expression - facilities: + 10. PCRE provides some extensions to the Perl regular expression facil- + ities: - (a) Although lookbehind assertions must match fixed length strings, + (a) Although lookbehind assertions must match fixed length strings, each alternative branch of a lookbehind assertion can match a different length of string. Perl requires them all to have the same length. - (b) If PCRE_DOLLAR_ENDONLY is set and PCRE_MULTILINE is not set, the $ + (b) If PCRE_DOLLAR_ENDONLY is set and PCRE_MULTILINE is not set, the $ meta-character matches only at the very end of the string. (c) If PCRE_EXTRA is set, a backslash followed by a letter with no spe- cial meaning is faulted. - (d) If PCRE_UNGREEDY is set, the greediness of the repetition quanti- + (d) If PCRE_UNGREEDY is set, the greediness of the repetition quanti- fiers is inverted, that is, by default they are not greedy, but if fol- lowed by a question mark they are. - (e) PCRE_ANCHORED can be used to force a pattern to be tried only at - the first matching position in the subject string. + (e) PCRE_ANCHORED can be used at matching time to force a pattern to be + tried only at the first matching position in the subject string. - (f) The PCRE_NOTBOL, PCRE_NOTEOL, PCRE_NOTEMPTY, and PCRE_NO_AUTO_CAP- + (f) The PCRE_NOTBOL, PCRE_NOTEOL, PCRE_NOTEMPTY, and PCRE_NO_AUTO_CAP- TURE options for pcre_exec() have no Perl equivalents. - (g) The (?R), (?number), and (?P>name) constructs allows for recursive - pattern matching (Perl can do this using the (?p{code}) construct, + (g) The (?R), (?number), and (?P>name) constructs allows for recursive + pattern matching (Perl can do this using the (?p{code}) construct, which PCRE cannot support.) - (h) PCRE supports named capturing substrings, using the Python syntax. + (h) PCRE supports named capturing substrings, using the Python syntax. - (i) PCRE supports the possessive quantifier "++" syntax, taken from + (i) PCRE supports the possessive quantifier "++" syntax, taken from Sun's Java package. (j) The (R) condition, for testing recursion, is a PCRE extension. (k) The callout facility is PCRE-specific. -Last updated: 09 December 2003 -Copyright (c) 1997-2003 University of Cambridge. ------------------------------------------------------------------------------ + (l) The partial matching facility is PCRE-specific. -PCRE(3) PCRE(3) + (m) Patterns compiled by PCRE can be saved and re-used at a later time, + even on different hosts that have the other endianness. + + (n) The alternative matching function (pcre_dfa_exec()) matches in a + different way and is not Perl-compatible. + +Last updated: 28 February 2005 +Copyright (c) 1997-2005 University of Cambridge. +------------------------------------------------------------------------------ +PCREPATTERN(3) PCREPATTERN(3) + NAME PCRE - Perl-compatible regular expressions + PCRE REGULAR EXPRESSION DETAILS The syntax and semantics of the regular expressions supported by PCRE are described below. Regular expressions are also described in the Perl - documentation and in a number of other books, some of which have copi- - ous examples. Jeffrey Friedl's "Mastering Regular Expressions", pub- - lished by O'Reilly, covers them in great detail. The description here - is intended as reference documentation. - - The basic operation of PCRE is on strings of bytes. However, there is - also support for UTF-8 character strings. To use this support you must - build PCRE to include UTF-8 support, and then call pcre_compile() with - the PCRE_UTF8 option. How this affects the pattern matching is men- - tioned in several places below. There is also a summary of UTF-8 fea- - tures in the section on UTF-8 support in the main pcre page. - - A regular expression is a pattern that is matched against a subject - string from left to right. Most characters stand for themselves in a - pattern, and match the corresponding characters in the subject. As a + documentation and in a number of books, some of which have copious + examples. Jeffrey Friedl's "Mastering Regular Expressions", published + by O'Reilly, covers regular expressions in great detail. This descrip- + tion of PCRE's regular expressions is intended as reference material. + + The original operation of PCRE was on strings of one-byte characters. + However, there is now also support for UTF-8 character strings. To use + this, you must build PCRE to include UTF-8 support, and then call + pcre_compile() with the PCRE_UTF8 option. How this affects pattern + matching is mentioned in several places below. There is also a summary + of UTF-8 features in the section on UTF-8 support in the main pcre + page. + + The remainder of this document discusses the patterns that are sup- + ported by PCRE when its main matching function, pcre_exec(), is used. + From release 6.0, PCRE offers a second matching function, + pcre_dfa_exec(), which matches using a different algorithm that is not + Perl-compatible. The advantages and disadvantages of the alternative + function, and how it differs from the normal function, are discussed in + the pcrematching page. + + A regular expression is a pattern that is matched against a subject + string from left to right. Most characters stand for themselves in a + pattern, and match the corresponding characters in the subject. As a trivial example, the pattern The quick brown fox - matches a portion of a subject string that is identical to itself. The - power of regular expressions comes from the ability to include alterna- - tives and repetitions in the pattern. These are encoded in the pattern - by the use of meta-characters, which do not stand for themselves but - instead are interpreted in some special way. - - There are two different sets of meta-characters: those that are recog- + matches a portion of a subject string that is identical to itself. When + caseless matching is specified (the PCRE_CASELESS option), letters are + matched independently of case. In UTF-8 mode, PCRE always understands + the concept of case for characters whose values are less than 128, so + caseless matching is always possible. For characters with higher val- + ues, the concept of case is supported if PCRE is compiled with Unicode + property support, but not otherwise. If you want to use caseless + matching for characters 128 and above, you must ensure that PCRE is + compiled with Unicode property support as well as with UTF-8 support. + + The power of regular expressions comes from the ability to include + alternatives and repetitions in the pattern. These are encoded in the + pattern by the use of metacharacters, which do not stand for themselves + but instead are interpreted in some special way. + + There are two different sets of metacharacters: those that are recog- nized anywhere in the pattern except within square brackets, and those that are recognized in square brackets. Outside square brackets, the - meta-characters are as follows: + metacharacters are as follows: \ general escape character with several uses ^ assert start of string (or line, in multiline mode) @@ -1631,7 +2398,7 @@ PCRE REGULAR EXPRESSION DETAILS { start min/max quantifier Part of a pattern that is in square brackets is called a "character - class". In a character class the only meta-characters are: + class". In a character class the only metacharacters are: \ general escape character ^ negate the class, but only if the first character @@ -1640,22 +2407,22 @@ PCRE REGULAR EXPRESSION DETAILS syntax) ] terminates the character class - The following sections describe the use of each of the meta-characters. + The following sections describe the use of each of the metacharacters. BACKSLASH The backslash character has several uses. Firstly, if it is followed by - a non-alphameric character, it takes away any special meaning that + a non-alphanumeric character, it takes away any special meaning that character may have. This use of backslash as an escape character applies both inside and outside character classes. For example, if you want to match a * character, you write \* in the pattern. This escaping action applies whether or not the following - character would otherwise be interpreted as a meta-character, so it is - always safe to precede a non-alphameric with backslash to specify that - it stands for itself. In particular, if you want to match a backslash, - you write \\. + character would otherwise be interpreted as a metacharacter, so it is + always safe to precede a non-alphanumeric with backslash to specify + that it stands for itself. In particular, if you want to match a back- + slash, you write \\. If a pattern is compiled with the PCRE_EXTENDED option, whitespace in the pattern (other than in a character class) and characters between a @@ -1679,6 +2446,8 @@ BACKSLASH The \Q...\E sequence is recognized both inside and outside character classes. + Non-printing characters + A second use of backslash provides a way of encoding non-printing char- acters in patterns in a visible manner. There is no restriction on the appearance of non-printing characters, apart from the binary zero that @@ -1708,9 +2477,9 @@ BACKSLASH must be less than 2**31 (that is, the maximum hexadecimal value is 7FFFFFFF). If characters other than hexadecimal digits appear between \x{ and }, or if there is no terminating }, this form of escape is not - recognized. Instead, the initial \x will be interpreted as a basic hex- - adecimal escape, with no following digits, giving a byte whose value is - zero. + recognized. Instead, the initial \x will be interpreted as a basic + hexadecimal escape, with no following digits, giving a character whose + value is zero. Characters whose value is less than 256 can be defined by either of the two syntaxes for \x when PCRE is in UTF-8 mode. There is no difference @@ -1721,19 +2490,20 @@ BACKSLASH there are fewer than two digits, just those that are present are used. Thus the sequence \0\x\07 specifies two binary zeros followed by a BEL character (code value 7). Make sure you supply two digits after the - initial zero if the character that follows is itself an octal digit. + initial zero if the pattern character that follows is itself an octal + digit. The handling of a backslash followed by a digit other than 0 is compli- cated. Outside a character class, PCRE reads it and any following dig- - its as a decimal number. If the number is less than 10, or if there + its as a decimal number. If the number is less than 10, or if there have been at least that many previous capturing left parentheses in the - expression, the entire sequence is taken as a back reference. A - description of how this works is given later, following the discussion + expression, the entire sequence is taken as a back reference. A + description of how this works is given later, following the discussion of parenthesized subpatterns. - Inside a character class, or if the decimal number is greater than 9 - and there have not been that many capturing subpatterns, PCRE re-reads - up to three octal digits following the backslash, and generates a sin- + Inside a character class, or if the decimal number is greater than 9 + and there have not been that many capturing subpatterns, PCRE re-reads + up to three octal digits following the backslash, and generates a sin- gle byte from the least significant 8 bits of the value. Any subsequent digits stand for themselves. For example: @@ -1752,16 +2522,20 @@ BACKSLASH \81 is either a back reference, or a binary zero followed by the two characters "8" and "1" - Note that octal values of 100 or greater must not be introduced by a + Note that octal values of 100 or greater must not be introduced by a leading zero, because no more than three octal digits are ever read. - All the sequences that define a single byte value or a single UTF-8 + All the sequences that define a single byte value or a single UTF-8 character (in UTF-8 mode) can be used both inside and outside character - classes. In addition, inside a character class, the sequence \b is - interpreted as the backspace character (hex 08). Outside a character - class it has a different meaning (see below). + classes. In addition, inside a character class, the sequence \b is + interpreted as the backspace character (hex 08), and the sequence \X is + interpreted as the character "X". Outside a character class, these + sequences have different meanings (see below). - The third use of backslash is for specifying generic character types: + Generic character types + + The third use of backslash is for specifying generic character types. + The following are always recognized: \d any decimal digit \D any character that is not a decimal digit @@ -1771,34 +2545,129 @@ BACKSLASH \W any "non-word" character Each pair of escape sequences partitions the complete set of characters - into two disjoint sets. Any given character matches one, and only one, + into two disjoint sets. Any given character matches one, and only one, of each pair. - In UTF-8 mode, characters with values greater than 255 never match \d, - \s, or \w, and always match \D, \S, and \W. - - For compatibility with Perl, \s does not match the VT character (code - 11). This makes it different from the the POSIX "space" class. The \s - characters are HT (9), LF (10), FF (12), CR (13), and space (32). - - A "word" character is any letter or digit or the underscore character, - that is, any character which can be part of a Perl "word". The defini- - tion of letters and digits is controlled by PCRE's character tables, - and may vary if locale- specific matching is taking place (see "Locale - support" in the pcreapi page). For example, in the "fr" (French) - locale, some character codes greater than 128 are used for accented - letters, and these are matched by \w. - These character type sequences can appear both inside and outside char- acter classes. They each match one character of the appropriate type. If the current matching point is at the end of the subject string, all of them fail, since there is no character to match. + For compatibility with Perl, \s does not match the VT character (code + 11). This makes it different from the the POSIX "space" class. The \s + characters are HT (9), LF (10), FF (12), CR (13), and space (32). + + A "word" character is an underscore or any character less than 256 that + is a letter or digit. The definition of letters and digits is con- + trolled by PCRE's low-valued character tables, and may vary if locale- + specific matching is taking place (see "Locale support" in the pcreapi + page). For example, in the "fr_FR" (French) locale, some character + codes greater than 128 are used for accented letters, and these are + matched by \w. + + In UTF-8 mode, characters with values greater than 128 never match \d, + \s, or \w, and always match \D, \S, and \W. This is true even when Uni- + code character property support is available. + + Unicode character properties + + When PCRE is built with Unicode character property support, three addi- + tional escape sequences to match generic character types are available + when UTF-8 mode is selected. They are: + + \p{xx} a character with the xx property + \P{xx} a character without the xx property + \X an extended Unicode sequence + + The property names represented by xx above are limited to the Unicode + general category properties. Each character has exactly one such prop- + erty, specified by a two-letter abbreviation. For compatibility with + Perl, negation can be specified by including a circumflex between the + opening brace and the property name. For example, \p{^Lu} is the same + as \P{Lu}. + + If only one letter is specified with \p or \P, it includes all the + properties that start with that letter. In this case, in the absence of + negation, the curly brackets in the escape sequence are optional; these + two examples have the same effect: + + \p{L} + \pL + + The following property codes are supported: + + C Other + Cc Control + Cf Format + Cn Unassigned + Co Private use + Cs Surrogate + + L Letter + Ll Lower case letter + Lm Modifier letter + Lo Other letter + Lt Title case letter + Lu Upper case letter + + M Mark + Mc Spacing mark + Me Enclosing mark + Mn Non-spacing mark + + N Number + Nd Decimal number + Nl Letter number + No Other number + + P Punctuation + Pc Connector punctuation + Pd Dash punctuation + Pe Close punctuation + Pf Final punctuation + Pi Initial punctuation + Po Other punctuation + Ps Open punctuation + + S Symbol + Sc Currency symbol + Sk Modifier symbol + Sm Mathematical symbol + So Other symbol + + Z Separator + Zl Line separator + Zp Paragraph separator + Zs Space separator + + Extended properties such as "Greek" or "InMusicalSymbols" are not sup- + ported by PCRE. + + Specifying caseless matching does not affect these escape sequences. + For example, \p{Lu} always matches only upper case letters. + + The \X escape matches any number of Unicode characters that form an + extended Unicode sequence. \X is equivalent to + + (?>\PM\pM*) + + That is, it matches a character without the "mark" property, followed + by zero or more characters with the "mark" property, and treats the + sequence as an atomic group (see below). Characters with the "mark" + property are typically accents that affect the preceding character. + + Matching characters by Unicode property is not fast, because PCRE has + to search a structure that contains data for over fifteen thousand + characters. That is why the traditional escape sequences such as \d and + \w do not use Unicode properties in PCRE. + + Simple assertions + The fourth use of backslash is for certain simple assertions. An asser- - tion specifies a condition that has to be met at a particular point in - a match, without consuming any characters from the subject string. The - use of subpatterns for more complicated assertions is described below. - The backslashed assertions are + tion specifies a condition that has to be met at a particular point in + a match, without consuming any characters from the subject string. The + use of subpatterns for more complicated assertions is described below. + The backslashed assertions are: \b matches at a word boundary \B matches when not at a word boundary @@ -1807,26 +2676,27 @@ BACKSLASH \z matches at end of subject \G matches at first matching position in subject - These assertions may not appear in character classes (but note that \b + These assertions may not appear in character classes (but note that \b has a different meaning, namely the backspace character, inside a char- acter class). - A word boundary is a position in the subject string where the current - character and the previous character do not both match \w or \W (i.e. - one matches \w and the other matches \W), or the start or end of the + A word boundary is a position in the subject string where the current + character and the previous character do not both match \w or \W (i.e. + one matches \w and the other matches \W), or the start or end of the string if the first or last character matches \w, respectively. - The \A, \Z, and \z assertions differ from the traditional circumflex - and dollar (described below) in that they only ever match at the very - start and end of the subject string, whatever options are set. Thus, - they are independent of multiline mode. - - They are not affected by the PCRE_NOTBOL or PCRE_NOTEOL options. If the - startoffset argument of pcre_exec() is non-zero, indicating that match- - ing is to start at a point other than the beginning of the subject, \A - can never match. The difference between \Z and \z is that \Z matches - before a newline that is the last character of the string as well as at - the end of the string, whereas \z matches only at the end. + The \A, \Z, and \z assertions differ from the traditional circumflex + and dollar (described in the next section) in that they only ever match + at the very start and end of the subject string, whatever options are + set. Thus, they are independent of multiline mode. These three asser- + tions are not affected by the PCRE_NOTBOL or PCRE_NOTEOL options, which + affect only the behaviour of the circumflex and dollar metacharacters. + However, if the startoffset argument of pcre_exec() is non-zero, indi- + cating that matching is to start at a point other than the beginning of + the subject, \A can never match. The difference between \Z and \z is + that \Z matches before a newline that is the last character of the + string as well as at the end of the string, whereas \z matches only at + the end. The \G assertion is true only when the current matching position is at the start point of the match, as specified by the startoffset argument @@ -1849,7 +2719,7 @@ BACKSLASH CIRCUMFLEX AND DOLLAR Outside a character class, in the default matching mode, the circumflex - character is an assertion which is true only if the current matching + character is an assertion that is true only if the current matching point is at the start of the subject string. If the startoffset argu- ment of pcre_exec() is non-zero, circumflex can never match if the PCRE_MULTILINE option is unset. Inside a character class, circumflex @@ -1863,7 +2733,7 @@ CIRCUMFLEX AND DOLLAR ject, it is said to be an "anchored" pattern. (There are also other constructs that can cause a pattern to be anchored.) - A dollar character is an assertion which is true only if the current + A dollar character is an assertion that is true only if the current matching point is at the end of the subject string, or immediately before a newline character that is the last character in the string (by default). Dollar need not be the last character of the pattern if a @@ -1880,12 +2750,12 @@ CIRCUMFLEX AND DOLLAR ately after and immediately before an internal newline character, respectively, in addition to matching at the start and end of the sub- ject string. For example, the pattern /^abc$/ matches the subject - string "def\nabc" in multiline mode, but not otherwise. Consequently, - patterns that are anchored in single line mode because all branches - start with ^ are not anchored in multiline mode, and a match for cir- - cumflex is possible when the startoffset argument of pcre_exec() is - non-zero. The PCRE_DOLLAR_ENDONLY option is ignored if PCRE_MULTILINE - is set. + string "def\nabc" (where \n represents a newline character) in multi- + line mode, but not otherwise. Consequently, patterns that are anchored + in single line mode because all branches start with ^ are not anchored + in multiline mode, and a match for circumflex is possible when the + startoffset argument of pcre_exec() is non-zero. The PCRE_DOL- + LAR_ENDONLY option is ignored if PCRE_MULTILINE is set. Note that the sequences \A, \Z, and \z can be used to match the start and end of the subject in both modes, and if all branches of a pattern @@ -1898,28 +2768,28 @@ FULL STOP (PERIOD, DOT) Outside a character class, a dot in the pattern matches any one charac- ter in the subject, including a non-printing character, but not (by default) newline. In UTF-8 mode, a dot matches any UTF-8 character, - which might be more than one byte long, except (by default) for new- - line. If the PCRE_DOTALL option is set, dots match newlines as well. - The handling of dot is entirely independent of the handling of circum- - flex and dollar, the only relationship being that they both involve - newline characters. Dot has no special meaning in a character class. + which might be more than one byte long, except (by default) newline. If + the PCRE_DOTALL option is set, dots match newlines as well. The han- + dling of dot is entirely independent of the handling of circumflex and + dollar, the only relationship being that they both involve newline + characters. Dot has no special meaning in a character class. MATCHING A SINGLE BYTE Outside a character class, the escape sequence \C matches any one byte, - both in and out of UTF-8 mode. Unlike a dot, it always matches a new- - line. The feature is provided in Perl in order to match individual - bytes in UTF-8 mode. Because it breaks up UTF-8 characters into indi- - vidual bytes, what remains in the string may be a malformed UTF-8 - string. For this reason it is best avoided. + both in and out of UTF-8 mode. Unlike a dot, it can match a newline. + The feature is provided in Perl in order to match individual bytes in + UTF-8 mode. Because it breaks up UTF-8 characters into individual + bytes, what remains in the string may be a malformed UTF-8 string. For + this reason, the \C escape sequence is best avoided. - PCRE does not allow \C to appear in lookbehind assertions (see below), - because in UTF-8 mode it makes it impossible to calculate the length of - the lookbehind. + PCRE does not allow \C to appear in lookbehind assertions (described + below), because in UTF-8 mode this would make it impossible to calcu- + late the length of the lookbehind. -SQUARE BRACKETS +SQUARE BRACKETS AND CHARACTER CLASSES An opening square bracket introduces a character class, terminated by a closing square bracket. A closing square bracket on its own is not spe- @@ -1938,69 +2808,81 @@ SQUARE BRACKETS For example, the character class [aeiou] matches any lower case vowel, while [^aeiou] matches any character that is not a lower case vowel. Note that a circumflex is just a convenient notation for specifying the - characters which are in the class by enumerating those that are not. It - is not an assertion: it still consumes a character from the subject - string, and fails if the current pointer is at the end of the string. + characters that are in the class by enumerating those that are not. A + class that starts with a circumflex is not an assertion: it still con- + sumes a character from the subject string, and therefore it fails if + the current pointer is at the end of the string. - In UTF-8 mode, characters with values greater than 255 can be included - in a class as a literal string of bytes, or by using the \x{ escaping + In UTF-8 mode, characters with values greater than 255 can be included + in a class as a literal string of bytes, or by using the \x{ escaping mechanism. - When caseless matching is set, any letters in a class represent both - their upper case and lower case versions, so for example, a caseless - [aeiou] matches "A" as well as "a", and a caseless [^aeiou] does not - match "A", whereas a caseful version would. PCRE does not support the - concept of case for characters with values greater than 255. - - The newline character is never treated in any special way in character - classes, whatever the setting of the PCRE_DOTALL or PCRE_MULTILINE + When caseless matching is set, any letters in a class represent both + their upper case and lower case versions, so for example, a caseless + [aeiou] matches "A" as well as "a", and a caseless [^aeiou] does not + match "A", whereas a caseful version would. In UTF-8 mode, PCRE always + understands the concept of case for characters whose values are less + than 128, so caseless matching is always possible. For characters with + higher values, the concept of case is supported if PCRE is compiled + with Unicode property support, but not otherwise. If you want to use + caseless matching for characters 128 and above, you must ensure that + PCRE is compiled with Unicode property support as well as with UTF-8 + support. + + The newline character is never treated in any special way in character + classes, whatever the setting of the PCRE_DOTALL or PCRE_MULTILINE options is. A class such as [^a] will always match a newline. - The minus (hyphen) character can be used to specify a range of charac- - ters in a character class. For example, [d-m] matches any letter - between d and m, inclusive. If a minus character is required in a - class, it must be escaped with a backslash or appear in a position - where it cannot be interpreted as indicating a range, typically as the + The minus (hyphen) character can be used to specify a range of charac- + ters in a character class. For example, [d-m] matches any letter + between d and m, inclusive. If a minus character is required in a + class, it must be escaped with a backslash or appear in a position + where it cannot be interpreted as indicating a range, typically as the first or last character in the class. It is not possible to have the literal character "]" as the end charac- - ter of a range. A pattern such as [W-]46] is interpreted as a class of - two characters ("W" and "-") followed by a literal string "46]", so it - would match "W46]" or "-46]". However, if the "]" is escaped with a - backslash it is interpreted as the end of range, so [W-\]46] is inter- - preted as a single class containing a range followed by two separate - characters. The octal or hexadecimal representation of "]" can also be - used to end a range. - - Ranges operate in the collating sequence of character values. They can - also be used for characters specified numerically, for example - [\000-\037]. In UTF-8 mode, ranges can include characters whose values + ter of a range. A pattern such as [W-]46] is interpreted as a class of + two characters ("W" and "-") followed by a literal string "46]", so it + would match "W46]" or "-46]". However, if the "]" is escaped with a + backslash it is interpreted as the end of range, so [W-\]46] is inter- + preted as a class containing a range followed by two other characters. + The octal or hexadecimal representation of "]" can also be used to end + a range. + + Ranges operate in the collating sequence of character values. They can + also be used for characters specified numerically, for example + [\000-\037]. In UTF-8 mode, ranges can include characters whose values are greater than 255, for example [\x{100}-\x{2ff}]. If a range that includes letters is used when caseless matching is set, it matches the letters in either case. For example, [W-c] is equivalent - to [][\^_`wxyzabc], matched caselessly, and if character tables for the - "fr" locale are in use, [\xc8-\xcb] matches accented E characters in - both cases. - - The character types \d, \D, \s, \S, \w, and \W may also appear in a - character class, and add the characters that they match to the class. - For example, [\dABCDEF] matches any hexadecimal digit. A circumflex can - conveniently be used with the upper case character types to specify a - more restricted set of characters than the matching lower case type. - For example, the class [^\W_] matches any letter or digit, but not - underscore. - - All non-alphameric characters other than \, -, ^ (at the start) and the - terminating ] are non-special in character classes, but it does no harm - if they are escaped. + to [][\\^_`wxyzabc], matched caselessly, and in non-UTF-8 mode, if + character tables for the "fr_FR" locale are in use, [\xc8-\xcb] matches + accented E characters in both cases. In UTF-8 mode, PCRE supports the + concept of case for characters with values greater than 128 only when + it is compiled with Unicode property support. + + The character types \d, \D, \p, \P, \s, \S, \w, and \W may also appear + in a character class, and add the characters that they match to the + class. For example, [\dABCDEF] matches any hexadecimal digit. A circum- + flex can conveniently be used with the upper case character types to + specify a more restricted set of characters than the matching lower + case type. For example, the class [^\W_] matches any letter or digit, + but not underscore. + + The only metacharacters that are recognized in character classes are + backslash, hyphen (only where it can be interpreted as specifying a + range), circumflex (only at the start), opening square bracket (only + when it can be interpreted as introducing a POSIX class name - see the + next section), and the terminating closing square bracket. However, + escaping other non-alphanumeric characters does no harm. POSIX CHARACTER CLASSES - Perl supports the POSIX notation for character classes, which uses - names enclosed by [: and :] within the enclosing square brackets. PCRE - also supports this notation. For example, + Perl supports the POSIX notation for character classes. This uses names + enclosed by [: and :] within the enclosing square brackets. PCRE also + supports this notation. For example, [01[:alpha:]%] @@ -2037,7 +2919,7 @@ POSIX CHARACTER CLASSES POSIX syntax [.ch.] and [=ch=] where "ch" is a "collating element", but these are not supported, and an error is given if they are encountered. - In UTF-8 mode, characters with values greater than 255 do not match any + In UTF-8 mode, characters with values greater than 128 do not match any of the POSIX character classes. @@ -2104,13 +2986,14 @@ INTERNAL OPTION SETTING in the same way as the Perl-compatible options by using the characters U and X respectively. The (?X) flag setting is special in that it must always occur earlier in the pattern than any of the additional features - it turns on, even when it is at top level. It is best put at the start. + it turns on, even when it is at top level. It is best to put it at the + start. SUBPATTERNS Subpatterns are delimited by parentheses (round brackets), which can be - nested. Marking part of a pattern as a subpattern does two things: + nested. Turning part of a pattern into a subpattern does two things: 1. It localizes a set of alternatives. For example, the pattern @@ -2120,11 +3003,11 @@ SUBPATTERNS the parentheses, it would match "cataract", "erpillar" or the empty string. - 2. It sets up the subpattern as a capturing subpattern (as defined - above). When the whole pattern matches, that portion of the subject + 2. It sets up the subpattern as a capturing subpattern. This means + that, when the whole pattern matches, that portion of the subject string that matched the subpattern is passed back to the caller via the ovector argument of pcre_exec(). Opening parentheses are counted from - left to right (starting from 1) to obtain the numbers of the capturing + left to right (starting from 1) to obtain numbers for the capturing subpatterns. For example, if the string "the red king" is matched against the pat- @@ -2169,41 +3052,43 @@ NAMED SUBPATTERNS Identifying capturing parentheses by number is simple, but it can be very hard to keep track of the numbers in complicated regular expres- sions. Furthermore, if an expression is modified, the numbers may - change. To help with the difficulty, PCRE supports the naming of sub- + change. To help with this difficulty, PCRE supports the naming of sub- patterns, something that Perl does not provide. The Python syntax (?P...) is used. Names consist of alphanumeric characters and underscores, and must be unique within a pattern. Named capturing parentheses are still allocated numbers as well as names. The PCRE API provides function calls for extracting the name-to- - number translation table from a compiled pattern. For further details - see the pcreapi documentation. + number translation table from a compiled pattern. There is also a con- + venience function for extracting a captured substring by name. For fur- + ther details see the pcreapi documentation. REPETITION - Repetition is specified by quantifiers, which can follow any of the + Repetition is specified by quantifiers, which can follow any of the following items: a literal data character the . metacharacter the \C escape sequence - escapes such as \d that match single characters + the \X escape sequence (in UTF-8 mode with Unicode properties) + an escape such as \d that matches a single character a character class a back reference (see next section) a parenthesized subpattern (unless it is an assertion) - The general repetition quantifier specifies a minimum and maximum num- - ber of permitted matches, by giving the two numbers in curly brackets - (braces), separated by a comma. The numbers must be less than 65536, + The general repetition quantifier specifies a minimum and maximum num- + ber of permitted matches, by giving the two numbers in curly brackets + (braces), separated by a comma. The numbers must be less than 65536, and the first must be less than or equal to the second. For example: z{2,4} - matches "zz", "zzz", or "zzzz". A closing brace on its own is not a - special character. If the second number is omitted, but the comma is - present, there is no upper limit; if the second number and the comma - are both omitted, the quantifier specifies an exact number of required + matches "zz", "zzz", or "zzzz". A closing brace on its own is not a + special character. If the second number is omitted, but the comma is + present, there is no upper limit; if the second number and the comma + are both omitted, the quantifier specifies an exact number of required matches. Thus [aeiou]{3,} @@ -2212,14 +3097,17 @@ REPETITION \d{8} - matches exactly 8 digits. An opening curly bracket that appears in a - position where a quantifier is not allowed, or one that does not match - the syntax of a quantifier, is taken as a literal character. For exam- + matches exactly 8 digits. An opening curly bracket that appears in a + position where a quantifier is not allowed, or one that does not match + the syntax of a quantifier, is taken as a literal character. For exam- ple, {,6} is not a quantifier, but a literal string of four characters. - In UTF-8 mode, quantifiers apply to UTF-8 characters rather than to + In UTF-8 mode, quantifiers apply to UTF-8 characters rather than to individual bytes. Thus, for example, \x{100}{2} matches two UTF-8 char- - acters, each of which is represented by a two-byte sequence. + acters, each of which is represented by a two-byte sequence. Similarly, + when Unicode property support is available, \X{3} matches three Unicode + extended sequences, each of which may be several bytes long (and they + may be of different lengths). The quantifier {0} is permitted, causing the expression to behave as if the previous item and the quantifier were not present. @@ -2247,15 +3135,15 @@ REPETITION as possible (up to the maximum number of permitted times), without causing the rest of the pattern to fail. The classic example of where this gives problems is in trying to match comments in C programs. These - appear between the sequences /* and */ and within the sequence, indi- - vidual * and / characters may appear. An attempt to match C comments by - applying the pattern + appear between /* and */ and within the comment, individual * and / + characters may appear. An attempt to match C comments by applying the + pattern /\*.*\*/ to the string - /* first command */ not comment /* second comment */ + /* first comment */ not comment /* second comment */ fails, because it matches the entire string owing to the greediness of the .* item. @@ -2283,7 +3171,7 @@ REPETITION words, it inverts the default behaviour. When a parenthesized subpattern is quantified with a minimum repeat - count that is greater than 1 or with a limited maximum, more store is + count that is greater than 1 or with a limited maximum, more memory is required for the compiled pattern, in proportion to the size of the minimum or maximum. @@ -2374,7 +3262,7 @@ ATOMIC GROUPING AND POSSESSIVE QUANTIFIERS consists of an additional + character following a quantifier. Using this notation, the previous example can be rewritten as - \d++bar + \d++foo Possessive quantifiers are always greedy; the setting of the PCRE_UNGREEDY option is ignored. They are a convenient notation for the @@ -2399,68 +3287,70 @@ ATOMIC GROUPING AND POSSESSIVE QUANTIFIERS aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa it takes a long time before reporting failure. This is because the - string can be divided between the two repeats in a large number of - ways, and all have to be tried. (The example used [!?] rather than a - single character at the end, because both PCRE and Perl have an opti- - mization that allows for fast failure when a single character is used. - They remember the last single character that is required for a match, - and fail early if it is not present in the string.) If the pattern is - changed to + string can be divided between the internal \D+ repeat and the external + * repeat in a large number of ways, and all have to be tried. (The + example uses [!?] rather than a single character at the end, because + both PCRE and Perl have an optimization that allows for fast failure + when a single character is used. They remember the last single charac- + ter that is required for a match, and fail early if it is not present + in the string.) If the pattern is changed so that it uses an atomic + group, like this: ((?>\D+)|<\d+>)*[!?] - sequences of non-digits cannot be broken, and failure happens quickly. + sequences of non-digits cannot be broken, and failure happens quickly. BACK REFERENCES Outside a character class, a backslash followed by a digit greater than 0 (and possibly further digits) is a back reference to a capturing sub- - pattern earlier (that is, to its left) in the pattern, provided there + pattern earlier (that is, to its left) in the pattern, provided there have been that many previous capturing left parentheses. However, if the decimal number following the backslash is less than 10, - it is always taken as a back reference, and causes an error only if - there are not that many capturing left parentheses in the entire pat- - tern. In other words, the parentheses that are referenced need not be - to the left of the reference for numbers less than 10. See the section - entitled "Backslash" above for further details of the handling of dig- - its following a backslash. - - A back reference matches whatever actually matched the capturing sub- - pattern in the current subject string, rather than anything matching + it is always taken as a back reference, and causes an error only if + there are not that many capturing left parentheses in the entire pat- + tern. In other words, the parentheses that are referenced need not be + to the left of the reference for numbers less than 10. See the subsec- + tion entitled "Non-printing characters" above for further details of + the handling of digits following a backslash. + + A back reference matches whatever actually matched the capturing sub- + pattern in the current subject string, rather than anything matching the subpattern itself (see "Subpatterns as subroutines" below for a way of doing that). So the pattern (sens|respons)e and \1ibility - matches "sense and sensibility" and "response and responsibility", but - not "sense and responsibility". If caseful matching is in force at the - time of the back reference, the case of letters is relevant. For exam- + matches "sense and sensibility" and "response and responsibility", but + not "sense and responsibility". If caseful matching is in force at the + time of the back reference, the case of letters is relevant. For exam- ple, ((?i)rah)\s+\1 - matches "rah rah" and "RAH RAH", but not "RAH rah", even though the + matches "rah rah" and "RAH RAH", but not "RAH rah", even though the original capturing subpattern is matched caselessly. - Back references to named subpatterns use the Python syntax (?P=name). + Back references to named subpatterns use the Python syntax (?P=name). We could rewrite the above example as follows: (?(?i)rah)\s+(?P=p1) - There may be more than one back reference to the same subpattern. If a - subpattern has not actually been used in a particular match, any back + There may be more than one back reference to the same subpattern. If a + subpattern has not actually been used in a particular match, any back references to it always fail. For example, the pattern (a|(bc))\2 - always fails if it starts to match "a" rather than "bc". Because there - may be many capturing parentheses in a pattern, all digits following - the backslash are taken as part of a potential back reference number. + always fails if it starts to match "a" rather than "bc". Because there + may be many capturing parentheses in a pattern, all digits following + the backslash are taken as part of a potential back reference number. If the pattern continues with a digit character, some delimiter must be - used to terminate the back reference. If the PCRE_EXTENDED option is - set, this can be whitespace. Otherwise an empty comment can be used. + used to terminate the back reference. If the PCRE_EXTENDED option is + set, this can be whitespace. Otherwise an empty comment (see "Com- + ments" below) can be used. A back reference that occurs inside the parentheses to which it refers fails when the subpattern is first used, so, for example, (a\1) never @@ -2482,14 +3372,26 @@ ASSERTIONS An assertion is a test on the characters following or preceding the current matching point that does not actually consume any characters. The simple assertions coded as \b, \B, \A, \G, \Z, \z, ^ and $ are - described above. More complicated assertions are coded as subpatterns. - There are two kinds: those that look ahead of the current position in - the subject string, and those that look behind it. + described above. + + More complicated assertions are coded as subpatterns. There are two + kinds: those that look ahead of the current position in the subject + string, and those that look behind it. An assertion subpattern is + matched in the normal way, except that it does not cause the current + matching position to be changed. + + Assertion subpatterns are not capturing subpatterns, and may not be + repeated, because it makes no sense to assert the same thing several + times. If any kind of assertion contains capturing subpatterns within + it, these are counted for the purposes of numbering the capturing sub- + patterns in the whole pattern. However, substring capturing is carried + out only for positive assertions, because it does not make sense for + negative assertions. + + Lookahead assertions - An assertion subpattern is matched in the normal way, except that it - does not cause the current matching position to be changed. Lookahead - assertions start with (?= for positive assertions and (?! for negative - assertions. For example, + Lookahead assertions start with (?= for positive assertions and (?! for + negative assertions. For example, \w+(?=;) @@ -2506,13 +3408,15 @@ ASSERTIONS does not find an occurrence of "bar" that is preceded by something other than "foo"; it finds any occurrence of "bar" whatsoever, because the assertion (?!foo) is always true when the next three characters are - "bar". A lookbehind assertion is needed to achieve this effect. + "bar". A lookbehind assertion is needed to achieve the other effect. If you want to force a matching failure at some point in a pattern, the most convenient way to do it is with (?!) because an empty string always matches, so an assertion that requires there not to be an empty string must always fail. + Lookbehind assertions + Lookbehind assertions start with (?<= for positive assertions and (?.*)(?<=abcd) - or, equivalently, + or, equivalently, using the possessive quantifier syntax, ^.*+(?<=abcd) - there can be no backtracking for the .* item; it can match only the - entire string. The subsequent lookbehind assertion does a single test - on the last four characters. If it fails, the match fails immediately. - For long strings, this approach makes a significant difference to the + there can be no backtracking for the .* item; it can match only the + entire string. The subsequent lookbehind assertion does a single test + on the last four characters. If it fails, the match fails immediately. + For long strings, this approach makes a significant difference to the processing time. + Using multiple assertions + Several assertions (of any sort) may occur in succession. For example, (?<=\d{3})(?[^()]+) | (?p{$re}) )* \)}x; The (?p{...}) item interpolates Perl code at run time, and in this case - refers recursively to the pattern in which it appears. Obviously, PCRE - cannot support the interpolation of Perl code. Instead, it supports - some special syntax for recursion of the entire pattern, and also for + refers recursively to the pattern in which it appears. Obviously, PCRE + cannot support the interpolation of Perl code. Instead, it supports + some special syntax for recursion of the entire pattern, and also for individual subpattern recursion. - The special item that consists of (? followed by a number greater than + The special item that consists of (? followed by a number greater than zero and a closing parenthesis is a recursive call of the subpattern of - the given number, provided that it occurs inside that subpattern. (If - not, it is a "subroutine" call, which is described in the next sec- - tion.) The special item (?R) is a recursive call of the entire regular + the given number, provided that it occurs inside that subpattern. (If + not, it is a "subroutine" call, which is described in the next sec- + tion.) The special item (?R) is a recursive call of the entire regular expression. - For example, this PCRE pattern solves the nested parentheses problem - (assume the PCRE_EXTENDED option is set so that white space is + For example, this PCRE pattern solves the nested parentheses problem + (assume the PCRE_EXTENDED option is set so that white space is ignored): \( ( (?>[^()]+) | (?R) )* \) - First it matches an opening parenthesis. Then it matches any number of - substrings which can either be a sequence of non-parentheses, or a - recursive match of the pattern itself (that is a correctly parenthe- + First it matches an opening parenthesis. Then it matches any number of + substrings which can either be a sequence of non-parentheses, or a + recursive match of the pattern itself (that is a correctly parenthe- sized substring). Finally there is a closing parenthesis. - If this were part of a larger pattern, you would not want to recurse + If this were part of a larger pattern, you would not want to recurse the entire pattern, so instead you could use this: ( \( ( (?>[^()]+) | (?1) )* \) ) - We have put the pattern into parentheses, and caused the recursion to - refer to them instead of the whole pattern. In a larger pattern, keep- - ing track of parenthesis numbers can be tricky. It may be more conve- - nient to use named parentheses instead. For this, PCRE uses (?P>name), - which is an extension to the Python syntax that PCRE uses for named + We have put the pattern into parentheses, and caused the recursion to + refer to them instead of the whole pattern. In a larger pattern, keep- + ing track of parenthesis numbers can be tricky. It may be more conve- + nient to use named parentheses instead. For this, PCRE uses (?P>name), + which is an extension to the Python syntax that PCRE uses for named parentheses (Perl does not provide named parentheses). We could rewrite the above example as follows: (?P \( ( (?>[^()]+) | (?P>pn) )* \) ) - This particular example pattern contains nested unlimited repeats, and - so the use of atomic grouping for matching strings of non-parentheses - is important when applying the pattern to strings that do not match. + This particular example pattern contains nested unlimited repeats, and + so the use of atomic grouping for matching strings of non-parentheses + is important when applying the pattern to strings that do not match. For example, when this pattern is applied to (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa() - it yields "no match" quickly. However, if atomic grouping is not used, - the match runs for a very long time indeed because there are so many - different ways the + and * repeats can carve up the subject, and all + it yields "no match" quickly. However, if atomic grouping is not used, + the match runs for a very long time indeed because there are so many + different ways the + and * repeats can carve up the subject, and all have to be tested before failure can be reported. At the end of a match, the values set for any capturing subpatterns are those from the outermost level of the recursion at which the subpattern - value is set. If you want to obtain intermediate values, a callout - function can be used (see below and the pcrecallout documentation). If - the pattern above is matched against + value is set. If you want to obtain intermediate values, a callout + function can be used (see the next section and the pcrecallout documen- + tation). If the pattern above is matched against (ab(cd)ef) - the value for the capturing parentheses is "ef", which is the last - value taken on at the top level. If additional parentheses are added, + the value for the capturing parentheses is "ef", which is the last + value taken on at the top level. If additional parentheses are added, giving \( ( ( (?>[^()]+) | (?R) )* ) \) ^ ^ ^ ^ - the string they capture is "ab(cd)ef", the contents of the top level - parentheses. If there are more than 15 capturing parentheses in a pat- + the string they capture is "ab(cd)ef", the contents of the top level + parentheses. If there are more than 15 capturing parentheses in a pat- tern, PCRE has to obtain extra memory to store data during a recursion, - which it does by using pcre_malloc, freeing it via pcre_free after- - wards. If no memory can be obtained, the match fails with the + which it does by using pcre_malloc, freeing it via pcre_free after- + wards. If no memory can be obtained, the match fails with the PCRE_ERROR_NOMEMORY error. - Do not confuse the (?R) item with the condition (R), which tests for - recursion. Consider this pattern, which matches text in angle brack- - ets, allowing for arbitrary nesting. Only digits are allowed in nested - brackets (that is, when recursing), whereas any characters are permit- + Do not confuse the (?R) item with the condition (R), which tests for + recursion. Consider this pattern, which matches text in angle brack- + ets, allowing for arbitrary nesting. Only digits are allowed in nested + brackets (that is, when recursing), whereas any characters are permit- ted at the outer level. < (?: (?(R) \d++ | [^<>]*+) | (?R)) * > - In this pattern, (?(R) is the start of a conditional subpattern, with - two different alternatives for the recursive and non-recursive cases. + In this pattern, (?(R) is the start of a conditional subpattern, with + two different alternatives for the recursive and non-recursive cases. The (?R) item is the actual recursive call. SUBPATTERNS AS SUBROUTINES If the syntax for a recursive subpattern reference (either by number or - by name) is used outside the parentheses to which it refers, it oper- - ates like a subroutine in a programming language. An earlier example + by name) is used outside the parentheses to which it refers, it oper- + ates like a subroutine in a programming language. An earlier example pointed out that the pattern (sens|respons)e and \1ibility - matches "sense and sensibility" and "response and responsibility", but + matches "sense and sensibility" and "response and responsibility", but not "sense and responsibility". If instead the pattern (sens|respons)e and (?1)ibility - is used, it does match "sense and responsibility" as well as the other - two strings. Such references must, however, follow the subpattern to + is used, it does match "sense and responsibility" as well as the other + two strings. Such references must, however, follow the subpattern to which they refer. CALLOUTS Perl has a feature whereby using the sequence (?{...}) causes arbitrary - Perl code to be obeyed in the middle of matching a regular expression. + Perl code to be obeyed in the middle of matching a regular expression. This makes it possible, amongst other things, to extract different sub- strings that match the same pair of parentheses when there is a repeti- tion. PCRE provides a similar feature, but of course it cannot obey arbitrary Perl code. The feature is called "callout". The caller of PCRE provides - an external function by putting its entry point in the global variable - pcre_callout. By default, this variable contains NULL, which disables + an external function by putting its entry point in the global variable + pcre_callout. By default, this variable contains NULL, which disables all calling out. - Within a regular expression, (?C) indicates the points at which the - external function is to be called. If you want to identify different - callout points, you can put a number less than 256 after the letter C. - The default value is zero. For example, this pattern has two callout + Within a regular expression, (?C) indicates the points at which the + external function is to be called. If you want to identify different + callout points, you can put a number less than 256 after the letter C. + The default value is zero. For example, this pattern has two callout points: (?C1)abc(?C2)def + If the PCRE_AUTO_CALLOUT flag is passed to pcre_compile(), callouts are + automatically installed before each item in the pattern. They are all + numbered 255. + During matching, when PCRE reaches a callout point (and pcre_callout is - set), the external function is called. It is provided with the number - of the callout, and, optionally, one item of data originally supplied - by the caller of pcre_exec(). The callout function may cause matching - to backtrack, or to fail altogether. A complete description of the - interface to the callout function is given in the pcrecallout documen- + set), the external function is called. It is provided with the number + of the callout, the position in the pattern, and, optionally, one item + of data originally supplied by the caller of pcre_exec(). The callout + function may cause matching to proceed, to backtrack, or to fail alto- + gether. A complete description of the interface to the callout function + is given in the pcrecallout documentation. + +Last updated: 28 February 2005 +Copyright (c) 1997-2005 University of Cambridge. +------------------------------------------------------------------------------ + + +PCREPARTIAL(3) PCREPARTIAL(3) + + +NAME + PCRE - Perl-compatible regular expressions + + +PARTIAL MATCHING IN PCRE + + In normal use of PCRE, if the subject string that is passed to + pcre_exec() or pcre_dfa_exec() matches as far as it goes, but is too + short to match the entire pattern, PCRE_ERROR_NOMATCH is returned. + There are circumstances where it might be helpful to distinguish this + case from other cases in which there is no match. + + Consider, for example, an application where a human is required to type + in data for a field with specific formatting requirements. An example + might be a date in the form ddmmmyy, defined by this pattern: + + ^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$ + + If the application sees the user's keystrokes one by one, and can check + that what has been typed so far is potentially valid, it is able to + raise an error as soon as a mistake is made, possibly beeping and not + reflecting the character that has been typed. This immediate feedback + is likely to be a better user interface than a check that is delayed + until the entire string has been entered. + + PCRE supports the concept of partial matching by means of the PCRE_PAR- + TIAL option, which can be set when calling pcre_exec() or + pcre_dfa_exec(). When this flag is set for pcre_exec(), the return code + PCRE_ERROR_NOMATCH is converted into PCRE_ERROR_PARTIAL if at any time + during the matching process the last part of the subject string matched + part of the pattern. Unfortunately, for non-anchored matching, it is + not possible to obtain the position of the start of the partial match. + No captured data is set when PCRE_ERROR_PARTIAL is returned. + + When PCRE_PARTIAL is set for pcre_dfa_exec(), the return code + PCRE_ERROR_NOMATCH is converted into PCRE_ERROR_PARTIAL if the end of + the subject is reached, there have been no complete matches, but there + is still at least one matching possibility. The portion of the string + that provided the partial match is set as the first matching string. + + Using PCRE_PARTIAL disables one of PCRE's optimizations. PCRE remembers + the last literal byte in a pattern, and abandons matching immediately + if such a byte is not present in the subject string. This optimization + cannot be used for a subject string that might match only partially. + + +RESTRICTED PATTERNS FOR PCRE_PARTIAL + + Because of the way certain internal optimizations are implemented in + the pcre_exec() function, the PCRE_PARTIAL option cannot be used with + all patterns. These restrictions do not apply when pcre_dfa_exec() is + used. For pcre_exec(), repeated single characters such as + + a{2,4} + + and repeated single metasequences such as + + \d+ + + are not permitted if the maximum number of occurrences is greater than + one. Optional items such as \d? (where the maximum is one) are permit- + ted. Quantifiers with any values are permitted after parentheses, so + the invalid examples above can be coded thus: + + (a){2,4} + (\d)+ + + These constructions run more slowly, but for the kinds of application + that are envisaged for this facility, this is not felt to be a major + restriction. + + If PCRE_PARTIAL is set for a pattern that does not conform to the + restrictions, pcre_exec() returns the error code PCRE_ERROR_BADPARTIAL + (-13). + + +EXAMPLE OF PARTIAL MATCHING USING PCRETEST + + If the escape sequence \P is present in a pcretest data line, the + PCRE_PARTIAL flag is used for the match. Here is a run of pcretest that + uses the date example quoted above: + + re> /^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$/ + data> 25jun04P + 0: 25jun04 + 1: jun + data> 25dec3P + Partial match + data> 3juP + Partial match + data> 3jujP + No match + data> jP + No match + + The first data string is matched completely, so pcretest shows the + matched substrings. The remaining four strings do not match the com- + plete pattern, but the first two are partial matches. The same test, + using DFA matching (by means of the \D escape sequence), produces the + following output: + + re> /^?(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)$/ + data> 25jun04\P\D + 0: 25jun04 + data> 23dec3\P\D + Partial match: 23dec3 + data> 3ju\P\D + Partial match: 3ju + data> 3juj\P\D + No match + data> j\P\D + No match + + Notice that in this case the portion of the string that was matched is + made available. + + +MULTI-SEGMENT MATCHING WITH pcre_dfa_exec() + + When a partial match has been found using pcre_dfa_exec(), it is possi- + ble to continue the match by providing additional subject data and + calling pcre_dfa_exec() again with the PCRE_DFA_RESTART option and the + same working space (where details of the previous partial match are + stored). Here is an example using pcretest, where the \R escape + sequence sets the PCRE_DFA_RESTART option and the \D escape sequence + requests the use of pcre_dfa_exec(): + + re> /^?(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)$/ + data> 23ja\P\D + Partial match: 23ja + data> n05\R\D + 0: n05 + + The first call has "23ja" as the subject, and requests partial match- + ing; the second call has "n05" as the subject for the continued + (restarted) match. Notice that when the match is complete, only the + last part is shown; PCRE does not retain the previously partially- + matched string. It is up to the calling program to do that if it needs + to. + + This facility can be used to pass very long subject strings to + pcre_dfa_exec(). However, some care is needed for certain types of pat- + tern. + + 1. If the pattern contains tests for the beginning or end of a line, + you need to pass the PCRE_NOTBOL or PCRE_NOTEOL options, as appropri- + ate, when the subject string for any call does not contain the begin- + ning or end of a line. + + 2. If the pattern contains backward assertions (including \b or \B), + you need to arrange for some overlap in the subject strings to allow + for this. For example, you could pass the subject in chunks that were + 500 bytes long, but in a buffer of 700 bytes, with the starting offset + set to 200 and the previous 200 bytes at the start of the buffer. + + 3. Matching a subject string that is split into multiple segments does + not always produce exactly the same result as matching over one single + long string. The difference arises when there are multiple matching + possibilities, because a partial match result is given only when there + are no completed matches in a call to fBpcre_dfa_exec(). This means + that as soon as the shortest match has been found, continuation to a + new subject segment is no longer possible. Consider this pcretest + example: + + re> /dog(sbody)?/ + data> do\P\D + Partial match: do + data> gsb\R\P\D + 0: g + data> dogsbody\D + 0: dogsbody + 1: dog + + The pattern matches the words "dog" or "dogsbody". When the subject is + presented in several parts ("do" and "gsb" being the first two) the + match stops when "dog" has been found, and it is not possible to con- + tinue. On the other hand, if "dogsbody" is presented as a single + string, both matches are found. + + Because of this phenomenon, it does not usually make sense to end a + pattern that is going to be matched in this way with a variable repeat. + +Last updated: 28 February 2005 +Copyright (c) 1997-2005 University of Cambridge. +------------------------------------------------------------------------------ + + +PCREPRECOMPILE(3) PCREPRECOMPILE(3) + + +NAME + PCRE - Perl-compatible regular expressions + + +SAVING AND RE-USING PRECOMPILED PCRE PATTERNS + + If you are running an application that uses a large number of regular + expression patterns, it may be useful to store them in a precompiled + form instead of having to compile them every time the application is + run. If you are not using any private character tables (see the + pcre_maketables() documentation), this is relatively straightforward. + If you are using private tables, it is a little bit more complicated. + + If you save compiled patterns to a file, you can copy them to a differ- + ent host and run them there. This works even if the new host has the + opposite endianness to the one on which the patterns were compiled. + There may be a small performance penalty, but it should be insignifi- + cant. + + +SAVING A COMPILED PATTERN + The value returned by pcre_compile() points to a single block of memory + that holds the compiled pattern and associated data. You can find the + length of this block in bytes by calling pcre_fullinfo() with an argu- + ment of PCRE_INFO_SIZE. You can then save the data in any appropriate + manner. Here is sample code that compiles a pattern and writes it to a + file. It assumes that the variable fd refers to a file that is open for + output: + + int erroroffset, rc, size; + char *error; + pcre *re; + + re = pcre_compile("my pattern", 0, &error, &erroroffset, NULL); + if (re == NULL) { ... handle errors ... } + rc = pcre_fullinfo(re, NULL, PCRE_INFO_SIZE, &size); + if (rc < 0) { ... handle errors ... } + rc = fwrite(re, 1, size, fd); + if (rc != size) { ... handle errors ... } + + In this example, the bytes that comprise the compiled pattern are + copied exactly. Note that this is binary data that may contain any of + the 256 possible byte values. On systems that make a distinction + between binary and non-binary data, be sure that the file is opened for + binary output. + + If you want to write more than one pattern to a file, you will have to + devise a way of separating them. For binary data, preceding each pat- + tern with its length is probably the most straightforward approach. + Another possibility is to write out the data in hexadecimal instead of + binary, one pattern to a line. + + Saving compiled patterns in a file is only one possible way of storing + them for later use. They could equally well be saved in a database, or + in the memory of some daemon process that passes them via sockets to + the processes that want them. + + If the pattern has been studied, it is also possible to save the study + data in a similar way to the compiled pattern itself. When studying + generates additional information, pcre_study() returns a pointer to a + pcre_extra data block. Its format is defined in the section on matching + a pattern in the pcreapi documentation. The study_data field points to + the binary study data, and this is what you must save (not the + pcre_extra block itself). The length of the study data can be obtained + by calling pcre_fullinfo() with an argument of PCRE_INFO_STUDYSIZE. + Remember to check that pcre_study() did return a non-NULL value before + trying to save the study data. + + +RE-USING A PRECOMPILED PATTERN + + Re-using a precompiled pattern is straightforward. Having reloaded it + into main memory, you pass its pointer to pcre_exec() or + pcre_dfa_exec() in the usual way. This should work even on another + host, and even if that host has the opposite endianness to the one + where the pattern was compiled. + + However, if you passed a pointer to custom character tables when the + pattern was compiled (the tableptr argument of pcre_compile()), you + must now pass a similar pointer to pcre_exec() or pcre_dfa_exec(), + because the value saved with the compiled pattern will obviously be + nonsense. A field in a pcre_extra() block is used to pass this data, as + described in the section on matching a pattern in the pcreapi documen- tation. -Last updated: 03 February 2003 -Copyright (c) 1997-2003 University of Cambridge. ------------------------------------------------------------------------------ + If you did not provide custom character tables when the pattern was + compiled, the pointer in the compiled pattern is NULL, which causes + pcre_exec() to use PCRE's internal tables. Thus, you do not need to + take any special action at run time in this case. -PCRE(3) PCRE(3) + If you saved study data with the compiled pattern, you need to create + your own pcre_extra data block and set the study_data field to point to + the reloaded study data. You must also set the PCRE_EXTRA_STUDY_DATA + bit in the flags field to indicate that study data is present. Then + pass the pcre_extra block to pcre_exec() or pcre_dfa_exec() in the + usual way. + + +COMPATIBILITY WITH DIFFERENT PCRE RELEASES + The layout of the control block that is at the start of the data that + makes up a compiled pattern was changed for release 5.0. If you have + any saved patterns that were compiled with previous releases (not a + facility that was previously advertised), you will have to recompile + them for release 5.0. However, from now on, it should be possible to + make changes in a compatible manner. + +Last updated: 28 February 2005 +Copyright (c) 1997-2005 University of Cambridge. +------------------------------------------------------------------------------ + + +PCREPERFORM(3) PCREPERFORM(3) NAME PCRE - Perl-compatible regular expressions + PCRE PERFORMANCE Certain items that may appear in regular expression patterns are more @@ -2862,73 +4071,85 @@ PCRE PERFORMANCE like [aeiou] than a set of alternatives such as (a|e|i|o|u). In gen- eral, the simplest construction that provides the required behaviour is usually the most efficient. Jeffrey Friedl's book contains a lot of - discussion about optimizing regular expressions for efficient perfor- - mance. + useful general discussion about optimizing regular expressions for + efficient performance. This document contains a few observations about + PCRE. + + Using Unicode character properties (the \p, \P, and \X escapes) is + slow, because PCRE has to scan a structure that contains data for over + fifteen thousand characters whenever it needs a character's property. + If you can find an alternative pattern that does not use character + properties, it will probably be faster. - When a pattern begins with .* not in parentheses, or in parentheses + When a pattern begins with .* not in parentheses, or in parentheses that are not the subject of a backreference, and the PCRE_DOTALL option - is set, the pattern is implicitly anchored by PCRE, since it can match - only at the start of a subject string. However, if PCRE_DOTALL is not - set, PCRE cannot make this optimization, because the . metacharacter - does not then match a newline, and if the subject string contains new- - lines, the pattern may match from the character immediately following + is set, the pattern is implicitly anchored by PCRE, since it can match + only at the start of a subject string. However, if PCRE_DOTALL is not + set, PCRE cannot make this optimization, because the . metacharacter + does not then match a newline, and if the subject string contains new- + lines, the pattern may match from the character immediately following one of them instead of from the very start. For example, the pattern .*second - matches the subject "first\nand second" (where \n stands for a newline - character), with the match starting at the seventh character. In order + matches the subject "first\nand second" (where \n stands for a newline + character), with the match starting at the seventh character. In order to do this, PCRE has to retry the match starting after every newline in the subject. - If you are using such a pattern with subject strings that do not con- + If you are using such a pattern with subject strings that do not con- tain newlines, the best performance is obtained by setting PCRE_DOTALL, - or starting the pattern with ^.* to indicate explicit anchoring. That - saves PCRE from having to scan along the subject looking for a newline - to restart at. + or starting the pattern with ^.* or ^.*? to indicate explicit anchor- + ing. That saves PCRE from having to scan along the subject looking for + a newline to restart at. - Beware of patterns that contain nested indefinite repeats. These can - take a long time to run when applied to a string that does not match. + Beware of patterns that contain nested indefinite repeats. These can + take a long time to run when applied to a string that does not match. Consider the pattern fragment (a+)* - This can match "aaaa" in 33 different ways, and this number increases - very rapidly as the string gets longer. (The * repeat can match 0, 1, - 2, 3, or 4 times, and for each of those cases other than 0, the + - repeats can match different numbers of times.) When the remainder of + This can match "aaaa" in 33 different ways, and this number increases + very rapidly as the string gets longer. (The * repeat can match 0, 1, + 2, 3, or 4 times, and for each of those cases other than 0, the + + repeats can match different numbers of times.) When the remainder of the pattern is such that the entire match is going to fail, PCRE has in - principle to try every possible variation, and this can take an + principle to try every possible variation, and this can take an extremely long time. An optimization catches some of the more simple cases such as (a+)*b - where a literal character follows. Before embarking on the standard - matching procedure, PCRE checks that there is a "b" later in the sub- - ject string, and if there is not, it fails the match immediately. How- - ever, when there is no following literal this optimization cannot be + where a literal character follows. Before embarking on the standard + matching procedure, PCRE checks that there is a "b" later in the sub- + ject string, and if there is not, it fails the match immediately. How- + ever, when there is no following literal this optimization cannot be used. You can see the difference by comparing the behaviour of (a+)*\d - with the pattern above. The former gives a failure almost instantly - when applied to a whole line of "a" characters, whereas the latter + with the pattern above. The former gives a failure almost instantly + when applied to a whole line of "a" characters, whereas the latter takes an appreciable time with strings longer than about 20 characters. -Last updated: 03 February 2003 -Copyright (c) 1997-2003 University of Cambridge. ------------------------------------------------------------------------------ + In many cases, the solution to this kind of performance issue is to use + an atomic group or a possessive quantifier. + +Last updated: 28 February 2005 +Copyright (c) 1997-2005 University of Cambridge. +------------------------------------------------------------------------------ -PCRE(3) PCRE(3) +PCREPOSIX(3) PCREPOSIX(3) NAME PCRE - Perl-compatible regular expressions. + SYNOPSIS OF POSIX API + #include int regcomp(regex_t *preg, const char *pattern, @@ -2947,13 +4168,13 @@ DESCRIPTION This set of functions provides a POSIX-style API to the PCRE regular expression package. See the pcreapi documentation for a description of - the native API, which contains additional functionality. + PCRE's native API, which contains much additional functionality. The functions described here are just wrapper functions that ultimately call the PCRE native API. Their prototypes are defined in the pcreposix.h header file, and on Unix systems the library itself is called pcreposix.a, so can be accessed by adding -lpcreposix to the - command for linking an application which uses them. Because the POSIX + command for linking an application that uses them. Because the POSIX functions call the native ones, it is also necessary to add -lpcre. I have implemented only those option bits that can be reasonably mapped @@ -2985,12 +4206,18 @@ COMPILING A PATTERN The function regcomp() is called to compile a pattern into an internal form. The pattern is a C string terminated by a binary zero, and is passed in the argument pattern. The preg argument is a pointer to a - regex_t structure which is used as a base for storing information about + regex_t structure that is used as a base for storing information about the compiled expression. The argument cflags is either zero, or contains one or more of the bits defined by the following macros: + REG_DOTALL + + The PCRE_DOTALL option is set when the expression is passed for compi- + lation to the native function. Note that REG_DOTALL is not part of the + POSIX standard. + REG_ICASE The PCRE_CASELESS option is set when the expression is passed for com- @@ -3036,24 +4263,24 @@ MATCHING NEWLINE CHARACTERS Default Change with - . matches newline yes REG_NEWLINE - newline matches [^a] yes REG_NEWLINE - $ matches \n at end no REG_NEWLINE - $ matches \n in middle no REG_NEWLINE - ^ matches \n in middle no REG_NEWLINE + . matches newline yes REG_NEWLINE + newline matches [^a] yes REG_NEWLINE + $ matches \n at end no REG_NEWLINE + $ matches \n in middle no REG_NEWLINE + ^ matches \n in middle no REG_NEWLINE PCRE's behaviour is the same as Perl's, except that there is no equiva- - lent for PCRE_DOLLARENDONLY in Perl. In both PCRE and Perl, there is no - way to stop newline from matching [^a]. + lent for PCRE_DOLLAR_ENDONLY in Perl. In both PCRE and Perl, there is + no way to stop newline from matching [^a]. The default POSIX newline handling can be obtained by setting - PCRE_DOTALL and PCRE_DOLLARENDONLY, but there is no way to make PCRE + PCRE_DOTALL and PCRE_DOLLAR_ENDONLY, but there is no way to make PCRE behave exactly as for the REG_NEWLINE action. MATCHING A PATTERN - The function regexec() is called to match a pre-compiled pattern preg + The function regexec() is called to match a compiled pattern preg against a given string, which is terminated by a zero byte, subject to the options in eflags. These can be: @@ -3092,7 +4319,7 @@ ERROR MESSAGES tion is the size of buffer needed to hold the whole message. -STORAGE +MEMORY USAGE Compiling a regular expression causes memory to be allocated and asso- ciated with the preg structure. The function regfree() frees all such @@ -3102,21 +4329,326 @@ STORAGE AUTHOR - Philip Hazel + Philip Hazel University Computing Service, Cambridge CB2 3QG, England. -Last updated: 03 February 2003 -Copyright (c) 1997-2003 University of Cambridge. ------------------------------------------------------------------------------ +Last updated: 28 February 2005 +Copyright (c) 1997-2005 University of Cambridge. +------------------------------------------------------------------------------ -PCRE(3) PCRE(3) +PCRECPP(3) PCRECPP(3) + + +NAME + PCRE - Perl-compatible regular expressions. + + +SYNOPSIS OF C++ WRAPPER + + #include + + +DESCRIPTION + + The C++ wrapper for PCRE was provided by Google Inc. Some additional + functionality was added by Giuseppe Maxia. This brief man page was con- + structed from the notes in the pcrecpp.h file, which should be con- + sulted for further details. + + +MATCHING INTERFACE + + The "FullMatch" operation checks that supplied text matches a supplied + pattern exactly. If pointer arguments are supplied, it copies matched + sub-strings that match sub-patterns into them. + + Example: successful match + pcrecpp::RE re("h.*o"); + re.FullMatch("hello"); + + Example: unsuccessful match (requires full match): + pcrecpp::RE re("e"); + !re.FullMatch("hello"); + + Example: creating a temporary RE object: + pcrecpp::RE("h.*o").FullMatch("hello"); + + You can pass in a "const char*" or a "string" for "text". The examples + below tend to use a const char*. You can, as in the different examples + above, store the RE object explicitly in a variable or use a temporary + RE object. The examples below use one mode or the other arbitrarily. + Either could correctly be used for any of these examples. + + You must supply extra pointer arguments to extract matched subpieces. + + Example: extracts "ruby" into "s" and 1234 into "i" + int i; + string s; + pcrecpp::RE re("(\\w+):(\\d+)"); + re.FullMatch("ruby:1234", &s, &i); + + Example: does not try to extract any extra sub-patterns + re.FullMatch("ruby:1234", &s); + + Example: does not try to extract into NULL + re.FullMatch("ruby:1234", NULL, &i); + + Example: integer overflow causes failure + !re.FullMatch("ruby:1234567891234", NULL, &i); + + Example: fails because there aren't enough sub-patterns: + !pcrecpp::RE("\\w+:\\d+").FullMatch("ruby:1234", &s); + + Example: fails because string cannot be stored in integer + !pcrecpp::RE("(.*)").FullMatch("ruby", &i); + + The provided pointer arguments can be pointers to any scalar numeric + type, or one of: + + string (matched piece is copied to string) + StringPiece (StringPiece is mutated to point to matched piece) + T (where "bool T::ParseFrom(const char*, int)" exists) + NULL (the corresponding matched sub-pattern is not copied) + + The function returns true iff all of the following conditions are sat- + isfied: + + a. "text" matches "pattern" exactly; + + b. The number of matched sub-patterns is >= number of supplied + pointers; + + c. The "i"th argument has a suitable type for holding the + string captured as the "i"th sub-pattern. If you pass in + NULL for the "i"th argument, or pass fewer arguments than + number of sub-patterns, "i"th captured sub-pattern is + ignored. + + The matching interface supports at most 16 arguments per call. If you + need more, consider using the more general interface + pcrecpp::RE::DoMatch. See pcrecpp.h for the signature for DoMatch. + + +PARTIAL MATCHES + + You can use the "PartialMatch" operation when you want the pattern to + match any substring of the text. + + Example: simple search for a string: + pcrecpp::RE("ell").PartialMatch("hello"); + + Example: find first number in a string: + int number; + pcrecpp::RE re("(\\d+)"); + re.PartialMatch("x*100 + 20", &number); + assert(number == 100); + + +UTF-8 AND THE MATCHING INTERFACE + + By default, pattern and text are plain text, one byte per character. + The UTF8 flag, passed to the constructor, causes both pattern and + string to be treated as UTF-8 text, still a byte stream but potentially + multiple bytes per character. In practice, the text is likelier to be + UTF-8 than the pattern, but the match returned may depend on the UTF8 + flag, so always use it when matching UTF8 text. For example, "." will + match one byte normally but with UTF8 set may match up to three bytes + of a multi-byte character. + + Example: + pcrecpp::RE_Options options; + options.set_utf8(); + pcrecpp::RE re(utf8_pattern, options); + re.FullMatch(utf8_string); + + Example: using the convenience function UTF8(): + pcrecpp::RE re(utf8_pattern, pcrecpp::UTF8()); + re.FullMatch(utf8_string); + + NOTE: The UTF8 flag is ignored if pcre was not configured with the + --enable-utf8 flag. + + +PASSING MODIFIERS TO THE REGULAR EXPRESSION ENGINE + + PCRE defines some modifiers to change the behavior of the regular + expression engine. The C++ wrapper defines an auxiliary class, + RE_Options, as a vehicle to pass such modifiers to a RE class. Cur- + rently, the following modifiers are supported: + + modifier description Perl corresponding + + PCRE_CASELESS case insensitive match /i + PCRE_MULTILINE multiple lines match /m + PCRE_DOTALL dot matches newlines /s + PCRE_DOLLAR_ENDONLY $ matches only at end N/A + PCRE_EXTRA strict escape parsing N/A + PCRE_EXTENDED ignore whitespaces /x + PCRE_UTF8 handles UTF8 chars built-in + PCRE_UNGREEDY reverses * and *? N/A + PCRE_NO_AUTO_CAPTURE disables capturing parens N/A (*) + + (*) Both Perl and PCRE allow non capturing parentheses by means of the + "?:" modifier within the pattern itself. e.g. (?:ab|cd) does not cap- + ture, while (ab|cd) does. + + For a full account on how each modifier works, please check the PCRE + API reference page. + + For each modifier, there are two member functions whose name is made + out of the modifier in lowercase, without the "PCRE_" prefix. For + instance, PCRE_CASELESS is handled by + + bool caseless() + + which returns true if the modifier is set, and + + RE_Options & set_caseless(bool) + + which sets or unsets the modifier. Moreover, PCRE_CONFIG_MATCH_LIMIT + can be accessed through the set_match_limit() and match_limit() member + functions. Setting match_limit to a non-zero value will limit the exe- + cution of pcre to keep it from doing bad things like blowing the stack + or taking an eternity to return a result. A value of 5000 is good + enough to stop stack blowup in a 2MB thread stack. Setting match_limit + to zero disables match limiting. + + Normally, to pass one or more modifiers to a RE class, you declare a + RE_Options object, set the appropriate options, and pass this object to + a RE constructor. Example: + + RE_options opt; + opt.set_caseless(true); + if (RE("HELLO", opt).PartialMatch("hello world")) ... + + RE_options has two constructors. The default constructor takes no argu- + ments and creates a set of flags that are off by default. The optional + parameter option_flags is to facilitate transfer of legacy code from C + programs. This lets you do + + RE(pattern, + RE_Options(PCRE_CASELESS|PCRE_MULTILINE)).PartialMatch(str); + + However, new code is better off doing + + RE(pattern, + RE_Options().set_caseless(true).set_multiline(true)) + .PartialMatch(str); + + If you are going to pass one of the most used modifiers, there are some + convenience functions that return a RE_Options class with the appropri- + ate modifier already set: CASELESS(), UTF8(), MULTILINE(), DOTALL(), + and EXTENDED(). + + If you need to set several options at once, and you don't want to go + through the pains of declaring a RE_Options object and setting several + options, there is a parallel method that give you such ability on the + fly. You can concatenate several set_xxxxx() member functions, since + each of them returns a reference to its class object. For example, to + pass PCRE_CASELESS, PCRE_EXTENDED, and PCRE_MULTILINE to a RE with one + statement, you may write: + + RE(" ^ xyz \\s+ .* blah$", + RE_Options() + .set_caseless(true) + .set_extended(true) + .set_multiline(true)).PartialMatch(sometext); + + +SCANNING TEXT INCREMENTALLY + + The "Consume" operation may be useful if you want to repeatedly match + regular expressions at the front of a string and skip over them as they + match. This requires use of the "StringPiece" type, which represents a + sub-range of a real string. Like RE, StringPiece is defined in the + pcrecpp namespace. + + Example: read lines of the form "var = value" from a string. + string contents = ...; // Fill string somehow + pcrecpp::StringPiece input(contents); // Wrap in a StringPiece + + string var; + int value; + pcrecpp::RE re("(\\w+) = (\\d+)\n"); + while (re.Consume(&input, &var, &value)) { + ...; + } + + Each successful call to "Consume" will set "var/value", and also + advance "input" so it points past the matched text. + + The "FindAndConsume" operation is similar to "Consume" but does not + anchor your match at the beginning of the string. For example, you + could extract all words from a string by repeatedly calling + + pcrecpp::RE("(\\w+)").FindAndConsume(&input, &word) + + +PARSING HEX/OCTAL/C-RADIX NUMBERS + + By default, if you pass a pointer to a numeric value, the corresponding + text is interpreted as a base-10 number. You can instead wrap the + pointer with a call to one of the operators Hex(), Octal(), or CRadix() + to interpret the text in another base. The CRadix operator interprets + C-style "0" (base-8) and "0x" (base-16) prefixes, but defaults to + base-10. + + Example: + int a, b, c, d; + pcrecpp::RE re("(.*) (.*) (.*) (.*)"); + re.FullMatch("100 40 0100 0x40", + pcrecpp::Octal(&a), pcrecpp::Hex(&b), + pcrecpp::CRadix(&c), pcrecpp::CRadix(&d)); + + will leave 64 in a, b, c, and d. + + +REPLACING PARTS OF STRINGS + + You can replace the first match of "pattern" in "str" with "rewrite". + Within "rewrite", backslash-escaped digits (\1 to \9) can be used to + insert text matching corresponding parenthesized group from the pat- + tern. \0 in "rewrite" refers to the entire matching text. For example: + + string s = "yabba dabba doo"; + pcrecpp::RE("b+").Replace("d", &s); + + will leave "s" containing "yada dabba doo". The result is true if the + pattern matches and a replacement occurs, false otherwise. + + GlobalReplace is like Replace except that it replaces all occurrences + of the pattern in the string with the rewrite. Replacements are not + subject to re-matching. For example: + + string s = "yabba dabba doo"; + pcrecpp::RE("b+").GlobalReplace("d", &s); + + will leave "s" containing "yada dada doo". It returns the number of + replacements made. + + Extract is like Replace, except that if the pattern matches, "rewrite" + is copied into "out" (an additional argument) with substitutions. The + non-matching portions of "text" are ignored. Returns true iff a match + occurred and the extraction happened successfully; if no match occurs, + the string is left unaffected. + + +AUTHOR + + The C++ wrapper was contributed by Google Inc. + Copyright (c) 2005 Google Inc. +------------------------------------------------------------------------------ + + +PCRESAMPLE(3) PCRESAMPLE(3) NAME PCRE - Perl-compatible regular expressions + PCRE SAMPLE PROGRAM A simple, complete demonstration program, to get you started with using @@ -3134,24 +4666,34 @@ PCRE SAMPLE PROGRAM bility of matching an empty string. Comments in the code explain what is going on. - On a Unix system that has PCRE installed in /usr/local, you can compile - the demonstration program using a command like this: + If PCRE is installed in the standard include and library directories + for your system, you should be able to compile the demonstration pro- + gram using this command: + + gcc -o pcredemo pcredemo.c -lpcre - gcc -o pcredemo pcredemo.c -I/usr/local/include \ + If PCRE is installed elsewhere, you may need to add additional options + to the command line. For example, on a Unix-like system that has PCRE + installed in /usr/local, you can compile the demonstration program + using a command like this: + + gcc -o pcredemo -I/usr/local/include pcredemo.c \ -L/usr/local/lib -lpcre - Then you can run simple tests like this: + Once you have compiled the demonstration program, you can run simple + tests like this: ./pcredemo 'cat|dog' 'the cat sat on the mat' ./pcredemo -g 'cat|dog' 'the dog sat on the cat' - Note that there is a much more comprehensive test program, called - pcretest, which supports many more facilities for testing regular + Note that there is a much more comprehensive test program, called + pcretest, which supports many more facilities for testing regular expressions and the PCRE library. The pcredemo program is provided as a simple coding example. - On some operating systems (e.g. Solaris) you may get an error like this - when you try to run pcredemo: + On some operating systems (e.g. Solaris), when PCRE is not installed in + the standard library directory, you may get an error like this when you + try to run pcredemo: ld.so.1: a.out: fatal: libpcre.so.0: open failed: No such file or directory @@ -3161,9 +4703,8 @@ PCRE SAMPLE PROGRAM -R/usr/local/lib - to the compile command to get round this problem. - -Last updated: 28 January 2003 -Copyright (c) 1997-2003 University of Cambridge. ------------------------------------------------------------------------------ + (for example) to the compile command to get round this problem. +Last updated: 09 September 2004 +Copyright (c) 1997-2004 University of Cambridge. +------------------------------------------------------------------------------ diff --git a/ext/pcre/pcrelib/internal.h b/ext/pcre/pcrelib/internal.h index 544f1c273615..a3df3b5257bd 100644 --- a/ext/pcre/pcrelib/internal.h +++ b/ext/pcre/pcrelib/internal.h @@ -5,30 +5,38 @@ /* This is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. See -the file Tech.Notes for some information on the internals. +the file doc/Tech.Notes for some information on the internals. Written by: Philip Hazel - Copyright (c) 1997-2003 University of Cambridge + Copyright (c) 1997-2004 University of Cambridge ----------------------------------------------------------------------------- -Permission is granted to anyone to use this software for any purpose on any -computer system, and to redistribute it freely, subject to the following -restrictions: - -1. This software is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -2. The origin of this software must not be misrepresented, either by - explicit claim or by omission. - -3. Altered versions must be plainly marked as such, and must not be - misrepresented as being the original software. - -4. If PCRE is embedded in any software that is released under the GNU - General Purpose Licence (GPL), then the terms of that licence shall - supersede any condition above with which it is incompatible. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------------------- */ @@ -39,12 +47,22 @@ modules, but which are not relevant to the outside. */ #ifdef PHP_WIN32 # include "config.w32.h" -#elif defined(NETWARE) -# include "config.nw.h" #else -# include "php_config.h" +# include #endif +/* Standard C headers plus the external interface definition. The only time +setjmp and stdarg are used is when NO_RECURSE is set. */ + +#include +#include +#include +#include +#include +#include +#include +#include + #ifndef PCRE_SPY #define PCRE_DEFINITION /* Win32 __declspec(export) trigger for .dll */ #endif @@ -57,24 +75,45 @@ On Unix systems, "configure" can be used to override this default. */ #define NEWLINE '\n' #endif -/* The value of MATCH_LIMIT determines the default number of times the match() -function can be called during a single execution of pcre_exec(). (There is a -runtime method of setting a different limit.) The limit exists in order to -catch runaway regular expressions that take for ever to determine that they do -not match. The default is set very large so that it does not accidentally catch -legitimate cases. On Unix systems, "configure" can be used to override this -default default. */ - -#ifndef MATCH_LIMIT -#define MATCH_LIMIT 10000000 -#endif - /* If you are compiling for a system that needs some magic to be inserted * before the definition of an exported function, define this macro to contain * the relevant magic. It apears at the start of every exported function. */ #define EXPORT +/* We need to have types that specify unsigned 16-bit and 32-bit integers. We +cannot determine these outside the compilation (e.g. by running a program as +part of "configure") because PCRE is often cross-compiled for use on other +systems. Instead we make use of the maximum sizes that are available at +preprocessor time in standard C environments. */ + +#if USHRT_MAX == 65535 + typedef unsigned short pcre_uint16; +#elif UINT_MAX == 65535 + typedef unsigned int pcre_uint16; +#else + #error Cannot determine a type for 16-bit unsigned integers +#endif + +#if UINT_MAX == 4294967295 + typedef unsigned int pcre_uint32; +#elif ULONG_MAX == 4294967295 + typedef unsigned long int pcre_uint32; +#else + #error Cannot determine a type for 32-bit unsigned integers +#endif + +/* All character handling must be done as unsigned characters. Otherwise there +are problems with top-bit-set characters and functions such as isspace(). +However, we leave the interface to the outside world as char *, because that +should make things easier for callers. We define a short type for unsigned char +to save lots of typing. I tried "uchar", but it causes problems on Digital +Unix, where it is defined in sys/types, so use "uschar" instead. */ + +typedef unsigned char uschar; + +/* Include the public PCRE header */ + #include "pcre.h" /* When compiling for use with the Virtual Pascal compiler, these functions @@ -95,18 +134,6 @@ neither (there some non-Unix environments where this is the case). This assumes that all calls to memmove are moving strings upwards in store, which is the case in PCRE. */ -/* Standard C headers plus the external interface definition. The only time -setjmp and stdarg are used is when NO_RECURSE is set. */ - -#include -#include -#include -#include -#include -#include -#include -#include - #if ! HAVE_MEMMOVE #undef memmove /* some systems may have a macro */ #if HAVE_BCOPY @@ -126,13 +153,14 @@ for (i = 0; i < n; ++i) *(--dest) = *(--src); #endif /* not VPCOMPAT */ -/* PCRE keeps offsets in its compiled code as 2-byte quantities by default. -These are used, for example, to link from the start of a subpattern to its -alternatives and its end. The use of 2 bytes per offset limits the size of the -compiled regex to around 64K, which is big enough for almost everybody. -However, I received a request for an even bigger limit. For this reason, and -also to make the code easier to maintain, the storing and loading of offsets -from the byte string is now handled by the macros that are defined here. +/* PCRE keeps offsets in its compiled code as 2-byte quantities (always stored +in big-endian order) by default. These are used, for example, to link from the +start of a subpattern to its alternatives and its end. The use of 2 bytes per +offset limits the size of the compiled regex to around 64K, which is big enough +for almost everybody. However, I received a request for an even bigger limit. +For this reason, and also to make the code easier to maintain, the storing and +loading of offsets from the byte string is now handled by the macros that are +defined here. The macros are controlled by the value of LINK_SIZE. This defaults to 2 in the config.h file, but can be overridden by using -D on the command line. This @@ -208,6 +236,7 @@ Standard C system should have one. */ #define offsetof(p_type,field) ((size_t)&(((p_type *)0)->field)) #endif + /* These are the public options that can change during matching. */ #define PCRE_IMS (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL) @@ -216,12 +245,13 @@ Standard C system should have one. */ but skip the top bit so we can use ints for convenience without getting tangled with negative values. The public options defined in pcre.h start at the least significant end. Make sure they don't overlap, though now that we have expanded -to four bytes there is plenty of space. */ +to four bytes, there is plenty of space. */ #define PCRE_FIRSTSET 0x40000000 /* first_byte is set */ #define PCRE_REQCHSET 0x20000000 /* req_byte is set */ #define PCRE_STARTLINE 0x10000000 /* start after \n for multiline */ #define PCRE_ICHANGED 0x08000000 /* i option changes within regex */ +#define PCRE_NOPARTIAL 0x04000000 /* can't use partial with this regex */ /* Options for the "extra" block produced by pcre_study(). */ @@ -233,10 +263,11 @@ time, run time or study time, respectively. */ #define PUBLIC_OPTIONS \ (PCRE_CASELESS|PCRE_EXTENDED|PCRE_ANCHORED|PCRE_MULTILINE| \ PCRE_DOTALL|PCRE_DOLLAR_ENDONLY|PCRE_EXTRA|PCRE_UNGREEDY|PCRE_UTF8| \ - PCRE_NO_AUTO_CAPTURE|PCRE_NO_UTF8_CHECK) + PCRE_NO_AUTO_CAPTURE|PCRE_NO_UTF8_CHECK|PCRE_AUTO_CALLOUT) #define PUBLIC_EXEC_OPTIONS \ - (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY|PCRE_NO_UTF8_CHECK) + (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY|PCRE_NO_UTF8_CHECK| \ + PCRE_PARTIAL) #define PUBLIC_STUDY_OPTIONS 0 /* None defined */ @@ -296,12 +327,13 @@ definitions below, up to ESC_z. There's a dummy for OP_ANY because it corresponds to "." rather than an escape sequence. The final one must be ESC_REF as subsequent values are used for \1, \2, \3, etc. There is are two tests in the code for an escape greater than ESC_b and less than ESC_Z to -detect the types that may be repeated. These are the types that consume a -character. If any new escapes are put in between that don't consume a +detect the types that may be repeated. These are the types that consume +characters. If any new escapes are put in between that don't consume a character, that code will have to change. */ enum { ESC_A = 1, ESC_G, ESC_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s, ESC_W, - ESC_w, ESC_dum1, ESC_C, ESC_Z, ESC_z, ESC_E, ESC_Q, ESC_REF }; + ESC_w, ESC_dum1, ESC_C, ESC_P, ESC_p, ESC_X, ESC_Z, ESC_z, ESC_E, + ESC_Q, ESC_REF }; /* Flag bits and data types for the extended class (OP_XCLASS) for classes that contain UTF-8 characters with values greater than 255. */ @@ -312,6 +344,8 @@ contain UTF-8 characters with values greater than 255. */ #define XCL_END 0 /* Marks end of individual items */ #define XCL_SINGLE 1 /* Single item (one multibyte char) follows */ #define XCL_RANGE 2 /* A range (two multibyte chars) follows */ +#define XCL_PROP 3 /* Unicode property (one property code) follows */ +#define XCL_NOTPROP 4 /* Unicode inverted property (ditto) */ /* Opcode table: OP_BRA must be last, as all values >= it are used for brackets @@ -337,100 +371,112 @@ enum { OP_WORDCHAR, /* 10 \w */ OP_ANY, /* 11 Match any character */ OP_ANYBYTE, /* 12 Match any byte (\C); different to OP_ANY for UTF-8 */ - OP_EODN, /* 13 End of data or \n at end of data: \Z. */ - OP_EOD, /* 14 End of data: \z */ - - OP_OPT, /* 15 Set runtime options */ - OP_CIRC, /* 16 Start of line - varies with multiline switch */ - OP_DOLL, /* 17 End of line - varies with multiline switch */ - OP_CHARS, /* 18 Match string of characters */ - OP_NOT, /* 19 Match anything but the following char */ - - OP_STAR, /* 20 The maximizing and minimizing versions of */ - OP_MINSTAR, /* 21 all these opcodes must come in pairs, with */ - OP_PLUS, /* 22 the minimizing one second. */ - OP_MINPLUS, /* 23 This first set applies to single characters */ - OP_QUERY, /* 24 */ - OP_MINQUERY, /* 25 */ - OP_UPTO, /* 26 From 0 to n matches */ - OP_MINUPTO, /* 27 */ - OP_EXACT, /* 28 Exactly n matches */ - - OP_NOTSTAR, /* 29 The maximizing and minimizing versions of */ - OP_NOTMINSTAR, /* 30 all these opcodes must come in pairs, with */ - OP_NOTPLUS, /* 31 the minimizing one second. */ - OP_NOTMINPLUS, /* 32 This set applies to "not" single characters */ - OP_NOTQUERY, /* 33 */ - OP_NOTMINQUERY, /* 34 */ - OP_NOTUPTO, /* 35 From 0 to n matches */ - OP_NOTMINUPTO, /* 36 */ - OP_NOTEXACT, /* 37 Exactly n matches */ - - OP_TYPESTAR, /* 38 The maximizing and minimizing versions of */ - OP_TYPEMINSTAR, /* 39 all these opcodes must come in pairs, with */ - OP_TYPEPLUS, /* 40 the minimizing one second. These codes must */ - OP_TYPEMINPLUS, /* 41 be in exactly the same order as those above. */ - OP_TYPEQUERY, /* 42 This set applies to character types such as \d */ - OP_TYPEMINQUERY, /* 43 */ - OP_TYPEUPTO, /* 44 From 0 to n matches */ - OP_TYPEMINUPTO, /* 45 */ - OP_TYPEEXACT, /* 46 Exactly n matches */ - - OP_CRSTAR, /* 47 The maximizing and minimizing versions of */ - OP_CRMINSTAR, /* 48 all these opcodes must come in pairs, with */ - OP_CRPLUS, /* 49 the minimizing one second. These codes must */ - OP_CRMINPLUS, /* 50 be in exactly the same order as those above. */ - OP_CRQUERY, /* 51 These are for character classes and back refs */ - OP_CRMINQUERY, /* 52 */ - OP_CRRANGE, /* 53 These are different to the three seta above. */ - OP_CRMINRANGE, /* 54 */ - - OP_CLASS, /* 55 Match a character class, chars < 256 only */ - OP_NCLASS, /* 56 Same, but the bitmap was created from a negative + OP_NOTPROP, /* 13 \P (not Unicode property) */ + OP_PROP, /* 14 \p (Unicode property) */ + OP_EXTUNI, /* 15 \X (extended Unicode sequence */ + OP_EODN, /* 16 End of data or \n at end of data: \Z. */ + OP_EOD, /* 17 End of data: \z */ + + OP_OPT, /* 18 Set runtime options */ + OP_CIRC, /* 19 Start of line - varies with multiline switch */ + OP_DOLL, /* 20 End of line - varies with multiline switch */ + OP_CHAR, /* 21 Match one character, casefully */ + OP_CHARNC, /* 22 Match one character, caselessly */ + OP_NOT, /* 23 Match anything but the following char */ + + OP_STAR, /* 24 The maximizing and minimizing versions of */ + OP_MINSTAR, /* 25 all these opcodes must come in pairs, with */ + OP_PLUS, /* 26 the minimizing one second. */ + OP_MINPLUS, /* 27 This first set applies to single characters */ + OP_QUERY, /* 28 */ + OP_MINQUERY, /* 29 */ + OP_UPTO, /* 30 From 0 to n matches */ + OP_MINUPTO, /* 31 */ + OP_EXACT, /* 32 Exactly n matches */ + + OP_NOTSTAR, /* 33 The maximizing and minimizing versions of */ + OP_NOTMINSTAR, /* 34 all these opcodes must come in pairs, with */ + OP_NOTPLUS, /* 35 the minimizing one second. */ + OP_NOTMINPLUS, /* 36 This set applies to "not" single characters */ + OP_NOTQUERY, /* 37 */ + OP_NOTMINQUERY, /* 38 */ + OP_NOTUPTO, /* 39 From 0 to n matches */ + OP_NOTMINUPTO, /* 40 */ + OP_NOTEXACT, /* 41 Exactly n matches */ + + OP_TYPESTAR, /* 42 The maximizing and minimizing versions of */ + OP_TYPEMINSTAR, /* 43 all these opcodes must come in pairs, with */ + OP_TYPEPLUS, /* 44 the minimizing one second. These codes must */ + OP_TYPEMINPLUS, /* 45 be in exactly the same order as those above. */ + OP_TYPEQUERY, /* 46 This set applies to character types such as \d */ + OP_TYPEMINQUERY, /* 47 */ + OP_TYPEUPTO, /* 48 From 0 to n matches */ + OP_TYPEMINUPTO, /* 49 */ + OP_TYPEEXACT, /* 50 Exactly n matches */ + + OP_CRSTAR, /* 51 The maximizing and minimizing versions of */ + OP_CRMINSTAR, /* 52 all these opcodes must come in pairs, with */ + OP_CRPLUS, /* 53 the minimizing one second. These codes must */ + OP_CRMINPLUS, /* 54 be in exactly the same order as those above. */ + OP_CRQUERY, /* 55 These are for character classes and back refs */ + OP_CRMINQUERY, /* 56 */ + OP_CRRANGE, /* 57 These are different to the three sets above. */ + OP_CRMINRANGE, /* 58 */ + + OP_CLASS, /* 59 Match a character class, chars < 256 only */ + OP_NCLASS, /* 60 Same, but the bitmap was created from a negative class - the difference is relevant only when a UTF-8 character > 255 is encountered. */ - OP_XCLASS, /* 57 Extended class for handling UTF-8 chars within the + OP_XCLASS, /* 61 Extended class for handling UTF-8 chars within the class. This does both positive and negative. */ - OP_REF, /* 58 Match a back reference */ - OP_RECURSE, /* 59 Match a numbered subpattern (possibly recursive) */ - OP_CALLOUT, /* 60 Call out to external function if provided */ + OP_REF, /* 62 Match a back reference */ + OP_RECURSE, /* 63 Match a numbered subpattern (possibly recursive) */ + OP_CALLOUT, /* 64 Call out to external function if provided */ - OP_ALT, /* 61 Start of alternation */ - OP_KET, /* 62 End of group that doesn't have an unbounded repeat */ - OP_KETRMAX, /* 63 These two must remain together and in this */ - OP_KETRMIN, /* 64 order. They are for groups the repeat for ever. */ + OP_ALT, /* 65 Start of alternation */ + OP_KET, /* 66 End of group that doesn't have an unbounded repeat */ + OP_KETRMAX, /* 67 These two must remain together and in this */ + OP_KETRMIN, /* 68 order. They are for groups the repeat for ever. */ /* The assertions must come before ONCE and COND */ - OP_ASSERT, /* 65 Positive lookahead */ - OP_ASSERT_NOT, /* 66 Negative lookahead */ - OP_ASSERTBACK, /* 67 Positive lookbehind */ - OP_ASSERTBACK_NOT, /* 68 Negative lookbehind */ - OP_REVERSE, /* 69 Move pointer back - used in lookbehind assertions */ + OP_ASSERT, /* 69 Positive lookahead */ + OP_ASSERT_NOT, /* 70 Negative lookahead */ + OP_ASSERTBACK, /* 71 Positive lookbehind */ + OP_ASSERTBACK_NOT, /* 72 Negative lookbehind */ + OP_REVERSE, /* 73 Move pointer back - used in lookbehind assertions */ /* ONCE and COND must come after the assertions, with ONCE first, as there's a test for >= ONCE for a subpattern that isn't an assertion. */ - OP_ONCE, /* 70 Once matched, don't back up into the subpattern */ - OP_COND, /* 71 Conditional group */ - OP_CREF, /* 72 Used to hold an extraction string number (cond ref) */ + OP_ONCE, /* 74 Once matched, don't back up into the subpattern */ + OP_COND, /* 75 Conditional group */ + OP_CREF, /* 76 Used to hold an extraction string number (cond ref) */ - OP_BRAZERO, /* 73 These two must remain together and in this */ - OP_BRAMINZERO, /* 74 order. */ + OP_BRAZERO, /* 77 These two must remain together and in this */ + OP_BRAMINZERO, /* 78 order. */ - OP_BRANUMBER, /* 75 Used for extracting brackets whose number is greater + OP_BRANUMBER, /* 79 Used for extracting brackets whose number is greater than can fit into an opcode. */ - OP_BRA /* 76 This and greater values are used for brackets that - extract substrings up to a basic limit. After that, - use is made of OP_BRANUMBER. */ + OP_BRA /* 80 This and greater values are used for brackets that + extract substrings up to EXTRACT_BASIC_MAX. After + that, use is made of OP_BRANUMBER. */ }; -/* WARNING: There is an implicit assumption in study.c that all opcodes are -less than 128 in value. This makes handling UTF-8 character sequences easier. -*/ +/* WARNING WARNING WARNING: There is an implicit assumption in pcre.c and +study.c that all opcodes are less than 128 in value. This makes handling UTF-8 +character sequences easier. */ + +/* The highest extraction number before we have to start using additional +bytes. (Originally PCRE didn't have support for extraction counts highter than +this number.) The value is limited by the number of opcodes left after OP_BRA, +i.e. 255 - OP_BRA. We actually set it a bit lower to leave room for additional +opcodes. */ + +#define EXTRACT_BASIC_MAX 100 /* This macro defines textual names for all the opcodes. There are used only @@ -439,8 +485,10 @@ macro is referenced only in printint.c. */ #define OP_NAME_LIST \ "End", "\\A", "\\G", "\\B", "\\b", "\\D", "\\d", \ - "\\S", "\\s", "\\W", "\\w", "Any", "Anybyte", "\\Z", "\\z", \ - "Opt", "^", "$", "chars", "not", \ + "\\S", "\\s", "\\W", "\\w", "Any", "Anybyte", \ + "notprop", "prop", "extuni", \ + "\\Z", "\\z", \ + "Opt", "^", "$", "char", "charnc", "not", \ "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \ "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \ "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \ @@ -463,8 +511,11 @@ in UTF-8 mode. The code that uses this table must know about such things. */ #define OP_LENGTHS \ 1, /* End */ \ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* \A, \G, \B, \B, \D, \d, \S, \s, \W, \w */ \ - 1, 1, 1, 1, 2, 1, 1, /* Any, Anybyte, \Z, \z, Opt, ^, $ */ \ - 2, /* Chars - the minimum length */ \ + 1, 1, /* Any, Anybyte */ \ + 2, 2, 1, /* NOTPROP, PROP, EXTUNI */ \ + 1, 1, 2, 1, 1, /* \Z, \z, Opt, ^, $ */ \ + 2, /* Char - the minimum length */ \ + 2, /* Charnc - the minimum length */ \ 2, /* not */ \ /* Positive single-char repeats ** These are */ \ 2, 2, 2, 2, 2, 2, /* *, *?, +, +?, ?, ?? ** minima in */ \ @@ -483,7 +534,7 @@ in UTF-8 mode. The code that uses this table must know about such things. */ 0, /* XCLASS - variable length */ \ 3, /* REF */ \ 1+LINK_SIZE, /* RECURSE */ \ - 2, /* CALLOUT */ \ + 2+2*LINK_SIZE, /* CALLOUT */ \ 1+LINK_SIZE, /* Alt */ \ 1+LINK_SIZE, /* Ket */ \ 1+LINK_SIZE, /* KetRmax */ \ @@ -501,14 +552,6 @@ in UTF-8 mode. The code that uses this table must know about such things. */ 1+LINK_SIZE /* BRA */ \ -/* The highest extraction number before we have to start using additional -bytes. (Originally PCRE didn't have support for extraction counts highter than -this number.) The value is limited by the number of opcodes left after OP_BRA, -i.e. 255 - OP_BRA. We actually set it a bit lower to leave room for additional -opcodes. */ - -#define EXTRACT_BASIC_MAX 150 - /* A magic value for OP_CREF to indicate the "in recursion" condition. */ #define CREF_RECURSE 0xffff @@ -554,7 +597,7 @@ just to accommodate the POSIX wrapper. */ #define ERR34 "character value in \\x{...} sequence is too large" #define ERR35 "invalid condition (?(0)" #define ERR36 "\\C not allowed in lookbehind assertion" -#define ERR37 "PCRE does not support \\L, \\l, \\N, \\P, \\p, \\U, \\u, or \\X" +#define ERR37 "PCRE does not support \\L, \\l, \\N, \\U, or \\u" #define ERR38 "number after (?C is > 255" #define ERR39 "closing ) for (?C expected" #define ERR40 "recursive call could loop indefinitely" @@ -562,37 +605,51 @@ just to accommodate the POSIX wrapper. */ #define ERR42 "syntax error after (?P" #define ERR43 "two named groups have the same name" #define ERR44 "invalid UTF-8 string" - -/* All character handling must be done as unsigned characters. Otherwise there -are problems with top-bit-set characters and functions such as isspace(). -However, we leave the interface to the outside world as char *, because that -should make things easier for callers. We define a short type for unsigned char -to save lots of typing. I tried "uchar", but it causes problems on Digital -Unix, where it is defined in sys/types, so use "uschar" instead. */ - -typedef unsigned char uschar; +#define ERR45 "support for \\P, \\p, and \\X has not been compiled" +#define ERR46 "malformed \\P or \\p sequence" +#define ERR47 "unknown property name after \\P or \\p" /* The real format of the start of the pcre block; the index of names and the -code vector run on as long as necessary after the end. */ +code vector run on as long as necessary after the end. We store an explicit +offset to the name table so that if a regex is compiled on one host, saved, and +then run on another where the size of pointers is different, all might still +be well. For the case of compiled-on-4 and run-on-8, we include an extra +pointer that is always NULL. For future-proofing, we also include a few dummy +fields - even though you can never get this planning right! + +NOTE NOTE NOTE: +Because people can now save and re-use compiled patterns, any additions to this +structure should be made at the end, and something earlier (e.g. a new +flag in the options or one of the dummy fields) should indicate that the new +fields are present. Currently PCRE always sets the dummy fields to zero. +NOTE NOTE NOTE: +*/ typedef struct real_pcre { - unsigned long int magic_number; - size_t size; /* Total that was malloced */ - const unsigned char *tables; /* Pointer to tables */ - unsigned long int options; - unsigned short int top_bracket; - unsigned short int top_backref; - unsigned short int first_byte; - unsigned short int req_byte; - unsigned short int name_entry_size; /* Size of any name items; 0 => none */ - unsigned short int name_count; /* Number of name items */ + pcre_uint32 magic_number; + pcre_uint32 size; /* Total that was malloced */ + pcre_uint32 options; + pcre_uint32 dummy1; /* For future use, maybe */ + + pcre_uint16 top_bracket; + pcre_uint16 top_backref; + pcre_uint16 first_byte; + pcre_uint16 req_byte; + pcre_uint16 name_table_offset; /* Offset to name table that follows */ + pcre_uint16 name_entry_size; /* Size of any name items */ + pcre_uint16 name_count; /* Number of name items */ + pcre_uint16 dummy2; /* For future use, maybe */ + + const unsigned char *tables; /* Pointer to tables or NULL for std */ + const unsigned char *nullpad; /* NULL padding */ } real_pcre; -/* The format of the block used to store data from pcre_study(). */ +/* The format of the block used to store data from pcre_study(). The same +remark (see NOTE above) about extending this structure applies. */ typedef struct pcre_study_data { - size_t size; /* Total that was malloced */ - uschar options; + pcre_uint32 size; /* Total that was malloced */ + pcre_uint32 options; uschar start_bits[32]; } pcre_study_data; @@ -605,12 +662,14 @@ typedef struct compile_data { const uschar *cbits; /* Points to character type table */ const uschar *ctypes; /* Points to table of type maps */ const uschar *start_code; /* The start of the compiled code */ + const uschar *start_pattern; /* The start of the pattern */ uschar *name_table; /* The name/number table */ int names_found; /* Number of entries so far */ int name_entry_size; /* Size of each entry */ int top_backref; /* Maximum back reference */ unsigned int backref_map; /* Bitmap of low back refs */ int req_varyopt; /* "After variable item" flag for reqbyte */ + BOOL nopartial; /* Set TRUE if partial won't work */ } compile_data; /* Structure for maintaining a chain of pointers to the currently incomplete @@ -660,6 +719,8 @@ typedef struct match_data { BOOL utf8; /* UTF8 flag */ BOOL endonly; /* Dollar not before final \n */ BOOL notempty; /* Empty string match not wanted */ + BOOL partial; /* PARTIAL flag */ + BOOL hitend; /* Hit the end of the subject at some point */ const uschar *start_code; /* For use when recursing */ const uschar *start_subject; /* Start of the subject string */ const uschar *end_subject; /* End of the subject string */ diff --git a/ext/pcre/pcrelib/libpcre.def b/ext/pcre/pcrelib/libpcre.def new file mode 100644 index 000000000000..01db4bd22c44 --- /dev/null +++ b/ext/pcre/pcrelib/libpcre.def @@ -0,0 +1,20 @@ +LIBRARY libpcre +EXPORTS +pcre_malloc +pcre_free +pcre_config +pcre_callout +pcre_compile +pcre_copy_substring +pcre_dfa_exec +pcre_exec +pcre_get_substring +pcre_get_stringnumber +pcre_get_substring_list +pcre_free_substring +pcre_free_substring_list +pcre_info +pcre_fullinfo +pcre_maketables +pcre_study +pcre_version diff --git a/ext/pcre/pcrelib/libpcreposix.def b/ext/pcre/pcrelib/libpcreposix.def new file mode 100644 index 000000000000..5f3024796946 --- /dev/null +++ b/ext/pcre/pcrelib/libpcreposix.def @@ -0,0 +1,25 @@ +LIBRARY libpcreposix +EXPORTS +pcre_malloc +pcre_free +pcre_config +pcre_callout +pcre_compile +pcre_copy_substring +pcre_dfa_exec +pcre_exec +pcre_get_substring +pcre_get_stringnumber +pcre_get_substring_list +pcre_free_substring +pcre_free_substring_list +pcre_info +pcre_fullinfo +pcre_maketables +pcre_study +pcre_version + +regcomp +regexec +regerror +regfree diff --git a/ext/pcre/pcrelib/pcre.c b/ext/pcre/pcrelib/pcre.c deleted file mode 100644 index e50b9b69e361..000000000000 --- a/ext/pcre/pcrelib/pcre.c +++ /dev/null @@ -1,8304 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* -This is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. See -the file Tech.Notes for some information on the internals. - -Written by: Philip Hazel - - Copyright (c) 1997-2004 University of Cambridge - ------------------------------------------------------------------------------ -Permission is granted to anyone to use this software for any purpose on any -computer system, and to redistribute it freely, subject to the following -restrictions: - -1. This software is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -2. The origin of this software must not be misrepresented, either by - explicit claim or by omission. - -3. Altered versions must be plainly marked as such, and must not be - misrepresented as being the original software. - -4. If PCRE is embedded in any software that is released under the GNU - General Purpose Licence (GPL), then the terms of that licence shall - supersede any condition above with which it is incompatible. ------------------------------------------------------------------------------ -*/ - - -/* Define DEBUG to get debugging output on stdout. */ -/* #define DEBUG */ - -/* Use a macro for debugging printing, 'cause that eliminates the use of #ifdef -inline, and there are *still* stupid compilers about that don't like indented -pre-processor statements. I suppose it's only been 10 years... */ - -#ifdef DEBUG -#define DPRINTF(p) printf p -#else -#define DPRINTF(p) /*nothing*/ -#endif - -/* Include the internals header, which itself includes "config.h", the Standard -C headers, and the external pcre header. */ - -#include "internal.h" - - -/* Allow compilation as C++ source code, should anybody want to do that. */ - -#ifdef __cplusplus -#define class pcre_class -#endif - - -/* Maximum number of items on the nested bracket stacks at compile time. This -applies to the nesting of all kinds of parentheses. It does not limit -un-nested, non-capturing parentheses. This number can be made bigger if -necessary - it is used to dimension one int and one unsigned char vector at -compile time. */ - -#define BRASTACK_SIZE 200 - - -/* Maximum number of ints of offset to save on the stack for recursive calls. -If the offset vector is bigger, malloc is used. This should be a multiple of 3, -because the offset vector is always a multiple of 3 long. */ - -#define REC_STACK_SAVE_MAX 30 - - -/* The number of bytes in a literal character string above which we can't add -any more is set at 250 in order to allow for UTF-8 characters. (In theory it -could be 255 when UTF-8 support is excluded, but that means that some of the -test output would be different, which just complicates things.) */ - -#define MAXLIT 250 - - -/* The maximum remaining length of subject we are prepared to search for a -req_byte match. */ - -#define REQ_BYTE_MAX 1000 - - -/* Table of sizes for the fixed-length opcodes. It's defined in a macro so that -the definition is next to the definition of the opcodes in internal.h. */ - -static const uschar OP_lengths[] = { OP_LENGTHS }; - -/* Min and max values for the common repeats; for the maxima, 0 => infinity */ - -static const char rep_min[] = { 0, 0, 1, 1, 0, 0 }; -static const char rep_max[] = { 0, 0, 0, 0, 1, 1 }; - -/* Table for handling escaped characters in the range '0'-'z'. Positive returns -are simple data values; negative values are for special things like \d and so -on. Zero means further processing is needed (for things like \x), or the escape -is invalid. */ - -#if !EBCDIC /* This is the "normal" table for ASCII systems */ -static const short int escapes[] = { - 0, 0, 0, 0, 0, 0, 0, 0, /* 0 - 7 */ - 0, 0, ':', ';', '<', '=', '>', '?', /* 8 - ? */ - '@', -ESC_A, -ESC_B, -ESC_C, -ESC_D, -ESC_E, 0, -ESC_G, /* @ - G */ - 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ - 0, -ESC_Q, 0, -ESC_S, 0, 0, 0, -ESC_W, /* P - W */ - 0, 0, -ESC_Z, '[', '\\', ']', '^', '_', /* X - _ */ - '`', 7, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, /* ` - g */ - 0, 0, 0, 0, 0, 0, ESC_n, 0, /* h - o */ - 0, 0, ESC_r, -ESC_s, ESC_tee, 0, 0, -ESC_w, /* p - w */ - 0, 0, -ESC_z /* x - z */ -}; - -#else /* This is the "abnormal" table for EBCDIC systems */ -static const short int escapes[] = { -/* 48 */ 0, 0, 0, '.', '<', '(', '+', '|', -/* 50 */ '&', 0, 0, 0, 0, 0, 0, 0, -/* 58 */ 0, 0, '!', '$', '*', ')', ';', '~', -/* 60 */ '-', '/', 0, 0, 0, 0, 0, 0, -/* 68 */ 0, 0, '|', ',', '%', '_', '>', '?', -/* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, -/* 78 */ 0, '`', ':', '#', '@', '\'', '=', '"', -/* 80 */ 0, 7, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, -/* 88 */ 0, 0, 0, '{', 0, 0, 0, 0, -/* 90 */ 0, 0, 0, 'l', 0, ESC_n, 0, 0, -/* 98 */ 0, ESC_r, 0, '}', 0, 0, 0, 0, -/* A0 */ 0, '~', -ESC_s, ESC_tee, 0, 0, -ESC_w, 0, -/* A8 */ 0,-ESC_z, 0, 0, 0, '[', 0, 0, -/* B0 */ 0, 0, 0, 0, 0, 0, 0, 0, -/* B8 */ 0, 0, 0, 0, 0, ']', '=', '-', -/* C0 */ '{',-ESC_A, -ESC_B, -ESC_C, -ESC_D,-ESC_E, 0, -ESC_G, -/* C8 */ 0, 0, 0, 0, 0, 0, 0, 0, -/* D0 */ '}', 0, 0, 0, 0, 0, 0, 0, -/* D8 */-ESC_Q, 0, 0, 0, 0, 0, 0, 0, -/* E0 */ '\\', 0, -ESC_S, 0, 0, 0, -ESC_W, 0, -/* E8 */ 0,-ESC_Z, 0, 0, 0, 0, 0, 0, -/* F0 */ 0, 0, 0, 0, 0, 0, 0, 0, -/* F8 */ 0, 0, 0, 0, 0, 0, 0, 0 -}; -#endif - - -/* Tables of names of POSIX character classes and their lengths. The list is -terminated by a zero length entry. The first three must be alpha, upper, lower, -as this is assumed for handling case independence. */ - -static const char *const posix_names[] = { - "alpha", "lower", "upper", - "alnum", "ascii", "blank", "cntrl", "digit", "graph", - "print", "punct", "space", "word", "xdigit" }; - -static const uschar posix_name_lengths[] = { - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0 }; - -/* Table of class bit maps for each POSIX class; up to three may be combined -to form the class. The table for [:blank:] is dynamically modified to remove -the vertical space characters. */ - -static const int posix_class_maps[] = { - cbit_lower, cbit_upper, -1, /* alpha */ - cbit_lower, -1, -1, /* lower */ - cbit_upper, -1, -1, /* upper */ - cbit_digit, cbit_lower, cbit_upper, /* alnum */ - cbit_print, cbit_cntrl, -1, /* ascii */ - cbit_space, -1, -1, /* blank - a GNU extension */ - cbit_cntrl, -1, -1, /* cntrl */ - cbit_digit, -1, -1, /* digit */ - cbit_graph, -1, -1, /* graph */ - cbit_print, -1, -1, /* print */ - cbit_punct, -1, -1, /* punct */ - cbit_space, -1, -1, /* space */ - cbit_word, -1, -1, /* word - a Perl extension */ - cbit_xdigit,-1, -1 /* xdigit */ -}; - -/* Table to identify digits and hex digits. This is used when compiling -patterns. Note that the tables in chartables are dependent on the locale, and -may mark arbitrary characters as digits - but the PCRE compiling code expects -to handle only 0-9, a-z, and A-Z as digits when compiling. That is why we have -a private table here. It costs 256 bytes, but it is a lot faster than doing -character value tests (at least in some simple cases I timed), and in some -applications one wants PCRE to compile efficiently as well as match -efficiently. - -For convenience, we use the same bit definitions as in chartables: - - 0x04 decimal digit - 0x08 hexadecimal digit - -Then we can use ctype_digit and ctype_xdigit in the code. */ - -#if !EBCDIC /* This is the "normal" case, for ASCII systems */ -static const unsigned char digitab[] = - { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 8- 15 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - ' */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ( - / */ - 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, /* 0 - 7 */ - 0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00, /* 8 - ? */ - 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* @ - G */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* H - O */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* P - W */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* X - _ */ - 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* ` - g */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* h - o */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p - w */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* x -127 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */ - -#else /* This is the "abnormal" case, for EBCDIC systems */ -static const unsigned char digitab[] = - { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 0 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 8- 15 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 10 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 32- 39 20 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 40- 47 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 48- 55 30 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 56- 63 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - 71 40 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 72- | */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* & - 87 50 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 88- ¬ */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - -103 60 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 104- ? */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 112-119 70 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 120- " */ - 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* 128- g 80 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* h -143 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144- p 90 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* q -159 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160- x A0 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* y -175 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ^ -183 B0 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ - 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* { - G C0 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* H -207 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* } - P D0 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Q -223 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* \ - X E0 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Y -239 */ - 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, /* 0 - 7 F0 */ - 0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00};/* 8 -255 */ - -static const unsigned char ebcdic_chartab[] = { /* chartable partial dup */ - 0x80,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 0- 7 */ - 0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x00, /* 8- 15 */ - 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 16- 23 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ - 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 32- 39 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 40- 47 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 48- 55 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 56- 63 */ - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - 71 */ - 0x00,0x00,0x00,0x80,0x00,0x80,0x80,0x80, /* 72- | */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* & - 87 */ - 0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00, /* 88- ¬ */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - -103 */ - 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x80, /* 104- ? */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 112-119 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 120- " */ - 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* 128- g */ - 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* h -143 */ - 0x00,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* 144- p */ - 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* q -159 */ - 0x00,0x00,0x12,0x12,0x12,0x12,0x12,0x12, /* 160- x */ - 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* y -175 */ - 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ^ -183 */ - 0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ - 0x80,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* { - G */ - 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* H -207 */ - 0x00,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* } - P */ - 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* Q -223 */ - 0x00,0x00,0x12,0x12,0x12,0x12,0x12,0x12, /* \ - X */ - 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* Y -239 */ - 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */ - 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x00};/* 8 -255 */ -#endif - - -/* Definition to allow mutual recursion */ - -static BOOL - compile_regex(int, int, int *, uschar **, const uschar **, const char **, - BOOL, int, int *, int *, branch_chain *, compile_data *); - -/* Structure for building a chain of data that actually lives on the -stack, for holding the values of the subject pointer at the start of each -subpattern, so as to detect when an empty string has been matched by a -subpattern - to break infinite loops. When NO_RECURSE is set, these blocks -are on the heap, not on the stack. */ - -typedef struct eptrblock { - struct eptrblock *epb_prev; - const uschar *epb_saved_eptr; -} eptrblock; - -/* Flag bits for the match() function */ - -#define match_condassert 0x01 /* Called to check a condition assertion */ -#define match_isgroup 0x02 /* Set if start of bracketed group */ - -/* Non-error returns from the match() function. Error returns are externally -defined PCRE_ERROR_xxx codes, which are all negative. */ - -#define MATCH_MATCH 1 -#define MATCH_NOMATCH 0 - - - -/************************************************* -* Global variables * -*************************************************/ - -/* PCRE is thread-clean and doesn't use any global variables in the normal -sense. However, it calls memory allocation and free functions via the four -indirections below, and it can optionally do callouts. These values can be -changed by the caller, but are shared between all threads. However, when -compiling for Virtual Pascal, things are done differently (see pcre.in). */ - -#ifndef VPCOMPAT -#ifdef __cplusplus -extern "C" void *(*pcre_malloc)(size_t) = malloc; -extern "C" void (*pcre_free)(void *) = free; -extern "C" void *(*pcre_stack_malloc)(size_t) = malloc; -extern "C" void (*pcre_stack_free)(void *) = free; -extern "C" int (*pcre_callout)(pcre_callout_block *) = NULL; -#else -void *(*pcre_malloc)(size_t) = malloc; -void (*pcre_free)(void *) = free; -void *(*pcre_stack_malloc)(size_t) = malloc; -void (*pcre_stack_free)(void *) = free; -int (*pcre_callout)(pcre_callout_block *) = NULL; -#endif -#endif - - -/************************************************* -* Macros and tables for character handling * -*************************************************/ - -/* When UTF-8 encoding is being used, a character is no longer just a single -byte. The macros for character handling generate simple sequences when used in -byte-mode, and more complicated ones for UTF-8 characters. */ - -#ifndef SUPPORT_UTF8 -#define GETCHAR(c, eptr) c = *eptr; -#define GETCHARINC(c, eptr) c = *eptr++; -#define GETCHARINCTEST(c, eptr) c = *eptr++; -#define GETCHARLEN(c, eptr, len) c = *eptr; -#define BACKCHAR(eptr) - -#else /* SUPPORT_UTF8 */ - -/* Get the next UTF-8 character, not advancing the pointer. This is called when -we know we are in UTF-8 mode. */ - -#define GETCHAR(c, eptr) \ - c = *eptr; \ - if ((c & 0xc0) == 0xc0) \ - { \ - int gcii; \ - int gcaa = utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ - int gcss = 6*gcaa; \ - c = (c & utf8_table3[gcaa]) << gcss; \ - for (gcii = 1; gcii <= gcaa; gcii++) \ - { \ - gcss -= 6; \ - c |= (eptr[gcii] & 0x3f) << gcss; \ - } \ - } - -/* Get the next UTF-8 character, advancing the pointer. This is called when we -know we are in UTF-8 mode. */ - -#define GETCHARINC(c, eptr) \ - c = *eptr++; \ - if ((c & 0xc0) == 0xc0) \ - { \ - int gcaa = utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ - int gcss = 6*gcaa; \ - c = (c & utf8_table3[gcaa]) << gcss; \ - while (gcaa-- > 0) \ - { \ - gcss -= 6; \ - c |= (*eptr++ & 0x3f) << gcss; \ - } \ - } - -/* Get the next character, testing for UTF-8 mode, and advancing the pointer */ - -#define GETCHARINCTEST(c, eptr) \ - c = *eptr++; \ - if (md->utf8 && (c & 0xc0) == 0xc0) \ - { \ - int gcaa = utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ - int gcss = 6*gcaa; \ - c = (c & utf8_table3[gcaa]) << gcss; \ - while (gcaa-- > 0) \ - { \ - gcss -= 6; \ - c |= (*eptr++ & 0x3f) << gcss; \ - } \ - } - -/* Get the next UTF-8 character, not advancing the pointer, incrementing length -if there are extra bytes. This is called when we know we are in UTF-8 mode. */ - -#define GETCHARLEN(c, eptr, len) \ - c = *eptr; \ - if ((c & 0xc0) == 0xc0) \ - { \ - int gcii; \ - int gcaa = utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ - int gcss = 6*gcaa; \ - c = (c & utf8_table3[gcaa]) << gcss; \ - for (gcii = 1; gcii <= gcaa; gcii++) \ - { \ - gcss -= 6; \ - c |= (eptr[gcii] & 0x3f) << gcss; \ - } \ - len += gcaa; \ - } - -/* If the pointer is not at the start of a character, move it back until -it is. Called only in UTF-8 mode. */ - -#define BACKCHAR(eptr) while((*eptr & 0xc0) == 0x80) eptr--; - -#endif - - - -/************************************************* -* Default character tables * -*************************************************/ - -/* A default set of character tables is included in the PCRE binary. Its source -is built by the maketables auxiliary program, which uses the default C ctypes -functions, and put in the file chartables.c. These tables are used by PCRE -whenever the caller of pcre_compile() does not provide an alternate set of -tables. */ - -#include "chartables.c" - - - -#ifdef SUPPORT_UTF8 -/************************************************* -* Tables for UTF-8 support * -*************************************************/ - -/* These are the breakpoints for different numbers of bytes in a UTF-8 -character. */ - -static const int utf8_table1[] = - { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff}; - -/* These are the indicator bits and the mask for the data bits to set in the -first byte of a character, indexed by the number of additional bytes. */ - -static const int utf8_table2[] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}; -static const int utf8_table3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01}; - -/* Table of the number of extra characters, indexed by the first character -masked with 0x3f. The highest number for a valid UTF-8 character is in fact -0x3d. */ - -static const uschar utf8_table4[] = { - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 }; - - -/************************************************* -* Convert character value to UTF-8 * -*************************************************/ - -/* This function takes an integer value in the range 0 - 0x7fffffff -and encodes it as a UTF-8 character in 0 to 6 bytes. - -Arguments: - cvalue the character value - buffer pointer to buffer for result - at least 6 bytes long - -Returns: number of characters placed in the buffer -*/ - -static int -ord2utf8(int cvalue, uschar *buffer) -{ -register int i, j; -for (i = 0; i < sizeof(utf8_table1)/sizeof(int); i++) - if (cvalue <= utf8_table1[i]) break; -buffer += i; -for (j = i; j > 0; j--) - { - *buffer-- = 0x80 | (cvalue & 0x3f); - cvalue >>= 6; - } -*buffer = utf8_table2[i] | cvalue; -return i + 1; -} -#endif - - - -/************************************************* -* Print compiled regex * -*************************************************/ - -/* The code for doing this is held in a separate file that is also included in -pcretest.c. It defines a function called print_internals(). */ - -#ifdef DEBUG -#include "printint.c" -#endif - - - -/************************************************* -* Return version string * -*************************************************/ - -#define STRING(a) # a -#define XSTRING(s) STRING(s) - -EXPORT const char * -pcre_version(void) -{ -return XSTRING(PCRE_MAJOR) "." XSTRING(PCRE_MINOR) " " XSTRING(PCRE_DATE); -} - - - - -/************************************************* -* (Obsolete) Return info about compiled pattern * -*************************************************/ - -/* This is the original "info" function. It picks potentially useful data out -of the private structure, but its interface was too rigid. It remains for -backwards compatibility. The public options are passed back in an int - though -the re->options field has been expanded to a long int, all the public options -at the low end of it, and so even on 16-bit systems this will still be OK. -Therefore, I haven't changed the API for pcre_info(). - -Arguments: - external_re points to compiled code - optptr where to pass back the options - first_byte where to pass back the first character, - or -1 if multiline and all branches start ^, - or -2 otherwise - -Returns: number of capturing subpatterns - or negative values on error -*/ - -EXPORT int -pcre_info(const pcre *external_re, int *optptr, int *first_byte) -{ -const real_pcre *re = (const real_pcre *)external_re; -if (re == NULL) return PCRE_ERROR_NULL; -if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC; -if (optptr != NULL) *optptr = (int)(re->options & PUBLIC_OPTIONS); -if (first_byte != NULL) - *first_byte = ((re->options & PCRE_FIRSTSET) != 0)? re->first_byte : - ((re->options & PCRE_STARTLINE) != 0)? -1 : -2; -return re->top_bracket; -} - - - -/************************************************* -* Return info about compiled pattern * -*************************************************/ - -/* This is a newer "info" function which has an extensible interface so -that additional items can be added compatibly. - -Arguments: - external_re points to compiled code - extra_data points extra data, or NULL - what what information is required - where where to put the information - -Returns: 0 if data returned, negative on error -*/ - -EXPORT int -pcre_fullinfo(const pcre *external_re, const pcre_extra *extra_data, int what, - void *where) -{ -const real_pcre *re = (const real_pcre *)external_re; -const pcre_study_data *study = NULL; - -if (re == NULL || where == NULL) return PCRE_ERROR_NULL; -if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC; - -if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_STUDY_DATA) != 0) - study = (const pcre_study_data *)extra_data->study_data; - -switch (what) - { - case PCRE_INFO_OPTIONS: - *((unsigned long int *)where) = re->options & PUBLIC_OPTIONS; - break; - - case PCRE_INFO_SIZE: - *((size_t *)where) = re->size; - break; - - case PCRE_INFO_STUDYSIZE: - *((size_t *)where) = (study == NULL)? 0 : study->size; - break; - - case PCRE_INFO_CAPTURECOUNT: - *((int *)where) = re->top_bracket; - break; - - case PCRE_INFO_BACKREFMAX: - *((int *)where) = re->top_backref; - break; - - case PCRE_INFO_FIRSTBYTE: - *((int *)where) = - ((re->options & PCRE_FIRSTSET) != 0)? re->first_byte : - ((re->options & PCRE_STARTLINE) != 0)? -1 : -2; - break; - - case PCRE_INFO_FIRSTTABLE: - *((const uschar **)where) = - (study != NULL && (study->options & PCRE_STUDY_MAPPED) != 0)? - study->start_bits : NULL; - break; - - case PCRE_INFO_LASTLITERAL: - *((int *)where) = - ((re->options & PCRE_REQCHSET) != 0)? re->req_byte : -1; - break; - - case PCRE_INFO_NAMEENTRYSIZE: - *((int *)where) = re->name_entry_size; - break; - - case PCRE_INFO_NAMECOUNT: - *((int *)where) = re->name_count; - break; - - case PCRE_INFO_NAMETABLE: - *((const uschar **)where) = (const uschar *)re + sizeof(real_pcre); - break; - - default: return PCRE_ERROR_BADOPTION; - } - -return 0; -} - - - -/************************************************* -* Return info about what features are configured * -*************************************************/ - -/* This is function which has an extensible interface so that additional items -can be added compatibly. - -Arguments: - what what information is required - where where to put the information - -Returns: 0 if data returned, negative on error -*/ - -EXPORT int -pcre_config(int what, void *where) -{ -switch (what) - { - case PCRE_CONFIG_UTF8: -#ifdef SUPPORT_UTF8 - *((int *)where) = 1; -#else - *((int *)where) = 0; -#endif - break; - - case PCRE_CONFIG_NEWLINE: - *((int *)where) = NEWLINE; - break; - - case PCRE_CONFIG_LINK_SIZE: - *((int *)where) = LINK_SIZE; - break; - - case PCRE_CONFIG_POSIX_MALLOC_THRESHOLD: - *((int *)where) = POSIX_MALLOC_THRESHOLD; - break; - - case PCRE_CONFIG_MATCH_LIMIT: - *((unsigned int *)where) = MATCH_LIMIT; - break; - - case PCRE_CONFIG_STACKRECURSE: -#ifdef NO_RECURSE - *((int *)where) = 0; -#else - *((int *)where) = 1; -#endif - break; - - default: return PCRE_ERROR_BADOPTION; - } - -return 0; -} - - - -#ifdef DEBUG -/************************************************* -* Debugging function to print chars * -*************************************************/ - -/* Print a sequence of chars in printable format, stopping at the end of the -subject if the requested. - -Arguments: - p points to characters - length number to print - is_subject TRUE if printing from within md->start_subject - md pointer to matching data block, if is_subject is TRUE - -Returns: nothing -*/ - -static void -pchars(const uschar *p, int length, BOOL is_subject, match_data *md) -{ -int c; -if (is_subject && length > md->end_subject - p) length = md->end_subject - p; -while (length-- > 0) - if (isprint(c = *(p++))) printf("%c", c); else printf("\\x%02x", c); -} -#endif - - - - -/************************************************* -* Handle escapes * -*************************************************/ - -/* This function is called when a \ has been encountered. It either returns a -positive value for a simple escape such as \n, or a negative value which -encodes one of the more complicated things such as \d. When UTF-8 is enabled, -a positive value greater than 255 may be returned. On entry, ptr is pointing at -the \. On exit, it is on the final character of the escape sequence. - -Arguments: - ptrptr points to the pattern position pointer - errorptr points to the pointer to the error message - bracount number of previous extracting brackets - options the options bits - isclass TRUE if inside a character class - -Returns: zero or positive => a data character - negative => a special escape sequence - on error, errorptr is set -*/ - -static int -check_escape(const uschar **ptrptr, const char **errorptr, int bracount, - int options, BOOL isclass) -{ -const uschar *ptr = *ptrptr; -int c, i; - -/* If backslash is at the end of the pattern, it's an error. */ - -c = *(++ptr); -if (c == 0) *errorptr = ERR1; - -/* Non-alphamerics are literals. For digits or letters, do an initial lookup in -a table. A non-zero result is something that can be returned immediately. -Otherwise further processing may be required. */ - -#if !EBCDIC /* ASCII coding */ -else if (c < '0' || c > 'z') {} /* Not alphameric */ -else if ((i = escapes[c - '0']) != 0) c = i; - -#else /* EBCDIC coding */ -else if (c < 'a' || (ebcdic_chartab[c] & 0x0E) == 0) {} /* Not alphameric */ -else if ((i = escapes[c - 0x48]) != 0) c = i; -#endif - -/* Escapes that need further processing, or are illegal. */ - -else - { - const uschar *oldptr; - switch (c) - { - /* A number of Perl escapes are not handled by PCRE. We give an explicit - error. */ - - case 'l': - case 'L': - case 'N': - case 'p': - case 'P': - case 'u': - case 'U': - case 'X': - *errorptr = ERR37; - break; - - /* The handling of escape sequences consisting of a string of digits - starting with one that is not zero is not straightforward. By experiment, - the way Perl works seems to be as follows: - - Outside a character class, the digits are read as a decimal number. If the - number is less than 10, or if there are that many previous extracting - left brackets, then it is a back reference. Otherwise, up to three octal - digits are read to form an escaped byte. Thus \123 is likely to be octal - 123 (cf \0123, which is octal 012 followed by the literal 3). If the octal - value is greater than 377, the least significant 8 bits are taken. Inside a - character class, \ followed by a digit is always an octal number. */ - - case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': - - if (!isclass) - { - oldptr = ptr; - c -= '0'; - while ((digitab[ptr[1]] & ctype_digit) != 0) - c = c * 10 + *(++ptr) - '0'; - if (c < 10 || c <= bracount) - { - c = -(ESC_REF + c); - break; - } - ptr = oldptr; /* Put the pointer back and fall through */ - } - - /* Handle an octal number following \. If the first digit is 8 or 9, Perl - generates a binary zero byte and treats the digit as a following literal. - Thus we have to pull back the pointer by one. */ - - if ((c = *ptr) >= '8') - { - ptr--; - c = 0; - break; - } - - /* \0 always starts an octal number, but we may drop through to here with a - larger first octal digit. */ - - case '0': - c -= '0'; - while(i++ < 2 && ptr[1] >= '0' && ptr[1] <= '7') - c = c * 8 + *(++ptr) - '0'; - c &= 255; /* Take least significant 8 bits */ - break; - - /* \x is complicated when UTF-8 is enabled. \x{ddd} is a character number - which can be greater than 0xff, but only if the ddd are hex digits. */ - - case 'x': -#ifdef SUPPORT_UTF8 - if (ptr[1] == '{' && (options & PCRE_UTF8) != 0) - { - const uschar *pt = ptr + 2; - register int count = 0; - c = 0; - while ((digitab[*pt] & ctype_xdigit) != 0) - { - int cc = *pt++; - count++; -#if !EBCDIC /* ASCII coding */ - if (cc >= 'a') cc -= 32; /* Convert to upper case */ - c = c * 16 + cc - ((cc < 'A')? '0' : ('A' - 10)); -#else /* EBCDIC coding */ - if (cc >= 'a' && cc <= 'z') cc += 64; /* Convert to upper case */ - c = c * 16 + cc - ((cc >= '0')? '0' : ('A' - 10)); -#endif - } - if (*pt == '}') - { - if (c < 0 || count > 8) *errorptr = ERR34; - ptr = pt; - break; - } - /* If the sequence of hex digits does not end with '}', then we don't - recognize this construct; fall through to the normal \x handling. */ - } -#endif - - /* Read just a single hex char */ - - c = 0; - while (i++ < 2 && (digitab[ptr[1]] & ctype_xdigit) != 0) - { - int cc; /* Some compilers don't like ++ */ - cc = *(++ptr); /* in initializers */ -#if !EBCDIC /* ASCII coding */ - if (cc >= 'a') cc -= 32; /* Convert to upper case */ - c = c * 16 + cc - ((cc < 'A')? '0' : ('A' - 10)); -#else /* EBCDIC coding */ - if (cc <= 'z') cc += 64; /* Convert to upper case */ - c = c * 16 + cc - ((cc >= '0')? '0' : ('A' - 10)); -#endif - } - break; - - /* Other special escapes not starting with a digit are straightforward */ - - case 'c': - c = *(++ptr); - if (c == 0) - { - *errorptr = ERR2; - return 0; - } - - /* A letter is upper-cased; then the 0x40 bit is flipped. This coding - is ASCII-specific, but then the whole concept of \cx is ASCII-specific. - (However, an EBCDIC equivalent has now been added.) */ - -#if !EBCDIC /* ASCII coding */ - if (c >= 'a' && c <= 'z') c -= 32; - c ^= 0x40; -#else /* EBCDIC coding */ - if (c >= 'a' && c <= 'z') c += 64; - c ^= 0xC0; -#endif - break; - - /* PCRE_EXTRA enables extensions to Perl in the matter of escapes. Any - other alphameric following \ is an error if PCRE_EXTRA was set; otherwise, - for Perl compatibility, it is a literal. This code looks a bit odd, but - there used to be some cases other than the default, and there may be again - in future, so I haven't "optimized" it. */ - - default: - if ((options & PCRE_EXTRA) != 0) switch(c) - { - default: - *errorptr = ERR3; - break; - } - break; - } - } - -*ptrptr = ptr; -return c; -} - - - -/************************************************* -* Check for counted repeat * -*************************************************/ - -/* This function is called when a '{' is encountered in a place where it might -start a quantifier. It looks ahead to see if it really is a quantifier or not. -It is only a quantifier if it is one of the forms {ddd} {ddd,} or {ddd,ddd} -where the ddds are digits. - -Arguments: - p pointer to the first char after '{' - -Returns: TRUE or FALSE -*/ - -static BOOL -is_counted_repeat(const uschar *p) -{ -if ((digitab[*p++] & ctype_digit) == 0) return FALSE; -while ((digitab[*p] & ctype_digit) != 0) p++; -if (*p == '}') return TRUE; - -if (*p++ != ',') return FALSE; -if (*p == '}') return TRUE; - -if ((digitab[*p++] & ctype_digit) == 0) return FALSE; -while ((digitab[*p] & ctype_digit) != 0) p++; - -return (*p == '}'); -} - - - -/************************************************* -* Read repeat counts * -*************************************************/ - -/* Read an item of the form {n,m} and return the values. This is called only -after is_counted_repeat() has confirmed that a repeat-count quantifier exists, -so the syntax is guaranteed to be correct, but we need to check the values. - -Arguments: - p pointer to first char after '{' - minp pointer to int for min - maxp pointer to int for max - returned as -1 if no max - errorptr points to pointer to error message - -Returns: pointer to '}' on success; - current ptr on error, with errorptr set -*/ - -static const uschar * -read_repeat_counts(const uschar *p, int *minp, int *maxp, const char **errorptr) -{ -int min = 0; -int max = -1; - -while ((digitab[*p] & ctype_digit) != 0) min = min * 10 + *p++ - '0'; - -if (*p == '}') max = min; else - { - if (*(++p) != '}') - { - max = 0; - while((digitab[*p] & ctype_digit) != 0) max = max * 10 + *p++ - '0'; - if (max < min) - { - *errorptr = ERR4; - return p; - } - } - } - -/* Do paranoid checks, then fill in the required variables, and pass back the -pointer to the terminating '}'. */ - -if (min > 65535 || max > 65535) - *errorptr = ERR5; -else - { - *minp = min; - *maxp = max; - } -return p; -} - - - -/************************************************* -* Find first significant op code * -*************************************************/ - -/* This is called by several functions that scan a compiled expression looking -for a fixed first character, or an anchoring op code etc. It skips over things -that do not influence this. For some calls, a change of option is important. - -Arguments: - code pointer to the start of the group - options pointer to external options - optbit the option bit whose changing is significant, or - zero if none are - -Returns: pointer to the first significant opcode -*/ - -static const uschar* -first_significant_code(const uschar *code, int *options, int optbit) -{ -for (;;) - { - switch ((int)*code) - { - case OP_OPT: - if (optbit > 0 && ((int)code[1] & optbit) != (*options & optbit)) - *options = (int)code[1]; - code += 2; - break; - - case OP_ASSERT_NOT: - case OP_ASSERTBACK: - case OP_ASSERTBACK_NOT: - do code += GET(code, 1); while (*code == OP_ALT); - /* Fall through */ - - case OP_CALLOUT: - case OP_CREF: - case OP_BRANUMBER: - case OP_WORD_BOUNDARY: - case OP_NOT_WORD_BOUNDARY: - code += OP_lengths[*code]; - break; - - default: - return code; - } - } -/* Control never reaches here */ -} - - - - -/************************************************* -* Find the fixed length of a pattern * -*************************************************/ - -/* Scan a pattern and compute the fixed length of subject that will match it, -if the length is fixed. This is needed for dealing with backward assertions. -In UTF8 mode, the result is in characters rather than bytes. - -Arguments: - code points to the start of the pattern (the bracket) - options the compiling options - -Returns: the fixed length, or -1 if there is no fixed length, - or -2 if \C was encountered -*/ - -static int -find_fixedlength(uschar *code, int options) -{ -int length = -1; - -register int branchlength = 0; -register uschar *cc = code + 1 + LINK_SIZE; - -/* Scan along the opcodes for this branch. If we get to the end of the -branch, check the length against that of the other branches. */ - -for (;;) - { - int d; - register int op = *cc; - if (op >= OP_BRA) op = OP_BRA; - - switch (op) - { - case OP_BRA: - case OP_ONCE: - case OP_COND: - d = find_fixedlength(cc, options); - if (d < 0) return d; - branchlength += d; - do cc += GET(cc, 1); while (*cc == OP_ALT); - cc += 1 + LINK_SIZE; - break; - - /* Reached end of a branch; if it's a ket it is the end of a nested - call. If it's ALT it is an alternation in a nested call. If it is - END it's the end of the outer call. All can be handled by the same code. */ - - case OP_ALT: - case OP_KET: - case OP_KETRMAX: - case OP_KETRMIN: - case OP_END: - if (length < 0) length = branchlength; - else if (length != branchlength) return -1; - if (*cc != OP_ALT) return length; - cc += 1 + LINK_SIZE; - branchlength = 0; - break; - - /* Skip over assertive subpatterns */ - - case OP_ASSERT: - case OP_ASSERT_NOT: - case OP_ASSERTBACK: - case OP_ASSERTBACK_NOT: - do cc += GET(cc, 1); while (*cc == OP_ALT); - /* Fall through */ - - /* Skip over things that don't match chars */ - - case OP_REVERSE: - case OP_BRANUMBER: - case OP_CREF: - case OP_OPT: - case OP_CALLOUT: - case OP_SOD: - case OP_SOM: - case OP_EOD: - case OP_EODN: - case OP_CIRC: - case OP_DOLL: - case OP_NOT_WORD_BOUNDARY: - case OP_WORD_BOUNDARY: - cc += OP_lengths[*cc]; - break; - - /* Handle char strings. In UTF-8 mode we must count characters, not bytes. - This requires a scan of the string, unfortunately. We assume valid UTF-8 - strings, so all we do is reduce the length by one for every byte whose bits - are 10xxxxxx. */ - - case OP_CHARS: - branchlength += *(++cc); -#ifdef SUPPORT_UTF8 - if ((options & PCRE_UTF8) != 0) - for (d = 1; d <= *cc; d++) - if ((cc[d] & 0xc0) == 0x80) branchlength--; -#endif - cc += *cc + 1; - break; - - /* Handle exact repetitions. The count is already in characters, but we - need to skip over a multibyte character in UTF8 mode. */ - - case OP_EXACT: - branchlength += GET2(cc,1); - cc += 4; -#ifdef SUPPORT_UTF8 - if ((options & PCRE_UTF8) != 0) - { - while((*cc & 0x80) == 0x80) cc++; - } -#endif - break; - - case OP_TYPEEXACT: - branchlength += GET2(cc,1); - cc += 4; - break; - - /* Handle single-char matchers */ - - case OP_NOT_DIGIT: - case OP_DIGIT: - case OP_NOT_WHITESPACE: - case OP_WHITESPACE: - case OP_NOT_WORDCHAR: - case OP_WORDCHAR: - case OP_ANY: - branchlength++; - cc++; - break; - - /* The single-byte matcher isn't allowed */ - - case OP_ANYBYTE: - return -2; - - /* Check a class for variable quantification */ - -#ifdef SUPPORT_UTF8 - case OP_XCLASS: - cc += GET(cc, 1) - 33; - /* Fall through */ -#endif - - case OP_CLASS: - case OP_NCLASS: - cc += 33; - - switch (*cc) - { - case OP_CRSTAR: - case OP_CRMINSTAR: - case OP_CRQUERY: - case OP_CRMINQUERY: - return -1; - - case OP_CRRANGE: - case OP_CRMINRANGE: - if (GET2(cc,1) != GET2(cc,3)) return -1; - branchlength += GET2(cc,1); - cc += 5; - break; - - default: - branchlength++; - } - break; - - /* Anything else is variable length */ - - default: - return -1; - } - } -/* Control never gets here */ -} - - - - -/************************************************* -* Scan compiled regex for numbered bracket * -*************************************************/ - -/* This little function scans through a compiled pattern until it finds a -capturing bracket with the given number. - -Arguments: - code points to start of expression - utf8 TRUE in UTF-8 mode - number the required bracket number - -Returns: pointer to the opcode for the bracket, or NULL if not found -*/ - -static const uschar * -find_bracket(const uschar *code, BOOL utf8, int number) -{ -#ifndef SUPPORT_UTF8 -utf8 = utf8; /* Stop pedantic compilers complaining */ -#endif - -for (;;) - { - register int c = *code; - if (c == OP_END) return NULL; - else if (c == OP_CHARS) code += code[1] + OP_lengths[c]; - else if (c > OP_BRA) - { - int n = c - OP_BRA; - if (n > EXTRACT_BASIC_MAX) n = GET2(code, 2+LINK_SIZE); - if (n == number) return (uschar *)code; - code += OP_lengths[OP_BRA]; - } - else - { - code += OP_lengths[c]; - -#ifdef SUPPORT_UTF8 - - /* In UTF-8 mode, opcodes that are followed by a character may be followed - by a multi-byte character. The length in the table is a minimum, so we have - to scan along to skip the extra characters. All opcodes are less than 128, - so we can use relatively efficient code. */ - - if (utf8) switch(c) - { - case OP_EXACT: - case OP_UPTO: - case OP_MINUPTO: - case OP_STAR: - case OP_MINSTAR: - case OP_PLUS: - case OP_MINPLUS: - case OP_QUERY: - case OP_MINQUERY: - while ((*code & 0xc0) == 0x80) code++; - break; - - /* XCLASS is used for classes that cannot be represented just by a bit - map. This includes negated single high-valued characters. The length in - the table is zero; the actual length is stored in the compled code. */ - - case OP_XCLASS: - code += GET(code, 1) + 1; - break; - } -#endif - } - } -} - - - -/************************************************* -* Scan compiled regex for recursion reference * -*************************************************/ - -/* This little function scans through a compiled pattern until it finds an -instance of OP_RECURSE. - -Arguments: - code points to start of expression - utf8 TRUE in UTF-8 mode - -Returns: pointer to the opcode for OP_RECURSE, or NULL if not found -*/ - -static const uschar * -find_recurse(const uschar *code, BOOL utf8) -{ -#ifndef SUPPORT_UTF8 -utf8 = utf8; /* Stop pedantic compilers complaining */ -#endif - -for (;;) - { - register int c = *code; - if (c == OP_END) return NULL; - else if (c == OP_RECURSE) return code; - else if (c == OP_CHARS) code += code[1] + OP_lengths[c]; - else if (c > OP_BRA) - { - code += OP_lengths[OP_BRA]; - } - else - { - code += OP_lengths[c]; - -#ifdef SUPPORT_UTF8 - - /* In UTF-8 mode, opcodes that are followed by a character may be followed - by a multi-byte character. The length in the table is a minimum, so we have - to scan along to skip the extra characters. All opcodes are less than 128, - so we can use relatively efficient code. */ - - if (utf8) switch(c) - { - case OP_EXACT: - case OP_UPTO: - case OP_MINUPTO: - case OP_STAR: - case OP_MINSTAR: - case OP_PLUS: - case OP_MINPLUS: - case OP_QUERY: - case OP_MINQUERY: - while ((*code & 0xc0) == 0x80) code++; - break; - - /* XCLASS is used for classes that cannot be represented just by a bit - map. This includes negated single high-valued characters. The length in - the table is zero; the actual length is stored in the compled code. */ - - case OP_XCLASS: - code += GET(code, 1) + 1; - break; - } -#endif - } - } -} - - - -/************************************************* -* Scan compiled branch for non-emptiness * -*************************************************/ - -/* This function scans through a branch of a compiled pattern to see whether it -can match the empty string or not. It is called only from could_be_empty() -below. Note that first_significant_code() skips over assertions. If we hit an -unclosed bracket, we return "empty" - this means we've struck an inner bracket -whose current branch will already have been scanned. - -Arguments: - code points to start of search - endcode points to where to stop - utf8 TRUE if in UTF8 mode - -Returns: TRUE if what is matched could be empty -*/ - -static BOOL -could_be_empty_branch(const uschar *code, const uschar *endcode, BOOL utf8) -{ -register int c; -for (code = first_significant_code(code + 1 + LINK_SIZE, NULL, 0); - code < endcode; - code = first_significant_code(code + OP_lengths[c], NULL, 0)) - { - const uschar *ccode; - - c = *code; - - if (c >= OP_BRA) - { - BOOL empty_branch; - if (GET(code, 1) == 0) return TRUE; /* Hit unclosed bracket */ - - /* Scan a closed bracket */ - - empty_branch = FALSE; - do - { - if (!empty_branch && could_be_empty_branch(code, endcode, utf8)) - empty_branch = TRUE; - code += GET(code, 1); - } - while (*code == OP_ALT); - if (!empty_branch) return FALSE; /* All branches are non-empty */ - code += 1 + LINK_SIZE; - c = *code; - } - - else switch (c) - { - /* Check for quantifiers after a class */ - -#ifdef SUPPORT_UTF8 - case OP_XCLASS: - ccode = code + GET(code, 1); - goto CHECK_CLASS_REPEAT; -#endif - - case OP_CLASS: - case OP_NCLASS: - ccode = code + 33; - -#ifdef SUPPORT_UTF8 - CHECK_CLASS_REPEAT: -#endif - - switch (*ccode) - { - case OP_CRSTAR: /* These could be empty; continue */ - case OP_CRMINSTAR: - case OP_CRQUERY: - case OP_CRMINQUERY: - break; - - default: /* Non-repeat => class must match */ - case OP_CRPLUS: /* These repeats aren't empty */ - case OP_CRMINPLUS: - return FALSE; - - case OP_CRRANGE: - case OP_CRMINRANGE: - if (GET2(ccode, 1) > 0) return FALSE; /* Minimum > 0 */ - break; - } - break; - - /* Opcodes that must match a character */ - - case OP_NOT_DIGIT: - case OP_DIGIT: - case OP_NOT_WHITESPACE: - case OP_WHITESPACE: - case OP_NOT_WORDCHAR: - case OP_WORDCHAR: - case OP_ANY: - case OP_ANYBYTE: - case OP_CHARS: - case OP_NOT: - case OP_PLUS: - case OP_MINPLUS: - case OP_EXACT: - case OP_NOTPLUS: - case OP_NOTMINPLUS: - case OP_NOTEXACT: - case OP_TYPEPLUS: - case OP_TYPEMINPLUS: - case OP_TYPEEXACT: - return FALSE; - - /* End of branch */ - - case OP_KET: - case OP_KETRMAX: - case OP_KETRMIN: - case OP_ALT: - return TRUE; - - /* In UTF-8 mode, STAR, MINSTAR, QUERY, MINQUERY, UPTO, and MINUPTO may be - followed by a multibyte character */ - -#ifdef SUPPORT_UTF8 - case OP_STAR: - case OP_MINSTAR: - case OP_QUERY: - case OP_MINQUERY: - case OP_UPTO: - case OP_MINUPTO: - if (utf8) while ((code[2] & 0xc0) == 0x80) code++; - break; -#endif - } - } - -return TRUE; -} - - - -/************************************************* -* Scan compiled regex for non-emptiness * -*************************************************/ - -/* This function is called to check for left recursive calls. We want to check -the current branch of the current pattern to see if it could match the empty -string. If it could, we must look outwards for branches at other levels, -stopping when we pass beyond the bracket which is the subject of the recursion. - -Arguments: - code points to start of the recursion - endcode points to where to stop (current RECURSE item) - bcptr points to the chain of current (unclosed) branch starts - utf8 TRUE if in UTF-8 mode - -Returns: TRUE if what is matched could be empty -*/ - -static BOOL -could_be_empty(const uschar *code, const uschar *endcode, branch_chain *bcptr, - BOOL utf8) -{ -while (bcptr != NULL && bcptr->current >= code) - { - if (!could_be_empty_branch(bcptr->current, endcode, utf8)) return FALSE; - bcptr = bcptr->outer; - } -return TRUE; -} - - - -/************************************************* -* Check for POSIX class syntax * -*************************************************/ - -/* This function is called when the sequence "[:" or "[." or "[=" is -encountered in a character class. It checks whether this is followed by an -optional ^ and then a sequence of letters, terminated by a matching ":]" or -".]" or "=]". - -Argument: - ptr pointer to the initial [ - endptr where to return the end pointer - cd pointer to compile data - -Returns: TRUE or FALSE -*/ - -static BOOL -check_posix_syntax(const uschar *ptr, const uschar **endptr, compile_data *cd) -{ -int terminator; /* Don't combine these lines; the Solaris cc */ -terminator = *(++ptr); /* compiler warns about "non-constant" initializer. */ -if (*(++ptr) == '^') ptr++; -while ((cd->ctypes[*ptr] & ctype_letter) != 0) ptr++; -if (*ptr == terminator && ptr[1] == ']') - { - *endptr = ptr; - return TRUE; - } -return FALSE; -} - - - - -/************************************************* -* Check POSIX class name * -*************************************************/ - -/* This function is called to check the name given in a POSIX-style class entry -such as [:alnum:]. - -Arguments: - ptr points to the first letter - len the length of the name - -Returns: a value representing the name, or -1 if unknown -*/ - -static int -check_posix_name(const uschar *ptr, int len) -{ -register int yield = 0; -while (posix_name_lengths[yield] != 0) - { - if (len == posix_name_lengths[yield] && - strncmp((const char *)ptr, posix_names[yield], len) == 0) return yield; - yield++; - } -return -1; -} - - -/************************************************* -* Adjust OP_RECURSE items in repeated group * -*************************************************/ - -/* OP_RECURSE items contain an offset from the start of the regex to the group -that is referenced. This means that groups can be replicated for fixed -repetition simply by copying (because the recursion is allowed to refer to -earlier groups that are outside the current group). However, when a group is -optional (i.e. the minimum quantifier is zero), OP_BRAZERO is inserted before -it, after it has been compiled. This means that any OP_RECURSE items within it -that refer to the group itself or any contained groups have to have their -offsets adjusted. That is the job of this function. Before it is called, the -partially compiled regex must be temporarily terminated with OP_END. - -Arguments: - group points to the start of the group - adjust the amount by which the group is to be moved - utf8 TRUE in UTF-8 mode - cd contains pointers to tables etc. - -Returns: nothing -*/ - -static void -adjust_recurse(uschar *group, int adjust, BOOL utf8, compile_data *cd) -{ -uschar *ptr = group; -while ((ptr = (uschar *)find_recurse(ptr, utf8)) != NULL) - { - int offset = GET(ptr, 1); - if (cd->start_code + offset >= group) PUT(ptr, 1, offset + adjust); - ptr += 1 + LINK_SIZE; - } -} - - - -/************************************************* -* Compile one branch * -*************************************************/ - -/* Scan the pattern, compiling it into the code vector. If the options are -changed during the branch, the pointer is used to change the external options -bits. - -Arguments: - optionsptr pointer to the option bits - brackets points to number of extracting brackets used - code points to the pointer to the current code point - ptrptr points to the current pattern pointer - errorptr points to pointer to error message - firstbyteptr set to initial literal character, or < 0 (REQ_UNSET, REQ_NONE) - reqbyteptr set to the last literal character required, else < 0 - bcptr points to current branch chain - cd contains pointers to tables etc. - -Returns: TRUE on success - FALSE, with *errorptr set on error -*/ - -static BOOL -compile_branch(int *optionsptr, int *brackets, uschar **codeptr, - const uschar **ptrptr, const char **errorptr, int *firstbyteptr, - int *reqbyteptr, branch_chain *bcptr, compile_data *cd) -{ -int repeat_type, op_type; -int repeat_min = 0, repeat_max = 0; /* To please picky compilers */ -int bravalue = 0; -int length; -int greedy_default, greedy_non_default; -int firstbyte, reqbyte; -int zeroreqbyte, zerofirstbyte; -int req_caseopt, reqvary, tempreqvary; -int condcount = 0; -int options = *optionsptr; -register int c; -register uschar *code = *codeptr; -uschar *tempcode; -BOOL inescq = FALSE; -BOOL groupsetfirstbyte = FALSE; -const uschar *ptr = *ptrptr; -const uschar *tempptr; -uschar *previous = NULL; -uschar class[32]; - -#ifdef SUPPORT_UTF8 -BOOL class_utf8; -BOOL utf8 = (options & PCRE_UTF8) != 0; -uschar *class_utf8data; -uschar utf8_char[6]; -#else -BOOL utf8 = FALSE; -#endif - -/* Set up the default and non-default settings for greediness */ - -greedy_default = ((options & PCRE_UNGREEDY) != 0); -greedy_non_default = greedy_default ^ 1; - -/* Initialize no first char, no required char. REQ_UNSET means "no char -matching encountered yet". It gets changed to REQ_NONE if we hit something that -matches a non-fixed char first char; reqbyte just remains unset if we never -find one. - -When we hit a repeat whose minimum is zero, we may have to adjust these values -to take the zero repeat into account. This is implemented by setting them to -zerofirstbyte and zeroreqbyte when such a repeat is encountered. The individual -item types that can be repeated set these backoff variables appropriately. */ - -firstbyte = reqbyte = zerofirstbyte = zeroreqbyte = REQ_UNSET; - -/* The variable req_caseopt contains either the REQ_CASELESS value or zero, -according to the current setting of the caseless flag. REQ_CASELESS is a bit -value > 255. It is added into the firstbyte or reqbyte variables to record the -case status of the value. */ - -req_caseopt = ((options & PCRE_CASELESS) != 0)? REQ_CASELESS : 0; - -/* Switch on next character until the end of the branch */ - -for (;; ptr++) - { - BOOL negate_class; - BOOL possessive_quantifier; - int class_charcount; - int class_lastchar; - int newoptions; - int recno; - int skipbytes; - int subreqbyte; - int subfirstbyte; - - c = *ptr; - if (inescq && c != 0) goto NORMAL_CHAR; - - if ((options & PCRE_EXTENDED) != 0) - { - if ((cd->ctypes[c] & ctype_space) != 0) continue; - if (c == '#') - { - /* The space before the ; is to avoid a warning on a silly compiler - on the Macintosh. */ - while ((c = *(++ptr)) != 0 && c != NEWLINE) ; - if (c != 0) continue; /* Else fall through to handle end of string */ - } - } - - switch(c) - { - /* The branch terminates at end of string, |, or ). */ - - case 0: - case '|': - case ')': - *firstbyteptr = firstbyte; - *reqbyteptr = reqbyte; - *codeptr = code; - *ptrptr = ptr; - return TRUE; - - /* Handle single-character metacharacters. In multiline mode, ^ disables - the setting of any following char as a first character. */ - - case '^': - if ((options & PCRE_MULTILINE) != 0) - { - if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE; - } - previous = NULL; - *code++ = OP_CIRC; - break; - - case '$': - previous = NULL; - *code++ = OP_DOLL; - break; - - /* There can never be a first char if '.' is first, whatever happens about - repeats. The value of reqbyte doesn't change either. */ - - case '.': - if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE; - zerofirstbyte = firstbyte; - zeroreqbyte = reqbyte; - previous = code; - *code++ = OP_ANY; - break; - - /* Character classes. If the included characters are all < 255 in value, we - build a 32-byte bitmap of the permitted characters, except in the special - case where there is only one such character. For negated classes, we build - the map as usual, then invert it at the end. However, we use a different - opcode so that data characters > 255 can be handled correctly. - - If the class contains characters outside the 0-255 range, a different - opcode is compiled. It may optionally have a bit map for characters < 256, - but those above are are explicitly listed afterwards. A flag byte tells - whether the bitmap is present, and whether this is a negated class or not. - */ - - case '[': - previous = code; - - /* PCRE supports POSIX class stuff inside a class. Perl gives an error if - they are encountered at the top level, so we'll do that too. */ - - if ((ptr[1] == ':' || ptr[1] == '.' || ptr[1] == '=') && - check_posix_syntax(ptr, &tempptr, cd)) - { - *errorptr = (ptr[1] == ':')? ERR13 : ERR31; - goto FAILED; - } - - /* If the first character is '^', set the negation flag and skip it. */ - - if ((c = *(++ptr)) == '^') - { - negate_class = TRUE; - c = *(++ptr); - } - else - { - negate_class = FALSE; - } - - /* Keep a count of chars with values < 256 so that we can optimize the case - of just a single character (as long as it's < 256). For higher valued UTF-8 - characters, we don't yet do any optimization. */ - - class_charcount = 0; - class_lastchar = -1; - -#ifdef SUPPORT_UTF8 - class_utf8 = FALSE; /* No chars >= 256 */ - class_utf8data = code + LINK_SIZE + 34; /* For UTF-8 items */ -#endif - - /* Initialize the 32-char bit map to all zeros. We have to build the - map in a temporary bit of store, in case the class contains only 1 - character (< 256), because in that case the compiled code doesn't use the - bit map. */ - - memset(class, 0, 32 * sizeof(uschar)); - - /* Process characters until ] is reached. By writing this as a "do" it - means that an initial ] is taken as a data character. The first pass - through the regex checked the overall syntax, so we don't need to be very - strict here. At the start of the loop, c contains the first byte of the - character. */ - - do - { -#ifdef SUPPORT_UTF8 - if (utf8 && c > 127) - { /* Braces are required because the */ - GETCHARLEN(c, ptr, ptr); /* macro generates multiple statements */ - } -#endif - - /* Inside \Q...\E everything is literal except \E */ - - if (inescq) - { - if (c == '\\' && ptr[1] == 'E') - { - inescq = FALSE; - ptr++; - continue; - } - else goto LONE_SINGLE_CHARACTER; - } - - /* Handle POSIX class names. Perl allows a negation extension of the - form [:^name:]. A square bracket that doesn't match the syntax is - treated as a literal. We also recognize the POSIX constructions - [.ch.] and [=ch=] ("collating elements") and fault them, as Perl - 5.6 and 5.8 do. */ - - if (c == '[' && - (ptr[1] == ':' || ptr[1] == '.' || ptr[1] == '=') && - check_posix_syntax(ptr, &tempptr, cd)) - { - BOOL local_negate = FALSE; - int posix_class, i; - register const uschar *cbits = cd->cbits; - - if (ptr[1] != ':') - { - *errorptr = ERR31; - goto FAILED; - } - - ptr += 2; - if (*ptr == '^') - { - local_negate = TRUE; - ptr++; - } - - posix_class = check_posix_name(ptr, tempptr - ptr); - if (posix_class < 0) - { - *errorptr = ERR30; - goto FAILED; - } - - /* If matching is caseless, upper and lower are converted to - alpha. This relies on the fact that the class table starts with - alpha, lower, upper as the first 3 entries. */ - - if ((options & PCRE_CASELESS) != 0 && posix_class <= 2) - posix_class = 0; - - /* Or into the map we are building up to 3 of the static class - tables, or their negations. The [:blank:] class sets up the same - chars as the [:space:] class (all white space). We remove the vertical - white space chars afterwards. */ - - posix_class *= 3; - for (i = 0; i < 3; i++) - { - BOOL blankclass = strncmp((char *)ptr, "blank", 5) == 0; - int taboffset = posix_class_maps[posix_class + i]; - if (taboffset < 0) break; - if (local_negate) - { - for (c = 0; c < 32; c++) class[c] |= ~cbits[c+taboffset]; - if (blankclass) class[1] |= 0x3c; - } - else - { - for (c = 0; c < 32; c++) class[c] |= cbits[c+taboffset]; - if (blankclass) class[1] &= ~0x3c; - } - } - - ptr = tempptr + 1; - class_charcount = 10; /* Set > 1; assumes more than 1 per class */ - continue; /* End of POSIX syntax handling */ - } - - /* Backslash may introduce a single character, or it may introduce one - of the specials, which just set a flag. Escaped items are checked for - validity in the pre-compiling pass. The sequence \b is a special case. - Inside a class (and only there) it is treated as backspace. Elsewhere - it marks a word boundary. Other escapes have preset maps ready to - or into the one we are building. We assume they have more than one - character in them, so set class_charcount bigger than one. */ - - if (c == '\\') - { - c = check_escape(&ptr, errorptr, *brackets, options, TRUE); - if (-c == ESC_b) c = '\b'; /* \b is backslash in a class */ - - if (-c == ESC_Q) /* Handle start of quoted string */ - { - if (ptr[1] == '\\' && ptr[2] == 'E') - { - ptr += 2; /* avoid empty string */ - } - else inescq = TRUE; - continue; - } - - else if (c < 0) - { - register const uschar *cbits = cd->cbits; - class_charcount = 10; /* Greater than 1 is what matters */ - switch (-c) - { - case ESC_d: - for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_digit]; - continue; - - case ESC_D: - for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_digit]; - continue; - - case ESC_w: - for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_word]; - continue; - - case ESC_W: - for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_word]; - continue; - - case ESC_s: - for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_space]; - class[1] &= ~0x08; /* Perl 5.004 onwards omits VT from \s */ - continue; - - case ESC_S: - for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_space]; - class[1] |= 0x08; /* Perl 5.004 onwards omits VT from \s */ - continue; - - /* Unrecognized escapes are faulted if PCRE is running in its - strict mode. By default, for compatibility with Perl, they are - treated as literals. */ - - default: - if ((options & PCRE_EXTRA) != 0) - { - *errorptr = ERR7; - goto FAILED; - } - c = *ptr; /* The final character */ - } - } - - /* Fall through if we have a single character (c >= 0). This may be - > 256 in UTF-8 mode. */ - - } /* End of backslash handling */ - - /* A single character may be followed by '-' to form a range. However, - Perl does not permit ']' to be the end of the range. A '-' character - here is treated as a literal. */ - - if (ptr[1] == '-' && ptr[2] != ']') - { - int d; - ptr += 2; - -#ifdef SUPPORT_UTF8 - if (utf8) - { /* Braces are required because the */ - GETCHARLEN(d, ptr, ptr); /* macro generates multiple statements */ - } - else -#endif - d = *ptr; - - /* The second part of a range can be a single-character escape, but - not any of the other escapes. Perl 5.6 treats a hyphen as a literal - in such circumstances. */ - - if (d == '\\') - { - const uschar *oldptr = ptr; - d = check_escape(&ptr, errorptr, *brackets, options, TRUE); - - /* \b is backslash; any other special means the '-' was literal */ - - if (d < 0) - { - if (d == -ESC_b) d = '\b'; else - { - ptr = oldptr - 2; - goto LONE_SINGLE_CHARACTER; /* A few lines below */ - } - } - } - - /* Check that the two values are in the correct order */ - - if (d < c) - { - *errorptr = ERR8; - goto FAILED; - } - - /* If d is greater than 255, we can't just use the bit map, so set up - for the UTF-8 supporting class type. If we are not caseless, we can - just set up a single range. If we are caseless, the characters < 256 - are handled with a bitmap, in order to get the case-insensitive - handling. */ - -#ifdef SUPPORT_UTF8 - if (d > 255) - { - class_utf8 = TRUE; - *class_utf8data++ = XCL_RANGE; - if ((options & PCRE_CASELESS) == 0) - { - class_utf8data += ord2utf8(c, class_utf8data); - class_utf8data += ord2utf8(d, class_utf8data); - continue; /* Go get the next char in the class */ - } - class_utf8data += ord2utf8(256, class_utf8data); - class_utf8data += ord2utf8(d, class_utf8data); - d = 255; - /* Fall through */ - } -#endif - /* We use the bit map if the range is entirely < 255, or if part of it - is < 255 and matching is caseless. */ - - for (; c <= d; c++) - { - class[c/8] |= (1 << (c&7)); - if ((options & PCRE_CASELESS) != 0) - { - int uc = cd->fcc[c]; /* flip case */ - class[uc/8] |= (1 << (uc&7)); - } - class_charcount++; /* in case a one-char range */ - class_lastchar = c; - } - - continue; /* Go get the next char in the class */ - } - - /* Handle a lone single character - we can get here for a normal - non-escape char, or after \ that introduces a single character. */ - - LONE_SINGLE_CHARACTER: - - /* Handle a multibyte character */ - -#ifdef SUPPORT_UTF8 - if (utf8 && c > 255) - { - class_utf8 = TRUE; - *class_utf8data++ = XCL_SINGLE; - class_utf8data += ord2utf8(c, class_utf8data); - } - else -#endif - /* Handle a single-byte character */ - { - class [c/8] |= (1 << (c&7)); - if ((options & PCRE_CASELESS) != 0) - { - c = cd->fcc[c]; /* flip case */ - class[c/8] |= (1 << (c&7)); - } - class_charcount++; - class_lastchar = c; - } - } - - /* Loop until ']' reached; the check for end of string happens inside the - loop. This "while" is the end of the "do" above. */ - - while ((c = *(++ptr)) != ']' || inescq); - - /* If class_charcount is 1, we saw precisely one character with a value < - 256. In UTF-8 mode, we can optimize if there were no characters >= 256 and - the one character is < 128. In non-UTF-8 mode we can always optimize. - - The optimization throws away the bit map. We turn the item into a - 1-character OP_CHARS if it's positive, or OP_NOT if it's negative. Note - that OP_NOT does not support multibyte characters. In the positive case, it - can cause firstbyte to be set. Otherwise, there can be no first char if - this item is first, whatever repeat count may follow. In the case of - reqbyte, save the previous value for reinstating. */ - -#ifdef SUPPORT_UTF8 - if (class_charcount == 1 && - (!utf8 || - (!class_utf8 && class_lastchar < 128))) -#else - if (class_charcount == 1) -#endif - { - zeroreqbyte = reqbyte; - if (negate_class) - { - if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE; - zerofirstbyte = firstbyte; - *code++ = OP_NOT; - } - else - { - if (firstbyte == REQ_UNSET) - { - zerofirstbyte = REQ_NONE; - firstbyte = class_lastchar | req_caseopt; - } - else - { - zerofirstbyte = firstbyte; - reqbyte = class_lastchar | req_caseopt | cd->req_varyopt; - } - *code++ = OP_CHARS; - *code++ = 1; - } - *code++ = class_lastchar; - break; /* End of class handling */ - } /* End of 1-byte optimization */ - - /* Otherwise, if this is the first thing in the branch, there can be no - first char setting, whatever the repeat count. Any reqbyte setting must - remain unchanged after any kind of repeat. */ - - if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE; - zerofirstbyte = firstbyte; - zeroreqbyte = reqbyte; - - /* If there are characters with values > 255, we have to compile an - extended class, with its own opcode. If there are no characters < 256, - we can omit the bitmap. */ - -#ifdef SUPPORT_UTF8 - if (class_utf8) - { - *class_utf8data++ = XCL_END; /* Marks the end of extra data */ - *code++ = OP_XCLASS; - code += LINK_SIZE; - *code = negate_class? XCL_NOT : 0; - - /* If the map is required, install it, and move on to the end of - the extra data */ - - if (class_charcount > 0) - { - *code++ |= XCL_MAP; - memcpy(code, class, 32); - code = class_utf8data; - } - - /* If the map is not required, slide down the extra data. */ - - else - { - int len = class_utf8data - (code + 33); - memmove(code + 1, code + 33, len); - code += len + 1; - } - - /* Now fill in the complete length of the item */ - - PUT(previous, 1, code - previous); - break; /* End of class handling */ - } -#endif - - /* If there are no characters > 255, negate the 32-byte map if necessary, - and copy it into the code vector. If this is the first thing in the branch, - there can be no first char setting, whatever the repeat count. Any reqbyte - setting must remain unchanged after any kind of repeat. */ - - if (negate_class) - { - *code++ = OP_NCLASS; - for (c = 0; c < 32; c++) code[c] = ~class[c]; - } - else - { - *code++ = OP_CLASS; - memcpy(code, class, 32); - } - code += 32; - break; - - /* Various kinds of repeat */ - - case '{': - if (!is_counted_repeat(ptr+1)) goto NORMAL_CHAR; - ptr = read_repeat_counts(ptr+1, &repeat_min, &repeat_max, errorptr); - if (*errorptr != NULL) goto FAILED; - goto REPEAT; - - case '*': - repeat_min = 0; - repeat_max = -1; - goto REPEAT; - - case '+': - repeat_min = 1; - repeat_max = -1; - goto REPEAT; - - case '?': - repeat_min = 0; - repeat_max = 1; - - REPEAT: - if (previous == NULL) - { - *errorptr = ERR9; - goto FAILED; - } - - if (repeat_min == 0) - { - firstbyte = zerofirstbyte; /* Adjust for zero repeat */ - reqbyte = zeroreqbyte; /* Ditto */ - } - - /* Remember whether this is a variable length repeat */ - - reqvary = (repeat_min == repeat_max)? 0 : REQ_VARY; - - op_type = 0; /* Default single-char op codes */ - possessive_quantifier = FALSE; /* Default not possessive quantifier */ - - /* Save start of previous item, in case we have to move it up to make space - for an inserted OP_ONCE for the additional '+' extension. */ - - tempcode = previous; - - /* If the next character is '+', we have a possessive quantifier. This - implies greediness, whatever the setting of the PCRE_UNGREEDY option. - If the next character is '?' this is a minimizing repeat, by default, - but if PCRE_UNGREEDY is set, it works the other way round. We change the - repeat type to the non-default. */ - - if (ptr[1] == '+') - { - repeat_type = 0; /* Force greedy */ - possessive_quantifier = TRUE; - ptr++; - } - else if (ptr[1] == '?') - { - repeat_type = greedy_non_default; - ptr++; - } - else repeat_type = greedy_default; - - /* If previous was a recursion, we need to wrap it inside brackets so that - it can be replicated if necessary. */ - - if (*previous == OP_RECURSE) - { - memmove(previous + 1 + LINK_SIZE, previous, 1 + LINK_SIZE); - code += 1 + LINK_SIZE; - *previous = OP_BRA; - PUT(previous, 1, code - previous); - *code = OP_KET; - PUT(code, 1, code - previous); - code += 1 + LINK_SIZE; - } - - /* If previous was a string of characters, chop off the last one and use it - as the subject of the repeat. If there was only one character, we can - abolish the previous item altogether. If a one-char item has a minumum of - more than one, ensure that it is set in reqbyte - it might not be if a - sequence such as x{3} is the first thing in a branch because the x will - have gone into firstbyte instead. */ - - if (*previous == OP_CHARS) - { - /* Deal with UTF-8 characters that take up more than one byte. It's - easier to write this out separately than try to macrify it. Use c to - hold the length of the character in bytes, plus 0x80 to flag that it's a - length rather than a small character. */ - -#ifdef SUPPORT_UTF8 - if (utf8 && (code[-1] & 0x80) != 0) - { - uschar *lastchar = code - 1; - while((*lastchar & 0xc0) == 0x80) lastchar--; - c = code - lastchar; /* Length of UTF-8 character */ - memcpy(utf8_char, lastchar, c); /* Save the char */ - if (lastchar == previous + 2) /* There was only one character */ - { - code = previous; /* Abolish the previous item */ - } - else - { - previous[1] -= c; /* Adjust length of previous */ - code = lastchar; /* Lost char off the end */ - tempcode = code; /* Adjust position to be moved for '+' */ - } - c |= 0x80; /* Flag c as a length */ - } - else -#endif - - /* Handle the case of a single byte - either with no UTF8 support, or - with UTF-8 disabled, or for a UTF-8 character < 128. */ - - { - c = *(--code); - if (code == previous + 2) /* There was only one character */ - { - code = previous; /* Abolish the previous item */ - if (repeat_min > 1) reqbyte = c | req_caseopt | cd->req_varyopt; - } - else - { - previous[1]--; /* adjust length */ - tempcode = code; /* Adjust position to be moved for '+' */ - } - } - - goto OUTPUT_SINGLE_REPEAT; /* Code shared with single character types */ - } - - /* If previous was a single negated character ([^a] or similar), we use - one of the special opcodes, replacing it. The code is shared with single- - character repeats by setting opt_type to add a suitable offset into - repeat_type. OP_NOT is currently used only for single-byte chars. */ - - else if (*previous == OP_NOT) - { - op_type = OP_NOTSTAR - OP_STAR; /* Use "not" opcodes */ - c = previous[1]; - code = previous; - goto OUTPUT_SINGLE_REPEAT; - } - - /* If previous was a character type match (\d or similar), abolish it and - create a suitable repeat item. The code is shared with single-character - repeats by setting op_type to add a suitable offset into repeat_type. */ - - else if (*previous < OP_EODN) - { - op_type = OP_TYPESTAR - OP_STAR; /* Use type opcodes */ - c = *previous; - code = previous; - - OUTPUT_SINGLE_REPEAT: - - /* If the maximum is zero then the minimum must also be zero; Perl allows - this case, so we do too - by simply omitting the item altogether. */ - - if (repeat_max == 0) goto END_REPEAT; - - /* Combine the op_type with the repeat_type */ - - repeat_type += op_type; - - /* A minimum of zero is handled either as the special case * or ?, or as - an UPTO, with the maximum given. */ - - if (repeat_min == 0) - { - if (repeat_max == -1) *code++ = OP_STAR + repeat_type; - else if (repeat_max == 1) *code++ = OP_QUERY + repeat_type; - else - { - *code++ = OP_UPTO + repeat_type; - PUT2INC(code, 0, repeat_max); - } - } - - /* The case {1,} is handled as the special case + */ - - else if (repeat_min == 1 && repeat_max == -1) - *code++ = OP_PLUS + repeat_type; - - /* The case {n,n} is just an EXACT, while the general case {n,m} is - handled as an EXACT followed by an UPTO. An EXACT of 1 is optimized. */ - - else - { - if (repeat_min != 1) - { - *code++ = OP_EXACT + op_type; /* NB EXACT doesn't have repeat_type */ - PUT2INC(code, 0, repeat_min); - } - - /* If the mininum is 1 and the previous item was a character string, - we either have to put back the item that got cancelled if the string - length was 1, or add the character back onto the end of a longer - string. For a character type nothing need be done; it will just get - put back naturally. Note that the final character is always going to - get added below, so we leave code ready for its insertion. */ - - else if (*previous == OP_CHARS) - { - if (code == previous) code += 2; else - - /* In UTF-8 mode, a multibyte char has its length in c, with the 0x80 - bit set as a flag. The length will always be between 2 and 6. */ - -#ifdef SUPPORT_UTF8 - if (utf8 && c >= 128) previous[1] += c & 7; else -#endif - previous[1]++; - } - - /* For a single negated character we also have to put back the - item that got cancelled. At present this applies only to single byte - characters in any mode. */ - - else if (*previous == OP_NOT) code++; - - /* If the maximum is unlimited, insert an OP_STAR. Before doing so, - we have to insert the character for the previous code. In UTF-8 mode, - long characters have their length in c, with the 0x80 bit as a flag. */ - - if (repeat_max < 0) - { -#ifdef SUPPORT_UTF8 - if (utf8 && c >= 128) - { - memcpy(code, utf8_char, c & 7); - code += c & 7; - } - else -#endif - *code++ = c; - *code++ = OP_STAR + repeat_type; - } - - /* Else insert an UPTO if the max is greater than the min, again - preceded by the character, for the previously inserted code. */ - - else if (repeat_max != repeat_min) - { -#ifdef SUPPORT_UTF8 - if (utf8 && c >= 128) - { - memcpy(code, utf8_char, c & 7); - code += c & 7; - } - else -#endif - *code++ = c; - repeat_max -= repeat_min; - *code++ = OP_UPTO + repeat_type; - PUT2INC(code, 0, repeat_max); - } - } - - /* The character or character type itself comes last in all cases. */ - -#ifdef SUPPORT_UTF8 - if (utf8 && c >= 128) - { - memcpy(code, utf8_char, c & 7); - code += c & 7; - } - else -#endif - - *code++ = c; - } - - /* If previous was a character class or a back reference, we put the repeat - stuff after it, but just skip the item if the repeat was {0,0}. */ - - else if (*previous == OP_CLASS || - *previous == OP_NCLASS || -#ifdef SUPPORT_UTF8 - *previous == OP_XCLASS || -#endif - *previous == OP_REF) - { - if (repeat_max == 0) - { - code = previous; - goto END_REPEAT; - } - if (repeat_min == 0 && repeat_max == -1) - *code++ = OP_CRSTAR + repeat_type; - else if (repeat_min == 1 && repeat_max == -1) - *code++ = OP_CRPLUS + repeat_type; - else if (repeat_min == 0 && repeat_max == 1) - *code++ = OP_CRQUERY + repeat_type; - else - { - *code++ = OP_CRRANGE + repeat_type; - PUT2INC(code, 0, repeat_min); - if (repeat_max == -1) repeat_max = 0; /* 2-byte encoding for max */ - PUT2INC(code, 0, repeat_max); - } - } - - /* If previous was a bracket group, we may have to replicate it in certain - cases. */ - - else if (*previous >= OP_BRA || *previous == OP_ONCE || - *previous == OP_COND) - { - register int i; - int ketoffset = 0; - int len = code - previous; - uschar *bralink = NULL; - - /* If the maximum repeat count is unlimited, find the end of the bracket - by scanning through from the start, and compute the offset back to it - from the current code pointer. There may be an OP_OPT setting following - the final KET, so we can't find the end just by going back from the code - pointer. */ - - if (repeat_max == -1) - { - register uschar *ket = previous; - do ket += GET(ket, 1); while (*ket != OP_KET); - ketoffset = code - ket; - } - - /* The case of a zero minimum is special because of the need to stick - OP_BRAZERO in front of it, and because the group appears once in the - data, whereas in other cases it appears the minimum number of times. For - this reason, it is simplest to treat this case separately, as otherwise - the code gets far too messy. There are several special subcases when the - minimum is zero. */ - - if (repeat_min == 0) - { - /* If the maximum is also zero, we just omit the group from the output - altogether. */ - - if (repeat_max == 0) - { - code = previous; - goto END_REPEAT; - } - - /* If the maximum is 1 or unlimited, we just have to stick in the - BRAZERO and do no more at this point. However, we do need to adjust - any OP_RECURSE calls inside the group that refer to the group itself or - any internal group, because the offset is from the start of the whole - regex. Temporarily terminate the pattern while doing this. */ - - if (repeat_max <= 1) - { - *code = OP_END; - adjust_recurse(previous, 1, utf8, cd); - memmove(previous+1, previous, len); - code++; - *previous++ = OP_BRAZERO + repeat_type; - } - - /* If the maximum is greater than 1 and limited, we have to replicate - in a nested fashion, sticking OP_BRAZERO before each set of brackets. - The first one has to be handled carefully because it's the original - copy, which has to be moved up. The remainder can be handled by code - that is common with the non-zero minimum case below. We have to - adjust the value or repeat_max, since one less copy is required. Once - again, we may have to adjust any OP_RECURSE calls inside the group. */ - - else - { - int offset; - *code = OP_END; - adjust_recurse(previous, 2 + LINK_SIZE, utf8, cd); - memmove(previous + 2 + LINK_SIZE, previous, len); - code += 2 + LINK_SIZE; - *previous++ = OP_BRAZERO + repeat_type; - *previous++ = OP_BRA; - - /* We chain together the bracket offset fields that have to be - filled in later when the ends of the brackets are reached. */ - - offset = (bralink == NULL)? 0 : previous - bralink; - bralink = previous; - PUTINC(previous, 0, offset); - } - - repeat_max--; - } - - /* If the minimum is greater than zero, replicate the group as many - times as necessary, and adjust the maximum to the number of subsequent - copies that we need. If we set a first char from the group, and didn't - set a required char, copy the latter from the former. */ - - else - { - if (repeat_min > 1) - { - if (groupsetfirstbyte && reqbyte < 0) reqbyte = firstbyte; - for (i = 1; i < repeat_min; i++) - { - memcpy(code, previous, len); - code += len; - } - } - if (repeat_max > 0) repeat_max -= repeat_min; - } - - /* This code is common to both the zero and non-zero minimum cases. If - the maximum is limited, it replicates the group in a nested fashion, - remembering the bracket starts on a stack. In the case of a zero minimum, - the first one was set up above. In all cases the repeat_max now specifies - the number of additional copies needed. */ - - if (repeat_max >= 0) - { - for (i = repeat_max - 1; i >= 0; i--) - { - *code++ = OP_BRAZERO + repeat_type; - - /* All but the final copy start a new nesting, maintaining the - chain of brackets outstanding. */ - - if (i != 0) - { - int offset; - *code++ = OP_BRA; - offset = (bralink == NULL)? 0 : code - bralink; - bralink = code; - PUTINC(code, 0, offset); - } - - memcpy(code, previous, len); - code += len; - } - - /* Now chain through the pending brackets, and fill in their length - fields (which are holding the chain links pro tem). */ - - while (bralink != NULL) - { - int oldlinkoffset; - int offset = code - bralink + 1; - uschar *bra = code - offset; - oldlinkoffset = GET(bra, 1); - bralink = (oldlinkoffset == 0)? NULL : bralink - oldlinkoffset; - *code++ = OP_KET; - PUTINC(code, 0, offset); - PUT(bra, 1, offset); - } - } - - /* If the maximum is unlimited, set a repeater in the final copy. We - can't just offset backwards from the current code point, because we - don't know if there's been an options resetting after the ket. The - correct offset was computed above. */ - - else code[-ketoffset] = OP_KETRMAX + repeat_type; - } - - /* Else there's some kind of shambles */ - - else - { - *errorptr = ERR11; - goto FAILED; - } - - /* If the character following a repeat is '+', we wrap the entire repeated - item inside OP_ONCE brackets. This is just syntactic sugar, taken from - Sun's Java package. The repeated item starts at tempcode, not at previous, - which might be the first part of a string whose (former) last char we - repeated. However, we don't support '+' after a greediness '?'. */ - - if (possessive_quantifier) - { - int len = code - tempcode; - memmove(tempcode + 1+LINK_SIZE, tempcode, len); - code += 1 + LINK_SIZE; - len += 1 + LINK_SIZE; - tempcode[0] = OP_ONCE; - *code++ = OP_KET; - PUTINC(code, 0, len); - PUT(tempcode, 1, len); - } - - /* In all case we no longer have a previous item. We also set the - "follows varying string" flag for subsequently encountered reqbytes if - it isn't already set and we have just passed a varying length item. */ - - END_REPEAT: - previous = NULL; - cd->req_varyopt |= reqvary; - break; - - - /* Start of nested bracket sub-expression, or comment or lookahead or - lookbehind or option setting or condition. First deal with special things - that can come after a bracket; all are introduced by ?, and the appearance - of any of them means that this is not a referencing group. They were - checked for validity in the first pass over the string, so we don't have to - check for syntax errors here. */ - - case '(': - newoptions = options; - skipbytes = 0; - - if (*(++ptr) == '?') - { - int set, unset; - int *optset; - - switch (*(++ptr)) - { - case '#': /* Comment; skip to ket */ - ptr++; - while (*ptr != ')') ptr++; - continue; - - case ':': /* Non-extracting bracket */ - bravalue = OP_BRA; - ptr++; - break; - - case '(': - bravalue = OP_COND; /* Conditional group */ - - /* Condition to test for recursion */ - - if (ptr[1] == 'R') - { - code[1+LINK_SIZE] = OP_CREF; - PUT2(code, 2+LINK_SIZE, CREF_RECURSE); - skipbytes = 3; - ptr += 3; - } - - /* Condition to test for a numbered subpattern match. We know that - if a digit follows ( then there will just be digits until ) because - the syntax was checked in the first pass. */ - - else if ((digitab[ptr[1]] && ctype_digit) != 0) - { - int condref; /* Don't amalgamate; some compilers */ - condref = *(++ptr) - '0'; /* grumble at autoincrement in declaration */ - while (*(++ptr) != ')') condref = condref*10 + *ptr - '0'; - if (condref == 0) - { - *errorptr = ERR35; - goto FAILED; - } - ptr++; - code[1+LINK_SIZE] = OP_CREF; - PUT2(code, 2+LINK_SIZE, condref); - skipbytes = 3; - } - /* For conditions that are assertions, we just fall through, having - set bravalue above. */ - break; - - case '=': /* Positive lookahead */ - bravalue = OP_ASSERT; - ptr++; - break; - - case '!': /* Negative lookahead */ - bravalue = OP_ASSERT_NOT; - ptr++; - break; - - case '<': /* Lookbehinds */ - switch (*(++ptr)) - { - case '=': /* Positive lookbehind */ - bravalue = OP_ASSERTBACK; - ptr++; - break; - - case '!': /* Negative lookbehind */ - bravalue = OP_ASSERTBACK_NOT; - ptr++; - break; - } - break; - - case '>': /* One-time brackets */ - bravalue = OP_ONCE; - ptr++; - break; - - case 'C': /* Callout - may be followed by digits */ - *code++ = OP_CALLOUT; - { - int n = 0; - while ((digitab[*(++ptr)] & ctype_digit) != 0) - n = n * 10 + *ptr - '0'; - if (n > 255) - { - *errorptr = ERR38; - goto FAILED; - } - *code++ = n; - } - previous = NULL; - continue; - - case 'P': /* Named subpattern handling */ - if (*(++ptr) == '<') /* Definition */ - { - int i, namelen; - uschar *slot = cd->name_table; - const uschar *name; /* Don't amalgamate; some compilers */ - name = ++ptr; /* grumble at autoincrement in declaration */ - - while (*ptr++ != '>'); - namelen = ptr - name - 1; - - for (i = 0; i < cd->names_found; i++) - { - int crc = memcmp(name, slot+2, namelen); - if (crc == 0) - { - if (slot[2+namelen] == 0) - { - *errorptr = ERR43; - goto FAILED; - } - crc = -1; /* Current name is substring */ - } - if (crc < 0) - { - memmove(slot + cd->name_entry_size, slot, - (cd->names_found - i) * cd->name_entry_size); - break; - } - slot += cd->name_entry_size; - } - - PUT2(slot, 0, *brackets + 1); - memcpy(slot + 2, name, namelen); - slot[2+namelen] = 0; - cd->names_found++; - goto NUMBERED_GROUP; - } - - if (*ptr == '=' || *ptr == '>') /* Reference or recursion */ - { - int i, namelen; - int type = *ptr++; - const uschar *name = ptr; - uschar *slot = cd->name_table; - - while (*ptr != ')') ptr++; - namelen = ptr - name; - - for (i = 0; i < cd->names_found; i++) - { - if (strncmp((char *)name, (char *)slot+2, namelen) == 0) break; - slot += cd->name_entry_size; - } - if (i >= cd->names_found) - { - *errorptr = ERR15; - goto FAILED; - } - - recno = GET2(slot, 0); - - if (type == '>') goto HANDLE_RECURSION; /* A few lines below */ - - /* Back reference */ - - previous = code; - *code++ = OP_REF; - PUT2INC(code, 0, recno); - cd->backref_map |= (recno < 32)? (1 << recno) : 1; - if (recno > cd->top_backref) cd->top_backref = recno; - continue; - } - - /* Should never happen */ - break; - - case 'R': /* Pattern recursion */ - ptr++; /* Same as (?0) */ - /* Fall through */ - - /* Recursion or "subroutine" call */ - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - { - const uschar *called; - recno = 0; - while((digitab[*ptr] & ctype_digit) != 0) - recno = recno * 10 + *ptr++ - '0'; - - /* Come here from code above that handles a named recursion */ - - HANDLE_RECURSION: - - previous = code; - - /* Find the bracket that is being referenced. Temporarily end the - regex in case it doesn't exist. */ - - *code = OP_END; - called = (recno == 0)? - cd->start_code : find_bracket(cd->start_code, utf8, recno); - - if (called == NULL) - { - *errorptr = ERR15; - goto FAILED; - } - - /* If the subpattern is still open, this is a recursive call. We - check to see if this is a left recursion that could loop for ever, - and diagnose that case. */ - - if (GET(called, 1) == 0 && could_be_empty(called, code, bcptr, utf8)) - { - *errorptr = ERR40; - goto FAILED; - } - - /* Insert the recursion/subroutine item */ - - *code = OP_RECURSE; - PUT(code, 1, called - cd->start_code); - code += 1 + LINK_SIZE; - } - continue; - - /* Character after (? not specially recognized */ - - default: /* Option setting */ - set = unset = 0; - optset = &set; - - while (*ptr != ')' && *ptr != ':') - { - switch (*ptr++) - { - case '-': optset = &unset; break; - - case 'i': *optset |= PCRE_CASELESS; break; - case 'm': *optset |= PCRE_MULTILINE; break; - case 's': *optset |= PCRE_DOTALL; break; - case 'x': *optset |= PCRE_EXTENDED; break; - case 'U': *optset |= PCRE_UNGREEDY; break; - case 'X': *optset |= PCRE_EXTRA; break; - } - } - - /* Set up the changed option bits, but don't change anything yet. */ - - newoptions = (options | set) & (~unset); - - /* If the options ended with ')' this is not the start of a nested - group with option changes, so the options change at this level. Compile - code to change the ims options if this setting actually changes any of - them. We also pass the new setting back so that it can be put at the - start of any following branches, and when this group ends (if we are in - a group), a resetting item can be compiled. - - Note that if this item is right at the start of the pattern, the - options will have been abstracted and made global, so there will be no - change to compile. */ - - if (*ptr == ')') - { - if ((options & PCRE_IMS) != (newoptions & PCRE_IMS)) - { - *code++ = OP_OPT; - *code++ = newoptions & PCRE_IMS; - } - - /* Change options at this level, and pass them back for use - in subsequent branches. Reset the greedy defaults and the case - value for firstbyte and reqbyte. */ - - *optionsptr = options = newoptions; - greedy_default = ((newoptions & PCRE_UNGREEDY) != 0); - greedy_non_default = greedy_default ^ 1; - req_caseopt = ((options & PCRE_CASELESS) != 0)? REQ_CASELESS : 0; - - previous = NULL; /* This item can't be repeated */ - continue; /* It is complete */ - } - - /* If the options ended with ':' we are heading into a nested group - with possible change of options. Such groups are non-capturing and are - not assertions of any kind. All we need to do is skip over the ':'; - the newoptions value is handled below. */ - - bravalue = OP_BRA; - ptr++; - } - } - - /* If PCRE_NO_AUTO_CAPTURE is set, all unadorned brackets become - non-capturing and behave like (?:...) brackets */ - - else if ((options & PCRE_NO_AUTO_CAPTURE) != 0) - { - bravalue = OP_BRA; - } - - /* Else we have a referencing group; adjust the opcode. If the bracket - number is greater than EXTRACT_BASIC_MAX, we set the opcode one higher, and - arrange for the true number to follow later, in an OP_BRANUMBER item. */ - - else - { - NUMBERED_GROUP: - if (++(*brackets) > EXTRACT_BASIC_MAX) - { - bravalue = OP_BRA + EXTRACT_BASIC_MAX + 1; - code[1+LINK_SIZE] = OP_BRANUMBER; - PUT2(code, 2+LINK_SIZE, *brackets); - skipbytes = 3; - } - else bravalue = OP_BRA + *brackets; - } - - /* Process nested bracketed re. Assertions may not be repeated, but other - kinds can be. We copy code into a non-register variable in order to be able - to pass its address because some compilers complain otherwise. Pass in a - new setting for the ims options if they have changed. */ - - previous = (bravalue >= OP_ONCE)? code : NULL; - *code = bravalue; - tempcode = code; - tempreqvary = cd->req_varyopt; /* Save value before bracket */ - - if (!compile_regex( - newoptions, /* The complete new option state */ - options & PCRE_IMS, /* The previous ims option state */ - brackets, /* Extracting bracket count */ - &tempcode, /* Where to put code (updated) */ - &ptr, /* Input pointer (updated) */ - errorptr, /* Where to put an error message */ - (bravalue == OP_ASSERTBACK || - bravalue == OP_ASSERTBACK_NOT), /* TRUE if back assert */ - skipbytes, /* Skip over OP_COND/OP_BRANUMBER */ - &subfirstbyte, /* For possible first char */ - &subreqbyte, /* For possible last char */ - bcptr, /* Current branch chain */ - cd)) /* Tables block */ - goto FAILED; - - /* At the end of compiling, code is still pointing to the start of the - group, while tempcode has been updated to point past the end of the group - and any option resetting that may follow it. The pattern pointer (ptr) - is on the bracket. */ - - /* If this is a conditional bracket, check that there are no more than - two branches in the group. */ - - else if (bravalue == OP_COND) - { - uschar *tc = code; - condcount = 0; - - do { - condcount++; - tc += GET(tc,1); - } - while (*tc != OP_KET); - - if (condcount > 2) - { - *errorptr = ERR27; - goto FAILED; - } - - /* If there is just one branch, we must not make use of its firstbyte or - reqbyte, because this is equivalent to an empty second branch. */ - - if (condcount == 1) subfirstbyte = subreqbyte = REQ_NONE; - } - - /* Handle updating of the required and first characters. Update for normal - brackets of all kinds, and conditions with two branches (see code above). - If the bracket is followed by a quantifier with zero repeat, we have to - back off. Hence the definition of zeroreqbyte and zerofirstbyte outside the - main loop so that they can be accessed for the back off. */ - - zeroreqbyte = reqbyte; - zerofirstbyte = firstbyte; - groupsetfirstbyte = FALSE; - - if (bravalue >= OP_BRA || bravalue == OP_ONCE || bravalue == OP_COND) - { - /* If we have not yet set a firstbyte in this branch, take it from the - subpattern, remembering that it was set here so that a repeat of more - than one can replicate it as reqbyte if necessary. If the subpattern has - no firstbyte, set "none" for the whole branch. In both cases, a zero - repeat forces firstbyte to "none". */ - - if (firstbyte == REQ_UNSET) - { - if (subfirstbyte >= 0) - { - firstbyte = subfirstbyte; - groupsetfirstbyte = TRUE; - } - else firstbyte = REQ_NONE; - zerofirstbyte = REQ_NONE; - } - - /* If firstbyte was previously set, convert the subpattern's firstbyte - into reqbyte if there wasn't one, using the vary flag that was in - existence beforehand. */ - - else if (subfirstbyte >= 0 && subreqbyte < 0) - subreqbyte = subfirstbyte | tempreqvary; - - /* If the subpattern set a required byte (or set a first byte that isn't - really the first byte - see above), set it. */ - - if (subreqbyte >= 0) reqbyte = subreqbyte; - } - - /* For a forward assertion, we take the reqbyte, if set. This can be - helpful if the pattern that follows the assertion doesn't set a different - char. For example, it's useful for /(?=abcde).+/. We can't set firstbyte - for an assertion, however because it leads to incorrect effect for patterns - such as /(?=a)a.+/ when the "real" "a" would then become a reqbyte instead - of a firstbyte. This is overcome by a scan at the end if there's no - firstbyte, looking for an asserted first char. */ - - else if (bravalue == OP_ASSERT && subreqbyte >= 0) reqbyte = subreqbyte; - - /* Now update the main code pointer to the end of the group. */ - - code = tempcode; - - /* Error if hit end of pattern */ - - if (*ptr != ')') - { - *errorptr = ERR14; - goto FAILED; - } - break; - - /* Check \ for being a real metacharacter; if not, fall through and handle - it as a data character at the start of a string. Escape items are checked - for validity in the pre-compiling pass. */ - - case '\\': - tempptr = ptr; - c = check_escape(&ptr, errorptr, *brackets, options, FALSE); - - /* Handle metacharacters introduced by \. For ones like \d, the ESC_ values - are arranged to be the negation of the corresponding OP_values. For the - back references, the values are ESC_REF plus the reference number. Only - back references and those types that consume a character may be repeated. - We can test for values between ESC_b and ESC_Z for the latter; this may - have to change if any new ones are ever created. */ - - if (c < 0) - { - if (-c == ESC_Q) /* Handle start of quoted string */ - { - if (ptr[1] == '\\' && ptr[2] == 'E') ptr += 2; /* avoid empty string */ - else inescq = TRUE; - continue; - } - - /* For metasequences that actually match a character, we disable the - setting of a first character if it hasn't already been set. */ - - if (firstbyte == REQ_UNSET && -c > ESC_b && -c < ESC_Z) - firstbyte = REQ_NONE; - - /* Set values to reset to if this is followed by a zero repeat. */ - - zerofirstbyte = firstbyte; - zeroreqbyte = reqbyte; - - /* Back references are handled specially */ - - if (-c >= ESC_REF) - { - int number = -c - ESC_REF; - previous = code; - *code++ = OP_REF; - PUT2INC(code, 0, number); - } - else - { - previous = (-c > ESC_b && -c < ESC_Z)? code : NULL; - *code++ = -c; - } - continue; - } - - /* Data character: reset and fall through */ - - ptr = tempptr; - c = '\\'; - - /* Handle a run of data characters until a metacharacter is encountered. - The first character is guaranteed not to be whitespace or # when the - extended flag is set. */ - - NORMAL_CHAR: - default: - previous = code; - *code = OP_CHARS; - code += 2; - length = 0; - - do - { - /* If in \Q...\E, check for the end; if not, we always have a literal */ - - if (inescq) - { - if (c == '\\' && ptr[1] == 'E') - { - inescq = FALSE; - ptr++; - } - else - { - *code++ = c; - length++; - } - continue; - } - - /* Skip white space and comments for /x patterns */ - - if ((options & PCRE_EXTENDED) != 0) - { - if ((cd->ctypes[c] & ctype_space) != 0) continue; - if (c == '#') - { - /* The space before the ; is to avoid a warning on a silly compiler - on the Macintosh. */ - while ((c = *(++ptr)) != 0 && c != NEWLINE) ; - if (c == 0) break; - continue; - } - } - - /* Backslash may introduce a data char or a metacharacter. Escaped items - are checked for validity in the pre-compiling pass. Stop the string - before a metaitem. */ - - if (c == '\\') - { - tempptr = ptr; - c = check_escape(&ptr, errorptr, *brackets, options, FALSE); - if (c < 0) { ptr = tempptr; break; } - - /* If a character is > 127 in UTF-8 mode, we have to turn it into - two or more bytes in the UTF-8 encoding. */ - -#ifdef SUPPORT_UTF8 - if (utf8 && c > 127) - { - uschar buffer[8]; - int len = ord2utf8(c, buffer); - for (c = 0; c < len; c++) *code++ = buffer[c]; - length += len; - continue; - } -#endif - } - - /* Ordinary character or single-char escape */ - - *code++ = c; - length++; - } - - /* This "while" is the end of the "do" above. */ - - while (length < MAXLIT && (cd->ctypes[c = *(++ptr)] & ctype_meta) == 0); - - /* Update the first and last requirements. These are always bytes, even in - UTF-8 mode. However, there is a special case to be considered when there - are only one or two characters. Because this gets messy in UTF-8 mode, the - code is kept separate. When we get here "length" contains the number of - bytes. */ - -#ifdef SUPPORT_UTF8 - if (utf8 && length > 1) - { - uschar *t = previous + 3; /* After this code, t */ - while (t < code && (*t & 0xc0) == 0x80) t++; /* follows the 1st char */ - - /* Handle the case when there is only one multibyte character. It must - have at least two bytes because of the "length > 1" test above. */ - - if (t == code) - { - /* If no previous first byte, set it from this character, but revert to - none on a zero repeat. */ - - if (firstbyte == REQ_UNSET) - { - zerofirstbyte = REQ_NONE; - firstbyte = previous[2]; - } - - /* Otherwise, leave the first byte value alone, and don't change it on - a zero repeat */ - - else zerofirstbyte = firstbyte; - - /* In both cases, a zero repeat resets the previous required byte */ - - zeroreqbyte = reqbyte; - } - - /* Handle the case when there is more than one character. These may be - single-byte or multibyte characters */ - - else - { - t = code - 1; /* After this code, t is at the */ - while ((*t & 0xc0) == 0x80) t--; /* start of the last character */ - - /* If no previous first byte, set it from the first character, and - retain it on a zero repeat (of the last character). The required byte - is reset on a zero repeat, either to the byte before the last - character, unless this is the first byte of the string. In that case, - it reverts to its previous value. */ - - if (firstbyte == REQ_UNSET) - { - zerofirstbyte = firstbyte = previous[2] | req_caseopt; - zeroreqbyte = (t - 1 == previous + 2)? - reqbyte : t[-1] | req_caseopt | cd->req_varyopt; - } - - /* If there was a previous first byte, leave it alone, and don't change - it on a zero repeat. The required byte is reset on a zero repeat to the - byte before the last character. */ - - else - { - zerofirstbyte = firstbyte; - zeroreqbyte = t[-1] | req_caseopt | cd->req_varyopt; - } - } - - /* In all cases (we know length > 1), the new required byte is the last - byte of the string. */ - - reqbyte = code[-1] | req_caseopt | cd->req_varyopt; - } - - else /* End of UTF-8 coding */ -#endif - - /* This is the code for non-UTF-8 operation, either without UTF-8 support, - or when UTF-8 is not enabled. */ - - { - /* firstbyte was not previously set; take it from this string */ - - if (firstbyte == REQ_UNSET) - { - if (length == 1) - { - zerofirstbyte = REQ_NONE; - firstbyte = previous[2] | req_caseopt; - zeroreqbyte = reqbyte; - } - else - { - zerofirstbyte = firstbyte = previous[2] | req_caseopt; - zeroreqbyte = (length > 2)? - (code[-2] | req_caseopt | cd->req_varyopt) : reqbyte; - reqbyte = code[-1] | req_caseopt | cd->req_varyopt; - } - } - - /* firstbyte was previously set */ - - else - { - zerofirstbyte = firstbyte; - zeroreqbyte = (length == 1)? reqbyte : - code[-2] | req_caseopt | cd->req_varyopt; - reqbyte = code[-1] | req_caseopt | cd->req_varyopt; - } - } - - /* Set the length in the data vector, and advance to the next state. */ - - previous[1] = length; - if (length < MAXLIT) ptr--; - break; - } - } /* end of big loop */ - -/* Control never reaches here by falling through, only by a goto for all the -error states. Pass back the position in the pattern so that it can be displayed -to the user for diagnosing the error. */ - -FAILED: -*ptrptr = ptr; -return FALSE; -} - - - - -/************************************************* -* Compile sequence of alternatives * -*************************************************/ - -/* On entry, ptr is pointing past the bracket character, but on return -it points to the closing bracket, or vertical bar, or end of string. -The code variable is pointing at the byte into which the BRA operator has been -stored. If the ims options are changed at the start (for a (?ims: group) or -during any branch, we need to insert an OP_OPT item at the start of every -following branch to ensure they get set correctly at run time, and also pass -the new options into every subsequent branch compile. - -Argument: - options option bits, including any changes for this subpattern - oldims previous settings of ims option bits - brackets -> int containing the number of extracting brackets used - codeptr -> the address of the current code pointer - ptrptr -> the address of the current pattern pointer - errorptr -> pointer to error message - lookbehind TRUE if this is a lookbehind assertion - skipbytes skip this many bytes at start (for OP_COND, OP_BRANUMBER) - firstbyteptr place to put the first required character, or a negative number - reqbyteptr place to put the last required character, or a negative number - bcptr pointer to the chain of currently open branches - cd points to the data block with tables pointers etc. - -Returns: TRUE on success -*/ - -static BOOL -compile_regex(int options, int oldims, int *brackets, uschar **codeptr, - const uschar **ptrptr, const char **errorptr, BOOL lookbehind, int skipbytes, - int *firstbyteptr, int *reqbyteptr, branch_chain *bcptr, compile_data *cd) -{ -const uschar *ptr = *ptrptr; -uschar *code = *codeptr; -uschar *last_branch = code; -uschar *start_bracket = code; -uschar *reverse_count = NULL; -int firstbyte, reqbyte; -int branchfirstbyte, branchreqbyte; -branch_chain bc; - -bc.outer = bcptr; -bc.current = code; - -firstbyte = reqbyte = REQ_UNSET; - -/* Offset is set zero to mark that this bracket is still open */ - -PUT(code, 1, 0); -code += 1 + LINK_SIZE + skipbytes; - -/* Loop for each alternative branch */ - -for (;;) - { - /* Handle a change of ims options at the start of the branch */ - - if ((options & PCRE_IMS) != oldims) - { - *code++ = OP_OPT; - *code++ = options & PCRE_IMS; - } - - /* Set up dummy OP_REVERSE if lookbehind assertion */ - - if (lookbehind) - { - *code++ = OP_REVERSE; - reverse_count = code; - PUTINC(code, 0, 0); - } - - /* Now compile the branch */ - - if (!compile_branch(&options, brackets, &code, &ptr, errorptr, - &branchfirstbyte, &branchreqbyte, &bc, cd)) - { - *ptrptr = ptr; - return FALSE; - } - - /* If this is the first branch, the firstbyte and reqbyte values for the - branch become the values for the regex. */ - - if (*last_branch != OP_ALT) - { - firstbyte = branchfirstbyte; - reqbyte = branchreqbyte; - } - - /* If this is not the first branch, the first char and reqbyte have to - match the values from all the previous branches, except that if the previous - value for reqbyte didn't have REQ_VARY set, it can still match, and we set - REQ_VARY for the regex. */ - - else - { - /* If we previously had a firstbyte, but it doesn't match the new branch, - we have to abandon the firstbyte for the regex, but if there was previously - no reqbyte, it takes on the value of the old firstbyte. */ - - if (firstbyte >= 0 && firstbyte != branchfirstbyte) - { - if (reqbyte < 0) reqbyte = firstbyte; - firstbyte = REQ_NONE; - } - - /* If we (now or from before) have no firstbyte, a firstbyte from the - branch becomes a reqbyte if there isn't a branch reqbyte. */ - - if (firstbyte < 0 && branchfirstbyte >= 0 && branchreqbyte < 0) - branchreqbyte = branchfirstbyte; - - /* Now ensure that the reqbytes match */ - - if ((reqbyte & ~REQ_VARY) != (branchreqbyte & ~REQ_VARY)) - reqbyte = REQ_NONE; - else reqbyte |= branchreqbyte; /* To "or" REQ_VARY */ - } - - /* If lookbehind, check that this branch matches a fixed-length string, - and put the length into the OP_REVERSE item. Temporarily mark the end of - the branch with OP_END. */ - - if (lookbehind) - { - int length; - *code = OP_END; - length = find_fixedlength(last_branch, options); - DPRINTF(("fixed length = %d\n", length)); - if (length < 0) - { - *errorptr = (length == -2)? ERR36 : ERR25; - *ptrptr = ptr; - return FALSE; - } - PUT(reverse_count, 0, length); - } - - /* Reached end of expression, either ')' or end of pattern. Go back through - the alternative branches and reverse the chain of offsets, with the field in - the BRA item now becoming an offset to the first alternative. If there are - no alternatives, it points to the end of the group. The length in the - terminating ket is always the length of the whole bracketed item. If any of - the ims options were changed inside the group, compile a resetting op-code - following, except at the very end of the pattern. Return leaving the pointer - at the terminating char. */ - - if (*ptr != '|') - { - int length = code - last_branch; - do - { - int prev_length = GET(last_branch, 1); - PUT(last_branch, 1, length); - length = prev_length; - last_branch -= length; - } - while (length > 0); - - /* Fill in the ket */ - - *code = OP_KET; - PUT(code, 1, code - start_bracket); - code += 1 + LINK_SIZE; - - /* Resetting option if needed */ - - if ((options & PCRE_IMS) != oldims && *ptr == ')') - { - *code++ = OP_OPT; - *code++ = oldims; - } - - /* Set values to pass back */ - - *codeptr = code; - *ptrptr = ptr; - *firstbyteptr = firstbyte; - *reqbyteptr = reqbyte; - return TRUE; - } - - /* Another branch follows; insert an "or" node. Its length field points back - to the previous branch while the bracket remains open. At the end the chain - is reversed. It's done like this so that the start of the bracket has a - zero offset until it is closed, making it possible to detect recursion. */ - - *code = OP_ALT; - PUT(code, 1, code - last_branch); - bc.current = last_branch = code; - code += 1 + LINK_SIZE; - ptr++; - } -/* Control never reaches here */ -} - - - - -/************************************************* -* Check for anchored expression * -*************************************************/ - -/* Try to find out if this is an anchored regular expression. Consider each -alternative branch. If they all start with OP_SOD or OP_CIRC, or with a bracket -all of whose alternatives start with OP_SOD or OP_CIRC (recurse ad lib), then -it's anchored. However, if this is a multiline pattern, then only OP_SOD -counts, since OP_CIRC can match in the middle. - -We can also consider a regex to be anchored if OP_SOM starts all its branches. -This is the code for \G, which means "match at start of match position, taking -into account the match offset". - -A branch is also implicitly anchored if it starts with .* and DOTALL is set, -because that will try the rest of the pattern at all possible matching points, -so there is no point trying again.... er .... - -.... except when the .* appears inside capturing parentheses, and there is a -subsequent back reference to those parentheses. We haven't enough information -to catch that case precisely. - -At first, the best we could do was to detect when .* was in capturing brackets -and the highest back reference was greater than or equal to that level. -However, by keeping a bitmap of the first 31 back references, we can catch some -of the more common cases more precisely. - -Arguments: - code points to start of expression (the bracket) - options points to the options setting - bracket_map a bitmap of which brackets we are inside while testing; this - handles up to substring 31; after that we just have to take - the less precise approach - backref_map the back reference bitmap - -Returns: TRUE or FALSE -*/ - -static BOOL -is_anchored(register const uschar *code, int *options, unsigned int bracket_map, - unsigned int backref_map) -{ -do { - const uschar *scode = - first_significant_code(code + 1+LINK_SIZE, options, PCRE_MULTILINE); - register int op = *scode; - - /* Capturing brackets */ - - if (op > OP_BRA) - { - int new_map; - op -= OP_BRA; - if (op > EXTRACT_BASIC_MAX) op = GET2(scode, 2+LINK_SIZE); - new_map = bracket_map | ((op < 32)? (1 << op) : 1); - if (!is_anchored(scode, options, new_map, backref_map)) return FALSE; - } - - /* Other brackets */ - - else if (op == OP_BRA || op == OP_ASSERT || op == OP_ONCE || op == OP_COND) - { - if (!is_anchored(scode, options, bracket_map, backref_map)) return FALSE; - } - - /* .* is not anchored unless DOTALL is set and it isn't in brackets that - are or may be referenced. */ - - else if ((op == OP_TYPESTAR || op == OP_TYPEMINSTAR) && - (*options & PCRE_DOTALL) != 0) - { - if (scode[1] != OP_ANY || (bracket_map & backref_map) != 0) return FALSE; - } - - /* Check for explicit anchoring */ - - else if (op != OP_SOD && op != OP_SOM && - ((*options & PCRE_MULTILINE) != 0 || op != OP_CIRC)) - return FALSE; - code += GET(code, 1); - } -while (*code == OP_ALT); /* Loop for each alternative */ -return TRUE; -} - - - -/************************************************* -* Check for starting with ^ or .* * -*************************************************/ - -/* This is called to find out if every branch starts with ^ or .* so that -"first char" processing can be done to speed things up in multiline -matching and for non-DOTALL patterns that start with .* (which must start at -the beginning or after \n). As in the case of is_anchored() (see above), we -have to take account of back references to capturing brackets that contain .* -because in that case we can't make the assumption. - -Arguments: - code points to start of expression (the bracket) - bracket_map a bitmap of which brackets we are inside while testing; this - handles up to substring 31; after that we just have to take - the less precise approach - backref_map the back reference bitmap - -Returns: TRUE or FALSE -*/ - -static BOOL -is_startline(const uschar *code, unsigned int bracket_map, - unsigned int backref_map) -{ -do { - const uschar *scode = first_significant_code(code + 1+LINK_SIZE, NULL, 0); - register int op = *scode; - - /* Capturing brackets */ - - if (op > OP_BRA) - { - int new_map; - op -= OP_BRA; - if (op > EXTRACT_BASIC_MAX) op = GET2(scode, 2+LINK_SIZE); - new_map = bracket_map | ((op < 32)? (1 << op) : 1); - if (!is_startline(scode, new_map, backref_map)) return FALSE; - } - - /* Other brackets */ - - else if (op == OP_BRA || op == OP_ASSERT || op == OP_ONCE || op == OP_COND) - { if (!is_startline(scode, bracket_map, backref_map)) return FALSE; } - - /* .* is not anchored unless DOTALL is set and it isn't in brackets that - may be referenced. */ - - else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR) - { - if (scode[1] != OP_ANY || (bracket_map & backref_map) != 0) return FALSE; - } - - /* Check for explicit circumflex */ - - else if (op != OP_CIRC) return FALSE; - code += GET(code, 1); - } -while (*code == OP_ALT); /* Loop for each alternative */ -return TRUE; -} - - - -/************************************************* -* Check for asserted fixed first char * -*************************************************/ - -/* During compilation, the "first char" settings from forward assertions are -discarded, because they can cause conflicts with actual literals that follow. -However, if we end up without a first char setting for an unanchored pattern, -it is worth scanning the regex to see if there is an initial asserted first -char. If all branches start with the same asserted char, or with a bracket all -of whose alternatives start with the same asserted char (recurse ad lib), then -we return that char, otherwise -1. - -Arguments: - code points to start of expression (the bracket) - options pointer to the options (used to check casing changes) - inassert TRUE if in an assertion - -Returns: -1 or the fixed first char -*/ - -static int -find_firstassertedchar(const uschar *code, int *options, BOOL inassert) -{ -register int c = -1; -do { - int d; - const uschar *scode = - first_significant_code(code + 1+LINK_SIZE, options, PCRE_CASELESS); - register int op = *scode; - - if (op >= OP_BRA) op = OP_BRA; - - switch(op) - { - default: - return -1; - - case OP_BRA: - case OP_ASSERT: - case OP_ONCE: - case OP_COND: - if ((d = find_firstassertedchar(scode, options, op == OP_ASSERT)) < 0) - return -1; - if (c < 0) c = d; else if (c != d) return -1; - break; - - case OP_EXACT: /* Fall through */ - scode++; - - case OP_CHARS: /* Fall through */ - scode++; - - case OP_PLUS: - case OP_MINPLUS: - if (!inassert) return -1; - if (c < 0) - { - c = scode[1]; - if ((*options & PCRE_CASELESS) != 0) c |= REQ_CASELESS; - } - else if (c != scode[1]) return -1; - break; - } - - code += GET(code, 1); - } -while (*code == OP_ALT); -return c; -} - - - - -#ifdef SUPPORT_UTF8 -/************************************************* -* Validate a UTF-8 string * -*************************************************/ - -/* This function is called (optionally) at the start of compile or match, to -validate that a supposed UTF-8 string is actually valid. The early check means -that subsequent code can assume it is dealing with a valid string. The check -can be turned off for maximum performance, but then consequences of supplying -an invalid string are then undefined. - -Arguments: - string points to the string - length length of string, or -1 if the string is zero-terminated - -Returns: < 0 if the string is a valid UTF-8 string - >= 0 otherwise; the value is the offset of the bad byte -*/ - -static int -valid_utf8(const uschar *string, int length) -{ -register const uschar *p; - -if (length < 0) - { - for (p = string; *p != 0; p++); - length = p - string; - } - -for (p = string; length-- > 0; p++) - { - register int ab; - register int c = *p; - if (c < 128) continue; - if ((c & 0xc0) != 0xc0) return p - string; - ab = utf8_table4[c & 0x3f]; /* Number of additional bytes */ - if (length < ab) return p - string; - length -= ab; - - /* Check top bits in the second byte */ - if ((*(++p) & 0xc0) != 0x80) return p - string; - - /* Check for overlong sequences for each different length */ - switch (ab) - { - /* Check for xx00 000x */ - case 1: - if ((c & 0x3e) == 0) return p - string; - continue; /* We know there aren't any more bytes to check */ - - /* Check for 1110 0000, xx0x xxxx */ - case 2: - if (c == 0xe0 && (*p & 0x20) == 0) return p - string; - break; - - /* Check for 1111 0000, xx00 xxxx */ - case 3: - if (c == 0xf0 && (*p & 0x30) == 0) return p - string; - break; - - /* Check for 1111 1000, xx00 0xxx */ - case 4: - if (c == 0xf8 && (*p & 0x38) == 0) return p - string; - break; - - /* Check for leading 0xfe or 0xff, and then for 1111 1100, xx00 00xx */ - case 5: - if (c == 0xfe || c == 0xff || - (c == 0xfc && (*p & 0x3c) == 0)) return p - string; - break; - } - - /* Check for valid bytes after the 2nd, if any; all must start 10 */ - while (--ab > 0) - { - if ((*(++p) & 0xc0) != 0x80) return p - string; - } - } - -return -1; -} -#endif - - - -/************************************************* -* Compile a Regular Expression * -*************************************************/ - -/* This function takes a string and returns a pointer to a block of store -holding a compiled version of the expression. - -Arguments: - pattern the regular expression - options various option bits - errorptr pointer to pointer to error text - erroroffset ptr offset in pattern where error was detected - tables pointer to character tables or NULL - -Returns: pointer to compiled data block, or NULL on error, - with errorptr and erroroffset set -*/ - -EXPORT pcre * -pcre_compile(const char *pattern, int options, const char **errorptr, - int *erroroffset, const unsigned char *tables) -{ -real_pcre *re; -int length = 1 + LINK_SIZE; /* For initial BRA plus length */ -int runlength; -int c, firstbyte, reqbyte; -int bracount = 0; -int branch_extra = 0; -int branch_newextra; -int item_count = -1; -int name_count = 0; -int max_name_size = 0; -#ifdef SUPPORT_UTF8 -int lastcharlength = 0; -BOOL utf8; -BOOL class_utf8; -#endif -BOOL inescq = FALSE; -unsigned int brastackptr = 0; -size_t size; -uschar *code; -const uschar *codestart; -const uschar *ptr; -compile_data compile_block; -int brastack[BRASTACK_SIZE]; -uschar bralenstack[BRASTACK_SIZE]; - -/* We can't pass back an error message if errorptr is NULL; I guess the best we -can do is just return NULL. */ - -if (errorptr == NULL) return NULL; -*errorptr = NULL; - -/* However, we can give a message for this error */ - -if (erroroffset == NULL) - { - *errorptr = ERR16; - return NULL; - } -*erroroffset = 0; - -/* Can't support UTF8 unless PCRE has been compiled to include the code. */ - -#ifdef SUPPORT_UTF8 -utf8 = (options & PCRE_UTF8) != 0; -if (utf8 && (options & PCRE_NO_UTF8_CHECK) == 0 && - (*erroroffset = valid_utf8((uschar *)pattern, -1)) >= 0) - { - *errorptr = ERR44; - return NULL; - } -#else -if ((options & PCRE_UTF8) != 0) - { - *errorptr = ERR32; - return NULL; - } -#endif - -if ((options & ~PUBLIC_OPTIONS) != 0) - { - *errorptr = ERR17; - return NULL; - } - -/* Set up pointers to the individual character tables */ - -if (tables == NULL) tables = pcre_default_tables; -compile_block.lcc = tables + lcc_offset; -compile_block.fcc = tables + fcc_offset; -compile_block.cbits = tables + cbits_offset; -compile_block.ctypes = tables + ctypes_offset; - -/* Maximum back reference and backref bitmap. This is updated for numeric -references during the first pass, but for named references during the actual -compile pass. The bitmap records up to 31 back references to help in deciding -whether (.*) can be treated as anchored or not. */ - -compile_block.top_backref = 0; -compile_block.backref_map = 0; - -/* Reflect pattern for debugging output */ - -DPRINTF(("------------------------------------------------------------------\n")); -DPRINTF(("%s\n", pattern)); - -/* The first thing to do is to make a pass over the pattern to compute the -amount of store required to hold the compiled code. This does not have to be -perfect as long as errors are overestimates. At the same time we can detect any -flag settings right at the start, and extract them. Make an attempt to correct -for any counted white space if an "extended" flag setting appears late in the -pattern. We can't be so clever for #-comments. */ - -ptr = (const uschar *)(pattern - 1); -while ((c = *(++ptr)) != 0) - { - int min, max; - int class_optcount; - int bracket_length; - int duplength; - - /* If we are inside a \Q...\E sequence, all chars are literal */ - - if (inescq) goto NORMAL_CHAR; - - /* Otherwise, first check for ignored whitespace and comments */ - - if ((options & PCRE_EXTENDED) != 0) - { - if ((compile_block.ctypes[c] & ctype_space) != 0) continue; - if (c == '#') - { - /* The space before the ; is to avoid a warning on a silly compiler - on the Macintosh. */ - while ((c = *(++ptr)) != 0 && c != NEWLINE) ; - if (c == 0) break; - continue; - } - } - - item_count++; /* Is zero for the first non-comment item */ - - switch(c) - { - /* A backslashed item may be an escaped "normal" character or a - character type. For a "normal" character, put the pointers and - character back so that tests for whitespace etc. in the input - are done correctly. */ - - case '\\': - { - const uschar *save_ptr = ptr; - c = check_escape(&ptr, errorptr, bracount, options, FALSE); - if (*errorptr != NULL) goto PCRE_ERROR_RETURN; - if (c >= 0) - { - ptr = save_ptr; - c = '\\'; - goto NORMAL_CHAR; - } - } - - /* If \Q, enter "literal" mode */ - - if (-c == ESC_Q) - { - inescq = TRUE; - continue; - } - - /* Other escapes need one byte, and are of length one for repeats */ - - length++; -#ifdef SUPPORT_UTF8 - lastcharlength = 1; -#endif - - /* A back reference needs an additional 2 bytes, plus either one or 5 - bytes for a repeat. We also need to keep the value of the highest - back reference. */ - - if (c <= -ESC_REF) - { - int refnum = -c - ESC_REF; - compile_block.backref_map |= (refnum < 32)? (1 << refnum) : 1; - if (refnum > compile_block.top_backref) - compile_block.top_backref = refnum; - length += 2; /* For single back reference */ - if (ptr[1] == '{' && is_counted_repeat(ptr+2)) - { - ptr = read_repeat_counts(ptr+2, &min, &max, errorptr); - if (*errorptr != NULL) goto PCRE_ERROR_RETURN; - if ((min == 0 && (max == 1 || max == -1)) || - (min == 1 && max == -1)) - length++; - else length += 5; - if (ptr[1] == '?') ptr++; - } - } - continue; - - case '^': /* Single-byte metacharacters */ - case '.': - case '$': - length++; -#ifdef SUPPORT_UTF8 - lastcharlength = 1; -#endif - continue; - - case '*': /* These repeats won't be after brackets; */ - case '+': /* those are handled separately */ - case '?': - length++; - goto POSESSIVE; /* A few lines below */ - - /* This covers the cases of braced repeats after a single char, metachar, - class, or back reference. */ - - case '{': - if (!is_counted_repeat(ptr+1)) goto NORMAL_CHAR; - ptr = read_repeat_counts(ptr+1, &min, &max, errorptr); - if (*errorptr != NULL) goto PCRE_ERROR_RETURN; - - /* These special cases just insert one extra opcode */ - - if ((min == 0 && (max == 1 || max == -1)) || - (min == 1 && max == -1)) - length++; - - /* These cases might insert additional copies of a preceding character. */ - - else - { -#ifdef SUPPORT_UTF8 - /* In UTF-8 mode, we should find the length in lastcharlength */ - if (utf8) - { - if (min != 1) - { - length -= lastcharlength; /* Uncount the original char or metachar */ - if (min > 0) length += 3 + lastcharlength; - } - length += lastcharlength + ((max > 0)? 3 : 1); - } - else -#endif - - /* Not UTF-8 mode: all characters are one byte */ - { - if (min != 1) - { - length--; /* Uncount the original char or metachar */ - if (min > 0) length += 4; - } - - length += (max > 0)? 4 : 2; - } - } - - if (ptr[1] == '?') ptr++; /* Needs no extra length */ - - POSESSIVE: /* Test for possessive quantifier */ - if (ptr[1] == '+') - { - ptr++; - length += 2 + 2*LINK_SIZE; /* Allow for atomic brackets */ - } - continue; - - /* An alternation contains an offset to the next branch or ket. If any ims - options changed in the previous branch(es), and/or if we are in a - lookbehind assertion, extra space will be needed at the start of the - branch. This is handled by branch_extra. */ - - case '|': - length += 1 + LINK_SIZE + branch_extra; - continue; - - /* A character class uses 33 characters provided that all the character - values are less than 256. Otherwise, it uses a bit map for low valued - characters, and individual items for others. Don't worry about character - types that aren't allowed in classes - they'll get picked up during the - compile. A character class that contains only one single-byte character - uses 2 or 3 bytes, depending on whether it is negated or not. Notice this - where we can. (In UTF-8 mode we can do this only for chars < 128.) */ - - case '[': - class_optcount = 0; - -#ifdef SUPPORT_UTF8 - class_utf8 = FALSE; -#endif - - if (*(++ptr) == '^') ptr++; - - /* Written as a "do" so that an initial ']' is taken as data */ - - if (*ptr != 0) do - { - /* Inside \Q...\E everything is literal except \E */ - - if (inescq) - { - if (*ptr != '\\' || ptr[1] != 'E') goto NON_SPECIAL_CHARACTER; - inescq = FALSE; - ptr += 1; - continue; - } - - /* Outside \Q...\E, check for escapes */ - - if (*ptr == '\\') - { -#ifdef SUPPORT_UTF8 - int prevchar = ptr[-1]; -#endif - int ch = check_escape(&ptr, errorptr, bracount, options, TRUE); - if (*errorptr != NULL) goto PCRE_ERROR_RETURN; - - /* \b is backspace inside a class */ - - if (-ch == ESC_b) ch = '\b'; - - /* \Q enters quoting mode */ - - if (-ch == ESC_Q) - { - inescq = TRUE; - continue; - } - - /* Handle escapes that turn into characters */ - - if (ch >= 0) - { -#ifdef SUPPORT_UTF8 - if (utf8) - { - if (ch > 127) class_optcount = 10; /* Ensure > 1 */ - if (ch > 255) - { - uschar buffer[6]; - if (!class_utf8) - { - class_utf8 = TRUE; - length += LINK_SIZE + 1 + 1; - } - length += 1 + ord2utf8(ch, buffer); - - /* If this wide character is preceded by '-', add an extra 2 to - the length in case the previous character was < 128, because in - this case the whole range will be put into the list. */ - - if (prevchar == '-') length += 2; - } - } -#endif - class_optcount++; /* for possible optimization */ - } - else class_optcount = 10; /* \d, \s etc; make sure > 1 */ - } - - /* Check the syntax for POSIX stuff. The bits we actually handle are - checked during the real compile phase. */ - - else if (*ptr == '[' && check_posix_syntax(ptr, &ptr, &compile_block)) - { - ptr++; - class_optcount = 10; /* Make sure > 1 */ - } - - /* Anything else just increments the possible optimization count. If - there are wide characters, we are going to have to use an XCLASS. */ - - else - { - NON_SPECIAL_CHARACTER: - class_optcount++; - -#ifdef SUPPORT_UTF8 - if (utf8) - { - int ch; - int extra = 0; - GETCHARLEN(ch, ptr, extra); - if (ch > 127) class_optcount = 10; /* No optimization possible */ - if (ch > 255) - { - if (!class_utf8) - { - class_utf8 = TRUE; - length += LINK_SIZE + 1 + 1; - } - length += 2 + extra; - - /* If this wide character is preceded by '-', add an extra 2 to - the length in case the previous character was < 128, because in - this case the whole range will be put into the list. */ - - if (ptr[-1] == '-') length += 2; - - /* Advance to the end of this character */ - - ptr += extra; - } - } -#endif - } - } - while (*(++ptr) != 0 && (inescq || *ptr != ']')); /* Concludes "do" above */ - - if (*ptr == 0) /* Missing terminating ']' */ - { - *errorptr = ERR6; - goto PCRE_ERROR_RETURN; - } - - /* We can optimize when there was only one optimizable character. Repeats - for positive and negated single one-byte chars are handled by the general - code. Here, we handle repeats for the class opcodes. */ - - if (class_optcount == 1) length += 3; else - { - length += 33; - - /* A repeat needs either 1 or 5 bytes. If it is a possessive quantifier, - we also need extra for wrapping the whole thing in a sub-pattern. */ - - if (*ptr != 0 && ptr[1] == '{' && is_counted_repeat(ptr+2)) - { - ptr = read_repeat_counts(ptr+2, &min, &max, errorptr); - if (*errorptr != NULL) goto PCRE_ERROR_RETURN; - if ((min == 0 && (max == 1 || max == -1)) || - (min == 1 && max == -1)) - length++; - else length += 5; - if (ptr[1] == '+') - { - ptr++; - length += 2 + 2*LINK_SIZE; - } - else if (ptr[1] == '?') ptr++; - } - } - continue; - - /* Brackets may be genuine groups or special things */ - - case '(': - branch_newextra = 0; - bracket_length = 1 + LINK_SIZE; - - /* Handle special forms of bracket, which all start (? */ - - if (ptr[1] == '?') - { - int set, unset; - int *optset; - - switch (c = ptr[2]) - { - /* Skip over comments entirely */ - case '#': - ptr += 3; - while (*ptr != 0 && *ptr != ')') ptr++; - if (*ptr == 0) - { - *errorptr = ERR18; - goto PCRE_ERROR_RETURN; - } - continue; - - /* Non-referencing groups and lookaheads just move the pointer on, and - then behave like a non-special bracket, except that they don't increment - the count of extracting brackets. Ditto for the "once only" bracket, - which is in Perl from version 5.005. */ - - case ':': - case '=': - case '!': - case '>': - ptr += 2; - break; - - /* (?R) specifies a recursive call to the regex, which is an extension - to provide the facility which can be obtained by (?p{perl-code}) in - Perl 5.6. In Perl 5.8 this has become (??{perl-code}). - - From PCRE 4.00, items such as (?3) specify subroutine-like "calls" to - the appropriate numbered brackets. This includes both recursive and - non-recursive calls. (?R) is now synonymous with (?0). */ - - case 'R': - ptr++; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - ptr += 2; - if (c != 'R') - while ((digitab[*(++ptr)] & ctype_digit) != 0); - if (*ptr != ')') - { - *errorptr = ERR29; - goto PCRE_ERROR_RETURN; - } - length += 1 + LINK_SIZE; - - /* If this item is quantified, it will get wrapped inside brackets so - as to use the code for quantified brackets. We jump down and use the - code that handles this for real brackets. */ - - if (ptr[1] == '+' || ptr[1] == '*' || ptr[1] == '?' || ptr[1] == '{') - { - length += 2 + 2 * LINK_SIZE; /* to make bracketed */ - duplength = 5 + 3 * LINK_SIZE; - goto HANDLE_QUANTIFIED_BRACKETS; - } - continue; - - /* (?C) is an extension which provides "callout" - to provide a bit of - the functionality of the Perl (?{...}) feature. An optional number may - follow (default is zero). */ - - case 'C': - ptr += 2; - while ((digitab[*(++ptr)] & ctype_digit) != 0); - if (*ptr != ')') - { - *errorptr = ERR39; - goto PCRE_ERROR_RETURN; - } - length += 2; - continue; - - /* Named subpatterns are an extension copied from Python */ - - case 'P': - ptr += 3; - if (*ptr == '<') - { - const uschar *p; /* Don't amalgamate; some compilers */ - p = ++ptr; /* grumble at autoincrement in declaration */ - while ((compile_block.ctypes[*ptr] & ctype_word) != 0) ptr++; - if (*ptr != '>') - { - *errorptr = ERR42; - goto PCRE_ERROR_RETURN; - } - name_count++; - if (ptr - p > max_name_size) max_name_size = (ptr - p); - break; - } - - if (*ptr == '=' || *ptr == '>') - { - while ((compile_block.ctypes[*(++ptr)] & ctype_word) != 0); - if (*ptr != ')') - { - *errorptr = ERR42; - goto PCRE_ERROR_RETURN; - } - break; - } - - /* Unknown character after (?P */ - - *errorptr = ERR41; - goto PCRE_ERROR_RETURN; - - /* Lookbehinds are in Perl from version 5.005 */ - - case '<': - ptr += 3; - if (*ptr == '=' || *ptr == '!') - { - branch_newextra = 1 + LINK_SIZE; - length += 1 + LINK_SIZE; /* For the first branch */ - break; - } - *errorptr = ERR24; - goto PCRE_ERROR_RETURN; - - /* Conditionals are in Perl from version 5.005. The bracket must either - be followed by a number (for bracket reference) or by an assertion - group, or (a PCRE extension) by 'R' for a recursion test. */ - - case '(': - if (ptr[3] == 'R' && ptr[4] == ')') - { - ptr += 4; - length += 3; - } - else if ((digitab[ptr[3]] & ctype_digit) != 0) - { - ptr += 4; - length += 3; - while ((digitab[*ptr] & ctype_digit) != 0) ptr++; - if (*ptr != ')') - { - *errorptr = ERR26; - goto PCRE_ERROR_RETURN; - } - } - else /* An assertion must follow */ - { - ptr++; /* Can treat like ':' as far as spacing is concerned */ - if (ptr[2] != '?' || - (ptr[3] != '=' && ptr[3] != '!' && ptr[3] != '<') ) - { - ptr += 2; /* To get right offset in message */ - *errorptr = ERR28; - goto PCRE_ERROR_RETURN; - } - } - break; - - /* Else loop checking valid options until ) is met. Anything else is an - error. If we are without any brackets, i.e. at top level, the settings - act as if specified in the options, so massage the options immediately. - This is for backward compatibility with Perl 5.004. */ - - default: - set = unset = 0; - optset = &set; - ptr += 2; - - for (;; ptr++) - { - c = *ptr; - switch (c) - { - case 'i': - *optset |= PCRE_CASELESS; - continue; - - case 'm': - *optset |= PCRE_MULTILINE; - continue; - - case 's': - *optset |= PCRE_DOTALL; - continue; - - case 'x': - *optset |= PCRE_EXTENDED; - continue; - - case 'X': - *optset |= PCRE_EXTRA; - continue; - - case 'U': - *optset |= PCRE_UNGREEDY; - continue; - - case '-': - optset = &unset; - continue; - - /* A termination by ')' indicates an options-setting-only item; if - this is at the very start of the pattern (indicated by item_count - being zero), we use it to set the global options. This is helpful - when analyzing the pattern for first characters, etc. Otherwise - nothing is done here and it is handled during the compiling - process. - - [Historical note: Up to Perl 5.8, options settings at top level - were always global settings, wherever they appeared in the pattern. - That is, they were equivalent to an external setting. From 5.8 - onwards, they apply only to what follows (which is what you might - expect).] */ - - case ')': - if (item_count == 0) - { - options = (options | set) & (~unset); - set = unset = 0; /* To save length */ - item_count--; /* To allow for several */ - } - - /* Fall through */ - - /* A termination by ':' indicates the start of a nested group with - the given options set. This is again handled at compile time, but - we must allow for compiled space if any of the ims options are - set. We also have to allow for resetting space at the end of - the group, which is why 4 is added to the length and not just 2. - If there are several changes of options within the same group, this - will lead to an over-estimate on the length, but this shouldn't - matter very much. We also have to allow for resetting options at - the start of any alternations, which we do by setting - branch_newextra to 2. Finally, we record whether the case-dependent - flag ever changes within the regex. This is used by the "required - character" code. */ - - case ':': - if (((set|unset) & PCRE_IMS) != 0) - { - length += 4; - branch_newextra = 2; - if (((set|unset) & PCRE_CASELESS) != 0) options |= PCRE_ICHANGED; - } - goto END_OPTIONS; - - /* Unrecognized option character */ - - default: - *errorptr = ERR12; - goto PCRE_ERROR_RETURN; - } - } - - /* If we hit a closing bracket, that's it - this is a freestanding - option-setting. We need to ensure that branch_extra is updated if - necessary. The only values branch_newextra can have here are 0 or 2. - If the value is 2, then branch_extra must either be 2 or 5, depending - on whether this is a lookbehind group or not. */ - - END_OPTIONS: - if (c == ')') - { - if (branch_newextra == 2 && - (branch_extra == 0 || branch_extra == 1+LINK_SIZE)) - branch_extra += branch_newextra; - continue; - } - - /* If options were terminated by ':' control comes here. Fall through - to handle the group below. */ - } - } - - /* Extracting brackets must be counted so we can process escapes in a - Perlish way. If the number exceeds EXTRACT_BASIC_MAX we are going to - need an additional 3 bytes of store per extracting bracket. However, if - PCRE_NO_AUTO)CAPTURE is set, unadorned brackets become non-capturing, so we - must leave the count alone (it will aways be zero). */ - - else if ((options & PCRE_NO_AUTO_CAPTURE) == 0) - { - bracount++; - if (bracount > EXTRACT_BASIC_MAX) bracket_length += 3; - } - - /* Save length for computing whole length at end if there's a repeat that - requires duplication of the group. Also save the current value of - branch_extra, and start the new group with the new value. If non-zero, this - will either be 2 for a (?imsx: group, or 3 for a lookbehind assertion. */ - - if (brastackptr >= sizeof(brastack)/sizeof(int)) - { - *errorptr = ERR19; - goto PCRE_ERROR_RETURN; - } - - bralenstack[brastackptr] = branch_extra; - branch_extra = branch_newextra; - - brastack[brastackptr++] = length; - length += bracket_length; - continue; - - /* Handle ket. Look for subsequent max/min; for certain sets of values we - have to replicate this bracket up to that many times. If brastackptr is - 0 this is an unmatched bracket which will generate an error, but take care - not to try to access brastack[-1] when computing the length and restoring - the branch_extra value. */ - - case ')': - length += 1 + LINK_SIZE; - if (brastackptr > 0) - { - duplength = length - brastack[--brastackptr]; - branch_extra = bralenstack[brastackptr]; - } - else duplength = 0; - - /* The following code is also used when a recursion such as (?3) is - followed by a quantifier, because in that case, it has to be wrapped inside - brackets so that the quantifier works. The value of duplength must be - set before arrival. */ - - HANDLE_QUANTIFIED_BRACKETS: - - /* Leave ptr at the final char; for read_repeat_counts this happens - automatically; for the others we need an increment. */ - - if ((c = ptr[1]) == '{' && is_counted_repeat(ptr+2)) - { - ptr = read_repeat_counts(ptr+2, &min, &max, errorptr); - if (*errorptr != NULL) goto PCRE_ERROR_RETURN; - } - else if (c == '*') { min = 0; max = -1; ptr++; } - else if (c == '+') { min = 1; max = -1; ptr++; } - else if (c == '?') { min = 0; max = 1; ptr++; } - else { min = 1; max = 1; } - - /* If the minimum is zero, we have to allow for an OP_BRAZERO before the - group, and if the maximum is greater than zero, we have to replicate - maxval-1 times; each replication acquires an OP_BRAZERO plus a nesting - bracket set. */ - - if (min == 0) - { - length++; - if (max > 0) length += (max - 1) * (duplength + 3 + 2*LINK_SIZE); - } - - /* When the minimum is greater than zero, we have to replicate up to - minval-1 times, with no additions required in the copies. Then, if there - is a limited maximum we have to replicate up to maxval-1 times allowing - for a BRAZERO item before each optional copy and nesting brackets for all - but one of the optional copies. */ - - else - { - length += (min - 1) * duplength; - if (max > min) /* Need this test as max=-1 means no limit */ - length += (max - min) * (duplength + 3 + 2*LINK_SIZE) - - (2 + 2*LINK_SIZE); - } - - /* Allow space for once brackets for "possessive quantifier" */ - - if (ptr[1] == '+') - { - ptr++; - length += 2 + 2*LINK_SIZE; - } - continue; - - /* Non-special character. For a run of such characters the length required - is the number of characters + 2, except that the maximum run length is - MAXLIT. We won't get a skipped space or a non-data escape or the start of a - # comment as the first character, so the length can't be zero. */ - - NORMAL_CHAR: - default: - length += 2; - runlength = 0; - do - { -#ifdef SUPPORT_UTF8 - lastcharlength = 1; /* Need length of last char for UTF-8 repeats */ -#endif - - /* If in a \Q...\E sequence, check for end; otherwise it's a literal */ - if (inescq) - { - if (c == '\\' && ptr[1] == 'E') - { - inescq = FALSE; - ptr++; - } - else runlength++; - continue; - } - - /* Skip whitespace and comments for /x */ - - if ((options & PCRE_EXTENDED) != 0) - { - if ((compile_block.ctypes[c] & ctype_space) != 0) continue; - if (c == '#') - { - /* The space before the ; is to avoid a warning on a silly compiler - on the Macintosh. */ - while ((c = *(++ptr)) != 0 && c != NEWLINE) ; - continue; - } - } - - /* Backslash may introduce a data char or a metacharacter; stop the - string before the latter. */ - - if (c == '\\') - { - const uschar *saveptr = ptr; - c = check_escape(&ptr, errorptr, bracount, options, FALSE); - if (*errorptr != NULL) goto PCRE_ERROR_RETURN; - if (c < 0) { ptr = saveptr; break; } - - /* In UTF-8 mode, add on the number of additional bytes needed to - encode this character, and save the total length in case this is a - final char that is repeated. */ - -#ifdef SUPPORT_UTF8 - if (utf8 && c > 127) - { - int i; - for (i = 0; i < sizeof(utf8_table1)/sizeof(int); i++) - if (c <= utf8_table1[i]) break; - runlength += i; - lastcharlength += i; - } -#endif - } - - /* Ordinary character or single-char escape */ - - runlength++; - } - - /* This "while" is the end of the "do" above. */ - - while (runlength < MAXLIT && - (compile_block.ctypes[c = *(++ptr)] & ctype_meta) == 0); - - /* If we hit a meta-character, back off to point to it */ - - if (runlength < MAXLIT) ptr--; - - /* If the last char in the string is a UTF-8 multibyte character, we must - set lastcharlength correctly. If it was specified as an escape, this will - already have been done above. However, we also have to support in-line - UTF-8 characters, so check backwards from where we are. */ - -#ifdef SUPPORT_UTF8 - if (utf8) - { - const uschar *lastptr = ptr - 1; - if ((*lastptr & 0x80) != 0) - { - while((*lastptr & 0xc0) == 0x80) lastptr--; - lastcharlength = ptr - lastptr; - } - } -#endif - - length += runlength; - continue; - } - } - -length += 2 + LINK_SIZE; /* For final KET and END */ - -if (length > MAX_PATTERN_SIZE) - { - *errorptr = ERR20; - return NULL; - } - -/* Compute the size of data block needed and get it, either from malloc or -externally provided function. */ - -size = length + sizeof(real_pcre) + name_count * (max_name_size + 3); -re = (real_pcre *)(pcre_malloc)(size); - -if (re == NULL) - { - *errorptr = ERR21; - return NULL; - } - -/* Put in the magic number, and save the size, options, and table pointer */ - -re->magic_number = MAGIC_NUMBER; -re->size = size; -re->options = options; -re->tables = tables; -re->name_entry_size = max_name_size + 3; -re->name_count = name_count; - -/* The starting points of the name/number translation table and of the code are -passed around in the compile data block. */ - -compile_block.names_found = 0; -compile_block.name_entry_size = max_name_size + 3; -compile_block.name_table = (uschar *)re + sizeof(real_pcre); -codestart = compile_block.name_table + re->name_entry_size * re->name_count; -compile_block.start_code = codestart; -compile_block.req_varyopt = 0; - -/* Set up a starting, non-extracting bracket, then compile the expression. On -error, *errorptr will be set non-NULL, so we don't need to look at the result -of the function here. */ - -ptr = (const uschar *)pattern; -code = (uschar *)codestart; -*code = OP_BRA; -bracount = 0; -(void)compile_regex(options, options & PCRE_IMS, &bracount, &code, &ptr, - errorptr, FALSE, 0, &firstbyte, &reqbyte, NULL, &compile_block); -re->top_bracket = bracount; -re->top_backref = compile_block.top_backref; - -/* If not reached end of pattern on success, there's an excess bracket. */ - -if (*errorptr == NULL && *ptr != 0) *errorptr = ERR22; - -/* Fill in the terminating state and check for disastrous overflow, but -if debugging, leave the test till after things are printed out. */ - -*code++ = OP_END; - -#ifndef DEBUG -if (code - codestart > length) *errorptr = ERR23; -#endif - -/* Give an error if there's back reference to a non-existent capturing -subpattern. */ - -if (re->top_backref > re->top_bracket) *errorptr = ERR15; - -/* Failed to compile, or error while post-processing */ - -if (*errorptr != NULL) - { - (pcre_free)(re); - PCRE_ERROR_RETURN: - *erroroffset = ptr - (const uschar *)pattern; - return NULL; - } - -/* If the anchored option was not passed, set the flag if we can determine that -the pattern is anchored by virtue of ^ characters or \A or anything else (such -as starting with .* when DOTALL is set). - -Otherwise, if we know what the first character has to be, save it, because that -speeds up unanchored matches no end. If not, see if we can set the -PCRE_STARTLINE flag. This is helpful for multiline matches when all branches -start with ^. and also when all branches start with .* for non-DOTALL matches. -*/ - -if ((options & PCRE_ANCHORED) == 0) - { - int temp_options = options; - if (is_anchored(codestart, &temp_options, 0, compile_block.backref_map)) - re->options |= PCRE_ANCHORED; - else - { - if (firstbyte < 0) - firstbyte = find_firstassertedchar(codestart, &temp_options, FALSE); - if (firstbyte >= 0) /* Remove caseless flag for non-caseable chars */ - { - int ch = firstbyte & 255; - re->first_byte = ((firstbyte & REQ_CASELESS) != 0 && - compile_block.fcc[ch] == ch)? ch : firstbyte; - re->options |= PCRE_FIRSTSET; - } - else if (is_startline(codestart, 0, compile_block.backref_map)) - re->options |= PCRE_STARTLINE; - } - } - -/* For an anchored pattern, we use the "required byte" only if it follows a -variable length item in the regex. Remove the caseless flag for non-caseable -chars. */ - -if (reqbyte >= 0 && - ((re->options & PCRE_ANCHORED) == 0 || (reqbyte & REQ_VARY) != 0)) - { - int ch = reqbyte & 255; - re->req_byte = ((reqbyte & REQ_CASELESS) != 0 && - compile_block.fcc[ch] == ch)? (reqbyte & ~REQ_CASELESS) : reqbyte; - re->options |= PCRE_REQCHSET; - } - -/* Print out the compiled data for debugging */ - -#ifdef DEBUG - -printf("Length = %d top_bracket = %d top_backref = %d\n", - length, re->top_bracket, re->top_backref); - -if (re->options != 0) - { - printf("%s%s%s%s%s%s%s%s%s\n", - ((re->options & PCRE_ANCHORED) != 0)? "anchored " : "", - ((re->options & PCRE_CASELESS) != 0)? "caseless " : "", - ((re->options & PCRE_ICHANGED) != 0)? "case state changed " : "", - ((re->options & PCRE_EXTENDED) != 0)? "extended " : "", - ((re->options & PCRE_MULTILINE) != 0)? "multiline " : "", - ((re->options & PCRE_DOTALL) != 0)? "dotall " : "", - ((re->options & PCRE_DOLLAR_ENDONLY) != 0)? "endonly " : "", - ((re->options & PCRE_EXTRA) != 0)? "extra " : "", - ((re->options & PCRE_UNGREEDY) != 0)? "ungreedy " : ""); - } - -if ((re->options & PCRE_FIRSTSET) != 0) - { - int ch = re->first_byte & 255; - const char *caseless = ((re->first_byte & REQ_CASELESS) == 0)? "" : " (caseless)"; - if (isprint(ch)) printf("First char = %c%s\n", ch, caseless); - else printf("First char = \\x%02x%s\n", ch, caseless); - } - -if ((re->options & PCRE_REQCHSET) != 0) - { - int ch = re->req_byte & 255; - const char *caseless = ((re->req_byte & REQ_CASELESS) == 0)? "" : " (caseless)"; - if (isprint(ch)) printf("Req char = %c%s\n", ch, caseless); - else printf("Req char = \\x%02x%s\n", ch, caseless); - } - -print_internals(re, stdout); - -/* This check is done here in the debugging case so that the code that -was compiled can be seen. */ - -if (code - codestart > length) - { - *errorptr = ERR23; - (pcre_free)(re); - *erroroffset = ptr - (uschar *)pattern; - return NULL; - } -#endif - -return (pcre *)re; -} - - - -/************************************************* -* Match a back-reference * -*************************************************/ - -/* If a back reference hasn't been set, the length that is passed is greater -than the number of characters left in the string, so the match fails. - -Arguments: - offset index into the offset vector - eptr points into the subject - length length to be matched - md points to match data block - ims the ims flags - -Returns: TRUE if matched -*/ - -static BOOL -match_ref(int offset, register const uschar *eptr, int length, match_data *md, - unsigned long int ims) -{ -const uschar *p = md->start_subject + md->offset_vector[offset]; - -#ifdef DEBUG -if (eptr >= md->end_subject) - printf("matching subject "); -else - { - printf("matching subject "); - pchars(eptr, length, TRUE, md); - } -printf(" against backref "); -pchars(p, length, FALSE, md); -printf("\n"); -#endif - -/* Always fail if not enough characters left */ - -if (length > md->end_subject - eptr) return FALSE; - -/* Separate the caselesss case for speed */ - -if ((ims & PCRE_CASELESS) != 0) - { - while (length-- > 0) - if (md->lcc[*p++] != md->lcc[*eptr++]) return FALSE; - } -else - { while (length-- > 0) if (*p++ != *eptr++) return FALSE; } - -return TRUE; -} - - -#ifdef SUPPORT_UTF8 -/************************************************* -* Match character against an XCLASS * -*************************************************/ - -/* This function is called from within the XCLASS code below, to match a -character against an extended class which might match values > 255. - -Arguments: - c the character - data points to the flag byte of the XCLASS data - -Returns: TRUE if character matches, else FALSE -*/ - -static BOOL -match_xclass(int c, const uschar *data) -{ -int t; -BOOL negated = (*data & XCL_NOT) != 0; - -/* Character values < 256 are matched against a bitmap, if one is present. If -not, we still carry on, because there may be ranges that start below 256 in the -additional data. */ - -if (c < 256) - { - if ((*data & XCL_MAP) != 0 && (data[1 + c/8] & (1 << (c&7))) != 0) - return !negated; /* char found */ - } - -/* Now match against the list of large chars or ranges that end with a large -char. First skip the bit map if present. */ - -if ((*data++ & XCL_MAP) != 0) data += 32; - -while ((t = *data++) != XCL_END) - { - int x, y; - GETCHARINC(x, data); - if (t == XCL_SINGLE) - { - if (c == x) return !negated; - } - else - { - GETCHARINC(y, data); - if (c >= x && c <= y) return !negated; - } - } - -return negated; /* char was not found */ -} -#endif - - -/*************************************************************************** -**************************************************************************** - RECURSION IN THE match() FUNCTION - -The match() function is highly recursive. Some regular expressions can cause -it to recurse thousands of times. I was writing for Unix, so I just let it -call itself recursively. This uses the stack for saving everything that has -to be saved for a recursive call. On Unix, the stack can be large, and this -works fine. - -It turns out that on non-Unix systems there are problems with programs that -use a lot of stack. (This despite the fact that every last chip has oodles -of memory these days, and techniques for extending the stack have been known -for decades.) So.... - -There is a fudge, triggered by defining NO_RECURSE, which avoids recursive -calls by keeping local variables that need to be preserved in blocks of memory -obtained from malloc instead instead of on the stack. Macros are used to -achieve this so that the actual code doesn't look very different to what it -always used to. -**************************************************************************** -***************************************************************************/ - - -/* These versions of the macros use the stack, as normal */ - -#ifndef NO_RECURSE -#define REGISTER register -#define RMATCH(rx,ra,rb,rc,rd,re,rf,rg) rx = match(ra,rb,rc,rd,re,rf,rg) -#define RRETURN(ra) return ra -#else - - -/* These versions of the macros manage a private stack on the heap. Note -that the rd argument of RMATCH isn't actually used. It's the md argument of -match(), which never actually changes. */ - -#define REGISTER - -#define RMATCH(rx,ra,rb,rc,rd,re,rf,rg)\ - {\ - heapframe *newframe = (pcre_stack_malloc)(sizeof(heapframe));\ - if (setjmp(frame->Xwhere) == 0)\ - {\ - newframe->Xeptr = ra;\ - newframe->Xecode = rb;\ - newframe->Xoffset_top = rc;\ - newframe->Xims = re;\ - newframe->Xeptrb = rf;\ - newframe->Xflags = rg;\ - newframe->Xprevframe = frame;\ - frame = newframe;\ - DPRINTF(("restarting from line %d\n", __LINE__));\ - goto HEAP_RECURSE;\ - }\ - else\ - {\ - DPRINTF(("longjumped back to line %d\n", __LINE__));\ - frame = md->thisframe;\ - rx = frame->Xresult;\ - }\ - } - -#define RRETURN(ra)\ - {\ - heapframe *newframe = frame;\ - frame = newframe->Xprevframe;\ - (pcre_stack_free)(newframe);\ - if (frame != NULL)\ - {\ - frame->Xresult = ra;\ - md->thisframe = frame;\ - longjmp(frame->Xwhere, 1);\ - }\ - return ra;\ - } - - -/* Structure for remembering the local variables in a private frame */ - -typedef struct heapframe { - struct heapframe *Xprevframe; - - /* Function arguments that may change */ - - const uschar *Xeptr; - const uschar *Xecode; - int Xoffset_top; - long int Xims; - eptrblock *Xeptrb; - int Xflags; - - /* Function local variables */ - - const uschar *Xcallpat; - const uschar *Xcharptr; - const uschar *Xdata; - const uschar *Xlastptr; - const uschar *Xnext; - const uschar *Xpp; - const uschar *Xprev; - const uschar *Xsaved_eptr; - - recursion_info Xnew_recursive; - - BOOL Xcur_is_word; - BOOL Xcondition; - BOOL Xminimize; - BOOL Xprev_is_word; - - unsigned long int Xoriginal_ims; - - int Xctype; - int Xfc; - int Xfi; - int Xlength; - int Xmax; - int Xmin; - int Xnumber; - int Xoffset; - int Xop; - int Xsave_capture_last; - int Xsave_offset1, Xsave_offset2, Xsave_offset3; - int Xstacksave[REC_STACK_SAVE_MAX]; - - eptrblock Xnewptrb; - - /* Place to pass back result, and where to jump back to */ - - int Xresult; - jmp_buf Xwhere; - -} heapframe; - -#endif - - -/*************************************************************************** -***************************************************************************/ - - - -/************************************************* -* Match from current position * -*************************************************/ - -/* On entry ecode points to the first opcode, and eptr to the first character -in the subject string, while eptrb holds the value of eptr at the start of the -last bracketed group - used for breaking infinite loops matching zero-length -strings. This function is called recursively in many circumstances. Whenever it -returns a negative (error) response, the outer incarnation must also return the -same response. - -Performance note: It might be tempting to extract commonly used fields from the -md structure (e.g. utf8, end_subject) into individual variables to improve -performance. Tests using gcc on a SPARC disproved this; in the first case, it -made performance worse. - -Arguments: - eptr pointer in subject - ecode position in code - offset_top current top pointer - md pointer to "static" info for the match - ims current /i, /m, and /s options - eptrb pointer to chain of blocks containing eptr at start of - brackets - for testing for empty matches - flags can contain - match_condassert - this is an assertion condition - match_isgroup - this is the start of a bracketed group - -Returns: MATCH_MATCH if matched ) these values are >= 0 - MATCH_NOMATCH if failed to match ) - a negative PCRE_ERROR_xxx value if aborted by an error condition - (e.g. stopped by recursion limit) -*/ - -static int -match(REGISTER const uschar *eptr, REGISTER const uschar *ecode, - int offset_top, match_data *md, unsigned long int ims, eptrblock *eptrb, - int flags) -{ -/* These variables do not need to be preserved over recursion in this function, -so they can be ordinary variables in all cases. Mark them with "register" -because they are used a lot in loops. */ - -register int rrc; /* Returns from recursive calls */ -register int i; /* Used for loops not involving calls to RMATCH() */ -register int c; /* Character values not kept over RMATCH() calls */ - -/* When recursion is not being used, all "local" variables that have to be -preserved over calls to RMATCH() are part of a "frame" which is obtained from -heap storage. Set up the top-level frame here; others are obtained from the -heap whenever RMATCH() does a "recursion". See the macro definitions above. */ - -#ifdef NO_RECURSE -heapframe *frame = (pcre_stack_malloc)(sizeof(heapframe)); -frame->Xprevframe = NULL; /* Marks the top level */ - -/* Copy in the original argument variables */ - -frame->Xeptr = eptr; -frame->Xecode = ecode; -frame->Xoffset_top = offset_top; -frame->Xims = ims; -frame->Xeptrb = eptrb; -frame->Xflags = flags; - -/* This is where control jumps back to to effect "recursion" */ - -HEAP_RECURSE: - -/* Macros make the argument variables come from the current frame */ - -#define eptr frame->Xeptr -#define ecode frame->Xecode -#define offset_top frame->Xoffset_top -#define ims frame->Xims -#define eptrb frame->Xeptrb -#define flags frame->Xflags - -/* Ditto for the local variables */ - -#define callpat frame->Xcallpat -#define charptr frame->Xcharptr -#define data frame->Xdata -#define lastptr frame->Xlastptr -#define next frame->Xnext -#define pp frame->Xpp -#define prev frame->Xprev -#define saved_eptr frame->Xsaved_eptr - -#define new_recursive frame->Xnew_recursive - -#define cur_is_word frame->Xcur_is_word -#define condition frame->Xcondition -#define minimize frame->Xminimize -#define prev_is_word frame->Xprev_is_word - -#define original_ims frame->Xoriginal_ims - -#define ctype frame->Xctype -#define fc frame->Xfc -#define fi frame->Xfi -#define length frame->Xlength -#define max frame->Xmax -#define min frame->Xmin -#define number frame->Xnumber -#define offset frame->Xoffset -#define op frame->Xop -#define save_capture_last frame->Xsave_capture_last -#define save_offset1 frame->Xsave_offset1 -#define save_offset2 frame->Xsave_offset2 -#define save_offset3 frame->Xsave_offset3 -#define stacksave frame->Xstacksave - -#define newptrb frame->Xnewptrb - -/* When recursion is being used, local variables are allocated on the stack and -get preserved during recursion in the normal way. In this environment, fi and -i, and fc and c, can be the same variables. */ - -#else -#define fi i -#define fc c - -const uschar *callpat; /* Many of these variables are used ony */ -const uschar *charptr; /* small blocks of the code. My normal */ -const uschar *data; /* style of coding would have declared */ -const uschar *lastptr; /* them within each of those blocks. */ -const uschar *next; /* However, in order to accommodate the */ -const uschar *pp; /* version of this code that uses an */ -const uschar *prev; /* external "stack" implemented on the */ -const uschar *saved_eptr; /* heap, it is easier to declare them */ - /* all here, so the declarations can */ -recursion_info new_recursive; /* be cut out in a block. The only */ - /* declarations within blocks below are */ -BOOL cur_is_word; /* for variables that do not have to */ -BOOL condition; /* be preserved over a recursive call */ -BOOL minimize; /* to RMATCH(). */ -BOOL prev_is_word; - -unsigned long int original_ims; - -int ctype; -int length; -int max; -int min; -int number; -int offset; -int op; -int save_capture_last; -int save_offset1, save_offset2, save_offset3; -int stacksave[REC_STACK_SAVE_MAX]; - -eptrblock newptrb; -#endif - - -/* OK, now we can get on with the real code of the function. Recursion is -specified by the macros RMATCH and RRETURN. When NO_RECURSE is *not* defined, -these just turn into a recursive call to match() and a "return", respectively. -However, RMATCH isn't like a function call because it's quite a complicated -macro. It has to be used in one particular way. This shouldn't, however, impact -performance when true recursion is being used. */ - -if (md->match_call_count++ >= md->match_limit) RRETURN(PCRE_ERROR_MATCHLIMIT); - -original_ims = ims; /* Save for resetting on ')' */ - -/* At the start of a bracketed group, add the current subject pointer to the -stack of such pointers, to be re-instated at the end of the group when we hit -the closing ket. When match() is called in other circumstances, we don't add to -this stack. */ - -if ((flags & match_isgroup) != 0) - { - newptrb.epb_prev = eptrb; - newptrb.epb_saved_eptr = eptr; - eptrb = &newptrb; - } - -/* Now start processing the operations. */ - -for (;;) - { - op = *ecode; - minimize = FALSE; - - /* Opening capturing bracket. If there is space in the offset vector, save - the current subject position in the working slot at the top of the vector. We - mustn't change the current values of the data slot, because they may be set - from a previous iteration of this group, and be referred to by a reference - inside the group. - - If the bracket fails to match, we need to restore this value and also the - values of the final offsets, in case they were set by a previous iteration of - the same bracket. - - If there isn't enough space in the offset vector, treat this as if it were a - non-capturing bracket. Don't worry about setting the flag for the error case - here; that is handled in the code for KET. */ - - if (op > OP_BRA) - { - number = op - OP_BRA; - - /* For extended extraction brackets (large number), we have to fish out the - number from a dummy opcode at the start. */ - - if (number > EXTRACT_BASIC_MAX) - number = GET2(ecode, 2+LINK_SIZE); - offset = number << 1; - -#ifdef DEBUG - printf("start bracket %d subject=", number); - pchars(eptr, 16, TRUE, md); - printf("\n"); -#endif - - if (offset < md->offset_max) - { - save_offset1 = md->offset_vector[offset]; - save_offset2 = md->offset_vector[offset+1]; - save_offset3 = md->offset_vector[md->offset_end - number]; - save_capture_last = md->capture_last; - - DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3)); - md->offset_vector[md->offset_end - number] = eptr - md->start_subject; - - do - { - RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, - match_isgroup); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - md->capture_last = save_capture_last; - ecode += GET(ecode, 1); - } - while (*ecode == OP_ALT); - - DPRINTF(("bracket %d failed\n", number)); - - md->offset_vector[offset] = save_offset1; - md->offset_vector[offset+1] = save_offset2; - md->offset_vector[md->offset_end - number] = save_offset3; - - RRETURN(MATCH_NOMATCH); - } - - /* Insufficient room for saving captured contents */ - - else op = OP_BRA; - } - - /* Other types of node can be handled by a switch */ - - switch(op) - { - case OP_BRA: /* Non-capturing bracket: optimized */ - DPRINTF(("start bracket 0\n")); - do - { - RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, - match_isgroup); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - ecode += GET(ecode, 1); - } - while (*ecode == OP_ALT); - DPRINTF(("bracket 0 failed\n")); - RRETURN(MATCH_NOMATCH); - - /* Conditional group: compilation checked that there are no more than - two branches. If the condition is false, skipping the first branch takes us - past the end if there is only one branch, but that's OK because that is - exactly what going to the ket would do. */ - - case OP_COND: - if (ecode[LINK_SIZE+1] == OP_CREF) /* Condition extract or recurse test */ - { - offset = GET2(ecode, LINK_SIZE+2) << 1; /* Doubled ref number */ - condition = (offset == CREF_RECURSE * 2)? - (md->recursive != NULL) : - (offset < offset_top && md->offset_vector[offset] >= 0); - RMATCH(rrc, eptr, ecode + (condition? - (LINK_SIZE + 4) : (LINK_SIZE + 1 + GET(ecode, 1))), - offset_top, md, ims, eptrb, match_isgroup); - RRETURN(rrc); - } - - /* The condition is an assertion. Call match() to evaluate it - setting - the final argument TRUE causes it to stop at the end of an assertion. */ - - else - { - RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, - match_condassert | match_isgroup); - if (rrc == MATCH_MATCH) - { - ecode += 1 + LINK_SIZE + GET(ecode, LINK_SIZE+2); - while (*ecode == OP_ALT) ecode += GET(ecode, 1); - } - else if (rrc != MATCH_NOMATCH) - { - RRETURN(rrc); /* Need braces because of following else */ - } - else ecode += GET(ecode, 1); - RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, - match_isgroup); - RRETURN(rrc); - } - /* Control never reaches here */ - - /* Skip over conditional reference or large extraction number data if - encountered. */ - - case OP_CREF: - case OP_BRANUMBER: - ecode += 3; - break; - - /* End of the pattern. If we are in a recursion, we should restore the - offsets appropriately and continue from after the call. */ - - case OP_END: - if (md->recursive != NULL && md->recursive->group_num == 0) - { - recursion_info *rec = md->recursive; - DPRINTF(("Hit the end in a (?0) recursion\n")); - md->recursive = rec->prevrec; - memmove(md->offset_vector, rec->offset_save, - rec->saved_max * sizeof(int)); - md->start_match = rec->save_start; - ims = original_ims; - ecode = rec->after_call; - break; - } - - /* Otherwise, if PCRE_NOTEMPTY is set, fail if we have matched an empty - string - backtracking will then try other alternatives, if any. */ - - if (md->notempty && eptr == md->start_match) RRETURN(MATCH_NOMATCH); - md->end_match_ptr = eptr; /* Record where we ended */ - md->end_offset_top = offset_top; /* and how many extracts were taken */ - RRETURN(MATCH_MATCH); - - /* Change option settings */ - - case OP_OPT: - ims = ecode[1]; - ecode += 2; - DPRINTF(("ims set to %02lx\n", ims)); - break; - - /* Assertion brackets. Check the alternative branches in turn - the - matching won't pass the KET for an assertion. If any one branch matches, - the assertion is true. Lookbehind assertions have an OP_REVERSE item at the - start of each branch to move the current point backwards, so the code at - this level is identical to the lookahead case. */ - - case OP_ASSERT: - case OP_ASSERTBACK: - do - { - RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, - match_isgroup); - if (rrc == MATCH_MATCH) break; - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - ecode += GET(ecode, 1); - } - while (*ecode == OP_ALT); - if (*ecode == OP_KET) RRETURN(MATCH_NOMATCH); - - /* If checking an assertion for a condition, return MATCH_MATCH. */ - - if ((flags & match_condassert) != 0) RRETURN(MATCH_MATCH); - - /* Continue from after the assertion, updating the offsets high water - mark, since extracts may have been taken during the assertion. */ - - do ecode += GET(ecode,1); while (*ecode == OP_ALT); - ecode += 1 + LINK_SIZE; - offset_top = md->end_offset_top; - continue; - - /* Negative assertion: all branches must fail to match */ - - case OP_ASSERT_NOT: - case OP_ASSERTBACK_NOT: - do - { - RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, - match_isgroup); - if (rrc == MATCH_MATCH) RRETURN(MATCH_NOMATCH); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - ecode += GET(ecode,1); - } - while (*ecode == OP_ALT); - - if ((flags & match_condassert) != 0) RRETURN(MATCH_MATCH); - - ecode += 1 + LINK_SIZE; - continue; - - /* Move the subject pointer back. This occurs only at the start of - each branch of a lookbehind assertion. If we are too close to the start to - move back, this match function fails. When working with UTF-8 we move - back a number of characters, not bytes. */ - - case OP_REVERSE: -#ifdef SUPPORT_UTF8 - if (md->utf8) - { - c = GET(ecode,1); - for (i = 0; i < c; i++) - { - eptr--; - if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH); - BACKCHAR(eptr) - } - } - else -#endif - - /* No UTF-8 support, or not in UTF-8 mode: count is byte count */ - - { - eptr -= GET(ecode,1); - if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH); - } - - /* Skip to next op code */ - - ecode += 1 + LINK_SIZE; - break; - - /* The callout item calls an external function, if one is provided, passing - details of the match so far. This is mainly for debugging, though the - function is able to force a failure. */ - - case OP_CALLOUT: - if (pcre_callout != NULL) - { - pcre_callout_block cb; - cb.version = 0; /* Version 0 of the callout block */ - cb.callout_number = ecode[1]; - cb.offset_vector = md->offset_vector; - cb.subject = (const char *)md->start_subject; - cb.subject_length = md->end_subject - md->start_subject; - cb.start_match = md->start_match - md->start_subject; - cb.current_position = eptr - md->start_subject; - cb.capture_top = offset_top/2; - cb.capture_last = md->capture_last; - cb.callout_data = md->callout_data; - if ((rrc = (*pcre_callout)(&cb)) > 0) RRETURN(MATCH_NOMATCH); - if (rrc < 0) RRETURN(rrc); - } - ecode += 2; - break; - - /* Recursion either matches the current regex, or some subexpression. The - offset data is the offset to the starting bracket from the start of the - whole pattern. (This is so that it works from duplicated subpatterns.) - - If there are any capturing brackets started but not finished, we have to - save their starting points and reinstate them after the recursion. However, - we don't know how many such there are (offset_top records the completed - total) so we just have to save all the potential data. There may be up to - 65535 such values, which is too large to put on the stack, but using malloc - for small numbers seems expensive. As a compromise, the stack is used when - there are no more than REC_STACK_SAVE_MAX values to store; otherwise malloc - is used. A problem is what to do if the malloc fails ... there is no way of - returning to the top level with an error. Save the top REC_STACK_SAVE_MAX - values on the stack, and accept that the rest may be wrong. - - There are also other values that have to be saved. We use a chained - sequence of blocks that actually live on the stack. Thanks to Robin Houston - for the original version of this logic. */ - - case OP_RECURSE: - { - callpat = md->start_code + GET(ecode, 1); - new_recursive.group_num = *callpat - OP_BRA; - - /* For extended extraction brackets (large number), we have to fish out - the number from a dummy opcode at the start. */ - - if (new_recursive.group_num > EXTRACT_BASIC_MAX) - new_recursive.group_num = GET2(callpat, 2+LINK_SIZE); - - /* Add to "recursing stack" */ - - new_recursive.prevrec = md->recursive; - md->recursive = &new_recursive; - - /* Find where to continue from afterwards */ - - ecode += 1 + LINK_SIZE; - new_recursive.after_call = ecode; - - /* Now save the offset data. */ - - new_recursive.saved_max = md->offset_end; - if (new_recursive.saved_max <= REC_STACK_SAVE_MAX) - new_recursive.offset_save = stacksave; - else - { - new_recursive.offset_save = - (int *)(pcre_malloc)(new_recursive.saved_max * sizeof(int)); - if (new_recursive.offset_save == NULL) RRETURN(PCRE_ERROR_NOMEMORY); - } - - memcpy(new_recursive.offset_save, md->offset_vector, - new_recursive.saved_max * sizeof(int)); - new_recursive.save_start = md->start_match; - md->start_match = eptr; - - /* OK, now we can do the recursion. For each top-level alternative we - restore the offset and recursion data. */ - - DPRINTF(("Recursing into group %d\n", new_recursive.group_num)); - do - { - RMATCH(rrc, eptr, callpat + 1 + LINK_SIZE, offset_top, md, ims, - eptrb, match_isgroup); - if (rrc == MATCH_MATCH) - { - md->recursive = new_recursive.prevrec; - if (new_recursive.offset_save != stacksave) - (pcre_free)(new_recursive.offset_save); - RRETURN(MATCH_MATCH); - } - else if (rrc != MATCH_NOMATCH) RRETURN(rrc); - - md->recursive = &new_recursive; - memcpy(md->offset_vector, new_recursive.offset_save, - new_recursive.saved_max * sizeof(int)); - callpat += GET(callpat, 1); - } - while (*callpat == OP_ALT); - - DPRINTF(("Recursion didn't match\n")); - md->recursive = new_recursive.prevrec; - if (new_recursive.offset_save != stacksave) - (pcre_free)(new_recursive.offset_save); - RRETURN(MATCH_NOMATCH); - } - /* Control never reaches here */ - - /* "Once" brackets are like assertion brackets except that after a match, - the point in the subject string is not moved back. Thus there can never be - a move back into the brackets. Friedl calls these "atomic" subpatterns. - Check the alternative branches in turn - the matching won't pass the KET - for this kind of subpattern. If any one branch matches, we carry on as at - the end of a normal bracket, leaving the subject pointer. */ - - case OP_ONCE: - { - prev = ecode; - saved_eptr = eptr; - - do - { - RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, - eptrb, match_isgroup); - if (rrc == MATCH_MATCH) break; - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - ecode += GET(ecode,1); - } - while (*ecode == OP_ALT); - - /* If hit the end of the group (which could be repeated), fail */ - - if (*ecode != OP_ONCE && *ecode != OP_ALT) RRETURN(MATCH_NOMATCH); - - /* Continue as from after the assertion, updating the offsets high water - mark, since extracts may have been taken. */ - - do ecode += GET(ecode,1); while (*ecode == OP_ALT); - - offset_top = md->end_offset_top; - eptr = md->end_match_ptr; - - /* For a non-repeating ket, just continue at this level. This also - happens for a repeating ket if no characters were matched in the group. - This is the forcible breaking of infinite loops as implemented in Perl - 5.005. If there is an options reset, it will get obeyed in the normal - course of events. */ - - if (*ecode == OP_KET || eptr == saved_eptr) - { - ecode += 1+LINK_SIZE; - break; - } - - /* The repeating kets try the rest of the pattern or restart from the - preceding bracket, in the appropriate order. We need to reset any options - that changed within the bracket before re-running it, so check the next - opcode. */ - - if (ecode[1+LINK_SIZE] == OP_OPT) - { - ims = (ims & ~PCRE_IMS) | ecode[4]; - DPRINTF(("ims set to %02lx at group repeat\n", ims)); - } - - if (*ecode == OP_KETRMIN) - { - RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - RMATCH(rrc, eptr, prev, offset_top, md, ims, eptrb, match_isgroup); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - } - else /* OP_KETRMAX */ - { - RMATCH(rrc, eptr, prev, offset_top, md, ims, eptrb, match_isgroup); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - RMATCH(rrc, eptr, ecode + 1+LINK_SIZE, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - } - } - RRETURN(MATCH_NOMATCH); - - /* An alternation is the end of a branch; scan along to find the end of the - bracketed group and go to there. */ - - case OP_ALT: - do ecode += GET(ecode,1); while (*ecode == OP_ALT); - break; - - /* BRAZERO and BRAMINZERO occur just before a bracket group, indicating - that it may occur zero times. It may repeat infinitely, or not at all - - i.e. it could be ()* or ()? in the pattern. Brackets with fixed upper - repeat limits are compiled as a number of copies, with the optional ones - preceded by BRAZERO or BRAMINZERO. */ - - case OP_BRAZERO: - { - next = ecode+1; - RMATCH(rrc, eptr, next, offset_top, md, ims, eptrb, match_isgroup); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - do next += GET(next,1); while (*next == OP_ALT); - ecode = next + 1+LINK_SIZE; - } - break; - - case OP_BRAMINZERO: - { - next = ecode+1; - do next += GET(next,1); while (*next == OP_ALT); - RMATCH(rrc, eptr, next + 1+LINK_SIZE, offset_top, md, ims, eptrb, - match_isgroup); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - ecode++; - } - break; - - /* End of a group, repeated or non-repeating. If we are at the end of - an assertion "group", stop matching and return MATCH_MATCH, but record the - current high water mark for use by positive assertions. Do this also - for the "once" (not-backup up) groups. */ - - case OP_KET: - case OP_KETRMIN: - case OP_KETRMAX: - { - prev = ecode - GET(ecode, 1); - saved_eptr = eptrb->epb_saved_eptr; - - /* Back up the stack of bracket start pointers. */ - - eptrb = eptrb->epb_prev; - - if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT || - *prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT || - *prev == OP_ONCE) - { - md->end_match_ptr = eptr; /* For ONCE */ - md->end_offset_top = offset_top; - RRETURN(MATCH_MATCH); - } - - /* In all other cases except a conditional group we have to check the - group number back at the start and if necessary complete handling an - extraction by setting the offsets and bumping the high water mark. */ - - if (*prev != OP_COND) - { - number = *prev - OP_BRA; - - /* For extended extraction brackets (large number), we have to fish out - the number from a dummy opcode at the start. */ - - if (number > EXTRACT_BASIC_MAX) number = GET2(prev, 2+LINK_SIZE); - offset = number << 1; - -#ifdef DEBUG - printf("end bracket %d", number); - printf("\n"); -#endif - - /* Test for a numbered group. This includes groups called as a result - of recursion. Note that whole-pattern recursion is coded as a recurse - into group 0, so it won't be picked up here. Instead, we catch it when - the OP_END is reached. */ - - if (number > 0) - { - md->capture_last = number; - if (offset >= md->offset_max) md->offset_overflow = TRUE; else - { - md->offset_vector[offset] = - md->offset_vector[md->offset_end - number]; - md->offset_vector[offset+1] = eptr - md->start_subject; - if (offset_top <= offset) offset_top = offset + 2; - } - - /* Handle a recursively called group. Restore the offsets - appropriately and continue from after the call. */ - - if (md->recursive != NULL && md->recursive->group_num == number) - { - recursion_info *rec = md->recursive; - DPRINTF(("Recursion (%d) succeeded - continuing\n", number)); - md->recursive = rec->prevrec; - md->start_match = rec->save_start; - memcpy(md->offset_vector, rec->offset_save, - rec->saved_max * sizeof(int)); - ecode = rec->after_call; - ims = original_ims; - break; - } - } - } - - /* Reset the value of the ims flags, in case they got changed during - the group. */ - - ims = original_ims; - DPRINTF(("ims reset to %02lx\n", ims)); - - /* For a non-repeating ket, just continue at this level. This also - happens for a repeating ket if no characters were matched in the group. - This is the forcible breaking of infinite loops as implemented in Perl - 5.005. If there is an options reset, it will get obeyed in the normal - course of events. */ - - if (*ecode == OP_KET || eptr == saved_eptr) - { - ecode += 1 + LINK_SIZE; - break; - } - - /* The repeating kets try the rest of the pattern or restart from the - preceding bracket, in the appropriate order. */ - - if (*ecode == OP_KETRMIN) - { - RMATCH(rrc, eptr, ecode + 1+LINK_SIZE, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - RMATCH(rrc, eptr, prev, offset_top, md, ims, eptrb, match_isgroup); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - } - else /* OP_KETRMAX */ - { - RMATCH(rrc, eptr, prev, offset_top, md, ims, eptrb, match_isgroup); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - RMATCH(rrc, eptr, ecode + 1+LINK_SIZE, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - } - } - - RRETURN(MATCH_NOMATCH); - - /* Start of subject unless notbol, or after internal newline if multiline */ - - case OP_CIRC: - if (md->notbol && eptr == md->start_subject) RRETURN(MATCH_NOMATCH); - if ((ims & PCRE_MULTILINE) != 0) - { - if (eptr != md->start_subject && eptr[-1] != NEWLINE) - RRETURN(MATCH_NOMATCH); - ecode++; - break; - } - /* ... else fall through */ - - /* Start of subject assertion */ - - case OP_SOD: - if (eptr != md->start_subject) RRETURN(MATCH_NOMATCH); - ecode++; - break; - - /* Start of match assertion */ - - case OP_SOM: - if (eptr != md->start_subject + md->start_offset) RRETURN(MATCH_NOMATCH); - ecode++; - break; - - /* Assert before internal newline if multiline, or before a terminating - newline unless endonly is set, else end of subject unless noteol is set. */ - - case OP_DOLL: - if ((ims & PCRE_MULTILINE) != 0) - { - if (eptr < md->end_subject) - { if (*eptr != NEWLINE) RRETURN(MATCH_NOMATCH); } - else - { if (md->noteol) RRETURN(MATCH_NOMATCH); } - ecode++; - break; - } - else - { - if (md->noteol) RRETURN(MATCH_NOMATCH); - if (!md->endonly) - { - if (eptr < md->end_subject - 1 || - (eptr == md->end_subject - 1 && *eptr != NEWLINE)) - RRETURN(MATCH_NOMATCH); - ecode++; - break; - } - } - /* ... else fall through */ - - /* End of subject assertion (\z) */ - - case OP_EOD: - if (eptr < md->end_subject) RRETURN(MATCH_NOMATCH); - ecode++; - break; - - /* End of subject or ending \n assertion (\Z) */ - - case OP_EODN: - if (eptr < md->end_subject - 1 || - (eptr == md->end_subject - 1 && *eptr != NEWLINE)) RRETURN(MATCH_NOMATCH); - ecode++; - break; - - /* Word boundary assertions */ - - case OP_NOT_WORD_BOUNDARY: - case OP_WORD_BOUNDARY: - { - - /* Find out if the previous and current characters are "word" characters. - It takes a bit more work in UTF-8 mode. Characters > 255 are assumed to - be "non-word" characters. */ - -#ifdef SUPPORT_UTF8 - if (md->utf8) - { - if (eptr == md->start_subject) prev_is_word = FALSE; else - { - lastptr = eptr - 1; - while((*lastptr & 0xc0) == 0x80) lastptr--; - GETCHAR(c, lastptr); - prev_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0; - } - if (eptr >= md->end_subject) cur_is_word = FALSE; else - { - GETCHAR(c, eptr); - cur_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0; - } - } - else -#endif - - /* More streamlined when not in UTF-8 mode */ - - { - prev_is_word = (eptr != md->start_subject) && - ((md->ctypes[eptr[-1]] & ctype_word) != 0); - cur_is_word = (eptr < md->end_subject) && - ((md->ctypes[*eptr] & ctype_word) != 0); - } - - /* Now see if the situation is what we want */ - - if ((*ecode++ == OP_WORD_BOUNDARY)? - cur_is_word == prev_is_word : cur_is_word != prev_is_word) - RRETURN(MATCH_NOMATCH); - } - break; - - /* Match a single character type; inline for speed */ - - case OP_ANY: - if ((ims & PCRE_DOTALL) == 0 && eptr < md->end_subject && *eptr == NEWLINE) - RRETURN(MATCH_NOMATCH); - if (eptr++ >= md->end_subject) RRETURN(MATCH_NOMATCH); -#ifdef SUPPORT_UTF8 - if (md->utf8) - while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; -#endif - ecode++; - break; - - /* Match a single byte, even in UTF-8 mode. This opcode really does match - any byte, even newline, independent of the setting of PCRE_DOTALL. */ - - case OP_ANYBYTE: - if (eptr++ >= md->end_subject) RRETURN(MATCH_NOMATCH); - ecode++; - break; - - case OP_NOT_DIGIT: - if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); - GETCHARINCTEST(c, eptr); - if ( -#ifdef SUPPORT_UTF8 - c < 256 && -#endif - (md->ctypes[c] & ctype_digit) != 0 - ) - RRETURN(MATCH_NOMATCH); - ecode++; - break; - - case OP_DIGIT: - if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); - GETCHARINCTEST(c, eptr); - if ( -#ifdef SUPPORT_UTF8 - c >= 256 || -#endif - (md->ctypes[c] & ctype_digit) == 0 - ) - RRETURN(MATCH_NOMATCH); - ecode++; - break; - - case OP_NOT_WHITESPACE: - if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); - GETCHARINCTEST(c, eptr); - if ( -#ifdef SUPPORT_UTF8 - c < 256 && -#endif - (md->ctypes[c] & ctype_space) != 0 - ) - RRETURN(MATCH_NOMATCH); - ecode++; - break; - - case OP_WHITESPACE: - if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); - GETCHARINCTEST(c, eptr); - if ( -#ifdef SUPPORT_UTF8 - c >= 256 || -#endif - (md->ctypes[c] & ctype_space) == 0 - ) - RRETURN(MATCH_NOMATCH); - ecode++; - break; - - case OP_NOT_WORDCHAR: - if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); - GETCHARINCTEST(c, eptr); - if ( -#ifdef SUPPORT_UTF8 - c < 256 && -#endif - (md->ctypes[c] & ctype_word) != 0 - ) - RRETURN(MATCH_NOMATCH); - ecode++; - break; - - case OP_WORDCHAR: - if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); - GETCHARINCTEST(c, eptr); - if ( -#ifdef SUPPORT_UTF8 - c >= 256 || -#endif - (md->ctypes[c] & ctype_word) == 0 - ) - RRETURN(MATCH_NOMATCH); - ecode++; - break; - - /* Match a back reference, possibly repeatedly. Look past the end of the - item to see if there is repeat information following. The code is similar - to that for character classes, but repeated for efficiency. Then obey - similar code to character type repeats - written out again for speed. - However, if the referenced string is the empty string, always treat - it as matched, any number of times (otherwise there could be infinite - loops). */ - - case OP_REF: - { - offset = GET2(ecode, 1) << 1; /* Doubled ref number */ - ecode += 3; /* Advance past item */ - - /* If the reference is unset, set the length to be longer than the amount - of subject left; this ensures that every attempt at a match fails. We - can't just fail here, because of the possibility of quantifiers with zero - minima. */ - - length = (offset >= offset_top || md->offset_vector[offset] < 0)? - md->end_subject - eptr + 1 : - md->offset_vector[offset+1] - md->offset_vector[offset]; - - /* Set up for repetition, or handle the non-repeated case */ - - switch (*ecode) - { - case OP_CRSTAR: - case OP_CRMINSTAR: - case OP_CRPLUS: - case OP_CRMINPLUS: - case OP_CRQUERY: - case OP_CRMINQUERY: - c = *ecode++ - OP_CRSTAR; - minimize = (c & 1) != 0; - min = rep_min[c]; /* Pick up values from tables; */ - max = rep_max[c]; /* zero for max => infinity */ - if (max == 0) max = INT_MAX; - break; - - case OP_CRRANGE: - case OP_CRMINRANGE: - minimize = (*ecode == OP_CRMINRANGE); - min = GET2(ecode, 1); - max = GET2(ecode, 3); - if (max == 0) max = INT_MAX; - ecode += 5; - break; - - default: /* No repeat follows */ - if (!match_ref(offset, eptr, length, md, ims)) RRETURN(MATCH_NOMATCH); - eptr += length; - continue; /* With the main loop */ - } - - /* If the length of the reference is zero, just continue with the - main loop. */ - - if (length == 0) continue; - - /* First, ensure the minimum number of matches are present. We get back - the length of the reference string explicitly rather than passing the - address of eptr, so that eptr can be a register variable. */ - - for (i = 1; i <= min; i++) - { - if (!match_ref(offset, eptr, length, md, ims)) RRETURN(MATCH_NOMATCH); - eptr += length; - } - - /* If min = max, continue at the same level without recursion. - They are not both allowed to be zero. */ - - if (min == max) continue; - - /* If minimizing, keep trying and advancing the pointer */ - - if (minimize) - { - for (fi = min;; fi++) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max || !match_ref(offset, eptr, length, md, ims)) - RRETURN(MATCH_NOMATCH); - eptr += length; - } - /* Control never gets here */ - } - - /* If maximizing, find the longest string and work backwards */ - - else - { - pp = eptr; - for (i = min; i < max; i++) - { - if (!match_ref(offset, eptr, length, md, ims)) break; - eptr += length; - } - while (eptr >= pp) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - eptr -= length; - } - RRETURN(MATCH_NOMATCH); - } - } - /* Control never gets here */ - - - - /* Match a bit-mapped character class, possibly repeatedly. This op code is - used when all the characters in the class have values in the range 0-255. - The only difference between OP_CLASS and OP_NCLASS occurs when a data - character outside the range is encountered. - - First, look past the end of the item to see if there is repeat information - following. Then obey similar code to character type repeats - written out - again for speed. */ - - case OP_NCLASS: - case OP_CLASS: - { - data = ecode + 1; /* Save for matching */ - ecode += 33; /* Advance past the item */ - - switch (*ecode) - { - case OP_CRSTAR: - case OP_CRMINSTAR: - case OP_CRPLUS: - case OP_CRMINPLUS: - case OP_CRQUERY: - case OP_CRMINQUERY: - c = *ecode++ - OP_CRSTAR; - minimize = (c & 1) != 0; - min = rep_min[c]; /* Pick up values from tables; */ - max = rep_max[c]; /* zero for max => infinity */ - if (max == 0) max = INT_MAX; - break; - - case OP_CRRANGE: - case OP_CRMINRANGE: - minimize = (*ecode == OP_CRMINRANGE); - min = GET2(ecode, 1); - max = GET2(ecode, 3); - if (max == 0) max = INT_MAX; - ecode += 5; - break; - - default: /* No repeat follows */ - min = max = 1; - break; - } - - /* First, ensure the minimum number of matches are present. */ - -#ifdef SUPPORT_UTF8 - /* UTF-8 mode */ - if (md->utf8) - { - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); - GETCHARINC(c, eptr); - if (c > 255) - { - if (op == OP_CLASS) RRETURN(MATCH_NOMATCH); - } - else - { - if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); - } - } - } - else -#endif - /* Not UTF-8 mode */ - { - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); - c = *eptr++; - if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); - } - } - - /* If max == min we can continue with the main loop without the - need to recurse. */ - - if (min == max) continue; - - /* If minimizing, keep testing the rest of the expression and advancing - the pointer while it matches the class. */ - - if (minimize) - { -#ifdef SUPPORT_UTF8 - /* UTF-8 mode */ - if (md->utf8) - { - for (fi = min;; fi++) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); - GETCHARINC(c, eptr); - if (c > 255) - { - if (op == OP_CLASS) RRETURN(MATCH_NOMATCH); - } - else - { - if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); - } - } - } - else -#endif - /* Not UTF-8 mode */ - { - for (fi = min;; fi++) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); - c = *eptr++; - if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); - } - } - /* Control never gets here */ - } - - /* If maximizing, find the longest possible run, then work backwards. */ - - else - { - pp = eptr; - -#ifdef SUPPORT_UTF8 - /* UTF-8 mode */ - if (md->utf8) - { - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) break; - GETCHARLEN(c, eptr, len); - if (c > 255) - { - if (op == OP_CLASS) break; - } - else - { - if ((data[c/8] & (1 << (c&7))) == 0) break; - } - eptr += len; - } - for (;;) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (eptr-- == pp) break; /* Stop if tried at original pos */ - BACKCHAR(eptr); - } - } - else -#endif - /* Not UTF-8 mode */ - { - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject) break; - c = *eptr; - if ((data[c/8] & (1 << (c&7))) == 0) break; - eptr++; - } - while (eptr >= pp) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - eptr--; - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - } - } - - RRETURN(MATCH_NOMATCH); - } - } - /* Control never gets here */ - - - /* Match an extended character class. This opcode is encountered only - in UTF-8 mode, because that's the only time it is compiled. */ - -#ifdef SUPPORT_UTF8 - case OP_XCLASS: - { - data = ecode + 1 + LINK_SIZE; /* Save for matching */ - ecode += GET(ecode, 1); /* Advance past the item */ - - switch (*ecode) - { - case OP_CRSTAR: - case OP_CRMINSTAR: - case OP_CRPLUS: - case OP_CRMINPLUS: - case OP_CRQUERY: - case OP_CRMINQUERY: - c = *ecode++ - OP_CRSTAR; - minimize = (c & 1) != 0; - min = rep_min[c]; /* Pick up values from tables; */ - max = rep_max[c]; /* zero for max => infinity */ - if (max == 0) max = INT_MAX; - break; - - case OP_CRRANGE: - case OP_CRMINRANGE: - minimize = (*ecode == OP_CRMINRANGE); - min = GET2(ecode, 1); - max = GET2(ecode, 3); - if (max == 0) max = INT_MAX; - ecode += 5; - break; - - default: /* No repeat follows */ - min = max = 1; - break; - } - - /* First, ensure the minimum number of matches are present. */ - - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); - GETCHARINC(c, eptr); - if (!match_xclass(c, data)) RRETURN(MATCH_NOMATCH); - } - - /* If max == min we can continue with the main loop without the - need to recurse. */ - - if (min == max) continue; - - /* If minimizing, keep testing the rest of the expression and advancing - the pointer while it matches the class. */ - - if (minimize) - { - for (fi = min;; fi++) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); - GETCHARINC(c, eptr); - if (!match_xclass(c, data)) RRETURN(MATCH_NOMATCH); - } - /* Control never gets here */ - } - - /* If maximizing, find the longest possible run, then work backwards. */ - - else - { - pp = eptr; - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) break; - GETCHARLEN(c, eptr, len); - if (!match_xclass(c, data)) break; - eptr += len; - } - for(;;) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (eptr-- == pp) break; /* Stop if tried at original pos */ - BACKCHAR(eptr) - } - RRETURN(MATCH_NOMATCH); - } - - /* Control never gets here */ - } -#endif /* End of XCLASS */ - - /* Match a run of characters */ - - case OP_CHARS: - { - register int slen = ecode[1]; - ecode += 2; - -#ifdef DEBUG /* Sigh. Some compilers never learn. */ - if (eptr >= md->end_subject) - printf("matching subject against pattern "); - else - { - printf("matching subject "); - pchars(eptr, slen, TRUE, md); - printf(" against pattern "); - } - pchars(ecode, slen, FALSE, md); - printf("\n"); -#endif - - if (slen > md->end_subject - eptr) RRETURN(MATCH_NOMATCH); - if ((ims & PCRE_CASELESS) != 0) - { - while (slen-- > 0) - if (md->lcc[*ecode++] != md->lcc[*eptr++]) - RRETURN(MATCH_NOMATCH); - } - else - { - while (slen-- > 0) if (*ecode++ != *eptr++) RRETURN(MATCH_NOMATCH); - } - } - break; - - /* Match a single character repeatedly; different opcodes share code. */ - - case OP_EXACT: - min = max = GET2(ecode, 1); - ecode += 3; - goto REPEATCHAR; - - case OP_UPTO: - case OP_MINUPTO: - min = 0; - max = GET2(ecode, 1); - minimize = *ecode == OP_MINUPTO; - ecode += 3; - goto REPEATCHAR; - - case OP_STAR: - case OP_MINSTAR: - case OP_PLUS: - case OP_MINPLUS: - case OP_QUERY: - case OP_MINQUERY: - c = *ecode++ - OP_STAR; - minimize = (c & 1) != 0; - min = rep_min[c]; /* Pick up values from tables; */ - max = rep_max[c]; /* zero for max => infinity */ - if (max == 0) max = INT_MAX; - - /* Common code for all repeated single-character matches. We can give - up quickly if there are fewer than the minimum number of characters left in - the subject. */ - - REPEATCHAR: -#ifdef SUPPORT_UTF8 - if (md->utf8) - { - length = 1; - charptr = ecode; - GETCHARLEN(fc, ecode, length); - if (min * length > md->end_subject - eptr) RRETURN(MATCH_NOMATCH); - ecode += length; - - /* Handle multibyte character matching specially here. There is no - support for any kind of casing for multibyte characters. */ - - if (length > 1) - { - for (i = 1; i <= min; i++) - { - if (memcmp(eptr, charptr, length) != 0) RRETURN(MATCH_NOMATCH); - eptr += length; - } - - if (min == max) continue; - - if (minimize) - { - for (fi = min;; fi++) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max || - eptr >= md->end_subject || - memcmp(eptr, charptr, length) != 0) - RRETURN(MATCH_NOMATCH); - eptr += length; - } - /* Control never gets here */ - } - else - { - pp = eptr; - for (i = min; i < max; i++) - { - if (eptr > md->end_subject - length || - memcmp(eptr, charptr, length) != 0) - break; - eptr += length; - } - while (eptr >= pp) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - eptr -= length; - } - RRETURN(MATCH_NOMATCH); - } - /* Control never gets here */ - } - - /* If the length of a UTF-8 character is 1, we fall through here, and - obey the code as for non-UTF-8 characters below, though in this case the - value of fc will always be < 128. */ - } - else -#endif - - /* When not in UTF-8 mode, load a single-byte character. */ - { - if (min > md->end_subject - eptr) RRETURN(MATCH_NOMATCH); - fc = *ecode++; - } - - /* The value of fc at this point is always less than 256, though we may or - may not be in UTF-8 mode. The code is duplicated for the caseless and - caseful cases, for speed, since matching characters is likely to be quite - common. First, ensure the minimum number of matches are present. If min = - max, continue at the same level without recursing. Otherwise, if - minimizing, keep trying the rest of the expression and advancing one - matching character if failing, up to the maximum. Alternatively, if - maximizing, find the maximum number of characters and work backwards. */ - - DPRINTF(("matching %c{%d,%d} against subject %.*s\n", fc, min, max, - max, eptr)); - - if ((ims & PCRE_CASELESS) != 0) - { - fc = md->lcc[fc]; - for (i = 1; i <= min; i++) - if (fc != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH); - if (min == max) continue; - if (minimize) - { - for (fi = min;; fi++) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max || eptr >= md->end_subject || - fc != md->lcc[*eptr++]) - RRETURN(MATCH_NOMATCH); - } - /* Control never gets here */ - } - else - { - pp = eptr; - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject || fc != md->lcc[*eptr]) break; - eptr++; - } - while (eptr >= pp) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - eptr--; - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - } - RRETURN(MATCH_NOMATCH); - } - /* Control never gets here */ - } - - /* Caseful comparisons (includes all multi-byte characters) */ - - else - { - for (i = 1; i <= min; i++) if (fc != *eptr++) RRETURN(MATCH_NOMATCH); - if (min == max) continue; - if (minimize) - { - for (fi = min;; fi++) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max || eptr >= md->end_subject || fc != *eptr++) - RRETURN(MATCH_NOMATCH); - } - /* Control never gets here */ - } - else - { - pp = eptr; - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject || fc != *eptr) break; - eptr++; - } - while (eptr >= pp) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - eptr--; - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - } - RRETURN(MATCH_NOMATCH); - } - } - /* Control never gets here */ - - /* Match a negated single one-byte character. The character we are - checking can be multibyte. */ - - case OP_NOT: - if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); - ecode++; - GETCHARINCTEST(c, eptr); - if ((ims & PCRE_CASELESS) != 0) - { -#ifdef SUPPORT_UTF8 - if (c < 256) -#endif - c = md->lcc[c]; - if (md->lcc[*ecode++] == c) RRETURN(MATCH_NOMATCH); - } - else - { - if (*ecode++ == c) RRETURN(MATCH_NOMATCH); - } - break; - - /* Match a negated single one-byte character repeatedly. This is almost a - repeat of the code for a repeated single character, but I haven't found a - nice way of commoning these up that doesn't require a test of the - positive/negative option for each character match. Maybe that wouldn't add - very much to the time taken, but character matching *is* what this is all - about... */ - - case OP_NOTEXACT: - min = max = GET2(ecode, 1); - ecode += 3; - goto REPEATNOTCHAR; - - case OP_NOTUPTO: - case OP_NOTMINUPTO: - min = 0; - max = GET2(ecode, 1); - minimize = *ecode == OP_NOTMINUPTO; - ecode += 3; - goto REPEATNOTCHAR; - - case OP_NOTSTAR: - case OP_NOTMINSTAR: - case OP_NOTPLUS: - case OP_NOTMINPLUS: - case OP_NOTQUERY: - case OP_NOTMINQUERY: - c = *ecode++ - OP_NOTSTAR; - minimize = (c & 1) != 0; - min = rep_min[c]; /* Pick up values from tables; */ - max = rep_max[c]; /* zero for max => infinity */ - if (max == 0) max = INT_MAX; - - /* Common code for all repeated single-character (less than 255) matches. - We can give up quickly if there are fewer than the minimum number of - characters left in the subject. */ - - REPEATNOTCHAR: - if (min > md->end_subject - eptr) RRETURN(MATCH_NOMATCH); - fc = *ecode++; - - /* The code is duplicated for the caseless and caseful cases, for speed, - since matching characters is likely to be quite common. First, ensure the - minimum number of matches are present. If min = max, continue at the same - level without recursing. Otherwise, if minimizing, keep trying the rest of - the expression and advancing one matching character if failing, up to the - maximum. Alternatively, if maximizing, find the maximum number of - characters and work backwards. */ - - DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", fc, min, max, - max, eptr)); - - if ((ims & PCRE_CASELESS) != 0) - { - fc = md->lcc[fc]; - -#ifdef SUPPORT_UTF8 - /* UTF-8 mode */ - if (md->utf8) - { - register int d; - for (i = 1; i <= min; i++) - { - GETCHARINC(d, eptr); - if (d < 256) d = md->lcc[d]; - if (fc == d) RRETURN(MATCH_NOMATCH); - } - } - else -#endif - - /* Not UTF-8 mode */ - { - for (i = 1; i <= min; i++) - if (fc == md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH); - } - - if (min == max) continue; - - if (minimize) - { -#ifdef SUPPORT_UTF8 - /* UTF-8 mode */ - if (md->utf8) - { - register int d; - for (fi = min;; fi++) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - GETCHARINC(d, eptr); - if (d < 256) d = md->lcc[d]; - if (fi >= max || eptr >= md->end_subject || fc == d) - RRETURN(MATCH_NOMATCH); - } - } - else -#endif - /* Not UTF-8 mode */ - { - for (fi = min;; fi++) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max || eptr >= md->end_subject || fc == md->lcc[*eptr++]) - RRETURN(MATCH_NOMATCH); - } - } - /* Control never gets here */ - } - - /* Maximize case */ - - else - { - pp = eptr; - -#ifdef SUPPORT_UTF8 - /* UTF-8 mode */ - if (md->utf8) - { - register int d; - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) break; - GETCHARLEN(d, eptr, len); - if (d < 256) d = md->lcc[d]; - if (fc == d) break; - eptr += len; - } - for(;;) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (eptr-- == pp) break; /* Stop if tried at original pos */ - BACKCHAR(eptr); - } - } - else -#endif - /* Not UTF-8 mode */ - { - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject || fc == md->lcc[*eptr]) break; - eptr++; - } - while (eptr >= pp) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - eptr--; - } - } - - RRETURN(MATCH_NOMATCH); - } - /* Control never gets here */ - } - - /* Caseful comparisons */ - - else - { -#ifdef SUPPORT_UTF8 - /* UTF-8 mode */ - if (md->utf8) - { - register int d; - for (i = 1; i <= min; i++) - { - GETCHARINC(d, eptr); - if (fc == d) RRETURN(MATCH_NOMATCH); - } - } - else -#endif - /* Not UTF-8 mode */ - { - for (i = 1; i <= min; i++) - if (fc == *eptr++) RRETURN(MATCH_NOMATCH); - } - - if (min == max) continue; - - if (minimize) - { -#ifdef SUPPORT_UTF8 - /* UTF-8 mode */ - if (md->utf8) - { - register int d; - for (fi = min;; fi++) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - GETCHARINC(d, eptr); - if (fi >= max || eptr >= md->end_subject || fc == d) - RRETURN(MATCH_NOMATCH); - } - } - else -#endif - /* Not UTF-8 mode */ - { - for (fi = min;; fi++) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max || eptr >= md->end_subject || fc == *eptr++) - RRETURN(MATCH_NOMATCH); - } - } - /* Control never gets here */ - } - - /* Maximize case */ - - else - { - pp = eptr; - -#ifdef SUPPORT_UTF8 - /* UTF-8 mode */ - if (md->utf8) - { - register int d; - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) break; - GETCHARLEN(d, eptr, len); - if (fc == d) break; - eptr += len; - } - for(;;) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (eptr-- == pp) break; /* Stop if tried at original pos */ - BACKCHAR(eptr); - } - } - else -#endif - /* Not UTF-8 mode */ - { - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject || fc == *eptr) break; - eptr++; - } - while (eptr >= pp) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - eptr--; - } - } - - RRETURN(MATCH_NOMATCH); - } - } - /* Control never gets here */ - - /* Match a single character type repeatedly; several different opcodes - share code. This is very similar to the code for single characters, but we - repeat it in the interests of efficiency. */ - - case OP_TYPEEXACT: - min = max = GET2(ecode, 1); - minimize = TRUE; - ecode += 3; - goto REPEATTYPE; - - case OP_TYPEUPTO: - case OP_TYPEMINUPTO: - min = 0; - max = GET2(ecode, 1); - minimize = *ecode == OP_TYPEMINUPTO; - ecode += 3; - goto REPEATTYPE; - - case OP_TYPESTAR: - case OP_TYPEMINSTAR: - case OP_TYPEPLUS: - case OP_TYPEMINPLUS: - case OP_TYPEQUERY: - case OP_TYPEMINQUERY: - c = *ecode++ - OP_TYPESTAR; - minimize = (c & 1) != 0; - min = rep_min[c]; /* Pick up values from tables; */ - max = rep_max[c]; /* zero for max => infinity */ - if (max == 0) max = INT_MAX; - - /* Common code for all repeated single character type matches. Note that - in UTF-8 mode, '.' matches a character of any length, but for the other - character types, the valid characters are all one-byte long. */ - - REPEATTYPE: - ctype = *ecode++; /* Code for the character type */ - - /* First, ensure the minimum number of matches are present. Use inline - code for maximizing the speed, and do the type test once at the start - (i.e. keep it out of the loop). Also we can test that there are at least - the minimum number of bytes before we start. This isn't as effective in - UTF-8 mode, but it does no harm. Separate the UTF-8 code completely as that - is tidier. */ - - if (min > md->end_subject - eptr) RRETURN(MATCH_NOMATCH); - if (min > 0) - { -#ifdef SUPPORT_UTF8 - if (md->utf8) switch(ctype) - { - case OP_ANY: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject || - (*eptr++ == NEWLINE && (ims & PCRE_DOTALL) == 0)) - RRETURN(MATCH_NOMATCH); - while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; - } - break; - - case OP_ANYBYTE: - eptr += min; - break; - - case OP_NOT_DIGIT: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); - GETCHARINC(c, eptr); - if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) - RRETURN(MATCH_NOMATCH); - } - break; - - case OP_DIGIT: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject || - *eptr >= 128 || (md->ctypes[*eptr++] & ctype_digit) == 0) - RRETURN(MATCH_NOMATCH); - /* No need to skip more bytes - we know it's a 1-byte character */ - } - break; - - case OP_NOT_WHITESPACE: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject || - (*eptr < 128 && (md->ctypes[*eptr++] & ctype_space) != 0)) - RRETURN(MATCH_NOMATCH); - while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; - } - break; - - case OP_WHITESPACE: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject || - *eptr >= 128 || (md->ctypes[*eptr++] & ctype_space) == 0) - RRETURN(MATCH_NOMATCH); - /* No need to skip more bytes - we know it's a 1-byte character */ - } - break; - - case OP_NOT_WORDCHAR: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject || - (*eptr < 128 && (md->ctypes[*eptr++] & ctype_word) != 0)) - RRETURN(MATCH_NOMATCH); - while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; - } - break; - - case OP_WORDCHAR: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject || - *eptr >= 128 || (md->ctypes[*eptr++] & ctype_word) == 0) - RRETURN(MATCH_NOMATCH); - /* No need to skip more bytes - we know it's a 1-byte character */ - } - break; - } - else -#endif - - /* Code for the non-UTF-8 case for minimum matching */ - - switch(ctype) - { - case OP_ANY: - if ((ims & PCRE_DOTALL) == 0) - { - for (i = 1; i <= min; i++) - if (*eptr++ == NEWLINE) RRETURN(MATCH_NOMATCH); - } - else eptr += min; - break; - - case OP_ANYBYTE: - eptr += min; - break; - - case OP_NOT_DIGIT: - for (i = 1; i <= min; i++) - if ((md->ctypes[*eptr++] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH); - break; - - case OP_DIGIT: - for (i = 1; i <= min; i++) - if ((md->ctypes[*eptr++] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH); - break; - - case OP_NOT_WHITESPACE: - for (i = 1; i <= min; i++) - if ((md->ctypes[*eptr++] & ctype_space) != 0) RRETURN(MATCH_NOMATCH); - break; - - case OP_WHITESPACE: - for (i = 1; i <= min; i++) - if ((md->ctypes[*eptr++] & ctype_space) == 0) RRETURN(MATCH_NOMATCH); - break; - - case OP_NOT_WORDCHAR: - for (i = 1; i <= min; i++) - if ((md->ctypes[*eptr++] & ctype_word) != 0) - RRETURN(MATCH_NOMATCH); - break; - - case OP_WORDCHAR: - for (i = 1; i <= min; i++) - if ((md->ctypes[*eptr++] & ctype_word) == 0) - RRETURN(MATCH_NOMATCH); - break; - } - } - - /* If min = max, continue at the same level without recursing */ - - if (min == max) continue; - - /* If minimizing, we have to test the rest of the pattern before each - subsequent match. Again, separate the UTF-8 case for speed. */ - - if (minimize) - { -#ifdef SUPPORT_UTF8 - /* UTF-8 mode */ - if (md->utf8) - { - for (fi = min;; fi++) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); - - GETCHARINC(c, eptr); - switch(ctype) - { - case OP_ANY: - if ((ims & PCRE_DOTALL) == 0 && c == NEWLINE) RRETURN(MATCH_NOMATCH); - break; - - case OP_ANYBYTE: - break; - - case OP_NOT_DIGIT: - if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) - RRETURN(MATCH_NOMATCH); - break; - - case OP_DIGIT: - if (c >= 256 || (md->ctypes[c] & ctype_digit) == 0) - RRETURN(MATCH_NOMATCH); - break; - - case OP_NOT_WHITESPACE: - if (c < 256 && (md->ctypes[c] & ctype_space) != 0) - RRETURN(MATCH_NOMATCH); - break; - - case OP_WHITESPACE: - if (c >= 256 || (md->ctypes[c] & ctype_space) == 0) - RRETURN(MATCH_NOMATCH); - break; - - case OP_NOT_WORDCHAR: - if (c < 256 && (md->ctypes[c] & ctype_word) != 0) - RRETURN(MATCH_NOMATCH); - break; - - case OP_WORDCHAR: - if (c >= 256 && (md->ctypes[c] & ctype_word) == 0) - RRETURN(MATCH_NOMATCH); - break; - } - } - } - else -#endif - /* Not UTF-8 mode */ - { - for (fi = min;; fi++) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); - c = *eptr++; - switch(ctype) - { - case OP_ANY: - if ((ims & PCRE_DOTALL) == 0 && c == NEWLINE) RRETURN(MATCH_NOMATCH); - break; - - case OP_ANYBYTE: - break; - - case OP_NOT_DIGIT: - if ((md->ctypes[c] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH); - break; - - case OP_DIGIT: - if ((md->ctypes[c] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH); - break; - - case OP_NOT_WHITESPACE: - if ((md->ctypes[c] & ctype_space) != 0) RRETURN(MATCH_NOMATCH); - break; - - case OP_WHITESPACE: - if ((md->ctypes[c] & ctype_space) == 0) RRETURN(MATCH_NOMATCH); - break; - - case OP_NOT_WORDCHAR: - if ((md->ctypes[c] & ctype_word) != 0) RRETURN(MATCH_NOMATCH); - break; - - case OP_WORDCHAR: - if ((md->ctypes[c] & ctype_word) == 0) RRETURN(MATCH_NOMATCH); - break; - } - } - } - /* Control never gets here */ - } - - /* If maximizing it is worth using inline code for speed, doing the type - test once at the start (i.e. keep it out of the loop). Again, keep the - UTF-8 stuff separate. */ - - else - { - pp = eptr; - -#ifdef SUPPORT_UTF8 - /* UTF-8 mode */ - - if (md->utf8) - { - switch(ctype) - { - case OP_ANY: - - /* Special code is required for UTF8, but when the maximum is unlimited - we don't need it, so we repeat the non-UTF8 code. This is probably - worth it, because .* is quite a common idiom. */ - - if (max < INT_MAX) - { - if ((ims & PCRE_DOTALL) == 0) - { - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject || *eptr == NEWLINE) break; - eptr++; - while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; - } - } - else - { - for (i = min; i < max; i++) - { - eptr++; - while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; - } - } - } - - /* Handle unlimited UTF-8 repeat */ - - else - { - if ((ims & PCRE_DOTALL) == 0) - { - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject || *eptr == NEWLINE) break; - eptr++; - } - break; - } - else - { - c = max - min; - if (c > md->end_subject - eptr) c = md->end_subject - eptr; - eptr += c; - } - } - break; - - /* The byte case is the same as non-UTF8 */ - - case OP_ANYBYTE: - c = max - min; - if (c > md->end_subject - eptr) c = md->end_subject - eptr; - eptr += c; - break; - - case OP_NOT_DIGIT: - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) break; - GETCHARLEN(c, eptr, len); - if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) break; - eptr+= len; - } - break; - - case OP_DIGIT: - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) break; - GETCHARLEN(c, eptr, len); - if (c >= 256 ||(md->ctypes[c] & ctype_digit) == 0) break; - eptr+= len; - } - break; - - case OP_NOT_WHITESPACE: - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) break; - GETCHARLEN(c, eptr, len); - if (c < 256 && (md->ctypes[c] & ctype_space) != 0) break; - eptr+= len; - } - break; - - case OP_WHITESPACE: - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) break; - GETCHARLEN(c, eptr, len); - if (c >= 256 ||(md->ctypes[c] & ctype_space) == 0) break; - eptr+= len; - } - break; - - case OP_NOT_WORDCHAR: - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) break; - GETCHARLEN(c, eptr, len); - if (c < 256 && (md->ctypes[c] & ctype_word) != 0) break; - eptr+= len; - } - break; - - case OP_WORDCHAR: - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) break; - GETCHARLEN(c, eptr, len); - if (c >= 256 || (md->ctypes[c] & ctype_word) == 0) break; - eptr+= len; - } - break; - } - - /* eptr is now past the end of the maximum run */ - - for(;;) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (eptr-- == pp) break; /* Stop if tried at original pos */ - BACKCHAR(eptr); - } - } - else -#endif - - /* Not UTF-8 mode */ - { - switch(ctype) - { - case OP_ANY: - if ((ims & PCRE_DOTALL) == 0) - { - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject || *eptr == NEWLINE) break; - eptr++; - } - break; - } - /* For DOTALL case, fall through and treat as \C */ - - case OP_ANYBYTE: - c = max - min; - if (c > md->end_subject - eptr) c = md->end_subject - eptr; - eptr += c; - break; - - case OP_NOT_DIGIT: - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) != 0) - break; - eptr++; - } - break; - - case OP_DIGIT: - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) == 0) - break; - eptr++; - } - break; - - case OP_NOT_WHITESPACE: - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) != 0) - break; - eptr++; - } - break; - - case OP_WHITESPACE: - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) == 0) - break; - eptr++; - } - break; - - case OP_NOT_WORDCHAR: - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) != 0) - break; - eptr++; - } - break; - - case OP_WORDCHAR: - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) == 0) - break; - eptr++; - } - break; - } - - /* eptr is now past the end of the maximum run */ - - while (eptr >= pp) - { - RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); - eptr--; - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - } - } - - /* Get here if we can't make it match with any permitted repetitions */ - - RRETURN(MATCH_NOMATCH); - } - /* Control never gets here */ - - /* There's been some horrible disaster. Since all codes > OP_BRA are - for capturing brackets, and there shouldn't be any gaps between 0 and - OP_BRA, arrival here can only mean there is something seriously wrong - in the code above or the OP_xxx definitions. */ - - default: - DPRINTF(("Unknown opcode %d\n", *ecode)); - RRETURN(PCRE_ERROR_UNKNOWN_NODE); - } - - /* Do not stick any code in here without much thought; it is assumed - that "continue" in the code above comes out to here to repeat the main - loop. */ - - } /* End of main loop */ -/* Control never reaches here */ -} - - -/*************************************************************************** -**************************************************************************** - RECURSION IN THE match() FUNCTION - -Undefine all the macros that were defined above to handle this. */ - -#ifdef NO_RECURSE -#undef eptr -#undef ecode -#undef offset_top -#undef ims -#undef eptrb -#undef flags - -#undef callpat -#undef charptr -#undef data -#undef lastptr -#undef next -#undef pp -#undef prev -#undef saved_eptr - -#undef new_recursive - -#undef cur_is_word -#undef condition -#undef minimize -#undef prev_is_word - -#undef original_ims - -#undef ctype -#undef length -#undef max -#undef min -#undef number -#undef offset -#undef op -#undef save_capture_last -#undef save_offset1 -#undef save_offset2 -#undef save_offset3 -#undef stacksave - -#undef newptrb - -#endif - -/* These two are defined as macros in both cases */ - -#undef fc -#undef fi - -/*************************************************************************** -***************************************************************************/ - - - -/************************************************* -* Execute a Regular Expression * -*************************************************/ - -/* This function applies a compiled re to a subject string and picks out -portions of the string if it matches. Two elements in the vector are set for -each substring: the offsets to the start and end of the substring. - -Arguments: - external_re points to the compiled expression - extra_data points to extra data or is NULL - subject points to the subject string - length length of subject string (may contain binary zeros) - start_offset where to start in the subject string - options option bits - offsets points to a vector of ints to be filled in with offsets - offsetcount the number of elements in the vector - -Returns: > 0 => success; value is the number of elements filled in - = 0 => success, but offsets is not big enough - -1 => failed to match - < -1 => some kind of unexpected problem -*/ - -EXPORT int -pcre_exec(const pcre *external_re, const pcre_extra *extra_data, - const char *subject, int length, int start_offset, int options, int *offsets, - int offsetcount) -{ -int rc, resetcount, ocount; -int first_byte = -1; -int req_byte = -1; -int req_byte2 = -1; -unsigned long int ims = 0; -BOOL using_temporary_offsets = FALSE; -BOOL anchored; -BOOL startline; -BOOL first_byte_caseless = FALSE; -BOOL req_byte_caseless = FALSE; -match_data match_block; -const uschar *start_bits = NULL; -const uschar *start_match = (const uschar *)subject + start_offset; -const uschar *end_subject; -const uschar *req_byte_ptr = start_match - 1; -const pcre_study_data *study; -const real_pcre *re = (const real_pcre *)external_re; - -/* Plausibility checks */ - -if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION; -if (re == NULL || subject == NULL || - (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL; - -/* Fish out the optional data from the extra_data structure, first setting -the default values. */ - -study = NULL; -match_block.match_limit = MATCH_LIMIT; -match_block.callout_data = NULL; - -if (extra_data != NULL) - { - register unsigned int flags = extra_data->flags; - if ((flags & PCRE_EXTRA_STUDY_DATA) != 0) - study = (const pcre_study_data *)extra_data->study_data; - if ((flags & PCRE_EXTRA_MATCH_LIMIT) != 0) - match_block.match_limit = extra_data->match_limit; - if ((flags & PCRE_EXTRA_CALLOUT_DATA) != 0) - match_block.callout_data = extra_data->callout_data; - } - -/* Now we have re supposedly pointing to the regex */ - -if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC; - -anchored = ((re->options | options) & PCRE_ANCHORED) != 0; -startline = (re->options & PCRE_STARTLINE) != 0; - -match_block.start_code = - (const uschar *)re + sizeof(real_pcre) + re->name_count * re->name_entry_size; -match_block.start_subject = (const uschar *)subject; -match_block.start_offset = start_offset; -match_block.end_subject = match_block.start_subject + length; -end_subject = match_block.end_subject; - -match_block.endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0; -match_block.utf8 = (re->options & PCRE_UTF8) != 0; - -match_block.notbol = (options & PCRE_NOTBOL) != 0; -match_block.noteol = (options & PCRE_NOTEOL) != 0; -match_block.notempty = (options & PCRE_NOTEMPTY) != 0; - -match_block.recursive = NULL; /* No recursion at top level */ - -match_block.lcc = re->tables + lcc_offset; -match_block.ctypes = re->tables + ctypes_offset; - -/* Check a UTF-8 string if required. Unfortunately there's no way of passing -back the character offset. */ - -#ifdef SUPPORT_UTF8 -if (match_block.utf8 && (options & PCRE_NO_UTF8_CHECK) == 0) - { - if (valid_utf8((uschar *)subject, length) >= 0) - return PCRE_ERROR_BADUTF8; - if (start_offset > 0 && start_offset < length) - { - int tb = ((uschar *)subject)[start_offset]; - if (tb > 127) - { - tb &= 0xc0; - if (tb != 0 && tb != 0xc0) return PCRE_ERROR_BADUTF8_OFFSET; - } - } - } -#endif - -/* The ims options can vary during the matching as a result of the presence -of (?ims) items in the pattern. They are kept in a local variable so that -restoring at the exit of a group is easy. */ - -ims = re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL); - -/* If the expression has got more back references than the offsets supplied can -hold, we get a temporary bit of working store to use during the matching. -Otherwise, we can use the vector supplied, rounding down its size to a multiple -of 3. */ - -ocount = offsetcount - (offsetcount % 3); - -if (re->top_backref > 0 && re->top_backref >= ocount/3) - { - ocount = re->top_backref * 3 + 3; - match_block.offset_vector = (int *)(pcre_malloc)(ocount * sizeof(int)); - if (match_block.offset_vector == NULL) return PCRE_ERROR_NOMEMORY; - using_temporary_offsets = TRUE; - DPRINTF(("Got memory to hold back references\n")); - } -else match_block.offset_vector = offsets; - -match_block.offset_end = ocount; -match_block.offset_max = (2*ocount)/3; -match_block.offset_overflow = FALSE; -match_block.capture_last = -1; - -/* Compute the minimum number of offsets that we need to reset each time. Doing -this makes a huge difference to execution time when there aren't many brackets -in the pattern. */ - -resetcount = 2 + re->top_bracket * 2; -if (resetcount > offsetcount) resetcount = ocount; - -/* Reset the working variable associated with each extraction. These should -never be used unless previously set, but they get saved and restored, and so we -initialize them to avoid reading uninitialized locations. */ - -if (match_block.offset_vector != NULL) - { - register int *iptr = match_block.offset_vector + ocount; - register int *iend = iptr - resetcount/2 + 1; - while (--iptr >= iend) *iptr = -1; - } - -/* Set up the first character to match, if available. The first_byte value is -never set for an anchored regular expression, but the anchoring may be forced -at run time, so we have to test for anchoring. The first char may be unset for -an unanchored pattern, of course. If there's no first char and the pattern was -studied, there may be a bitmap of possible first characters. */ - -if (!anchored) - { - if ((re->options & PCRE_FIRSTSET) != 0) - { - first_byte = re->first_byte & 255; - if ((first_byte_caseless = ((re->first_byte & REQ_CASELESS) != 0)) == TRUE) - first_byte = match_block.lcc[first_byte]; - } - else - if (!startline && study != NULL && - (study->options & PCRE_STUDY_MAPPED) != 0) - start_bits = study->start_bits; - } - -/* For anchored or unanchored matches, there may be a "last known required -character" set. */ - -if ((re->options & PCRE_REQCHSET) != 0) - { - req_byte = re->req_byte & 255; - req_byte_caseless = (re->req_byte & REQ_CASELESS) != 0; - req_byte2 = (re->tables + fcc_offset)[req_byte]; /* case flipped */ - } - -/* Loop for handling unanchored repeated matching attempts; for anchored regexs -the loop runs just once. */ - -do - { - register int *iptr = match_block.offset_vector; - register int *iend = iptr + resetcount; - - /* Reset the maximum number of extractions we might see. */ - - while (iptr < iend) *iptr++ = -1; - - /* Advance to a unique first char if possible */ - - if (first_byte >= 0) - { - if (first_byte_caseless) - while (start_match < end_subject && - match_block.lcc[*start_match] != first_byte) - start_match++; - else - while (start_match < end_subject && *start_match != first_byte) - start_match++; - } - - /* Or to just after \n for a multiline match if possible */ - - else if (startline) - { - if (start_match > match_block.start_subject + start_offset) - { - while (start_match < end_subject && start_match[-1] != NEWLINE) - start_match++; - } - } - - /* Or to a non-unique first char after study */ - - else if (start_bits != NULL) - { - while (start_match < end_subject) - { - register int c = *start_match; - if ((start_bits[c/8] & (1 << (c&7))) == 0) start_match++; else break; - } - } - -#ifdef DEBUG /* Sigh. Some compilers never learn. */ - printf(">>>> Match against: "); - pchars(start_match, end_subject - start_match, TRUE, &match_block); - printf("\n"); -#endif - - /* If req_byte is set, we know that that character must appear in the subject - for the match to succeed. If the first character is set, req_byte must be - later in the subject; otherwise the test starts at the match point. This - optimization can save a huge amount of backtracking in patterns with nested - unlimited repeats that aren't going to match. Writing separate code for - cased/caseless versions makes it go faster, as does using an autoincrement - and backing off on a match. - - HOWEVER: when the subject string is very, very long, searching to its end can - take a long time, and give bad performance on quite ordinary patterns. This - showed up when somebody was matching /^C/ on a 32-megabyte string... so we - don't do this when the string is sufficiently long. */ - - if (req_byte >= 0 && end_subject - start_match < REQ_BYTE_MAX) - { - register const uschar *p = start_match + ((first_byte >= 0)? 1 : 0); - - /* We don't need to repeat the search if we haven't yet reached the - place we found it at last time. */ - - if (p > req_byte_ptr) - { - if (req_byte_caseless) - { - while (p < end_subject) - { - register int pp = *p++; - if (pp == req_byte || pp == req_byte2) { p--; break; } - } - } - else - { - while (p < end_subject) - { - if (*p++ == req_byte) { p--; break; } - } - } - - /* If we can't find the required character, break the matching loop */ - - if (p >= end_subject) break; - - /* If we have found the required character, save the point where we - found it, so that we don't search again next time round the loop if - the start hasn't passed this character yet. */ - - req_byte_ptr = p; - } - } - - /* When a match occurs, substrings will be set for all internal extractions; - we just need to set up the whole thing as substring 0 before returning. If - there were too many extractions, set the return code to zero. In the case - where we had to get some local store to hold offsets for backreferences, copy - those back references that we can. In this case there need not be overflow - if certain parts of the pattern were not used. */ - - match_block.start_match = start_match; - match_block.match_call_count = 0; - - rc = match(start_match, match_block.start_code, 2, &match_block, ims, NULL, - match_isgroup); - - if (rc == MATCH_NOMATCH) - { - start_match++; -#ifdef SUPPORT_UTF8 - if (match_block.utf8) - while((*start_match & 0xc0) == 0x80) start_match++; -#endif - continue; - } - - if (rc != MATCH_MATCH) - { - DPRINTF((">>>> error: returning %d\n", rc)); - return rc; - } - - /* We have a match! Copy the offset information from temporary store if - necessary */ - - if (using_temporary_offsets) - { - if (offsetcount >= 4) - { - memcpy(offsets + 2, match_block.offset_vector + 2, - (offsetcount - 2) * sizeof(int)); - DPRINTF(("Copied offsets from temporary memory\n")); - } - if (match_block.end_offset_top > offsetcount) - match_block.offset_overflow = TRUE; - - DPRINTF(("Freeing temporary memory\n")); - (pcre_free)(match_block.offset_vector); - } - - rc = match_block.offset_overflow? 0 : match_block.end_offset_top/2; - - if (offsetcount < 2) rc = 0; else - { - offsets[0] = start_match - match_block.start_subject; - offsets[1] = match_block.end_match_ptr - match_block.start_subject; - } - - DPRINTF((">>>> returning %d\n", rc)); - return rc; - } - -/* This "while" is the end of the "do" above */ - -while (!anchored && start_match <= end_subject); - -if (using_temporary_offsets) - { - DPRINTF(("Freeing temporary memory\n")); - (pcre_free)(match_block.offset_vector); - } - -DPRINTF((">>>> returning PCRE_ERROR_NOMATCH\n")); - -return PCRE_ERROR_NOMATCH; -} - -/* End of pcre.c */ diff --git a/ext/pcre/pcrelib/pcre.def b/ext/pcre/pcrelib/pcre.def index 4f6c4bff40da..adb53160d304 100644 --- a/ext/pcre/pcrelib/pcre.def +++ b/ext/pcre/pcrelib/pcre.def @@ -5,6 +5,7 @@ pcre_free DATA pcre_compile pcre_copy_substring +pcre_dfa_exec pcre_exec pcre_get_substring pcre_get_substring_list diff --git a/ext/pcre/pcrelib/pcre.h b/ext/pcre/pcrelib/pcre.h index 6582ca9e713a..ff3577402418 100644 --- a/ext/pcre/pcrelib/pcre.h +++ b/ext/pcre/pcrelib/pcre.h @@ -2,7 +2,39 @@ * Perl-Compatible Regular Expressions * *************************************************/ -/* Copyright (c) 1997-2003 University of Cambridge */ +/* In its original form, this is the .in file that is transformed by +"configure" into pcre.h. + + Copyright (c) 1997-2005 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ #ifndef _PCRE_H #define _PCRE_H @@ -12,11 +44,11 @@ make changes to pcre.in. */ #include "php_compat.h" -#define PCRE_MAJOR 4 -#define PCRE_MINOR 5 -#define PCRE_DATE 01-December-2003 +#define PCRE_MAJOR 6 +#define PCRE_MINOR 2 +#define PCRE_DATE 01-Aug-2005 -/* Win32 uses DLL by default */ +/* Win32 uses DLL by default; it needs special stuff for exported functions. */ #ifdef _WIN32 # ifdef PCRE_DEFINITION @@ -29,8 +61,15 @@ make changes to pcre.in. */ # endif # endif #endif + +/* For other operating systems, we use the standard "extern". */ + #ifndef PCRE_DATA_SCOPE -# define PCRE_DATA_SCOPE extern +# ifdef __cplusplus +# define PCRE_DATA_SCOPE extern "C" +# else +# define PCRE_DATA_SCOPE extern +# endif #endif /* Have to include stdlib.h in order to ensure that size_t is defined; @@ -46,20 +85,25 @@ extern "C" { /* Options */ -#define PCRE_CASELESS 0x0001 -#define PCRE_MULTILINE 0x0002 -#define PCRE_DOTALL 0x0004 -#define PCRE_EXTENDED 0x0008 -#define PCRE_ANCHORED 0x0010 -#define PCRE_DOLLAR_ENDONLY 0x0020 -#define PCRE_EXTRA 0x0040 -#define PCRE_NOTBOL 0x0080 -#define PCRE_NOTEOL 0x0100 -#define PCRE_UNGREEDY 0x0200 -#define PCRE_NOTEMPTY 0x0400 -#define PCRE_UTF8 0x0800 -#define PCRE_NO_AUTO_CAPTURE 0x1000 -#define PCRE_NO_UTF8_CHECK 0x2000 +#define PCRE_CASELESS 0x00000001 +#define PCRE_MULTILINE 0x00000002 +#define PCRE_DOTALL 0x00000004 +#define PCRE_EXTENDED 0x00000008 +#define PCRE_ANCHORED 0x00000010 +#define PCRE_DOLLAR_ENDONLY 0x00000020 +#define PCRE_EXTRA 0x00000040 +#define PCRE_NOTBOL 0x00000080 +#define PCRE_NOTEOL 0x00000100 +#define PCRE_UNGREEDY 0x00000200 +#define PCRE_NOTEMPTY 0x00000400 +#define PCRE_UTF8 0x00000800 +#define PCRE_NO_AUTO_CAPTURE 0x00001000 +#define PCRE_NO_UTF8_CHECK 0x00002000 +#define PCRE_AUTO_CALLOUT 0x00004000 +#define PCRE_PARTIAL 0x00008000 +#define PCRE_DFA_SHORTEST 0x00010000 +#define PCRE_DFA_RESTART 0x00020000 +#define PCRE_FIRSTLINE 0x00040000 /* Exec-time and get/set-time error codes */ @@ -74,6 +118,15 @@ extern "C" { #define PCRE_ERROR_CALLOUT (-9) /* Never used by PCRE itself */ #define PCRE_ERROR_BADUTF8 (-10) #define PCRE_ERROR_BADUTF8_OFFSET (-11) +#define PCRE_ERROR_PARTIAL (-12) +#define PCRE_ERROR_BADPARTIAL (-13) +#define PCRE_ERROR_INTERNAL (-14) +#define PCRE_ERROR_BADCOUNT (-15) +#define PCRE_ERROR_DFA_UITEM (-16) +#define PCRE_ERROR_DFA_UCOND (-17) +#define PCRE_ERROR_DFA_UMLIMIT (-18) +#define PCRE_ERROR_DFA_WSSIZE (-19) +#define PCRE_ERROR_DFA_RECURSE (-20) /* Request types for pcre_fullinfo() */ @@ -89,6 +142,7 @@ extern "C" { #define PCRE_INFO_NAMECOUNT 8 #define PCRE_INFO_NAMETABLE 9 #define PCRE_INFO_STUDYSIZE 10 +#define PCRE_INFO_DEFAULT_TABLES 11 /* Request types for pcre_config() */ @@ -98,12 +152,14 @@ extern "C" { #define PCRE_CONFIG_POSIX_MALLOC_THRESHOLD 3 #define PCRE_CONFIG_MATCH_LIMIT 4 #define PCRE_CONFIG_STACKRECURSE 5 +#define PCRE_CONFIG_UNICODE_PROPERTIES 6 /* Bit flags for the pcre_extra structure */ #define PCRE_EXTRA_STUDY_DATA 0x0001 #define PCRE_EXTRA_MATCH_LIMIT 0x0002 #define PCRE_EXTRA_CALLOUT_DATA 0x0004 +#define PCRE_EXTRA_TABLES 0x0008 /* Types */ @@ -111,13 +167,15 @@ struct real_pcre; /* declaration; the definition is private */ typedef struct real_pcre pcre; /* The structure for passing additional data to pcre_exec(). This is defined in -such as way as to be extensible. */ +such as way as to be extensible. Always add new fields at the end, in order to +remain compatible. */ typedef struct pcre_extra { unsigned long int flags; /* Bits for which fields are set */ void *study_data; /* Opaque data from pcre_study() */ unsigned long int match_limit; /* Maximum number of calls to match() */ void *callout_data; /* Data passed back in callouts */ + const unsigned char *tables; /* Pointer to character tables */ } pcre_extra; /* The structure for passing out data via the pcre_callout_function. We use a @@ -133,19 +191,21 @@ typedef struct pcre_callout_block { const char *subject; /* The subject being matched */ int subject_length; /* The length of the subject */ int start_match; /* Offset to start of this match attempt */ - int current_position; /* Where we currently are */ + int current_position; /* Where we currently are in the subject */ int capture_top; /* Max current capture */ int capture_last; /* Most recently closed capture */ void *callout_data; /* Data passed in with the call */ + /* ------------------- Added for Version 1 -------------------------- */ + int pattern_position; /* Offset to next item in the pattern */ + int next_item_length; /* Length of next item in the pattern */ /* ------------------------------------------------------------------ */ } pcre_callout_block; /* Indirection for store get and free functions. These can be set to alternative malloc/free functions if required. Special ones are used in the non-recursive case for "frames". There is also an optional callout function -that is triggered by the (?) regex item. Some magic is required for Win32 DLL; -it is null on other OS. For Virtual Pascal, these have to be different again. -*/ +that is triggered by the (?) regex item. For Virtual Pascal, these definitions +have to take another form. */ #ifndef VPCOMPAT PCRE_DATA_SCOPE void *(*pcre_malloc)(size_t); @@ -154,39 +214,44 @@ PCRE_DATA_SCOPE void *(*pcre_stack_malloc)(size_t); PCRE_DATA_SCOPE void (*pcre_stack_free)(void *); PCRE_DATA_SCOPE int (*pcre_callout)(pcre_callout_block *); #else /* VPCOMPAT */ -extern void *pcre_malloc(size_t); -extern void pcre_free(void *); -extern void *pcre_stack_malloc(size_t); -extern void pcre_stack_free(void *); -extern int pcre_callout(pcre_callout_block *); +PCRE_DATA_SCOPE void *pcre_malloc(size_t); +PCRE_DATA_SCOPE void pcre_free(void *); +PCRE_DATA_SCOPE void *pcre_stack_malloc(size_t); +PCRE_DATA_SCOPE void pcre_stack_free(void *); +PCRE_DATA_SCOPE int pcre_callout(pcre_callout_block *); #endif /* VPCOMPAT */ /* Exported PCRE functions */ -extern pcre *pcre_compile(const char *, int, const char **, - int *, const unsigned char *); -extern int pcre_config(int, void *); -extern int pcre_copy_named_substring(const pcre *, const char *, - int *, int, const char *, char *, int); -extern int pcre_copy_substring(const char *, int *, int, int, - char *, int); -extern int pcre_exec(const pcre *, const pcre_extra *, - const char *, int, int, int, int *, int); -extern void pcre_free_substring(const char *); -extern void pcre_free_substring_list(const char **); -extern int pcre_fullinfo(const pcre *, const pcre_extra *, int, - void *); -extern int pcre_get_named_substring(const pcre *, const char *, - int *, int, const char *, const char **); -extern int pcre_get_stringnumber(const pcre *, const char *); -extern int pcre_get_substring(const char *, int *, int, int, - const char **); -extern int pcre_get_substring_list(const char *, int *, int, - const char ***); -extern int pcre_info(const pcre *, int *, int *); -extern const unsigned char *pcre_maketables(void); -extern pcre_extra *pcre_study(const pcre *, int, const char **); -extern const char *pcre_version(void); +PCRE_DATA_SCOPE pcre *pcre_compile(const char *, int, const char **, int *, + const unsigned char *); +PCRE_DATA_SCOPE pcre *pcre_compile2(const char *, int, int *, const char **, + int *, const unsigned char *); +PCRE_DATA_SCOPE int pcre_config(int, void *); +PCRE_DATA_SCOPE int pcre_copy_named_substring(const pcre *, const char *, + int *, int, const char *, char *, int); +PCRE_DATA_SCOPE int pcre_copy_substring(const char *, int *, int, int, char *, + int); +PCRE_DATA_SCOPE int pcre_dfa_exec(const pcre *, const pcre_extra *, + const char *, int, int, int, int *, int , int *, int); +PCRE_DATA_SCOPE int pcre_exec(const pcre *, const pcre_extra *, const char *, + int, int, int, int *, int); +PCRE_DATA_SCOPE void pcre_free_substring(const char *); +PCRE_DATA_SCOPE void pcre_free_substring_list(const char **); +PCRE_DATA_SCOPE int pcre_fullinfo(const pcre *, const pcre_extra *, int, + void *); +PCRE_DATA_SCOPE int pcre_get_named_substring(const pcre *, const char *, + int *, int, const char *, const char **); +PCRE_DATA_SCOPE int pcre_get_stringnumber(const pcre *, const char *); +PCRE_DATA_SCOPE int pcre_get_substring(const char *, int *, int, int, + const char **); +PCRE_DATA_SCOPE int pcre_get_substring_list(const char *, int *, int, + const char ***); +PCRE_DATA_SCOPE int pcre_info(const pcre *, int *, int *); +PCRE_DATA_SCOPE const unsigned char *pcre_maketables(void); +PCRE_DATA_SCOPE int pcre_refcount(pcre *, int); +PCRE_DATA_SCOPE pcre_extra *pcre_study(const pcre *, int, const char **); +PCRE_DATA_SCOPE const char *pcre_version(void); #ifdef __cplusplus } /* extern "C" */ diff --git a/ext/pcre/pcrelib/chartables.c b/ext/pcre/pcrelib/pcre_chartables.c similarity index 96% rename from ext/pcre/pcrelib/chartables.c rename to ext/pcre/pcrelib/pcre_chartables.c index 55e413cfcaa8..d491433e2547 100644 --- a/ext/pcre/pcrelib/chartables.c +++ b/ext/pcre/pcrelib/pcre_chartables.c @@ -6,11 +6,11 @@ program. If you edit it by hand, you might like to edit the Makefile to prevent its ever being regenerated. -This file is #included in the compilation of pcre.c to build the default -character tables which are used when no tables are passed to the compile -function. */ +This file contains the default tables for characters with codes less than +128 (ASCII characters). These tables are used when no external tables are +passed to PCRE. */ -static unsigned char pcre_default_tables[] = { +const unsigned char _pcre_default_tables[] = { /* This table is a lower casing table. */ diff --git a/ext/pcre/pcrelib/pcre_compile.c b/ext/pcre/pcrelib/pcre_compile.c new file mode 100644 index 000000000000..228995252551 --- /dev/null +++ b/ext/pcre/pcrelib/pcre_compile.c @@ -0,0 +1,5059 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2005 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains the external function pcre_compile(), along with +supporting internal functions that are not used by other modules. */ + + +#include "pcre_internal.h" + + +/************************************************* +* Code parameters and static tables * +*************************************************/ + +/* Maximum number of items on the nested bracket stacks at compile time. This +applies to the nesting of all kinds of parentheses. It does not limit +un-nested, non-capturing parentheses. This number can be made bigger if +necessary - it is used to dimension one int and one unsigned char vector at +compile time. */ + +#define BRASTACK_SIZE 200 + + +/* Table for handling escaped characters in the range '0'-'z'. Positive returns +are simple data values; negative values are for special things like \d and so +on. Zero means further processing is needed (for things like \x), or the escape +is invalid. */ + +#if !EBCDIC /* This is the "normal" table for ASCII systems */ +static const short int escapes[] = { + 0, 0, 0, 0, 0, 0, 0, 0, /* 0 - 7 */ + 0, 0, ':', ';', '<', '=', '>', '?', /* 8 - ? */ + '@', -ESC_A, -ESC_B, -ESC_C, -ESC_D, -ESC_E, 0, -ESC_G, /* @ - G */ + 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ +-ESC_P, -ESC_Q, 0, -ESC_S, 0, 0, 0, -ESC_W, /* P - W */ +-ESC_X, 0, -ESC_Z, '[', '\\', ']', '^', '_', /* X - _ */ + '`', 7, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, /* ` - g */ + 0, 0, 0, 0, 0, 0, ESC_n, 0, /* h - o */ +-ESC_p, 0, ESC_r, -ESC_s, ESC_tee, 0, 0, -ESC_w, /* p - w */ + 0, 0, -ESC_z /* x - z */ +}; + +#else /* This is the "abnormal" table for EBCDIC systems */ +static const short int escapes[] = { +/* 48 */ 0, 0, 0, '.', '<', '(', '+', '|', +/* 50 */ '&', 0, 0, 0, 0, 0, 0, 0, +/* 58 */ 0, 0, '!', '$', '*', ')', ';', '~', +/* 60 */ '-', '/', 0, 0, 0, 0, 0, 0, +/* 68 */ 0, 0, '|', ',', '%', '_', '>', '?', +/* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* 78 */ 0, '`', ':', '#', '@', '\'', '=', '"', +/* 80 */ 0, 7, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, +/* 88 */ 0, 0, 0, '{', 0, 0, 0, 0, +/* 90 */ 0, 0, 0, 'l', 0, ESC_n, 0, -ESC_p, +/* 98 */ 0, ESC_r, 0, '}', 0, 0, 0, 0, +/* A0 */ 0, '~', -ESC_s, ESC_tee, 0, 0, -ESC_w, 0, +/* A8 */ 0,-ESC_z, 0, 0, 0, '[', 0, 0, +/* B0 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* B8 */ 0, 0, 0, 0, 0, ']', '=', '-', +/* C0 */ '{',-ESC_A, -ESC_B, -ESC_C, -ESC_D,-ESC_E, 0, -ESC_G, +/* C8 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* D0 */ '}', 0, 0, 0, 0, 0, 0, -ESC_P, +/* D8 */-ESC_Q, 0, 0, 0, 0, 0, 0, 0, +/* E0 */ '\\', 0, -ESC_S, 0, 0, 0, -ESC_W, -ESC_X, +/* E8 */ 0,-ESC_Z, 0, 0, 0, 0, 0, 0, +/* F0 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* F8 */ 0, 0, 0, 0, 0, 0, 0, 0 +}; +#endif + + +/* Tables of names of POSIX character classes and their lengths. The list is +terminated by a zero length entry. The first three must be alpha, upper, lower, +as this is assumed for handling case independence. */ + +static const char *const posix_names[] = { + "alpha", "lower", "upper", + "alnum", "ascii", "blank", "cntrl", "digit", "graph", + "print", "punct", "space", "word", "xdigit" }; + +static const uschar posix_name_lengths[] = { + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0 }; + +/* Table of class bit maps for each POSIX class; up to three may be combined +to form the class. The table for [:blank:] is dynamically modified to remove +the vertical space characters. */ + +static const int posix_class_maps[] = { + cbit_lower, cbit_upper, -1, /* alpha */ + cbit_lower, -1, -1, /* lower */ + cbit_upper, -1, -1, /* upper */ + cbit_digit, cbit_lower, cbit_upper, /* alnum */ + cbit_print, cbit_cntrl, -1, /* ascii */ + cbit_space, -1, -1, /* blank - a GNU extension */ + cbit_cntrl, -1, -1, /* cntrl */ + cbit_digit, -1, -1, /* digit */ + cbit_graph, -1, -1, /* graph */ + cbit_print, -1, -1, /* print */ + cbit_punct, -1, -1, /* punct */ + cbit_space, -1, -1, /* space */ + cbit_word, -1, -1, /* word - a Perl extension */ + cbit_xdigit,-1, -1 /* xdigit */ +}; + + +/* The texts of compile-time error messages. These are "char *" because they +are passed to the outside world. */ + +static const char *error_texts[] = { + "no error", + "\\ at end of pattern", + "\\c at end of pattern", + "unrecognized character follows \\", + "numbers out of order in {} quantifier", + /* 5 */ + "number too big in {} quantifier", + "missing terminating ] for character class", + "invalid escape sequence in character class", + "range out of order in character class", + "nothing to repeat", + /* 10 */ + "operand of unlimited repeat could match the empty string", + "internal error: unexpected repeat", + "unrecognized character after (?", + "POSIX named classes are supported only within a class", + "missing )", + /* 15 */ + "reference to non-existent subpattern", + "erroffset passed as NULL", + "unknown option bit(s) set", + "missing ) after comment", + "parentheses nested too deeply", + /* 20 */ + "regular expression too large", + "failed to get memory", + "unmatched parentheses", + "internal error: code overflow", + "unrecognized character after (?<", + /* 25 */ + "lookbehind assertion is not fixed length", + "malformed number after (?(", + "conditional group contains more than two branches", + "assertion expected after (?(", + "(?R or (?digits must be followed by )", + /* 30 */ + "unknown POSIX class name", + "POSIX collating elements are not supported", + "this version of PCRE is not compiled with PCRE_UTF8 support", + "spare error", + "character value in \\x{...} sequence is too large", + /* 35 */ + "invalid condition (?(0)", + "\\C not allowed in lookbehind assertion", + "PCRE does not support \\L, \\l, \\N, \\U, or \\u", + "number after (?C is > 255", + "closing ) for (?C expected", + /* 40 */ + "recursive call could loop indefinitely", + "unrecognized character after (?P", + "syntax error after (?P", + "two named groups have the same name", + "invalid UTF-8 string", + /* 45 */ + "support for \\P, \\p, and \\X has not been compiled", + "malformed \\P or \\p sequence", + "unknown property name after \\P or \\p" +}; + + +/* Table to identify digits and hex digits. This is used when compiling +patterns. Note that the tables in chartables are dependent on the locale, and +may mark arbitrary characters as digits - but the PCRE compiling code expects +to handle only 0-9, a-z, and A-Z as digits when compiling. That is why we have +a private table here. It costs 256 bytes, but it is a lot faster than doing +character value tests (at least in some simple cases I timed), and in some +applications one wants PCRE to compile efficiently as well as match +efficiently. + +For convenience, we use the same bit definitions as in chartables: + + 0x04 decimal digit + 0x08 hexadecimal digit + +Then we can use ctype_digit and ctype_xdigit in the code. */ + +#if !EBCDIC /* This is the "normal" case, for ASCII systems */ +static const unsigned char digitab[] = + { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 8- 15 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - ' */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ( - / */ + 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, /* 0 - 7 */ + 0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00, /* 8 - ? */ + 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* @ - G */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* H - O */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* P - W */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* X - _ */ + 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* ` - g */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* h - o */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p - w */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* x -127 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */ + +#else /* This is the "abnormal" case, for EBCDIC systems */ +static const unsigned char digitab[] = + { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 0 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 8- 15 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 10 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 32- 39 20 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 40- 47 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 48- 55 30 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 56- 63 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - 71 40 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 72- | */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* & - 87 50 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 88- ¬ */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - -103 60 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 104- ? */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 112-119 70 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 120- " */ + 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* 128- g 80 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* h -143 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144- p 90 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* q -159 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160- x A0 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* y -175 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ^ -183 B0 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ + 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* { - G C0 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* H -207 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* } - P D0 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Q -223 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* \ - X E0 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Y -239 */ + 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, /* 0 - 7 F0 */ + 0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00};/* 8 -255 */ + +static const unsigned char ebcdic_chartab[] = { /* chartable partial dup */ + 0x80,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 0- 7 */ + 0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x00, /* 8- 15 */ + 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 16- 23 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ + 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 32- 39 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 40- 47 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 48- 55 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 56- 63 */ + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - 71 */ + 0x00,0x00,0x00,0x80,0x00,0x80,0x80,0x80, /* 72- | */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* & - 87 */ + 0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00, /* 88- ¬ */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - -103 */ + 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x80, /* 104- ? */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 112-119 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 120- " */ + 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* 128- g */ + 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* h -143 */ + 0x00,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* 144- p */ + 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* q -159 */ + 0x00,0x00,0x12,0x12,0x12,0x12,0x12,0x12, /* 160- x */ + 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* y -175 */ + 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ^ -183 */ + 0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ + 0x80,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* { - G */ + 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* H -207 */ + 0x00,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* } - P */ + 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* Q -223 */ + 0x00,0x00,0x12,0x12,0x12,0x12,0x12,0x12, /* \ - X */ + 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* Y -239 */ + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */ + 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x00};/* 8 -255 */ +#endif + + +/* Definition to allow mutual recursion */ + +static BOOL + compile_regex(int, int, int *, uschar **, const uschar **, int *, BOOL, int, + int *, int *, branch_chain *, compile_data *); + + + +/************************************************* +* Handle escapes * +*************************************************/ + +/* This function is called when a \ has been encountered. It either returns a +positive value for a simple escape such as \n, or a negative value which +encodes one of the more complicated things such as \d. When UTF-8 is enabled, +a positive value greater than 255 may be returned. On entry, ptr is pointing at +the \. On exit, it is on the final character of the escape sequence. + +Arguments: + ptrptr points to the pattern position pointer + errorcodeptr points to the errorcode variable + bracount number of previous extracting brackets + options the options bits + isclass TRUE if inside a character class + +Returns: zero or positive => a data character + negative => a special escape sequence + on error, errorptr is set +*/ + +static int +check_escape(const uschar **ptrptr, int *errorcodeptr, int bracount, + int options, BOOL isclass) +{ +const uschar *ptr = *ptrptr; +int c, i; + +/* If backslash is at the end of the pattern, it's an error. */ + +c = *(++ptr); +if (c == 0) *errorcodeptr = ERR1; + +/* Non-alphamerics are literals. For digits or letters, do an initial lookup in +a table. A non-zero result is something that can be returned immediately. +Otherwise further processing may be required. */ + +#if !EBCDIC /* ASCII coding */ +else if (c < '0' || c > 'z') {} /* Not alphameric */ +else if ((i = escapes[c - '0']) != 0) c = i; + +#else /* EBCDIC coding */ +else if (c < 'a' || (ebcdic_chartab[c] & 0x0E) == 0) {} /* Not alphameric */ +else if ((i = escapes[c - 0x48]) != 0) c = i; +#endif + +/* Escapes that need further processing, or are illegal. */ + +else + { + const uschar *oldptr; + switch (c) + { + /* A number of Perl escapes are not handled by PCRE. We give an explicit + error. */ + + case 'l': + case 'L': + case 'N': + case 'u': + case 'U': + *errorcodeptr = ERR37; + break; + + /* The handling of escape sequences consisting of a string of digits + starting with one that is not zero is not straightforward. By experiment, + the way Perl works seems to be as follows: + + Outside a character class, the digits are read as a decimal number. If the + number is less than 10, or if there are that many previous extracting + left brackets, then it is a back reference. Otherwise, up to three octal + digits are read to form an escaped byte. Thus \123 is likely to be octal + 123 (cf \0123, which is octal 012 followed by the literal 3). If the octal + value is greater than 377, the least significant 8 bits are taken. Inside a + character class, \ followed by a digit is always an octal number. */ + + case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + + if (!isclass) + { + oldptr = ptr; + c -= '0'; + while ((digitab[ptr[1]] & ctype_digit) != 0) + c = c * 10 + *(++ptr) - '0'; + if (c < 10 || c <= bracount) + { + c = -(ESC_REF + c); + break; + } + ptr = oldptr; /* Put the pointer back and fall through */ + } + + /* Handle an octal number following \. If the first digit is 8 or 9, Perl + generates a binary zero byte and treats the digit as a following literal. + Thus we have to pull back the pointer by one. */ + + if ((c = *ptr) >= '8') + { + ptr--; + c = 0; + break; + } + + /* \0 always starts an octal number, but we may drop through to here with a + larger first octal digit. */ + + case '0': + c -= '0'; + while(i++ < 2 && ptr[1] >= '0' && ptr[1] <= '7') + c = c * 8 + *(++ptr) - '0'; + c &= 255; /* Take least significant 8 bits */ + break; + + /* \x is complicated when UTF-8 is enabled. \x{ddd} is a character number + which can be greater than 0xff, but only if the ddd are hex digits. */ + + case 'x': +#ifdef SUPPORT_UTF8 + if (ptr[1] == '{' && (options & PCRE_UTF8) != 0) + { + const uschar *pt = ptr + 2; + register int count = 0; + c = 0; + while ((digitab[*pt] & ctype_xdigit) != 0) + { + int cc = *pt++; + count++; +#if !EBCDIC /* ASCII coding */ + if (cc >= 'a') cc -= 32; /* Convert to upper case */ + c = c * 16 + cc - ((cc < 'A')? '0' : ('A' - 10)); +#else /* EBCDIC coding */ + if (cc >= 'a' && cc <= 'z') cc += 64; /* Convert to upper case */ + c = c * 16 + cc - ((cc >= '0')? '0' : ('A' - 10)); +#endif + } + if (*pt == '}') + { + if (c < 0 || count > 8) *errorcodeptr = ERR34; + ptr = pt; + break; + } + /* If the sequence of hex digits does not end with '}', then we don't + recognize this construct; fall through to the normal \x handling. */ + } +#endif + + /* Read just a single hex char */ + + c = 0; + while (i++ < 2 && (digitab[ptr[1]] & ctype_xdigit) != 0) + { + int cc; /* Some compilers don't like ++ */ + cc = *(++ptr); /* in initializers */ +#if !EBCDIC /* ASCII coding */ + if (cc >= 'a') cc -= 32; /* Convert to upper case */ + c = c * 16 + cc - ((cc < 'A')? '0' : ('A' - 10)); +#else /* EBCDIC coding */ + if (cc <= 'z') cc += 64; /* Convert to upper case */ + c = c * 16 + cc - ((cc >= '0')? '0' : ('A' - 10)); +#endif + } + break; + + /* Other special escapes not starting with a digit are straightforward */ + + case 'c': + c = *(++ptr); + if (c == 0) + { + *errorcodeptr = ERR2; + return 0; + } + + /* A letter is upper-cased; then the 0x40 bit is flipped. This coding + is ASCII-specific, but then the whole concept of \cx is ASCII-specific. + (However, an EBCDIC equivalent has now been added.) */ + +#if !EBCDIC /* ASCII coding */ + if (c >= 'a' && c <= 'z') c -= 32; + c ^= 0x40; +#else /* EBCDIC coding */ + if (c >= 'a' && c <= 'z') c += 64; + c ^= 0xC0; +#endif + break; + + /* PCRE_EXTRA enables extensions to Perl in the matter of escapes. Any + other alphameric following \ is an error if PCRE_EXTRA was set; otherwise, + for Perl compatibility, it is a literal. This code looks a bit odd, but + there used to be some cases other than the default, and there may be again + in future, so I haven't "optimized" it. */ + + default: + if ((options & PCRE_EXTRA) != 0) switch(c) + { + default: + *errorcodeptr = ERR3; + break; + } + break; + } + } + +*ptrptr = ptr; +return c; +} + + + +#ifdef SUPPORT_UCP +/************************************************* +* Handle \P and \p * +*************************************************/ + +/* This function is called after \P or \p has been encountered, provided that +PCRE is compiled with support for Unicode properties. On entry, ptrptr is +pointing at the P or p. On exit, it is pointing at the final character of the +escape sequence. + +Argument: + ptrptr points to the pattern position pointer + negptr points to a boolean that is set TRUE for negation else FALSE + errorcodeptr points to the error code variable + +Returns: value from ucp_type_table, or -1 for an invalid type +*/ + +static int +get_ucp(const uschar **ptrptr, BOOL *negptr, int *errorcodeptr) +{ +int c, i, bot, top; +const uschar *ptr = *ptrptr; +char name[4]; + +c = *(++ptr); +if (c == 0) goto ERROR_RETURN; + +*negptr = FALSE; + +/* \P or \p can be followed by a one- or two-character name in {}, optionally +preceded by ^ for negation. */ + +if (c == '{') + { + if (ptr[1] == '^') + { + *negptr = TRUE; + ptr++; + } + for (i = 0; i <= 2; i++) + { + c = *(++ptr); + if (c == 0) goto ERROR_RETURN; + if (c == '}') break; + name[i] = c; + } + if (c !='}') /* Try to distinguish error cases */ + { + while (*(++ptr) != 0 && *ptr != '}'); + if (*ptr == '}') goto UNKNOWN_RETURN; else goto ERROR_RETURN; + } + name[i] = 0; + } + +/* Otherwise there is just one following character */ + +else + { + name[0] = c; + name[1] = 0; + } + +*ptrptr = ptr; + +/* Search for a recognized property name using binary chop */ + +bot = 0; +top = _pcre_utt_size; + +while (bot < top) + { + i = (bot + top)/2; + c = strcmp(name, _pcre_utt[i].name); + if (c == 0) return _pcre_utt[i].value; + if (c > 0) bot = i + 1; else top = i; + } + +UNKNOWN_RETURN: +*errorcodeptr = ERR47; +*ptrptr = ptr; +return -1; + +ERROR_RETURN: +*errorcodeptr = ERR46; +*ptrptr = ptr; +return -1; +} +#endif + + + + +/************************************************* +* Check for counted repeat * +*************************************************/ + +/* This function is called when a '{' is encountered in a place where it might +start a quantifier. It looks ahead to see if it really is a quantifier or not. +It is only a quantifier if it is one of the forms {ddd} {ddd,} or {ddd,ddd} +where the ddds are digits. + +Arguments: + p pointer to the first char after '{' + +Returns: TRUE or FALSE +*/ + +static BOOL +is_counted_repeat(const uschar *p) +{ +if ((digitab[*p++] & ctype_digit) == 0) return FALSE; +while ((digitab[*p] & ctype_digit) != 0) p++; +if (*p == '}') return TRUE; + +if (*p++ != ',') return FALSE; +if (*p == '}') return TRUE; + +if ((digitab[*p++] & ctype_digit) == 0) return FALSE; +while ((digitab[*p] & ctype_digit) != 0) p++; + +return (*p == '}'); +} + + + +/************************************************* +* Read repeat counts * +*************************************************/ + +/* Read an item of the form {n,m} and return the values. This is called only +after is_counted_repeat() has confirmed that a repeat-count quantifier exists, +so the syntax is guaranteed to be correct, but we need to check the values. + +Arguments: + p pointer to first char after '{' + minp pointer to int for min + maxp pointer to int for max + returned as -1 if no max + errorcodeptr points to error code variable + +Returns: pointer to '}' on success; + current ptr on error, with errorcodeptr set non-zero +*/ + +static const uschar * +read_repeat_counts(const uschar *p, int *minp, int *maxp, int *errorcodeptr) +{ +int min = 0; +int max = -1; + +/* Read the minimum value and do a paranoid check: a negative value indicates +an integer overflow. */ + +while ((digitab[*p] & ctype_digit) != 0) min = min * 10 + *p++ - '0'; +if (min < 0 || min > 65535) + { + *errorcodeptr = ERR5; + return p; + } + +/* Read the maximum value if there is one, and again do a paranoid on its size. +Also, max must not be less than min. */ + +if (*p == '}') max = min; else + { + if (*(++p) != '}') + { + max = 0; + while((digitab[*p] & ctype_digit) != 0) max = max * 10 + *p++ - '0'; + if (max < 0 || max > 65535) + { + *errorcodeptr = ERR5; + return p; + } + if (max < min) + { + *errorcodeptr = ERR4; + return p; + } + } + } + +/* Fill in the required variables, and pass back the pointer to the terminating +'}'. */ + +*minp = min; +*maxp = max; +return p; +} + + + +/************************************************* +* Find first significant op code * +*************************************************/ + +/* This is called by several functions that scan a compiled expression looking +for a fixed first character, or an anchoring op code etc. It skips over things +that do not influence this. For some calls, a change of option is important. +For some calls, it makes sense to skip negative forward and all backward +assertions, and also the \b assertion; for others it does not. + +Arguments: + code pointer to the start of the group + options pointer to external options + optbit the option bit whose changing is significant, or + zero if none are + skipassert TRUE if certain assertions are to be skipped + +Returns: pointer to the first significant opcode +*/ + +static const uschar* +first_significant_code(const uschar *code, int *options, int optbit, + BOOL skipassert) +{ +for (;;) + { + switch ((int)*code) + { + case OP_OPT: + if (optbit > 0 && ((int)code[1] & optbit) != (*options & optbit)) + *options = (int)code[1]; + code += 2; + break; + + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + if (!skipassert) return code; + do code += GET(code, 1); while (*code == OP_ALT); + code += _pcre_OP_lengths[*code]; + break; + + case OP_WORD_BOUNDARY: + case OP_NOT_WORD_BOUNDARY: + if (!skipassert) return code; + /* Fall through */ + + case OP_CALLOUT: + case OP_CREF: + case OP_BRANUMBER: + code += _pcre_OP_lengths[*code]; + break; + + default: + return code; + } + } +/* Control never reaches here */ +} + + + + +/************************************************* +* Find the fixed length of a pattern * +*************************************************/ + +/* Scan a pattern and compute the fixed length of subject that will match it, +if the length is fixed. This is needed for dealing with backward assertions. +In UTF8 mode, the result is in characters rather than bytes. + +Arguments: + code points to the start of the pattern (the bracket) + options the compiling options + +Returns: the fixed length, or -1 if there is no fixed length, + or -2 if \C was encountered +*/ + +static int +find_fixedlength(uschar *code, int options) +{ +int length = -1; + +register int branchlength = 0; +register uschar *cc = code + 1 + LINK_SIZE; + +/* Scan along the opcodes for this branch. If we get to the end of the +branch, check the length against that of the other branches. */ + +for (;;) + { + int d; + register int op = *cc; + if (op >= OP_BRA) op = OP_BRA; + + switch (op) + { + case OP_BRA: + case OP_ONCE: + case OP_COND: + d = find_fixedlength(cc, options); + if (d < 0) return d; + branchlength += d; + do cc += GET(cc, 1); while (*cc == OP_ALT); + cc += 1 + LINK_SIZE; + break; + + /* Reached end of a branch; if it's a ket it is the end of a nested + call. If it's ALT it is an alternation in a nested call. If it is + END it's the end of the outer call. All can be handled by the same code. */ + + case OP_ALT: + case OP_KET: + case OP_KETRMAX: + case OP_KETRMIN: + case OP_END: + if (length < 0) length = branchlength; + else if (length != branchlength) return -1; + if (*cc != OP_ALT) return length; + cc += 1 + LINK_SIZE; + branchlength = 0; + break; + + /* Skip over assertive subpatterns */ + + case OP_ASSERT: + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + do cc += GET(cc, 1); while (*cc == OP_ALT); + /* Fall through */ + + /* Skip over things that don't match chars */ + + case OP_REVERSE: + case OP_BRANUMBER: + case OP_CREF: + case OP_OPT: + case OP_CALLOUT: + case OP_SOD: + case OP_SOM: + case OP_EOD: + case OP_EODN: + case OP_CIRC: + case OP_DOLL: + case OP_NOT_WORD_BOUNDARY: + case OP_WORD_BOUNDARY: + cc += _pcre_OP_lengths[*cc]; + break; + + /* Handle literal characters */ + + case OP_CHAR: + case OP_CHARNC: + branchlength++; + cc += 2; +#ifdef SUPPORT_UTF8 + if ((options & PCRE_UTF8) != 0) + { + while ((*cc & 0xc0) == 0x80) cc++; + } +#endif + break; + + /* Handle exact repetitions. The count is already in characters, but we + need to skip over a multibyte character in UTF8 mode. */ + + case OP_EXACT: + branchlength += GET2(cc,1); + cc += 4; +#ifdef SUPPORT_UTF8 + if ((options & PCRE_UTF8) != 0) + { + while((*cc & 0x80) == 0x80) cc++; + } +#endif + break; + + case OP_TYPEEXACT: + branchlength += GET2(cc,1); + cc += 4; + break; + + /* Handle single-char matchers */ + + case OP_PROP: + case OP_NOTPROP: + cc++; + /* Fall through */ + + case OP_NOT_DIGIT: + case OP_DIGIT: + case OP_NOT_WHITESPACE: + case OP_WHITESPACE: + case OP_NOT_WORDCHAR: + case OP_WORDCHAR: + case OP_ANY: + branchlength++; + cc++; + break; + + /* The single-byte matcher isn't allowed */ + + case OP_ANYBYTE: + return -2; + + /* Check a class for variable quantification */ + +#ifdef SUPPORT_UTF8 + case OP_XCLASS: + cc += GET(cc, 1) - 33; + /* Fall through */ +#endif + + case OP_CLASS: + case OP_NCLASS: + cc += 33; + + switch (*cc) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRQUERY: + case OP_CRMINQUERY: + return -1; + + case OP_CRRANGE: + case OP_CRMINRANGE: + if (GET2(cc,1) != GET2(cc,3)) return -1; + branchlength += GET2(cc,1); + cc += 5; + break; + + default: + branchlength++; + } + break; + + /* Anything else is variable length */ + + default: + return -1; + } + } +/* Control never gets here */ +} + + + + +/************************************************* +* Scan compiled regex for numbered bracket * +*************************************************/ + +/* This little function scans through a compiled pattern until it finds a +capturing bracket with the given number. + +Arguments: + code points to start of expression + utf8 TRUE in UTF-8 mode + number the required bracket number + +Returns: pointer to the opcode for the bracket, or NULL if not found +*/ + +static const uschar * +find_bracket(const uschar *code, BOOL utf8, int number) +{ +#ifndef SUPPORT_UTF8 +utf8 = utf8; /* Stop pedantic compilers complaining */ +#endif + +for (;;) + { + register int c = *code; + if (c == OP_END) return NULL; + else if (c > OP_BRA) + { + int n = c - OP_BRA; + if (n > EXTRACT_BASIC_MAX) n = GET2(code, 2+LINK_SIZE); + if (n == number) return (uschar *)code; + code += _pcre_OP_lengths[OP_BRA]; + } + else + { + code += _pcre_OP_lengths[c]; + +#ifdef SUPPORT_UTF8 + + /* In UTF-8 mode, opcodes that are followed by a character may be followed + by a multi-byte character. The length in the table is a minimum, so we have + to scan along to skip the extra bytes. All opcodes are less than 128, so we + can use relatively efficient code. */ + + if (utf8) switch(c) + { + case OP_CHAR: + case OP_CHARNC: + case OP_EXACT: + case OP_UPTO: + case OP_MINUPTO: + case OP_STAR: + case OP_MINSTAR: + case OP_PLUS: + case OP_MINPLUS: + case OP_QUERY: + case OP_MINQUERY: + while ((*code & 0xc0) == 0x80) code++; + break; + + /* XCLASS is used for classes that cannot be represented just by a bit + map. This includes negated single high-valued characters. The length in + the table is zero; the actual length is stored in the compiled code. */ + + case OP_XCLASS: + code += GET(code, 1) + 1; + break; + } +#endif + } + } +} + + + +/************************************************* +* Scan compiled regex for recursion reference * +*************************************************/ + +/* This little function scans through a compiled pattern until it finds an +instance of OP_RECURSE. + +Arguments: + code points to start of expression + utf8 TRUE in UTF-8 mode + +Returns: pointer to the opcode for OP_RECURSE, or NULL if not found +*/ + +static const uschar * +find_recurse(const uschar *code, BOOL utf8) +{ +#ifndef SUPPORT_UTF8 +utf8 = utf8; /* Stop pedantic compilers complaining */ +#endif + +for (;;) + { + register int c = *code; + if (c == OP_END) return NULL; + else if (c == OP_RECURSE) return code; + else if (c > OP_BRA) + { + code += _pcre_OP_lengths[OP_BRA]; + } + else + { + code += _pcre_OP_lengths[c]; + +#ifdef SUPPORT_UTF8 + + /* In UTF-8 mode, opcodes that are followed by a character may be followed + by a multi-byte character. The length in the table is a minimum, so we have + to scan along to skip the extra bytes. All opcodes are less than 128, so we + can use relatively efficient code. */ + + if (utf8) switch(c) + { + case OP_CHAR: + case OP_CHARNC: + case OP_EXACT: + case OP_UPTO: + case OP_MINUPTO: + case OP_STAR: + case OP_MINSTAR: + case OP_PLUS: + case OP_MINPLUS: + case OP_QUERY: + case OP_MINQUERY: + while ((*code & 0xc0) == 0x80) code++; + break; + + /* XCLASS is used for classes that cannot be represented just by a bit + map. This includes negated single high-valued characters. The length in + the table is zero; the actual length is stored in the compiled code. */ + + case OP_XCLASS: + code += GET(code, 1) + 1; + break; + } +#endif + } + } +} + + + +/************************************************* +* Scan compiled branch for non-emptiness * +*************************************************/ + +/* This function scans through a branch of a compiled pattern to see whether it +can match the empty string or not. It is called only from could_be_empty() +below. Note that first_significant_code() skips over assertions. If we hit an +unclosed bracket, we return "empty" - this means we've struck an inner bracket +whose current branch will already have been scanned. + +Arguments: + code points to start of search + endcode points to where to stop + utf8 TRUE if in UTF8 mode + +Returns: TRUE if what is matched could be empty +*/ + +static BOOL +could_be_empty_branch(const uschar *code, const uschar *endcode, BOOL utf8) +{ +register int c; +for (code = first_significant_code(code + 1 + LINK_SIZE, NULL, 0, TRUE); + code < endcode; + code = first_significant_code(code + _pcre_OP_lengths[c], NULL, 0, TRUE)) + { + const uschar *ccode; + + c = *code; + + if (c >= OP_BRA) + { + BOOL empty_branch; + if (GET(code, 1) == 0) return TRUE; /* Hit unclosed bracket */ + + /* Scan a closed bracket */ + + empty_branch = FALSE; + do + { + if (!empty_branch && could_be_empty_branch(code, endcode, utf8)) + empty_branch = TRUE; + code += GET(code, 1); + } + while (*code == OP_ALT); + if (!empty_branch) return FALSE; /* All branches are non-empty */ + code += 1 + LINK_SIZE; + c = *code; + } + + else switch (c) + { + /* Check for quantifiers after a class */ + +#ifdef SUPPORT_UTF8 + case OP_XCLASS: + ccode = code + GET(code, 1); + goto CHECK_CLASS_REPEAT; +#endif + + case OP_CLASS: + case OP_NCLASS: + ccode = code + 33; + +#ifdef SUPPORT_UTF8 + CHECK_CLASS_REPEAT: +#endif + + switch (*ccode) + { + case OP_CRSTAR: /* These could be empty; continue */ + case OP_CRMINSTAR: + case OP_CRQUERY: + case OP_CRMINQUERY: + break; + + default: /* Non-repeat => class must match */ + case OP_CRPLUS: /* These repeats aren't empty */ + case OP_CRMINPLUS: + return FALSE; + + case OP_CRRANGE: + case OP_CRMINRANGE: + if (GET2(ccode, 1) > 0) return FALSE; /* Minimum > 0 */ + break; + } + break; + + /* Opcodes that must match a character */ + + case OP_PROP: + case OP_NOTPROP: + case OP_EXTUNI: + case OP_NOT_DIGIT: + case OP_DIGIT: + case OP_NOT_WHITESPACE: + case OP_WHITESPACE: + case OP_NOT_WORDCHAR: + case OP_WORDCHAR: + case OP_ANY: + case OP_ANYBYTE: + case OP_CHAR: + case OP_CHARNC: + case OP_NOT: + case OP_PLUS: + case OP_MINPLUS: + case OP_EXACT: + case OP_NOTPLUS: + case OP_NOTMINPLUS: + case OP_NOTEXACT: + case OP_TYPEPLUS: + case OP_TYPEMINPLUS: + case OP_TYPEEXACT: + return FALSE; + + /* End of branch */ + + case OP_KET: + case OP_KETRMAX: + case OP_KETRMIN: + case OP_ALT: + return TRUE; + + /* In UTF-8 mode, STAR, MINSTAR, QUERY, MINQUERY, UPTO, and MINUPTO may be + followed by a multibyte character */ + +#ifdef SUPPORT_UTF8 + case OP_STAR: + case OP_MINSTAR: + case OP_QUERY: + case OP_MINQUERY: + case OP_UPTO: + case OP_MINUPTO: + if (utf8) while ((code[2] & 0xc0) == 0x80) code++; + break; +#endif + } + } + +return TRUE; +} + + + +/************************************************* +* Scan compiled regex for non-emptiness * +*************************************************/ + +/* This function is called to check for left recursive calls. We want to check +the current branch of the current pattern to see if it could match the empty +string. If it could, we must look outwards for branches at other levels, +stopping when we pass beyond the bracket which is the subject of the recursion. + +Arguments: + code points to start of the recursion + endcode points to where to stop (current RECURSE item) + bcptr points to the chain of current (unclosed) branch starts + utf8 TRUE if in UTF-8 mode + +Returns: TRUE if what is matched could be empty +*/ + +static BOOL +could_be_empty(const uschar *code, const uschar *endcode, branch_chain *bcptr, + BOOL utf8) +{ +while (bcptr != NULL && bcptr->current >= code) + { + if (!could_be_empty_branch(bcptr->current, endcode, utf8)) return FALSE; + bcptr = bcptr->outer; + } +return TRUE; +} + + + +/************************************************* +* Check for POSIX class syntax * +*************************************************/ + +/* This function is called when the sequence "[:" or "[." or "[=" is +encountered in a character class. It checks whether this is followed by an +optional ^ and then a sequence of letters, terminated by a matching ":]" or +".]" or "=]". + +Argument: + ptr pointer to the initial [ + endptr where to return the end pointer + cd pointer to compile data + +Returns: TRUE or FALSE +*/ + +static BOOL +check_posix_syntax(const uschar *ptr, const uschar **endptr, compile_data *cd) +{ +int terminator; /* Don't combine these lines; the Solaris cc */ +terminator = *(++ptr); /* compiler warns about "non-constant" initializer. */ +if (*(++ptr) == '^') ptr++; +while ((cd->ctypes[*ptr] & ctype_letter) != 0) ptr++; +if (*ptr == terminator && ptr[1] == ']') + { + *endptr = ptr; + return TRUE; + } +return FALSE; +} + + + + +/************************************************* +* Check POSIX class name * +*************************************************/ + +/* This function is called to check the name given in a POSIX-style class entry +such as [:alnum:]. + +Arguments: + ptr points to the first letter + len the length of the name + +Returns: a value representing the name, or -1 if unknown +*/ + +static int +check_posix_name(const uschar *ptr, int len) +{ +register int yield = 0; +while (posix_name_lengths[yield] != 0) + { + if (len == posix_name_lengths[yield] && + strncmp((const char *)ptr, posix_names[yield], len) == 0) return yield; + yield++; + } +return -1; +} + + +/************************************************* +* Adjust OP_RECURSE items in repeated group * +*************************************************/ + +/* OP_RECURSE items contain an offset from the start of the regex to the group +that is referenced. This means that groups can be replicated for fixed +repetition simply by copying (because the recursion is allowed to refer to +earlier groups that are outside the current group). However, when a group is +optional (i.e. the minimum quantifier is zero), OP_BRAZERO is inserted before +it, after it has been compiled. This means that any OP_RECURSE items within it +that refer to the group itself or any contained groups have to have their +offsets adjusted. That is the job of this function. Before it is called, the +partially compiled regex must be temporarily terminated with OP_END. + +Arguments: + group points to the start of the group + adjust the amount by which the group is to be moved + utf8 TRUE in UTF-8 mode + cd contains pointers to tables etc. + +Returns: nothing +*/ + +static void +adjust_recurse(uschar *group, int adjust, BOOL utf8, compile_data *cd) +{ +uschar *ptr = group; +while ((ptr = (uschar *)find_recurse(ptr, utf8)) != NULL) + { + int offset = GET(ptr, 1); + if (cd->start_code + offset >= group) PUT(ptr, 1, offset + adjust); + ptr += 1 + LINK_SIZE; + } +} + + + +/************************************************* +* Insert an automatic callout point * +*************************************************/ + +/* This function is called when the PCRE_AUTO_CALLOUT option is set, to insert +callout points before each pattern item. + +Arguments: + code current code pointer + ptr current pattern pointer + cd pointers to tables etc + +Returns: new code pointer +*/ + +static uschar * +auto_callout(uschar *code, const uschar *ptr, compile_data *cd) +{ +*code++ = OP_CALLOUT; +*code++ = 255; +PUT(code, 0, ptr - cd->start_pattern); /* Pattern offset */ +PUT(code, LINK_SIZE, 0); /* Default length */ +return code + 2*LINK_SIZE; +} + + + +/************************************************* +* Complete a callout item * +*************************************************/ + +/* A callout item contains the length of the next item in the pattern, which +we can't fill in till after we have reached the relevant point. This is used +for both automatic and manual callouts. + +Arguments: + previous_callout points to previous callout item + ptr current pattern pointer + cd pointers to tables etc + +Returns: nothing +*/ + +static void +complete_callout(uschar *previous_callout, const uschar *ptr, compile_data *cd) +{ +int length = ptr - cd->start_pattern - GET(previous_callout, 2); +PUT(previous_callout, 2 + LINK_SIZE, length); +} + + + +#ifdef SUPPORT_UCP +/************************************************* +* Get othercase range * +*************************************************/ + +/* This function is passed the start and end of a class range, in UTF-8 mode +with UCP support. It searches up the characters, looking for internal ranges of +characters in the "other" case. Each call returns the next one, updating the +start address. + +Arguments: + cptr points to starting character value; updated + d end value + ocptr where to put start of othercase range + odptr where to put end of othercase range + +Yield: TRUE when range returned; FALSE when no more +*/ + +static BOOL +get_othercase_range(int *cptr, int d, int *ocptr, int *odptr) +{ +int c, chartype, othercase, next; + +for (c = *cptr; c <= d; c++) + { + if (_pcre_ucp_findchar(c, &chartype, &othercase) == ucp_L && othercase != 0) + break; + } + +if (c > d) return FALSE; + +*ocptr = othercase; +next = othercase + 1; + +for (++c; c <= d; c++) + { + if (_pcre_ucp_findchar(c, &chartype, &othercase) != ucp_L || + othercase != next) + break; + next++; + } + +*odptr = next - 1; +*cptr = c; + +return TRUE; +} +#endif /* SUPPORT_UCP */ + + +/************************************************* +* Compile one branch * +*************************************************/ + +/* Scan the pattern, compiling it into the code vector. If the options are +changed during the branch, the pointer is used to change the external options +bits. + +Arguments: + optionsptr pointer to the option bits + brackets points to number of extracting brackets used + codeptr points to the pointer to the current code point + ptrptr points to the current pattern pointer + errorcodeptr points to error code variable + firstbyteptr set to initial literal character, or < 0 (REQ_UNSET, REQ_NONE) + reqbyteptr set to the last literal character required, else < 0 + bcptr points to current branch chain + cd contains pointers to tables etc. + +Returns: TRUE on success + FALSE, with *errorcodeptr set non-zero on error +*/ + +static BOOL +compile_branch(int *optionsptr, int *brackets, uschar **codeptr, + const uschar **ptrptr, int *errorcodeptr, int *firstbyteptr, + int *reqbyteptr, branch_chain *bcptr, compile_data *cd) +{ +int repeat_type, op_type; +int repeat_min = 0, repeat_max = 0; /* To please picky compilers */ +int bravalue = 0; +int greedy_default, greedy_non_default; +int firstbyte, reqbyte; +int zeroreqbyte, zerofirstbyte; +int req_caseopt, reqvary, tempreqvary; +int condcount = 0; +int options = *optionsptr; +int after_manual_callout = 0; +register int c; +register uschar *code = *codeptr; +uschar *tempcode; +BOOL inescq = FALSE; +BOOL groupsetfirstbyte = FALSE; +const uschar *ptr = *ptrptr; +const uschar *tempptr; +uschar *previous = NULL; +uschar *previous_callout = NULL; +uschar classbits[32]; + +#ifdef SUPPORT_UTF8 +BOOL class_utf8; +BOOL utf8 = (options & PCRE_UTF8) != 0; +uschar *class_utf8data; +uschar utf8_char[6]; +#else +BOOL utf8 = FALSE; +#endif + +/* Set up the default and non-default settings for greediness */ + +greedy_default = ((options & PCRE_UNGREEDY) != 0); +greedy_non_default = greedy_default ^ 1; + +/* Initialize no first byte, no required byte. REQ_UNSET means "no char +matching encountered yet". It gets changed to REQ_NONE if we hit something that +matches a non-fixed char first char; reqbyte just remains unset if we never +find one. + +When we hit a repeat whose minimum is zero, we may have to adjust these values +to take the zero repeat into account. This is implemented by setting them to +zerofirstbyte and zeroreqbyte when such a repeat is encountered. The individual +item types that can be repeated set these backoff variables appropriately. */ + +firstbyte = reqbyte = zerofirstbyte = zeroreqbyte = REQ_UNSET; + +/* The variable req_caseopt contains either the REQ_CASELESS value or zero, +according to the current setting of the caseless flag. REQ_CASELESS is a bit +value > 255. It is added into the firstbyte or reqbyte variables to record the +case status of the value. This is used only for ASCII characters. */ + +req_caseopt = ((options & PCRE_CASELESS) != 0)? REQ_CASELESS : 0; + +/* Switch on next character until the end of the branch */ + +for (;; ptr++) + { + BOOL negate_class; + BOOL possessive_quantifier; + BOOL is_quantifier; + int class_charcount; + int class_lastchar; + int newoptions; + int recno; + int skipbytes; + int subreqbyte; + int subfirstbyte; + int mclength; + uschar mcbuffer[8]; + + /* Next byte in the pattern */ + + c = *ptr; + + /* If in \Q...\E, check for the end; if not, we have a literal */ + + if (inescq && c != 0) + { + if (c == '\\' && ptr[1] == 'E') + { + inescq = FALSE; + ptr++; + continue; + } + else + { + if (previous_callout != NULL) + { + complete_callout(previous_callout, ptr, cd); + previous_callout = NULL; + } + if ((options & PCRE_AUTO_CALLOUT) != 0) + { + previous_callout = code; + code = auto_callout(code, ptr, cd); + } + goto NORMAL_CHAR; + } + } + + /* Fill in length of a previous callout, except when the next thing is + a quantifier. */ + + is_quantifier = c == '*' || c == '+' || c == '?' || + (c == '{' && is_counted_repeat(ptr+1)); + + if (!is_quantifier && previous_callout != NULL && + after_manual_callout-- <= 0) + { + complete_callout(previous_callout, ptr, cd); + previous_callout = NULL; + } + + /* In extended mode, skip white space and comments */ + + if ((options & PCRE_EXTENDED) != 0) + { + if ((cd->ctypes[c] & ctype_space) != 0) continue; + if (c == '#') + { + /* The space before the ; is to avoid a warning on a silly compiler + on the Macintosh. */ + while ((c = *(++ptr)) != 0 && c != NEWLINE) ; + if (c != 0) continue; /* Else fall through to handle end of string */ + } + } + + /* No auto callout for quantifiers. */ + + if ((options & PCRE_AUTO_CALLOUT) != 0 && !is_quantifier) + { + previous_callout = code; + code = auto_callout(code, ptr, cd); + } + + switch(c) + { + /* The branch terminates at end of string, |, or ). */ + + case 0: + case '|': + case ')': + *firstbyteptr = firstbyte; + *reqbyteptr = reqbyte; + *codeptr = code; + *ptrptr = ptr; + return TRUE; + + /* Handle single-character metacharacters. In multiline mode, ^ disables + the setting of any following char as a first character. */ + + case '^': + if ((options & PCRE_MULTILINE) != 0) + { + if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE; + } + previous = NULL; + *code++ = OP_CIRC; + break; + + case '$': + previous = NULL; + *code++ = OP_DOLL; + break; + + /* There can never be a first char if '.' is first, whatever happens about + repeats. The value of reqbyte doesn't change either. */ + + case '.': + if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE; + zerofirstbyte = firstbyte; + zeroreqbyte = reqbyte; + previous = code; + *code++ = OP_ANY; + break; + + /* Character classes. If the included characters are all < 255 in value, we + build a 32-byte bitmap of the permitted characters, except in the special + case where there is only one such character. For negated classes, we build + the map as usual, then invert it at the end. However, we use a different + opcode so that data characters > 255 can be handled correctly. + + If the class contains characters outside the 0-255 range, a different + opcode is compiled. It may optionally have a bit map for characters < 256, + but those above are are explicitly listed afterwards. A flag byte tells + whether the bitmap is present, and whether this is a negated class or not. + */ + + case '[': + previous = code; + + /* PCRE supports POSIX class stuff inside a class. Perl gives an error if + they are encountered at the top level, so we'll do that too. */ + + if ((ptr[1] == ':' || ptr[1] == '.' || ptr[1] == '=') && + check_posix_syntax(ptr, &tempptr, cd)) + { + *errorcodeptr = (ptr[1] == ':')? ERR13 : ERR31; + goto FAILED; + } + + /* If the first character is '^', set the negation flag and skip it. */ + + if ((c = *(++ptr)) == '^') + { + negate_class = TRUE; + c = *(++ptr); + } + else + { + negate_class = FALSE; + } + + /* Keep a count of chars with values < 256 so that we can optimize the case + of just a single character (as long as it's < 256). For higher valued UTF-8 + characters, we don't yet do any optimization. */ + + class_charcount = 0; + class_lastchar = -1; + +#ifdef SUPPORT_UTF8 + class_utf8 = FALSE; /* No chars >= 256 */ + class_utf8data = code + LINK_SIZE + 34; /* For UTF-8 items */ +#endif + + /* Initialize the 32-char bit map to all zeros. We have to build the + map in a temporary bit of store, in case the class contains only 1 + character (< 256), because in that case the compiled code doesn't use the + bit map. */ + + memset(classbits, 0, 32 * sizeof(uschar)); + + /* Process characters until ] is reached. By writing this as a "do" it + means that an initial ] is taken as a data character. The first pass + through the regex checked the overall syntax, so we don't need to be very + strict here. At the start of the loop, c contains the first byte of the + character. */ + + do + { +#ifdef SUPPORT_UTF8 + if (utf8 && c > 127) + { /* Braces are required because the */ + GETCHARLEN(c, ptr, ptr); /* macro generates multiple statements */ + } +#endif + + /* Inside \Q...\E everything is literal except \E */ + + if (inescq) + { + if (c == '\\' && ptr[1] == 'E') + { + inescq = FALSE; + ptr++; + continue; + } + else goto LONE_SINGLE_CHARACTER; + } + + /* Handle POSIX class names. Perl allows a negation extension of the + form [:^name:]. A square bracket that doesn't match the syntax is + treated as a literal. We also recognize the POSIX constructions + [.ch.] and [=ch=] ("collating elements") and fault them, as Perl + 5.6 and 5.8 do. */ + + if (c == '[' && + (ptr[1] == ':' || ptr[1] == '.' || ptr[1] == '=') && + check_posix_syntax(ptr, &tempptr, cd)) + { + BOOL local_negate = FALSE; + int posix_class, i; + register const uschar *cbits = cd->cbits; + + if (ptr[1] != ':') + { + *errorcodeptr = ERR31; + goto FAILED; + } + + ptr += 2; + if (*ptr == '^') + { + local_negate = TRUE; + ptr++; + } + + posix_class = check_posix_name(ptr, tempptr - ptr); + if (posix_class < 0) + { + *errorcodeptr = ERR30; + goto FAILED; + } + + /* If matching is caseless, upper and lower are converted to + alpha. This relies on the fact that the class table starts with + alpha, lower, upper as the first 3 entries. */ + + if ((options & PCRE_CASELESS) != 0 && posix_class <= 2) + posix_class = 0; + + /* Or into the map we are building up to 3 of the static class + tables, or their negations. The [:blank:] class sets up the same + chars as the [:space:] class (all white space). We remove the vertical + white space chars afterwards. */ + + posix_class *= 3; + for (i = 0; i < 3; i++) + { + BOOL blankclass = strncmp((char *)ptr, "blank", 5) == 0; + int taboffset = posix_class_maps[posix_class + i]; + if (taboffset < 0) break; + if (local_negate) + { + if (i == 0) + for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+taboffset]; + else + for (c = 0; c < 32; c++) classbits[c] &= ~cbits[c+taboffset]; + if (blankclass) classbits[1] |= 0x3c; + } + else + { + for (c = 0; c < 32; c++) classbits[c] |= cbits[c+taboffset]; + if (blankclass) classbits[1] &= ~0x3c; + } + } + + ptr = tempptr + 1; + class_charcount = 10; /* Set > 1; assumes more than 1 per class */ + continue; /* End of POSIX syntax handling */ + } + + /* Backslash may introduce a single character, or it may introduce one + of the specials, which just set a flag. Escaped items are checked for + validity in the pre-compiling pass. The sequence \b is a special case. + Inside a class (and only there) it is treated as backspace. Elsewhere + it marks a word boundary. Other escapes have preset maps ready to + or into the one we are building. We assume they have more than one + character in them, so set class_charcount bigger than one. */ + + if (c == '\\') + { + c = check_escape(&ptr, errorcodeptr, *brackets, options, TRUE); + + if (-c == ESC_b) c = '\b'; /* \b is backslash in a class */ + else if (-c == ESC_X) c = 'X'; /* \X is literal X in a class */ + else if (-c == ESC_Q) /* Handle start of quoted string */ + { + if (ptr[1] == '\\' && ptr[2] == 'E') + { + ptr += 2; /* avoid empty string */ + } + else inescq = TRUE; + continue; + } + + if (c < 0) + { + register const uschar *cbits = cd->cbits; + class_charcount += 2; /* Greater than 1 is what matters */ + switch (-c) + { + case ESC_d: + for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_digit]; + continue; + + case ESC_D: + for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_digit]; + continue; + + case ESC_w: + for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_word]; + continue; + + case ESC_W: + for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_word]; + continue; + + case ESC_s: + for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_space]; + classbits[1] &= ~0x08; /* Perl 5.004 onwards omits VT from \s */ + continue; + + case ESC_S: + for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_space]; + classbits[1] |= 0x08; /* Perl 5.004 onwards omits VT from \s */ + continue; + +#ifdef SUPPORT_UCP + case ESC_p: + case ESC_P: + { + BOOL negated; + int property = get_ucp(&ptr, &negated, errorcodeptr); + if (property < 0) goto FAILED; + class_utf8 = TRUE; + *class_utf8data++ = ((-c == ESC_p) != negated)? + XCL_PROP : XCL_NOTPROP; + *class_utf8data++ = property; + class_charcount -= 2; /* Not a < 256 character */ + } + continue; +#endif + + /* Unrecognized escapes are faulted if PCRE is running in its + strict mode. By default, for compatibility with Perl, they are + treated as literals. */ + + default: + if ((options & PCRE_EXTRA) != 0) + { + *errorcodeptr = ERR7; + goto FAILED; + } + c = *ptr; /* The final character */ + class_charcount -= 2; /* Undo the default count from above */ + } + } + + /* Fall through if we have a single character (c >= 0). This may be + > 256 in UTF-8 mode. */ + + } /* End of backslash handling */ + + /* A single character may be followed by '-' to form a range. However, + Perl does not permit ']' to be the end of the range. A '-' character + here is treated as a literal. */ + + if (ptr[1] == '-' && ptr[2] != ']') + { + int d; + ptr += 2; + +#ifdef SUPPORT_UTF8 + if (utf8) + { /* Braces are required because the */ + GETCHARLEN(d, ptr, ptr); /* macro generates multiple statements */ + } + else +#endif + d = *ptr; /* Not UTF-8 mode */ + + /* The second part of a range can be a single-character escape, but + not any of the other escapes. Perl 5.6 treats a hyphen as a literal + in such circumstances. */ + + if (d == '\\') + { + const uschar *oldptr = ptr; + d = check_escape(&ptr, errorcodeptr, *brackets, options, TRUE); + + /* \b is backslash; \X is literal X; any other special means the '-' + was literal */ + + if (d < 0) + { + if (d == -ESC_b) d = '\b'; + else if (d == -ESC_X) d = 'X'; else + { + ptr = oldptr - 2; + goto LONE_SINGLE_CHARACTER; /* A few lines below */ + } + } + } + + /* The check that the two values are in the correct order happens in + the pre-pass. Optimize one-character ranges */ + + if (d == c) goto LONE_SINGLE_CHARACTER; /* A few lines below */ + + /* In UTF-8 mode, if the upper limit is > 255, or > 127 for caseless + matching, we have to use an XCLASS with extra data items. Caseless + matching for characters > 127 is available only if UCP support is + available. */ + +#ifdef SUPPORT_UTF8 + if (utf8 && (d > 255 || ((options & PCRE_CASELESS) != 0 && d > 127))) + { + class_utf8 = TRUE; + + /* With UCP support, we can find the other case equivalents of + the relevant characters. There may be several ranges. Optimize how + they fit with the basic range. */ + +#ifdef SUPPORT_UCP + if ((options & PCRE_CASELESS) != 0) + { + int occ, ocd; + int cc = c; + int origd = d; + while (get_othercase_range(&cc, origd, &occ, &ocd)) + { + if (occ >= c && ocd <= d) continue; /* Skip embedded ranges */ + + if (occ < c && ocd >= c - 1) /* Extend the basic range */ + { /* if there is overlap, */ + c = occ; /* noting that if occ < c */ + continue; /* we can't have ocd > d */ + } /* because a subrange is */ + if (ocd > d && occ <= d + 1) /* always shorter than */ + { /* the basic range. */ + d = ocd; + continue; + } + + if (occ == ocd) + { + *class_utf8data++ = XCL_SINGLE; + } + else + { + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(occ, class_utf8data); + } + class_utf8data += _pcre_ord2utf8(ocd, class_utf8data); + } + } +#endif /* SUPPORT_UCP */ + + /* Now record the original range, possibly modified for UCP caseless + overlapping ranges. */ + + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(c, class_utf8data); + class_utf8data += _pcre_ord2utf8(d, class_utf8data); + + /* With UCP support, we are done. Without UCP support, there is no + caseless matching for UTF-8 characters > 127; we can use the bit map + for the smaller ones. */ + +#ifdef SUPPORT_UCP + continue; /* With next character in the class */ +#else + if ((options & PCRE_CASELESS) == 0 || c > 127) continue; + + /* Adjust upper limit and fall through to set up the map */ + + d = 127; + +#endif /* SUPPORT_UCP */ + } +#endif /* SUPPORT_UTF8 */ + + /* We use the bit map for all cases when not in UTF-8 mode; else + ranges that lie entirely within 0-127 when there is UCP support; else + for partial ranges without UCP support. */ + + for (; c <= d; c++) + { + classbits[c/8] |= (1 << (c&7)); + if ((options & PCRE_CASELESS) != 0) + { + int uc = cd->fcc[c]; /* flip case */ + classbits[uc/8] |= (1 << (uc&7)); + } + class_charcount++; /* in case a one-char range */ + class_lastchar = c; + } + + continue; /* Go get the next char in the class */ + } + + /* Handle a lone single character - we can get here for a normal + non-escape char, or after \ that introduces a single character or for an + apparent range that isn't. */ + + LONE_SINGLE_CHARACTER: + + /* Handle a character that cannot go in the bit map */ + +#ifdef SUPPORT_UTF8 + if (utf8 && (c > 255 || ((options & PCRE_CASELESS) != 0 && c > 127))) + { + class_utf8 = TRUE; + *class_utf8data++ = XCL_SINGLE; + class_utf8data += _pcre_ord2utf8(c, class_utf8data); + +#ifdef SUPPORT_UCP + if ((options & PCRE_CASELESS) != 0) + { + int chartype; + int othercase; + if (_pcre_ucp_findchar(c, &chartype, &othercase) >= 0 && + othercase > 0) + { + *class_utf8data++ = XCL_SINGLE; + class_utf8data += _pcre_ord2utf8(othercase, class_utf8data); + } + } +#endif /* SUPPORT_UCP */ + + } + else +#endif /* SUPPORT_UTF8 */ + + /* Handle a single-byte character */ + { + classbits[c/8] |= (1 << (c&7)); + if ((options & PCRE_CASELESS) != 0) + { + c = cd->fcc[c]; /* flip case */ + classbits[c/8] |= (1 << (c&7)); + } + class_charcount++; + class_lastchar = c; + } + } + + /* Loop until ']' reached; the check for end of string happens inside the + loop. This "while" is the end of the "do" above. */ + + while ((c = *(++ptr)) != ']' || inescq); + + /* If class_charcount is 1, we saw precisely one character whose value is + less than 256. In non-UTF-8 mode we can always optimize. In UTF-8 mode, we + can optimize the negative case only if there were no characters >= 128 + because OP_NOT and the related opcodes like OP_NOTSTAR operate on + single-bytes only. This is an historical hangover. Maybe one day we can + tidy these opcodes to handle multi-byte characters. + + The optimization throws away the bit map. We turn the item into a + 1-character OP_CHAR[NC] if it's positive, or OP_NOT if it's negative. Note + that OP_NOT does not support multibyte characters. In the positive case, it + can cause firstbyte to be set. Otherwise, there can be no first char if + this item is first, whatever repeat count may follow. In the case of + reqbyte, save the previous value for reinstating. */ + +#ifdef SUPPORT_UTF8 + if (class_charcount == 1 && + (!utf8 || + (!class_utf8 && (!negate_class || class_lastchar < 128)))) + +#else + if (class_charcount == 1) +#endif + { + zeroreqbyte = reqbyte; + + /* The OP_NOT opcode works on one-byte characters only. */ + + if (negate_class) + { + if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE; + zerofirstbyte = firstbyte; + *code++ = OP_NOT; + *code++ = class_lastchar; + break; + } + + /* For a single, positive character, get the value into mcbuffer, and + then we can handle this with the normal one-character code. */ + +#ifdef SUPPORT_UTF8 + if (utf8 && class_lastchar > 127) + mclength = _pcre_ord2utf8(class_lastchar, mcbuffer); + else +#endif + { + mcbuffer[0] = class_lastchar; + mclength = 1; + } + goto ONE_CHAR; + } /* End of 1-char optimization */ + + /* The general case - not the one-char optimization. If this is the first + thing in the branch, there can be no first char setting, whatever the + repeat count. Any reqbyte setting must remain unchanged after any kind of + repeat. */ + + if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE; + zerofirstbyte = firstbyte; + zeroreqbyte = reqbyte; + + /* If there are characters with values > 255, we have to compile an + extended class, with its own opcode. If there are no characters < 256, + we can omit the bitmap. */ + +#ifdef SUPPORT_UTF8 + if (class_utf8) + { + *class_utf8data++ = XCL_END; /* Marks the end of extra data */ + *code++ = OP_XCLASS; + code += LINK_SIZE; + *code = negate_class? XCL_NOT : 0; + + /* If the map is required, install it, and move on to the end of + the extra data */ + + if (class_charcount > 0) + { + *code++ |= XCL_MAP; + memcpy(code, classbits, 32); + code = class_utf8data; + } + + /* If the map is not required, slide down the extra data. */ + + else + { + int len = class_utf8data - (code + 33); + memmove(code + 1, code + 33, len); + code += len + 1; + } + + /* Now fill in the complete length of the item */ + + PUT(previous, 1, code - previous); + break; /* End of class handling */ + } +#endif + + /* If there are no characters > 255, negate the 32-byte map if necessary, + and copy it into the code vector. If this is the first thing in the branch, + there can be no first char setting, whatever the repeat count. Any reqbyte + setting must remain unchanged after any kind of repeat. */ + + if (negate_class) + { + *code++ = OP_NCLASS; + for (c = 0; c < 32; c++) code[c] = ~classbits[c]; + } + else + { + *code++ = OP_CLASS; + memcpy(code, classbits, 32); + } + code += 32; + break; + + /* Various kinds of repeat; '{' is not necessarily a quantifier, but this + has been tested above. */ + + case '{': + if (!is_quantifier) goto NORMAL_CHAR; + ptr = read_repeat_counts(ptr+1, &repeat_min, &repeat_max, errorcodeptr); + if (*errorcodeptr != 0) goto FAILED; + goto REPEAT; + + case '*': + repeat_min = 0; + repeat_max = -1; + goto REPEAT; + + case '+': + repeat_min = 1; + repeat_max = -1; + goto REPEAT; + + case '?': + repeat_min = 0; + repeat_max = 1; + + REPEAT: + if (previous == NULL) + { + *errorcodeptr = ERR9; + goto FAILED; + } + + if (repeat_min == 0) + { + firstbyte = zerofirstbyte; /* Adjust for zero repeat */ + reqbyte = zeroreqbyte; /* Ditto */ + } + + /* Remember whether this is a variable length repeat */ + + reqvary = (repeat_min == repeat_max)? 0 : REQ_VARY; + + op_type = 0; /* Default single-char op codes */ + possessive_quantifier = FALSE; /* Default not possessive quantifier */ + + /* Save start of previous item, in case we have to move it up to make space + for an inserted OP_ONCE for the additional '+' extension. */ + + tempcode = previous; + + /* If the next character is '+', we have a possessive quantifier. This + implies greediness, whatever the setting of the PCRE_UNGREEDY option. + If the next character is '?' this is a minimizing repeat, by default, + but if PCRE_UNGREEDY is set, it works the other way round. We change the + repeat type to the non-default. */ + + if (ptr[1] == '+') + { + repeat_type = 0; /* Force greedy */ + possessive_quantifier = TRUE; + ptr++; + } + else if (ptr[1] == '?') + { + repeat_type = greedy_non_default; + ptr++; + } + else repeat_type = greedy_default; + + /* If previous was a recursion, we need to wrap it inside brackets so that + it can be replicated if necessary. */ + + if (*previous == OP_RECURSE) + { + memmove(previous + 1 + LINK_SIZE, previous, 1 + LINK_SIZE); + code += 1 + LINK_SIZE; + *previous = OP_BRA; + PUT(previous, 1, code - previous); + *code = OP_KET; + PUT(code, 1, code - previous); + code += 1 + LINK_SIZE; + } + + /* If previous was a character match, abolish the item and generate a + repeat item instead. If a char item has a minumum of more than one, ensure + that it is set in reqbyte - it might not be if a sequence such as x{3} is + the first thing in a branch because the x will have gone into firstbyte + instead. */ + + if (*previous == OP_CHAR || *previous == OP_CHARNC) + { + /* Deal with UTF-8 characters that take up more than one byte. It's + easier to write this out separately than try to macrify it. Use c to + hold the length of the character in bytes, plus 0x80 to flag that it's a + length rather than a small character. */ + +#ifdef SUPPORT_UTF8 + if (utf8 && (code[-1] & 0x80) != 0) + { + uschar *lastchar = code - 1; + while((*lastchar & 0xc0) == 0x80) lastchar--; + c = code - lastchar; /* Length of UTF-8 character */ + memcpy(utf8_char, lastchar, c); /* Save the char */ + c |= 0x80; /* Flag c as a length */ + } + else +#endif + + /* Handle the case of a single byte - either with no UTF8 support, or + with UTF-8 disabled, or for a UTF-8 character < 128. */ + + { + c = code[-1]; + if (repeat_min > 1) reqbyte = c | req_caseopt | cd->req_varyopt; + } + + goto OUTPUT_SINGLE_REPEAT; /* Code shared with single character types */ + } + + /* If previous was a single negated character ([^a] or similar), we use + one of the special opcodes, replacing it. The code is shared with single- + character repeats by setting opt_type to add a suitable offset into + repeat_type. OP_NOT is currently used only for single-byte chars. */ + + else if (*previous == OP_NOT) + { + op_type = OP_NOTSTAR - OP_STAR; /* Use "not" opcodes */ + c = previous[1]; + goto OUTPUT_SINGLE_REPEAT; + } + + /* If previous was a character type match (\d or similar), abolish it and + create a suitable repeat item. The code is shared with single-character + repeats by setting op_type to add a suitable offset into repeat_type. Note + the the Unicode property types will be present only when SUPPORT_UCP is + defined, but we don't wrap the little bits of code here because it just + makes it horribly messy. */ + + else if (*previous < OP_EODN) + { + uschar *oldcode; + int prop_type; + op_type = OP_TYPESTAR - OP_STAR; /* Use type opcodes */ + c = *previous; + + OUTPUT_SINGLE_REPEAT: + prop_type = (*previous == OP_PROP || *previous == OP_NOTPROP)? + previous[1] : -1; + + oldcode = code; + code = previous; /* Usually overwrite previous item */ + + /* If the maximum is zero then the minimum must also be zero; Perl allows + this case, so we do too - by simply omitting the item altogether. */ + + if (repeat_max == 0) goto END_REPEAT; + + /* All real repeats make it impossible to handle partial matching (maybe + one day we will be able to remove this restriction). */ + + if (repeat_max != 1) cd->nopartial = TRUE; + + /* Combine the op_type with the repeat_type */ + + repeat_type += op_type; + + /* A minimum of zero is handled either as the special case * or ?, or as + an UPTO, with the maximum given. */ + + if (repeat_min == 0) + { + if (repeat_max == -1) *code++ = OP_STAR + repeat_type; + else if (repeat_max == 1) *code++ = OP_QUERY + repeat_type; + else + { + *code++ = OP_UPTO + repeat_type; + PUT2INC(code, 0, repeat_max); + } + } + + /* A repeat minimum of 1 is optimized into some special cases. If the + maximum is unlimited, we use OP_PLUS. Otherwise, the original item it + left in place and, if the maximum is greater than 1, we use OP_UPTO with + one less than the maximum. */ + + else if (repeat_min == 1) + { + if (repeat_max == -1) + *code++ = OP_PLUS + repeat_type; + else + { + code = oldcode; /* leave previous item in place */ + if (repeat_max == 1) goto END_REPEAT; + *code++ = OP_UPTO + repeat_type; + PUT2INC(code, 0, repeat_max - 1); + } + } + + /* The case {n,n} is just an EXACT, while the general case {n,m} is + handled as an EXACT followed by an UPTO. */ + + else + { + *code++ = OP_EXACT + op_type; /* NB EXACT doesn't have repeat_type */ + PUT2INC(code, 0, repeat_min); + + /* If the maximum is unlimited, insert an OP_STAR. Before doing so, + we have to insert the character for the previous code. For a repeated + Unicode property match, there is an extra byte that defines the + required property. In UTF-8 mode, long characters have their length in + c, with the 0x80 bit as a flag. */ + + if (repeat_max < 0) + { +#ifdef SUPPORT_UTF8 + if (utf8 && c >= 128) + { + memcpy(code, utf8_char, c & 7); + code += c & 7; + } + else +#endif + { + *code++ = c; + if (prop_type >= 0) *code++ = prop_type; + } + *code++ = OP_STAR + repeat_type; + } + + /* Else insert an UPTO if the max is greater than the min, again + preceded by the character, for the previously inserted code. */ + + else if (repeat_max != repeat_min) + { +#ifdef SUPPORT_UTF8 + if (utf8 && c >= 128) + { + memcpy(code, utf8_char, c & 7); + code += c & 7; + } + else +#endif + *code++ = c; + if (prop_type >= 0) *code++ = prop_type; + repeat_max -= repeat_min; + *code++ = OP_UPTO + repeat_type; + PUT2INC(code, 0, repeat_max); + } + } + + /* The character or character type itself comes last in all cases. */ + +#ifdef SUPPORT_UTF8 + if (utf8 && c >= 128) + { + memcpy(code, utf8_char, c & 7); + code += c & 7; + } + else +#endif + *code++ = c; + + /* For a repeated Unicode property match, there is an extra byte that + defines the required property. */ + +#ifdef SUPPORT_UCP + if (prop_type >= 0) *code++ = prop_type; +#endif + } + + /* If previous was a character class or a back reference, we put the repeat + stuff after it, but just skip the item if the repeat was {0,0}. */ + + else if (*previous == OP_CLASS || + *previous == OP_NCLASS || +#ifdef SUPPORT_UTF8 + *previous == OP_XCLASS || +#endif + *previous == OP_REF) + { + if (repeat_max == 0) + { + code = previous; + goto END_REPEAT; + } + + /* All real repeats make it impossible to handle partial matching (maybe + one day we will be able to remove this restriction). */ + + if (repeat_max != 1) cd->nopartial = TRUE; + + if (repeat_min == 0 && repeat_max == -1) + *code++ = OP_CRSTAR + repeat_type; + else if (repeat_min == 1 && repeat_max == -1) + *code++ = OP_CRPLUS + repeat_type; + else if (repeat_min == 0 && repeat_max == 1) + *code++ = OP_CRQUERY + repeat_type; + else + { + *code++ = OP_CRRANGE + repeat_type; + PUT2INC(code, 0, repeat_min); + if (repeat_max == -1) repeat_max = 0; /* 2-byte encoding for max */ + PUT2INC(code, 0, repeat_max); + } + } + + /* If previous was a bracket group, we may have to replicate it in certain + cases. */ + + else if (*previous >= OP_BRA || *previous == OP_ONCE || + *previous == OP_COND) + { + register int i; + int ketoffset = 0; + int len = code - previous; + uschar *bralink = NULL; + + /* If the maximum repeat count is unlimited, find the end of the bracket + by scanning through from the start, and compute the offset back to it + from the current code pointer. There may be an OP_OPT setting following + the final KET, so we can't find the end just by going back from the code + pointer. */ + + if (repeat_max == -1) + { + register uschar *ket = previous; + do ket += GET(ket, 1); while (*ket != OP_KET); + ketoffset = code - ket; + } + + /* The case of a zero minimum is special because of the need to stick + OP_BRAZERO in front of it, and because the group appears once in the + data, whereas in other cases it appears the minimum number of times. For + this reason, it is simplest to treat this case separately, as otherwise + the code gets far too messy. There are several special subcases when the + minimum is zero. */ + + if (repeat_min == 0) + { + /* If the maximum is also zero, we just omit the group from the output + altogether. */ + + if (repeat_max == 0) + { + code = previous; + goto END_REPEAT; + } + + /* If the maximum is 1 or unlimited, we just have to stick in the + BRAZERO and do no more at this point. However, we do need to adjust + any OP_RECURSE calls inside the group that refer to the group itself or + any internal group, because the offset is from the start of the whole + regex. Temporarily terminate the pattern while doing this. */ + + if (repeat_max <= 1) + { + *code = OP_END; + adjust_recurse(previous, 1, utf8, cd); + memmove(previous+1, previous, len); + code++; + *previous++ = OP_BRAZERO + repeat_type; + } + + /* If the maximum is greater than 1 and limited, we have to replicate + in a nested fashion, sticking OP_BRAZERO before each set of brackets. + The first one has to be handled carefully because it's the original + copy, which has to be moved up. The remainder can be handled by code + that is common with the non-zero minimum case below. We have to + adjust the value or repeat_max, since one less copy is required. Once + again, we may have to adjust any OP_RECURSE calls inside the group. */ + + else + { + int offset; + *code = OP_END; + adjust_recurse(previous, 2 + LINK_SIZE, utf8, cd); + memmove(previous + 2 + LINK_SIZE, previous, len); + code += 2 + LINK_SIZE; + *previous++ = OP_BRAZERO + repeat_type; + *previous++ = OP_BRA; + + /* We chain together the bracket offset fields that have to be + filled in later when the ends of the brackets are reached. */ + + offset = (bralink == NULL)? 0 : previous - bralink; + bralink = previous; + PUTINC(previous, 0, offset); + } + + repeat_max--; + } + + /* If the minimum is greater than zero, replicate the group as many + times as necessary, and adjust the maximum to the number of subsequent + copies that we need. If we set a first char from the group, and didn't + set a required char, copy the latter from the former. */ + + else + { + if (repeat_min > 1) + { + if (groupsetfirstbyte && reqbyte < 0) reqbyte = firstbyte; + for (i = 1; i < repeat_min; i++) + { + memcpy(code, previous, len); + code += len; + } + } + if (repeat_max > 0) repeat_max -= repeat_min; + } + + /* This code is common to both the zero and non-zero minimum cases. If + the maximum is limited, it replicates the group in a nested fashion, + remembering the bracket starts on a stack. In the case of a zero minimum, + the first one was set up above. In all cases the repeat_max now specifies + the number of additional copies needed. */ + + if (repeat_max >= 0) + { + for (i = repeat_max - 1; i >= 0; i--) + { + *code++ = OP_BRAZERO + repeat_type; + + /* All but the final copy start a new nesting, maintaining the + chain of brackets outstanding. */ + + if (i != 0) + { + int offset; + *code++ = OP_BRA; + offset = (bralink == NULL)? 0 : code - bralink; + bralink = code; + PUTINC(code, 0, offset); + } + + memcpy(code, previous, len); + code += len; + } + + /* Now chain through the pending brackets, and fill in their length + fields (which are holding the chain links pro tem). */ + + while (bralink != NULL) + { + int oldlinkoffset; + int offset = code - bralink + 1; + uschar *bra = code - offset; + oldlinkoffset = GET(bra, 1); + bralink = (oldlinkoffset == 0)? NULL : bralink - oldlinkoffset; + *code++ = OP_KET; + PUTINC(code, 0, offset); + PUT(bra, 1, offset); + } + } + + /* If the maximum is unlimited, set a repeater in the final copy. We + can't just offset backwards from the current code point, because we + don't know if there's been an options resetting after the ket. The + correct offset was computed above. */ + + else code[-ketoffset] = OP_KETRMAX + repeat_type; + } + + /* Else there's some kind of shambles */ + + else + { + *errorcodeptr = ERR11; + goto FAILED; + } + + /* If the character following a repeat is '+', we wrap the entire repeated + item inside OP_ONCE brackets. This is just syntactic sugar, taken from + Sun's Java package. The repeated item starts at tempcode, not at previous, + which might be the first part of a string whose (former) last char we + repeated. However, we don't support '+' after a greediness '?'. */ + + if (possessive_quantifier) + { + int len = code - tempcode; + memmove(tempcode + 1+LINK_SIZE, tempcode, len); + code += 1 + LINK_SIZE; + len += 1 + LINK_SIZE; + tempcode[0] = OP_ONCE; + *code++ = OP_KET; + PUTINC(code, 0, len); + PUT(tempcode, 1, len); + } + + /* In all case we no longer have a previous item. We also set the + "follows varying string" flag for subsequently encountered reqbytes if + it isn't already set and we have just passed a varying length item. */ + + END_REPEAT: + previous = NULL; + cd->req_varyopt |= reqvary; + break; + + + /* Start of nested bracket sub-expression, or comment or lookahead or + lookbehind or option setting or condition. First deal with special things + that can come after a bracket; all are introduced by ?, and the appearance + of any of them means that this is not a referencing group. They were + checked for validity in the first pass over the string, so we don't have to + check for syntax errors here. */ + + case '(': + newoptions = options; + skipbytes = 0; + + if (*(++ptr) == '?') + { + int set, unset; + int *optset; + + switch (*(++ptr)) + { + case '#': /* Comment; skip to ket */ + ptr++; + while (*ptr != ')') ptr++; + continue; + + case ':': /* Non-extracting bracket */ + bravalue = OP_BRA; + ptr++; + break; + + case '(': + bravalue = OP_COND; /* Conditional group */ + + /* Condition to test for recursion */ + + if (ptr[1] == 'R') + { + code[1+LINK_SIZE] = OP_CREF; + PUT2(code, 2+LINK_SIZE, CREF_RECURSE); + skipbytes = 3; + ptr += 3; + } + + /* Condition to test for a numbered subpattern match. We know that + if a digit follows ( then there will just be digits until ) because + the syntax was checked in the first pass. */ + + else if ((digitab[ptr[1]] && ctype_digit) != 0) + { + int condref; /* Don't amalgamate; some compilers */ + condref = *(++ptr) - '0'; /* grumble at autoincrement in declaration */ + while (*(++ptr) != ')') condref = condref*10 + *ptr - '0'; + if (condref == 0) + { + *errorcodeptr = ERR35; + goto FAILED; + } + ptr++; + code[1+LINK_SIZE] = OP_CREF; + PUT2(code, 2+LINK_SIZE, condref); + skipbytes = 3; + } + /* For conditions that are assertions, we just fall through, having + set bravalue above. */ + break; + + case '=': /* Positive lookahead */ + bravalue = OP_ASSERT; + ptr++; + break; + + case '!': /* Negative lookahead */ + bravalue = OP_ASSERT_NOT; + ptr++; + break; + + case '<': /* Lookbehinds */ + switch (*(++ptr)) + { + case '=': /* Positive lookbehind */ + bravalue = OP_ASSERTBACK; + ptr++; + break; + + case '!': /* Negative lookbehind */ + bravalue = OP_ASSERTBACK_NOT; + ptr++; + break; + } + break; + + case '>': /* One-time brackets */ + bravalue = OP_ONCE; + ptr++; + break; + + case 'C': /* Callout - may be followed by digits; */ + previous_callout = code; /* Save for later completion */ + after_manual_callout = 1; /* Skip one item before completing */ + *code++ = OP_CALLOUT; /* Already checked that the terminating */ + { /* closing parenthesis is present. */ + int n = 0; + while ((digitab[*(++ptr)] & ctype_digit) != 0) + n = n * 10 + *ptr - '0'; + if (n > 255) + { + *errorcodeptr = ERR38; + goto FAILED; + } + *code++ = n; + PUT(code, 0, ptr - cd->start_pattern + 1); /* Pattern offset */ + PUT(code, LINK_SIZE, 0); /* Default length */ + code += 2 * LINK_SIZE; + } + previous = NULL; + continue; + + case 'P': /* Named subpattern handling */ + if (*(++ptr) == '<') /* Definition */ + { + int i, namelen; + uschar *slot = cd->name_table; + const uschar *name; /* Don't amalgamate; some compilers */ + name = ++ptr; /* grumble at autoincrement in declaration */ + + while (*ptr++ != '>'); + namelen = ptr - name - 1; + + for (i = 0; i < cd->names_found; i++) + { + int crc = memcmp(name, slot+2, namelen); + if (crc == 0) + { + if (slot[2+namelen] == 0) + { + *errorcodeptr = ERR43; + goto FAILED; + } + crc = -1; /* Current name is substring */ + } + if (crc < 0) + { + memmove(slot + cd->name_entry_size, slot, + (cd->names_found - i) * cd->name_entry_size); + break; + } + slot += cd->name_entry_size; + } + + PUT2(slot, 0, *brackets + 1); + memcpy(slot + 2, name, namelen); + slot[2+namelen] = 0; + cd->names_found++; + goto NUMBERED_GROUP; + } + + if (*ptr == '=' || *ptr == '>') /* Reference or recursion */ + { + int i, namelen; + int type = *ptr++; + const uschar *name = ptr; + uschar *slot = cd->name_table; + + while (*ptr != ')') ptr++; + namelen = ptr - name; + + for (i = 0; i < cd->names_found; i++) + { + if (strncmp((char *)name, (char *)slot+2, namelen) == 0) break; + slot += cd->name_entry_size; + } + if (i >= cd->names_found) + { + *errorcodeptr = ERR15; + goto FAILED; + } + + recno = GET2(slot, 0); + + if (type == '>') goto HANDLE_RECURSION; /* A few lines below */ + + /* Back reference */ + + previous = code; + *code++ = OP_REF; + PUT2INC(code, 0, recno); + cd->backref_map |= (recno < 32)? (1 << recno) : 1; + if (recno > cd->top_backref) cd->top_backref = recno; + continue; + } + + /* Should never happen */ + break; + + case 'R': /* Pattern recursion */ + ptr++; /* Same as (?0) */ + /* Fall through */ + + /* Recursion or "subroutine" call */ + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + { + const uschar *called; + recno = 0; + while((digitab[*ptr] & ctype_digit) != 0) + recno = recno * 10 + *ptr++ - '0'; + + /* Come here from code above that handles a named recursion */ + + HANDLE_RECURSION: + + previous = code; + + /* Find the bracket that is being referenced. Temporarily end the + regex in case it doesn't exist. */ + + *code = OP_END; + called = (recno == 0)? + cd->start_code : find_bracket(cd->start_code, utf8, recno); + + if (called == NULL) + { + *errorcodeptr = ERR15; + goto FAILED; + } + + /* If the subpattern is still open, this is a recursive call. We + check to see if this is a left recursion that could loop for ever, + and diagnose that case. */ + + if (GET(called, 1) == 0 && could_be_empty(called, code, bcptr, utf8)) + { + *errorcodeptr = ERR40; + goto FAILED; + } + + /* Insert the recursion/subroutine item */ + + *code = OP_RECURSE; + PUT(code, 1, called - cd->start_code); + code += 1 + LINK_SIZE; + } + continue; + + /* Character after (? not specially recognized */ + + default: /* Option setting */ + set = unset = 0; + optset = &set; + + while (*ptr != ')' && *ptr != ':') + { + switch (*ptr++) + { + case '-': optset = &unset; break; + + case 'i': *optset |= PCRE_CASELESS; break; + case 'm': *optset |= PCRE_MULTILINE; break; + case 's': *optset |= PCRE_DOTALL; break; + case 'x': *optset |= PCRE_EXTENDED; break; + case 'U': *optset |= PCRE_UNGREEDY; break; + case 'X': *optset |= PCRE_EXTRA; break; + } + } + + /* Set up the changed option bits, but don't change anything yet. */ + + newoptions = (options | set) & (~unset); + + /* If the options ended with ')' this is not the start of a nested + group with option changes, so the options change at this level. Compile + code to change the ims options if this setting actually changes any of + them. We also pass the new setting back so that it can be put at the + start of any following branches, and when this group ends (if we are in + a group), a resetting item can be compiled. + + Note that if this item is right at the start of the pattern, the + options will have been abstracted and made global, so there will be no + change to compile. */ + + if (*ptr == ')') + { + if ((options & PCRE_IMS) != (newoptions & PCRE_IMS)) + { + *code++ = OP_OPT; + *code++ = newoptions & PCRE_IMS; + } + + /* Change options at this level, and pass them back for use + in subsequent branches. Reset the greedy defaults and the case + value for firstbyte and reqbyte. */ + + *optionsptr = options = newoptions; + greedy_default = ((newoptions & PCRE_UNGREEDY) != 0); + greedy_non_default = greedy_default ^ 1; + req_caseopt = ((options & PCRE_CASELESS) != 0)? REQ_CASELESS : 0; + + previous = NULL; /* This item can't be repeated */ + continue; /* It is complete */ + } + + /* If the options ended with ':' we are heading into a nested group + with possible change of options. Such groups are non-capturing and are + not assertions of any kind. All we need to do is skip over the ':'; + the newoptions value is handled below. */ + + bravalue = OP_BRA; + ptr++; + } + } + + /* If PCRE_NO_AUTO_CAPTURE is set, all unadorned brackets become + non-capturing and behave like (?:...) brackets */ + + else if ((options & PCRE_NO_AUTO_CAPTURE) != 0) + { + bravalue = OP_BRA; + } + + /* Else we have a referencing group; adjust the opcode. If the bracket + number is greater than EXTRACT_BASIC_MAX, we set the opcode one higher, and + arrange for the true number to follow later, in an OP_BRANUMBER item. */ + + else + { + NUMBERED_GROUP: + if (++(*brackets) > EXTRACT_BASIC_MAX) + { + bravalue = OP_BRA + EXTRACT_BASIC_MAX + 1; + code[1+LINK_SIZE] = OP_BRANUMBER; + PUT2(code, 2+LINK_SIZE, *brackets); + skipbytes = 3; + } + else bravalue = OP_BRA + *brackets; + } + + /* Process nested bracketed re. Assertions may not be repeated, but other + kinds can be. We copy code into a non-register variable in order to be able + to pass its address because some compilers complain otherwise. Pass in a + new setting for the ims options if they have changed. */ + + previous = (bravalue >= OP_ONCE)? code : NULL; + *code = bravalue; + tempcode = code; + tempreqvary = cd->req_varyopt; /* Save value before bracket */ + + if (!compile_regex( + newoptions, /* The complete new option state */ + options & PCRE_IMS, /* The previous ims option state */ + brackets, /* Extracting bracket count */ + &tempcode, /* Where to put code (updated) */ + &ptr, /* Input pointer (updated) */ + errorcodeptr, /* Where to put an error message */ + (bravalue == OP_ASSERTBACK || + bravalue == OP_ASSERTBACK_NOT), /* TRUE if back assert */ + skipbytes, /* Skip over OP_COND/OP_BRANUMBER */ + &subfirstbyte, /* For possible first char */ + &subreqbyte, /* For possible last char */ + bcptr, /* Current branch chain */ + cd)) /* Tables block */ + goto FAILED; + + /* At the end of compiling, code is still pointing to the start of the + group, while tempcode has been updated to point past the end of the group + and any option resetting that may follow it. The pattern pointer (ptr) + is on the bracket. */ + + /* If this is a conditional bracket, check that there are no more than + two branches in the group. */ + + else if (bravalue == OP_COND) + { + uschar *tc = code; + condcount = 0; + + do { + condcount++; + tc += GET(tc,1); + } + while (*tc != OP_KET); + + if (condcount > 2) + { + *errorcodeptr = ERR27; + goto FAILED; + } + + /* If there is just one branch, we must not make use of its firstbyte or + reqbyte, because this is equivalent to an empty second branch. */ + + if (condcount == 1) subfirstbyte = subreqbyte = REQ_NONE; + } + + /* Handle updating of the required and first characters. Update for normal + brackets of all kinds, and conditions with two branches (see code above). + If the bracket is followed by a quantifier with zero repeat, we have to + back off. Hence the definition of zeroreqbyte and zerofirstbyte outside the + main loop so that they can be accessed for the back off. */ + + zeroreqbyte = reqbyte; + zerofirstbyte = firstbyte; + groupsetfirstbyte = FALSE; + + if (bravalue >= OP_BRA || bravalue == OP_ONCE || bravalue == OP_COND) + { + /* If we have not yet set a firstbyte in this branch, take it from the + subpattern, remembering that it was set here so that a repeat of more + than one can replicate it as reqbyte if necessary. If the subpattern has + no firstbyte, set "none" for the whole branch. In both cases, a zero + repeat forces firstbyte to "none". */ + + if (firstbyte == REQ_UNSET) + { + if (subfirstbyte >= 0) + { + firstbyte = subfirstbyte; + groupsetfirstbyte = TRUE; + } + else firstbyte = REQ_NONE; + zerofirstbyte = REQ_NONE; + } + + /* If firstbyte was previously set, convert the subpattern's firstbyte + into reqbyte if there wasn't one, using the vary flag that was in + existence beforehand. */ + + else if (subfirstbyte >= 0 && subreqbyte < 0) + subreqbyte = subfirstbyte | tempreqvary; + + /* If the subpattern set a required byte (or set a first byte that isn't + really the first byte - see above), set it. */ + + if (subreqbyte >= 0) reqbyte = subreqbyte; + } + + /* For a forward assertion, we take the reqbyte, if set. This can be + helpful if the pattern that follows the assertion doesn't set a different + char. For example, it's useful for /(?=abcde).+/. We can't set firstbyte + for an assertion, however because it leads to incorrect effect for patterns + such as /(?=a)a.+/ when the "real" "a" would then become a reqbyte instead + of a firstbyte. This is overcome by a scan at the end if there's no + firstbyte, looking for an asserted first char. */ + + else if (bravalue == OP_ASSERT && subreqbyte >= 0) reqbyte = subreqbyte; + + /* Now update the main code pointer to the end of the group. */ + + code = tempcode; + + /* Error if hit end of pattern */ + + if (*ptr != ')') + { + *errorcodeptr = ERR14; + goto FAILED; + } + break; + + /* Check \ for being a real metacharacter; if not, fall through and handle + it as a data character at the start of a string. Escape items are checked + for validity in the pre-compiling pass. */ + + case '\\': + tempptr = ptr; + c = check_escape(&ptr, errorcodeptr, *brackets, options, FALSE); + + /* Handle metacharacters introduced by \. For ones like \d, the ESC_ values + are arranged to be the negation of the corresponding OP_values. For the + back references, the values are ESC_REF plus the reference number. Only + back references and those types that consume a character may be repeated. + We can test for values between ESC_b and ESC_Z for the latter; this may + have to change if any new ones are ever created. */ + + if (c < 0) + { + if (-c == ESC_Q) /* Handle start of quoted string */ + { + if (ptr[1] == '\\' && ptr[2] == 'E') ptr += 2; /* avoid empty string */ + else inescq = TRUE; + continue; + } + + /* For metasequences that actually match a character, we disable the + setting of a first character if it hasn't already been set. */ + + if (firstbyte == REQ_UNSET && -c > ESC_b && -c < ESC_Z) + firstbyte = REQ_NONE; + + /* Set values to reset to if this is followed by a zero repeat. */ + + zerofirstbyte = firstbyte; + zeroreqbyte = reqbyte; + + /* Back references are handled specially */ + + if (-c >= ESC_REF) + { + int number = -c - ESC_REF; + previous = code; + *code++ = OP_REF; + PUT2INC(code, 0, number); + } + + /* So are Unicode property matches, if supported. We know that get_ucp + won't fail because it was tested in the pre-pass. */ + +#ifdef SUPPORT_UCP + else if (-c == ESC_P || -c == ESC_p) + { + BOOL negated; + int value = get_ucp(&ptr, &negated, errorcodeptr); + previous = code; + *code++ = ((-c == ESC_p) != negated)? OP_PROP : OP_NOTPROP; + *code++ = value; + } +#endif + + /* For the rest, we can obtain the OP value by negating the escape + value */ + + else + { + previous = (-c > ESC_b && -c < ESC_Z)? code : NULL; + *code++ = -c; + } + continue; + } + + /* We have a data character whose value is in c. In UTF-8 mode it may have + a value > 127. We set its representation in the length/buffer, and then + handle it as a data character. */ + +#ifdef SUPPORT_UTF8 + if (utf8 && c > 127) + mclength = _pcre_ord2utf8(c, mcbuffer); + else +#endif + + { + mcbuffer[0] = c; + mclength = 1; + } + + goto ONE_CHAR; + + /* Handle a literal character. It is guaranteed not to be whitespace or # + when the extended flag is set. If we are in UTF-8 mode, it may be a + multi-byte literal character. */ + + default: + NORMAL_CHAR: + mclength = 1; + mcbuffer[0] = c; + +#ifdef SUPPORT_UTF8 + if (utf8 && (c & 0xc0) == 0xc0) + { + while ((ptr[1] & 0xc0) == 0x80) + mcbuffer[mclength++] = *(++ptr); + } +#endif + + /* At this point we have the character's bytes in mcbuffer, and the length + in mclength. When not in UTF-8 mode, the length is always 1. */ + + ONE_CHAR: + previous = code; + *code++ = ((options & PCRE_CASELESS) != 0)? OP_CHARNC : OP_CHAR; + for (c = 0; c < mclength; c++) *code++ = mcbuffer[c]; + + /* Set the first and required bytes appropriately. If no previous first + byte, set it from this character, but revert to none on a zero repeat. + Otherwise, leave the firstbyte value alone, and don't change it on a zero + repeat. */ + + if (firstbyte == REQ_UNSET) + { + zerofirstbyte = REQ_NONE; + zeroreqbyte = reqbyte; + + /* If the character is more than one byte long, we can set firstbyte + only if it is not to be matched caselessly. */ + + if (mclength == 1 || req_caseopt == 0) + { + firstbyte = mcbuffer[0] | req_caseopt; + if (mclength != 1) reqbyte = code[-1] | cd->req_varyopt; + } + else firstbyte = reqbyte = REQ_NONE; + } + + /* firstbyte was previously set; we can set reqbyte only the length is + 1 or the matching is caseful. */ + + else + { + zerofirstbyte = firstbyte; + zeroreqbyte = reqbyte; + if (mclength == 1 || req_caseopt == 0) + reqbyte = code[-1] | req_caseopt | cd->req_varyopt; + } + + break; /* End of literal character handling */ + } + } /* end of big loop */ + +/* Control never reaches here by falling through, only by a goto for all the +error states. Pass back the position in the pattern so that it can be displayed +to the user for diagnosing the error. */ + +FAILED: +*ptrptr = ptr; +return FALSE; +} + + + + +/************************************************* +* Compile sequence of alternatives * +*************************************************/ + +/* On entry, ptr is pointing past the bracket character, but on return +it points to the closing bracket, or vertical bar, or end of string. +The code variable is pointing at the byte into which the BRA operator has been +stored. If the ims options are changed at the start (for a (?ims: group) or +during any branch, we need to insert an OP_OPT item at the start of every +following branch to ensure they get set correctly at run time, and also pass +the new options into every subsequent branch compile. + +Argument: + options option bits, including any changes for this subpattern + oldims previous settings of ims option bits + brackets -> int containing the number of extracting brackets used + codeptr -> the address of the current code pointer + ptrptr -> the address of the current pattern pointer + errorcodeptr -> pointer to error code variable + lookbehind TRUE if this is a lookbehind assertion + skipbytes skip this many bytes at start (for OP_COND, OP_BRANUMBER) + firstbyteptr place to put the first required character, or a negative number + reqbyteptr place to put the last required character, or a negative number + bcptr pointer to the chain of currently open branches + cd points to the data block with tables pointers etc. + +Returns: TRUE on success +*/ + +static BOOL +compile_regex(int options, int oldims, int *brackets, uschar **codeptr, + const uschar **ptrptr, int *errorcodeptr, BOOL lookbehind, int skipbytes, + int *firstbyteptr, int *reqbyteptr, branch_chain *bcptr, compile_data *cd) +{ +const uschar *ptr = *ptrptr; +uschar *code = *codeptr; +uschar *last_branch = code; +uschar *start_bracket = code; +uschar *reverse_count = NULL; +int firstbyte, reqbyte; +int branchfirstbyte, branchreqbyte; +branch_chain bc; + +bc.outer = bcptr; +bc.current = code; + +firstbyte = reqbyte = REQ_UNSET; + +/* Offset is set zero to mark that this bracket is still open */ + +PUT(code, 1, 0); +code += 1 + LINK_SIZE + skipbytes; + +/* Loop for each alternative branch */ + +for (;;) + { + /* Handle a change of ims options at the start of the branch */ + + if ((options & PCRE_IMS) != oldims) + { + *code++ = OP_OPT; + *code++ = options & PCRE_IMS; + } + + /* Set up dummy OP_REVERSE if lookbehind assertion */ + + if (lookbehind) + { + *code++ = OP_REVERSE; + reverse_count = code; + PUTINC(code, 0, 0); + } + + /* Now compile the branch */ + + if (!compile_branch(&options, brackets, &code, &ptr, errorcodeptr, + &branchfirstbyte, &branchreqbyte, &bc, cd)) + { + *ptrptr = ptr; + return FALSE; + } + + /* If this is the first branch, the firstbyte and reqbyte values for the + branch become the values for the regex. */ + + if (*last_branch != OP_ALT) + { + firstbyte = branchfirstbyte; + reqbyte = branchreqbyte; + } + + /* If this is not the first branch, the first char and reqbyte have to + match the values from all the previous branches, except that if the previous + value for reqbyte didn't have REQ_VARY set, it can still match, and we set + REQ_VARY for the regex. */ + + else + { + /* If we previously had a firstbyte, but it doesn't match the new branch, + we have to abandon the firstbyte for the regex, but if there was previously + no reqbyte, it takes on the value of the old firstbyte. */ + + if (firstbyte >= 0 && firstbyte != branchfirstbyte) + { + if (reqbyte < 0) reqbyte = firstbyte; + firstbyte = REQ_NONE; + } + + /* If we (now or from before) have no firstbyte, a firstbyte from the + branch becomes a reqbyte if there isn't a branch reqbyte. */ + + if (firstbyte < 0 && branchfirstbyte >= 0 && branchreqbyte < 0) + branchreqbyte = branchfirstbyte; + + /* Now ensure that the reqbytes match */ + + if ((reqbyte & ~REQ_VARY) != (branchreqbyte & ~REQ_VARY)) + reqbyte = REQ_NONE; + else reqbyte |= branchreqbyte; /* To "or" REQ_VARY */ + } + + /* If lookbehind, check that this branch matches a fixed-length string, + and put the length into the OP_REVERSE item. Temporarily mark the end of + the branch with OP_END. */ + + if (lookbehind) + { + int length; + *code = OP_END; + length = find_fixedlength(last_branch, options); + DPRINTF(("fixed length = %d\n", length)); + if (length < 0) + { + *errorcodeptr = (length == -2)? ERR36 : ERR25; + *ptrptr = ptr; + return FALSE; + } + PUT(reverse_count, 0, length); + } + + /* Reached end of expression, either ')' or end of pattern. Go back through + the alternative branches and reverse the chain of offsets, with the field in + the BRA item now becoming an offset to the first alternative. If there are + no alternatives, it points to the end of the group. The length in the + terminating ket is always the length of the whole bracketed item. If any of + the ims options were changed inside the group, compile a resetting op-code + following, except at the very end of the pattern. Return leaving the pointer + at the terminating char. */ + + if (*ptr != '|') + { + int length = code - last_branch; + do + { + int prev_length = GET(last_branch, 1); + PUT(last_branch, 1, length); + length = prev_length; + last_branch -= length; + } + while (length > 0); + + /* Fill in the ket */ + + *code = OP_KET; + PUT(code, 1, code - start_bracket); + code += 1 + LINK_SIZE; + + /* Resetting option if needed */ + + if ((options & PCRE_IMS) != oldims && *ptr == ')') + { + *code++ = OP_OPT; + *code++ = oldims; + } + + /* Set values to pass back */ + + *codeptr = code; + *ptrptr = ptr; + *firstbyteptr = firstbyte; + *reqbyteptr = reqbyte; + return TRUE; + } + + /* Another branch follows; insert an "or" node. Its length field points back + to the previous branch while the bracket remains open. At the end the chain + is reversed. It's done like this so that the start of the bracket has a + zero offset until it is closed, making it possible to detect recursion. */ + + *code = OP_ALT; + PUT(code, 1, code - last_branch); + bc.current = last_branch = code; + code += 1 + LINK_SIZE; + ptr++; + } +/* Control never reaches here */ +} + + + + +/************************************************* +* Check for anchored expression * +*************************************************/ + +/* Try to find out if this is an anchored regular expression. Consider each +alternative branch. If they all start with OP_SOD or OP_CIRC, or with a bracket +all of whose alternatives start with OP_SOD or OP_CIRC (recurse ad lib), then +it's anchored. However, if this is a multiline pattern, then only OP_SOD +counts, since OP_CIRC can match in the middle. + +We can also consider a regex to be anchored if OP_SOM starts all its branches. +This is the code for \G, which means "match at start of match position, taking +into account the match offset". + +A branch is also implicitly anchored if it starts with .* and DOTALL is set, +because that will try the rest of the pattern at all possible matching points, +so there is no point trying again.... er .... + +.... except when the .* appears inside capturing parentheses, and there is a +subsequent back reference to those parentheses. We haven't enough information +to catch that case precisely. + +At first, the best we could do was to detect when .* was in capturing brackets +and the highest back reference was greater than or equal to that level. +However, by keeping a bitmap of the first 31 back references, we can catch some +of the more common cases more precisely. + +Arguments: + code points to start of expression (the bracket) + options points to the options setting + bracket_map a bitmap of which brackets we are inside while testing; this + handles up to substring 31; after that we just have to take + the less precise approach + backref_map the back reference bitmap + +Returns: TRUE or FALSE +*/ + +static BOOL +is_anchored(register const uschar *code, int *options, unsigned int bracket_map, + unsigned int backref_map) +{ +do { + const uschar *scode = + first_significant_code(code + 1+LINK_SIZE, options, PCRE_MULTILINE, FALSE); + register int op = *scode; + + /* Capturing brackets */ + + if (op > OP_BRA) + { + int new_map; + op -= OP_BRA; + if (op > EXTRACT_BASIC_MAX) op = GET2(scode, 2+LINK_SIZE); + new_map = bracket_map | ((op < 32)? (1 << op) : 1); + if (!is_anchored(scode, options, new_map, backref_map)) return FALSE; + } + + /* Other brackets */ + + else if (op == OP_BRA || op == OP_ASSERT || op == OP_ONCE || op == OP_COND) + { + if (!is_anchored(scode, options, bracket_map, backref_map)) return FALSE; + } + + /* .* is not anchored unless DOTALL is set and it isn't in brackets that + are or may be referenced. */ + + else if ((op == OP_TYPESTAR || op == OP_TYPEMINSTAR) && + (*options & PCRE_DOTALL) != 0) + { + if (scode[1] != OP_ANY || (bracket_map & backref_map) != 0) return FALSE; + } + + /* Check for explicit anchoring */ + + else if (op != OP_SOD && op != OP_SOM && + ((*options & PCRE_MULTILINE) != 0 || op != OP_CIRC)) + return FALSE; + code += GET(code, 1); + } +while (*code == OP_ALT); /* Loop for each alternative */ +return TRUE; +} + + + +/************************************************* +* Check for starting with ^ or .* * +*************************************************/ + +/* This is called to find out if every branch starts with ^ or .* so that +"first char" processing can be done to speed things up in multiline +matching and for non-DOTALL patterns that start with .* (which must start at +the beginning or after \n). As in the case of is_anchored() (see above), we +have to take account of back references to capturing brackets that contain .* +because in that case we can't make the assumption. + +Arguments: + code points to start of expression (the bracket) + bracket_map a bitmap of which brackets we are inside while testing; this + handles up to substring 31; after that we just have to take + the less precise approach + backref_map the back reference bitmap + +Returns: TRUE or FALSE +*/ + +static BOOL +is_startline(const uschar *code, unsigned int bracket_map, + unsigned int backref_map) +{ +do { + const uschar *scode = first_significant_code(code + 1+LINK_SIZE, NULL, 0, + FALSE); + register int op = *scode; + + /* Capturing brackets */ + + if (op > OP_BRA) + { + int new_map; + op -= OP_BRA; + if (op > EXTRACT_BASIC_MAX) op = GET2(scode, 2+LINK_SIZE); + new_map = bracket_map | ((op < 32)? (1 << op) : 1); + if (!is_startline(scode, new_map, backref_map)) return FALSE; + } + + /* Other brackets */ + + else if (op == OP_BRA || op == OP_ASSERT || op == OP_ONCE || op == OP_COND) + { if (!is_startline(scode, bracket_map, backref_map)) return FALSE; } + + /* .* means "start at start or after \n" if it isn't in brackets that + may be referenced. */ + + else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR) + { + if (scode[1] != OP_ANY || (bracket_map & backref_map) != 0) return FALSE; + } + + /* Check for explicit circumflex */ + + else if (op != OP_CIRC) return FALSE; + + /* Move on to the next alternative */ + + code += GET(code, 1); + } +while (*code == OP_ALT); /* Loop for each alternative */ +return TRUE; +} + + + +/************************************************* +* Check for asserted fixed first char * +*************************************************/ + +/* During compilation, the "first char" settings from forward assertions are +discarded, because they can cause conflicts with actual literals that follow. +However, if we end up without a first char setting for an unanchored pattern, +it is worth scanning the regex to see if there is an initial asserted first +char. If all branches start with the same asserted char, or with a bracket all +of whose alternatives start with the same asserted char (recurse ad lib), then +we return that char, otherwise -1. + +Arguments: + code points to start of expression (the bracket) + options pointer to the options (used to check casing changes) + inassert TRUE if in an assertion + +Returns: -1 or the fixed first char +*/ + +static int +find_firstassertedchar(const uschar *code, int *options, BOOL inassert) +{ +register int c = -1; +do { + int d; + const uschar *scode = + first_significant_code(code + 1+LINK_SIZE, options, PCRE_CASELESS, TRUE); + register int op = *scode; + + if (op >= OP_BRA) op = OP_BRA; + + switch(op) + { + default: + return -1; + + case OP_BRA: + case OP_ASSERT: + case OP_ONCE: + case OP_COND: + if ((d = find_firstassertedchar(scode, options, op == OP_ASSERT)) < 0) + return -1; + if (c < 0) c = d; else if (c != d) return -1; + break; + + case OP_EXACT: /* Fall through */ + scode += 2; + + case OP_CHAR: + case OP_CHARNC: + case OP_PLUS: + case OP_MINPLUS: + if (!inassert) return -1; + if (c < 0) + { + c = scode[1]; + if ((*options & PCRE_CASELESS) != 0) c |= REQ_CASELESS; + } + else if (c != scode[1]) return -1; + break; + } + + code += GET(code, 1); + } +while (*code == OP_ALT); +return c; +} + + + +/************************************************* +* Compile a Regular Expression * +*************************************************/ + +/* This function takes a string and returns a pointer to a block of store +holding a compiled version of the expression. The original API for this +function had no error code return variable; it is retained for backwards +compatibility. The new function is given a new name. + +Arguments: + pattern the regular expression + options various option bits + errorcodeptr pointer to error code variable (pcre_compile2() only) + can be NULL if you don't want a code value + errorptr pointer to pointer to error text + erroroffset ptr offset in pattern where error was detected + tables pointer to character tables or NULL + +Returns: pointer to compiled data block, or NULL on error, + with errorptr and erroroffset set +*/ + +EXPORT pcre * +pcre_compile(const char *pattern, int options, const char **errorptr, + int *erroroffset, const unsigned char *tables) +{ +return pcre_compile2(pattern, options, NULL, errorptr, erroroffset, tables); +} + + +EXPORT pcre * +pcre_compile2(const char *pattern, int options, int *errorcodeptr, + const char **errorptr, int *erroroffset, const unsigned char *tables) +{ +real_pcre *re; +int length = 1 + LINK_SIZE; /* For initial BRA plus length */ +int c, firstbyte, reqbyte; +int bracount = 0; +int branch_extra = 0; +int branch_newextra; +int item_count = -1; +int name_count = 0; +int max_name_size = 0; +int lastitemlength = 0; +int errorcode = 0; +#ifdef SUPPORT_UTF8 +BOOL utf8; +BOOL class_utf8; +#endif +BOOL inescq = FALSE; +BOOL capturing; +unsigned int brastackptr = 0; +size_t size; +uschar *code; +const uschar *codestart; +const uschar *ptr; +compile_data compile_block; +int brastack[BRASTACK_SIZE]; +uschar bralenstack[BRASTACK_SIZE]; + +/* We can't pass back an error message if errorptr is NULL; I guess the best we +can do is just return NULL, but we can set a code value if there is a code +pointer. */ + +if (errorptr == NULL) + { + if (errorcodeptr != NULL) *errorcodeptr = 99; + return NULL; + } + +*errorptr = NULL; +if (errorcodeptr != NULL) *errorcodeptr = ERR0; + +/* However, we can give a message for this error */ + +if (erroroffset == NULL) + { + errorcode = ERR16; + goto PCRE_EARLY_ERROR_RETURN; + } + +*erroroffset = 0; + +/* Can't support UTF8 unless PCRE has been compiled to include the code. */ + +#ifdef SUPPORT_UTF8 +utf8 = (options & PCRE_UTF8) != 0; +if (utf8 && (options & PCRE_NO_UTF8_CHECK) == 0 && + (*erroroffset = _pcre_valid_utf8((uschar *)pattern, -1)) >= 0) + { + errorcode = ERR44; + goto PCRE_EARLY_ERROR_RETURN; + } +#else +if ((options & PCRE_UTF8) != 0) + { + errorcode = ERR32; + goto PCRE_EARLY_ERROR_RETURN; + } +#endif + +if ((options & ~PUBLIC_OPTIONS) != 0) + { + errorcode = ERR17; + goto PCRE_EARLY_ERROR_RETURN; + } + +/* Set up pointers to the individual character tables */ + +if (tables == NULL) tables = _pcre_default_tables; +compile_block.lcc = tables + lcc_offset; +compile_block.fcc = tables + fcc_offset; +compile_block.cbits = tables + cbits_offset; +compile_block.ctypes = tables + ctypes_offset; + +/* Maximum back reference and backref bitmap. This is updated for numeric +references during the first pass, but for named references during the actual +compile pass. The bitmap records up to 31 back references to help in deciding +whether (.*) can be treated as anchored or not. */ + +compile_block.top_backref = 0; +compile_block.backref_map = 0; + +/* Reflect pattern for debugging output */ + +DPRINTF(("------------------------------------------------------------------\n")); +DPRINTF(("%s\n", pattern)); + +/* The first thing to do is to make a pass over the pattern to compute the +amount of store required to hold the compiled code. This does not have to be +perfect as long as errors are overestimates. At the same time we can detect any +flag settings right at the start, and extract them. Make an attempt to correct +for any counted white space if an "extended" flag setting appears late in the +pattern. We can't be so clever for #-comments. */ + +ptr = (const uschar *)(pattern - 1); +while ((c = *(++ptr)) != 0) + { + int min, max; + int class_optcount; + int bracket_length; + int duplength; + + /* If we are inside a \Q...\E sequence, all chars are literal */ + + if (inescq) + { + if ((options & PCRE_AUTO_CALLOUT) != 0) length += 2 + 2*LINK_SIZE; + goto NORMAL_CHAR; + } + + /* Otherwise, first check for ignored whitespace and comments */ + + if ((options & PCRE_EXTENDED) != 0) + { + if ((compile_block.ctypes[c] & ctype_space) != 0) continue; + if (c == '#') + { + /* The space before the ; is to avoid a warning on a silly compiler + on the Macintosh. */ + while ((c = *(++ptr)) != 0 && c != NEWLINE) ; + if (c == 0) break; + continue; + } + } + + item_count++; /* Is zero for the first non-comment item */ + + /* Allow space for auto callout before every item except quantifiers. */ + + if ((options & PCRE_AUTO_CALLOUT) != 0 && + c != '*' && c != '+' && c != '?' && + (c != '{' || !is_counted_repeat(ptr + 1))) + length += 2 + 2*LINK_SIZE; + + switch(c) + { + /* A backslashed item may be an escaped data character or it may be a + character type. */ + + case '\\': + c = check_escape(&ptr, &errorcode, bracount, options, FALSE); + if (errorcode != 0) goto PCRE_ERROR_RETURN; + + lastitemlength = 1; /* Default length of last item for repeats */ + + if (c >= 0) /* Data character */ + { + length += 2; /* For a one-byte character */ + +#ifdef SUPPORT_UTF8 + if (utf8 && c > 127) + { + int i; + for (i = 0; i < _pcre_utf8_table1_size; i++) + if (c <= _pcre_utf8_table1[i]) break; + length += i; + lastitemlength += i; + } +#endif + + continue; + } + + /* If \Q, enter "literal" mode */ + + if (-c == ESC_Q) + { + inescq = TRUE; + continue; + } + + /* \X is supported only if Unicode property support is compiled */ + +#ifndef SUPPORT_UCP + if (-c == ESC_X) + { + errorcode = ERR45; + goto PCRE_ERROR_RETURN; + } +#endif + + /* \P and \p are for Unicode properties, but only when the support has + been compiled. Each item needs 2 bytes. */ + + else if (-c == ESC_P || -c == ESC_p) + { +#ifdef SUPPORT_UCP + BOOL negated; + length += 2; + lastitemlength = 2; + if (get_ucp(&ptr, &negated, &errorcode) < 0) goto PCRE_ERROR_RETURN; + continue; +#else + errorcode = ERR45; + goto PCRE_ERROR_RETURN; +#endif + } + + /* Other escapes need one byte */ + + length++; + + /* A back reference needs an additional 2 bytes, plus either one or 5 + bytes for a repeat. We also need to keep the value of the highest + back reference. */ + + if (c <= -ESC_REF) + { + int refnum = -c - ESC_REF; + compile_block.backref_map |= (refnum < 32)? (1 << refnum) : 1; + if (refnum > compile_block.top_backref) + compile_block.top_backref = refnum; + length += 2; /* For single back reference */ + if (ptr[1] == '{' && is_counted_repeat(ptr+2)) + { + ptr = read_repeat_counts(ptr+2, &min, &max, &errorcode); + if (errorcode != 0) goto PCRE_ERROR_RETURN; + if ((min == 0 && (max == 1 || max == -1)) || + (min == 1 && max == -1)) + length++; + else length += 5; + if (ptr[1] == '?') ptr++; + } + } + continue; + + case '^': /* Single-byte metacharacters */ + case '.': + case '$': + length++; + lastitemlength = 1; + continue; + + case '*': /* These repeats won't be after brackets; */ + case '+': /* those are handled separately */ + case '?': + length++; + goto POSESSIVE; /* A few lines below */ + + /* This covers the cases of braced repeats after a single char, metachar, + class, or back reference. */ + + case '{': + if (!is_counted_repeat(ptr+1)) goto NORMAL_CHAR; + ptr = read_repeat_counts(ptr+1, &min, &max, &errorcode); + if (errorcode != 0) goto PCRE_ERROR_RETURN; + + /* These special cases just insert one extra opcode */ + + if ((min == 0 && (max == 1 || max == -1)) || + (min == 1 && max == -1)) + length++; + + /* These cases might insert additional copies of a preceding character. */ + + else + { + if (min != 1) + { + length -= lastitemlength; /* Uncount the original char or metachar */ + if (min > 0) length += 3 + lastitemlength; + } + length += lastitemlength + ((max > 0)? 3 : 1); + } + + if (ptr[1] == '?') ptr++; /* Needs no extra length */ + + POSESSIVE: /* Test for possessive quantifier */ + if (ptr[1] == '+') + { + ptr++; + length += 2 + 2*LINK_SIZE; /* Allow for atomic brackets */ + } + continue; + + /* An alternation contains an offset to the next branch or ket. If any ims + options changed in the previous branch(es), and/or if we are in a + lookbehind assertion, extra space will be needed at the start of the + branch. This is handled by branch_extra. */ + + case '|': + length += 1 + LINK_SIZE + branch_extra; + continue; + + /* A character class uses 33 characters provided that all the character + values are less than 256. Otherwise, it uses a bit map for low valued + characters, and individual items for others. Don't worry about character + types that aren't allowed in classes - they'll get picked up during the + compile. A character class that contains only one single-byte character + uses 2 or 3 bytes, depending on whether it is negated or not. Notice this + where we can. (In UTF-8 mode we can do this only for chars < 128.) */ + + case '[': + if (*(++ptr) == '^') + { + class_optcount = 10; /* Greater than one */ + ptr++; + } + else class_optcount = 0; + +#ifdef SUPPORT_UTF8 + class_utf8 = FALSE; +#endif + + /* Written as a "do" so that an initial ']' is taken as data */ + + if (*ptr != 0) do + { + /* Inside \Q...\E everything is literal except \E */ + + if (inescq) + { + if (*ptr != '\\' || ptr[1] != 'E') goto GET_ONE_CHARACTER; + inescq = FALSE; + ptr += 1; + continue; + } + + /* Outside \Q...\E, check for escapes */ + + if (*ptr == '\\') + { + c = check_escape(&ptr, &errorcode, bracount, options, TRUE); + if (errorcode != 0) goto PCRE_ERROR_RETURN; + + /* \b is backspace inside a class; \X is literal */ + + if (-c == ESC_b) c = '\b'; + else if (-c == ESC_X) c = 'X'; + + /* \Q enters quoting mode */ + + else if (-c == ESC_Q) + { + inescq = TRUE; + continue; + } + + /* Handle escapes that turn into characters */ + + if (c >= 0) goto NON_SPECIAL_CHARACTER; + + /* Escapes that are meta-things. The normal ones just affect the + bit map, but Unicode properties require an XCLASS extended item. */ + + else + { + class_optcount = 10; /* \d, \s etc; make sure > 1 */ +#ifdef SUPPORT_UTF8 + if (-c == ESC_p || -c == ESC_P) + { + if (!class_utf8) + { + class_utf8 = TRUE; + length += LINK_SIZE + 2; + } + length += 2; + } +#endif + } + } + + /* Check the syntax for POSIX stuff. The bits we actually handle are + checked during the real compile phase. */ + + else if (*ptr == '[' && check_posix_syntax(ptr, &ptr, &compile_block)) + { + ptr++; + class_optcount = 10; /* Make sure > 1 */ + } + + /* Anything else increments the possible optimization count. We have to + detect ranges here so that we can compute the number of extra ranges for + caseless wide characters when UCP support is available. If there are wide + characters, we are going to have to use an XCLASS, even for single + characters. */ + + else + { + int d; + + GET_ONE_CHARACTER: + +#ifdef SUPPORT_UTF8 + if (utf8) + { + int extra = 0; + GETCHARLEN(c, ptr, extra); + ptr += extra; + } + else c = *ptr; +#else + c = *ptr; +#endif + + /* Come here from handling \ above when it escapes to a char value */ + + NON_SPECIAL_CHARACTER: + class_optcount++; + + d = -1; + if (ptr[1] == '-') + { + uschar const *hyptr = ptr++; + if (ptr[1] == '\\') + { + ptr++; + d = check_escape(&ptr, &errorcode, bracount, options, TRUE); + if (errorcode != 0) goto PCRE_ERROR_RETURN; + if (-d == ESC_b) d = '\b'; /* backspace */ + else if (-d == ESC_X) d = 'X'; /* literal X in a class */ + } + else if (ptr[1] != 0 && ptr[1] != ']') + { + ptr++; +#ifdef SUPPORT_UTF8 + if (utf8) + { + int extra = 0; + GETCHARLEN(d, ptr, extra); + ptr += extra; + } + else +#endif + d = *ptr; + } + if (d < 0) ptr = hyptr; /* go back to hyphen as data */ + } + + /* If d >= 0 we have a range. In UTF-8 mode, if the end is > 255, or > + 127 for caseless matching, we will need to use an XCLASS. */ + + if (d >= 0) + { + class_optcount = 10; /* Ensure > 1 */ + if (d < c) + { + errorcode = ERR8; + goto PCRE_ERROR_RETURN; + } + +#ifdef SUPPORT_UTF8 + if (utf8 && (d > 255 || ((options & PCRE_CASELESS) != 0 && d > 127))) + { + uschar buffer[6]; + if (!class_utf8) /* Allow for XCLASS overhead */ + { + class_utf8 = TRUE; + length += LINK_SIZE + 2; + } + +#ifdef SUPPORT_UCP + /* If we have UCP support, find out how many extra ranges are + needed to map the other case of characters within this range. We + have to mimic the range optimization here, because extending the + range upwards might push d over a boundary that makes is use + another byte in the UTF-8 representation. */ + + if ((options & PCRE_CASELESS) != 0) + { + int occ, ocd; + int cc = c; + int origd = d; + while (get_othercase_range(&cc, origd, &occ, &ocd)) + { + if (occ >= c && ocd <= d) continue; /* Skip embedded */ + + if (occ < c && ocd >= c - 1) /* Extend the basic range */ + { /* if there is overlap, */ + c = occ; /* noting that if occ < c */ + continue; /* we can't have ocd > d */ + } /* because a subrange is */ + if (ocd > d && occ <= d + 1) /* always shorter than */ + { /* the basic range. */ + d = ocd; + continue; + } + + /* An extra item is needed */ + + length += 1 + _pcre_ord2utf8(occ, buffer) + + ((occ == ocd)? 0 : _pcre_ord2utf8(ocd, buffer)); + } + } +#endif /* SUPPORT_UCP */ + + /* The length of the (possibly extended) range */ + + length += 1 + _pcre_ord2utf8(c, buffer) + _pcre_ord2utf8(d, buffer); + } +#endif /* SUPPORT_UTF8 */ + + } + + /* We have a single character. There is nothing to be done unless we + are in UTF-8 mode. If the char is > 255, or 127 when caseless, we must + allow for an XCL_SINGLE item, doubled for caselessness if there is UCP + support. */ + + else + { +#ifdef SUPPORT_UTF8 + if (utf8 && (c > 255 || ((options & PCRE_CASELESS) != 0 && c > 127))) + { + uschar buffer[6]; + class_optcount = 10; /* Ensure > 1 */ + if (!class_utf8) /* Allow for XCLASS overhead */ + { + class_utf8 = TRUE; + length += LINK_SIZE + 2; + } +#ifdef SUPPORT_UCP + length += (((options & PCRE_CASELESS) != 0)? 2 : 1) * + (1 + _pcre_ord2utf8(c, buffer)); +#else /* SUPPORT_UCP */ + length += 1 + _pcre_ord2utf8(c, buffer); +#endif /* SUPPORT_UCP */ + } +#endif /* SUPPORT_UTF8 */ + } + } + } + while (*(++ptr) != 0 && (inescq || *ptr != ']')); /* Concludes "do" above */ + + if (*ptr == 0) /* Missing terminating ']' */ + { + errorcode = ERR6; + goto PCRE_ERROR_RETURN; + } + + /* We can optimize when there was only one optimizable character. Repeats + for positive and negated single one-byte chars are handled by the general + code. Here, we handle repeats for the class opcodes. */ + + if (class_optcount == 1) length += 3; else + { + length += 33; + + /* A repeat needs either 1 or 5 bytes. If it is a possessive quantifier, + we also need extra for wrapping the whole thing in a sub-pattern. */ + + if (*ptr != 0 && ptr[1] == '{' && is_counted_repeat(ptr+2)) + { + ptr = read_repeat_counts(ptr+2, &min, &max, &errorcode); + if (errorcode != 0) goto PCRE_ERROR_RETURN; + if ((min == 0 && (max == 1 || max == -1)) || + (min == 1 && max == -1)) + length++; + else length += 5; + if (ptr[1] == '+') + { + ptr++; + length += 2 + 2*LINK_SIZE; + } + else if (ptr[1] == '?') ptr++; + } + } + continue; + + /* Brackets may be genuine groups or special things */ + + case '(': + branch_newextra = 0; + bracket_length = 1 + LINK_SIZE; + capturing = FALSE; + + /* Handle special forms of bracket, which all start (? */ + + if (ptr[1] == '?') + { + int set, unset; + int *optset; + + switch (c = ptr[2]) + { + /* Skip over comments entirely */ + case '#': + ptr += 3; + while (*ptr != 0 && *ptr != ')') ptr++; + if (*ptr == 0) + { + errorcode = ERR18; + goto PCRE_ERROR_RETURN; + } + continue; + + /* Non-referencing groups and lookaheads just move the pointer on, and + then behave like a non-special bracket, except that they don't increment + the count of extracting brackets. Ditto for the "once only" bracket, + which is in Perl from version 5.005. */ + + case ':': + case '=': + case '!': + case '>': + ptr += 2; + break; + + /* (?R) specifies a recursive call to the regex, which is an extension + to provide the facility which can be obtained by (?p{perl-code}) in + Perl 5.6. In Perl 5.8 this has become (??{perl-code}). + + From PCRE 4.00, items such as (?3) specify subroutine-like "calls" to + the appropriate numbered brackets. This includes both recursive and + non-recursive calls. (?R) is now synonymous with (?0). */ + + case 'R': + ptr++; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + ptr += 2; + if (c != 'R') + while ((digitab[*(++ptr)] & ctype_digit) != 0); + if (*ptr != ')') + { + errorcode = ERR29; + goto PCRE_ERROR_RETURN; + } + length += 1 + LINK_SIZE; + + /* If this item is quantified, it will get wrapped inside brackets so + as to use the code for quantified brackets. We jump down and use the + code that handles this for real brackets. */ + + if (ptr[1] == '+' || ptr[1] == '*' || ptr[1] == '?' || ptr[1] == '{') + { + length += 2 + 2 * LINK_SIZE; /* to make bracketed */ + duplength = 5 + 3 * LINK_SIZE; + goto HANDLE_QUANTIFIED_BRACKETS; + } + continue; + + /* (?C) is an extension which provides "callout" - to provide a bit of + the functionality of the Perl (?{...}) feature. An optional number may + follow (default is zero). */ + + case 'C': + ptr += 2; + while ((digitab[*(++ptr)] & ctype_digit) != 0); + if (*ptr != ')') + { + errorcode = ERR39; + goto PCRE_ERROR_RETURN; + } + length += 2 + 2*LINK_SIZE; + continue; + + /* Named subpatterns are an extension copied from Python */ + + case 'P': + ptr += 3; + + /* Handle the definition of a named subpattern */ + + if (*ptr == '<') + { + const uschar *p; /* Don't amalgamate; some compilers */ + p = ++ptr; /* grumble at autoincrement in declaration */ + while ((compile_block.ctypes[*ptr] & ctype_word) != 0) ptr++; + if (*ptr != '>') + { + errorcode = ERR42; + goto PCRE_ERROR_RETURN; + } + name_count++; + if (ptr - p > max_name_size) max_name_size = (ptr - p); + capturing = TRUE; /* Named parentheses are always capturing */ + break; + } + + /* Handle back references and recursive calls to named subpatterns */ + + if (*ptr == '=' || *ptr == '>') + { + while ((compile_block.ctypes[*(++ptr)] & ctype_word) != 0); + if (*ptr != ')') + { + errorcode = ERR42; + goto PCRE_ERROR_RETURN; + } + break; + } + + /* Unknown character after (?P */ + + errorcode = ERR41; + goto PCRE_ERROR_RETURN; + + /* Lookbehinds are in Perl from version 5.005 */ + + case '<': + ptr += 3; + if (*ptr == '=' || *ptr == '!') + { + branch_newextra = 1 + LINK_SIZE; + length += 1 + LINK_SIZE; /* For the first branch */ + break; + } + errorcode = ERR24; + goto PCRE_ERROR_RETURN; + + /* Conditionals are in Perl from version 5.005. The bracket must either + be followed by a number (for bracket reference) or by an assertion + group, or (a PCRE extension) by 'R' for a recursion test. */ + + case '(': + if (ptr[3] == 'R' && ptr[4] == ')') + { + ptr += 4; + length += 3; + } + else if ((digitab[ptr[3]] & ctype_digit) != 0) + { + ptr += 4; + length += 3; + while ((digitab[*ptr] & ctype_digit) != 0) ptr++; + if (*ptr != ')') + { + errorcode = ERR26; + goto PCRE_ERROR_RETURN; + } + } + else /* An assertion must follow */ + { + ptr++; /* Can treat like ':' as far as spacing is concerned */ + if (ptr[2] != '?' || + (ptr[3] != '=' && ptr[3] != '!' && ptr[3] != '<') ) + { + ptr += 2; /* To get right offset in message */ + errorcode = ERR28; + goto PCRE_ERROR_RETURN; + } + } + break; + + /* Else loop checking valid options until ) is met. Anything else is an + error. If we are without any brackets, i.e. at top level, the settings + act as if specified in the options, so massage the options immediately. + This is for backward compatibility with Perl 5.004. */ + + default: + set = unset = 0; + optset = &set; + ptr += 2; + + for (;; ptr++) + { + c = *ptr; + switch (c) + { + case 'i': + *optset |= PCRE_CASELESS; + continue; + + case 'm': + *optset |= PCRE_MULTILINE; + continue; + + case 's': + *optset |= PCRE_DOTALL; + continue; + + case 'x': + *optset |= PCRE_EXTENDED; + continue; + + case 'X': + *optset |= PCRE_EXTRA; + continue; + + case 'U': + *optset |= PCRE_UNGREEDY; + continue; + + case '-': + optset = &unset; + continue; + + /* A termination by ')' indicates an options-setting-only item; if + this is at the very start of the pattern (indicated by item_count + being zero), we use it to set the global options. This is helpful + when analyzing the pattern for first characters, etc. Otherwise + nothing is done here and it is handled during the compiling + process. + + We allow for more than one options setting at the start. If such + settings do not change the existing options, nothing is compiled. + However, we must leave space just in case something is compiled. + This can happen for pathological sequences such as (?i)(?-i) + because the global options will end up with -i set. The space is + small and not significant. (Before I did this there was a reported + bug with (?i)(?-i) in a machine-generated pattern.) + + [Historical note: Up to Perl 5.8, options settings at top level + were always global settings, wherever they appeared in the pattern. + That is, they were equivalent to an external setting. From 5.8 + onwards, they apply only to what follows (which is what you might + expect).] */ + + case ')': + if (item_count == 0) + { + options = (options | set) & (~unset); + set = unset = 0; /* To save length */ + item_count--; /* To allow for several */ + length += 2; + } + + /* Fall through */ + + /* A termination by ':' indicates the start of a nested group with + the given options set. This is again handled at compile time, but + we must allow for compiled space if any of the ims options are + set. We also have to allow for resetting space at the end of + the group, which is why 4 is added to the length and not just 2. + If there are several changes of options within the same group, this + will lead to an over-estimate on the length, but this shouldn't + matter very much. We also have to allow for resetting options at + the start of any alternations, which we do by setting + branch_newextra to 2. Finally, we record whether the case-dependent + flag ever changes within the regex. This is used by the "required + character" code. */ + + case ':': + if (((set|unset) & PCRE_IMS) != 0) + { + length += 4; + branch_newextra = 2; + if (((set|unset) & PCRE_CASELESS) != 0) options |= PCRE_ICHANGED; + } + goto END_OPTIONS; + + /* Unrecognized option character */ + + default: + errorcode = ERR12; + goto PCRE_ERROR_RETURN; + } + } + + /* If we hit a closing bracket, that's it - this is a freestanding + option-setting. We need to ensure that branch_extra is updated if + necessary. The only values branch_newextra can have here are 0 or 2. + If the value is 2, then branch_extra must either be 2 or 5, depending + on whether this is a lookbehind group or not. */ + + END_OPTIONS: + if (c == ')') + { + if (branch_newextra == 2 && + (branch_extra == 0 || branch_extra == 1+LINK_SIZE)) + branch_extra += branch_newextra; + continue; + } + + /* If options were terminated by ':' control comes here. This is a + non-capturing group with an options change. There is nothing more that + needs to be done because "capturing" is already set FALSE by default; + we can just fall through. */ + + } + } + + /* Ordinary parentheses, not followed by '?', are capturing unless + PCRE_NO_AUTO_CAPTURE is set. */ + + else capturing = (options & PCRE_NO_AUTO_CAPTURE) == 0; + + /* Capturing brackets must be counted so we can process escapes in a + Perlish way. If the number exceeds EXTRACT_BASIC_MAX we are going to need + an additional 3 bytes of memory per capturing bracket. */ + + if (capturing) + { + bracount++; + if (bracount > EXTRACT_BASIC_MAX) bracket_length += 3; + } + + /* Save length for computing whole length at end if there's a repeat that + requires duplication of the group. Also save the current value of + branch_extra, and start the new group with the new value. If non-zero, this + will either be 2 for a (?imsx: group, or 3 for a lookbehind assertion. */ + + if (brastackptr >= sizeof(brastack)/sizeof(int)) + { + errorcode = ERR19; + goto PCRE_ERROR_RETURN; + } + + bralenstack[brastackptr] = branch_extra; + branch_extra = branch_newextra; + + brastack[brastackptr++] = length; + length += bracket_length; + continue; + + /* Handle ket. Look for subsequent max/min; for certain sets of values we + have to replicate this bracket up to that many times. If brastackptr is + 0 this is an unmatched bracket which will generate an error, but take care + not to try to access brastack[-1] when computing the length and restoring + the branch_extra value. */ + + case ')': + length += 1 + LINK_SIZE; + if (brastackptr > 0) + { + duplength = length - brastack[--brastackptr]; + branch_extra = bralenstack[brastackptr]; + } + else duplength = 0; + + /* The following code is also used when a recursion such as (?3) is + followed by a quantifier, because in that case, it has to be wrapped inside + brackets so that the quantifier works. The value of duplength must be + set before arrival. */ + + HANDLE_QUANTIFIED_BRACKETS: + + /* Leave ptr at the final char; for read_repeat_counts this happens + automatically; for the others we need an increment. */ + + if ((c = ptr[1]) == '{' && is_counted_repeat(ptr+2)) + { + ptr = read_repeat_counts(ptr+2, &min, &max, &errorcode); + if (errorcode != 0) goto PCRE_ERROR_RETURN; + } + else if (c == '*') { min = 0; max = -1; ptr++; } + else if (c == '+') { min = 1; max = -1; ptr++; } + else if (c == '?') { min = 0; max = 1; ptr++; } + else { min = 1; max = 1; } + + /* If the minimum is zero, we have to allow for an OP_BRAZERO before the + group, and if the maximum is greater than zero, we have to replicate + maxval-1 times; each replication acquires an OP_BRAZERO plus a nesting + bracket set. */ + + if (min == 0) + { + length++; + if (max > 0) length += (max - 1) * (duplength + 3 + 2*LINK_SIZE); + } + + /* When the minimum is greater than zero, we have to replicate up to + minval-1 times, with no additions required in the copies. Then, if there + is a limited maximum we have to replicate up to maxval-1 times allowing + for a BRAZERO item before each optional copy and nesting brackets for all + but one of the optional copies. */ + + else + { + length += (min - 1) * duplength; + if (max > min) /* Need this test as max=-1 means no limit */ + length += (max - min) * (duplength + 3 + 2*LINK_SIZE) + - (2 + 2*LINK_SIZE); + } + + /* Allow space for once brackets for "possessive quantifier" */ + + if (ptr[1] == '+') + { + ptr++; + length += 2 + 2*LINK_SIZE; + } + continue; + + /* Non-special character. It won't be space or # in extended mode, so it is + always a genuine character. If we are in a \Q...\E sequence, check for the + end; if not, we have a literal. */ + + default: + NORMAL_CHAR: + + if (inescq && c == '\\' && ptr[1] == 'E') + { + inescq = FALSE; + ptr++; + continue; + } + + length += 2; /* For a one-byte character */ + lastitemlength = 1; /* Default length of last item for repeats */ + + /* In UTF-8 mode, check for additional bytes. */ + +#ifdef SUPPORT_UTF8 + if (utf8 && (c & 0xc0) == 0xc0) + { + while ((ptr[1] & 0xc0) == 0x80) /* Can't flow over the end */ + { /* because the end is marked */ + lastitemlength++; /* by a zero byte. */ + length++; + ptr++; + } + } +#endif + + continue; + } + } + +length += 2 + LINK_SIZE; /* For final KET and END */ + +if ((options & PCRE_AUTO_CALLOUT) != 0) + length += 2 + 2*LINK_SIZE; /* For final callout */ + +if (length > MAX_PATTERN_SIZE) + { + errorcode = ERR20; + goto PCRE_EARLY_ERROR_RETURN; + } + +/* Compute the size of data block needed and get it, either from malloc or +externally provided function. */ + +size = length + sizeof(real_pcre) + name_count * (max_name_size + 3); +re = (real_pcre *)(pcre_malloc)(size); + +if (re == NULL) + { + errorcode = ERR21; + goto PCRE_EARLY_ERROR_RETURN; + } + +/* Put in the magic number, and save the sizes, options, and character table +pointer. NULL is used for the default character tables. The nullpad field is at +the end; it's there to help in the case when a regex compiled on a system with +4-byte pointers is run on another with 8-byte pointers. */ + +re->magic_number = MAGIC_NUMBER; +re->size = size; +re->options = options; +re->dummy1 = 0; +re->name_table_offset = sizeof(real_pcre); +re->name_entry_size = max_name_size + 3; +re->name_count = name_count; +re->ref_count = 0; +re->tables = (tables == _pcre_default_tables)? NULL : tables; +re->nullpad = NULL; + +/* The starting points of the name/number translation table and of the code are +passed around in the compile data block. */ + +compile_block.names_found = 0; +compile_block.name_entry_size = max_name_size + 3; +compile_block.name_table = (uschar *)re + re->name_table_offset; +codestart = compile_block.name_table + re->name_entry_size * re->name_count; +compile_block.start_code = codestart; +compile_block.start_pattern = (const uschar *)pattern; +compile_block.req_varyopt = 0; +compile_block.nopartial = FALSE; + +/* Set up a starting, non-extracting bracket, then compile the expression. On +error, errorcode will be set non-zero, so we don't need to look at the result +of the function here. */ + +ptr = (const uschar *)pattern; +code = (uschar *)codestart; +*code = OP_BRA; +bracount = 0; +(void)compile_regex(options, options & PCRE_IMS, &bracount, &code, &ptr, + &errorcode, FALSE, 0, &firstbyte, &reqbyte, NULL, &compile_block); +re->top_bracket = bracount; +re->top_backref = compile_block.top_backref; + +if (compile_block.nopartial) re->options |= PCRE_NOPARTIAL; + +/* If not reached end of pattern on success, there's an excess bracket. */ + +if (errorcode == 0 && *ptr != 0) errorcode = ERR22; + +/* Fill in the terminating state and check for disastrous overflow, but +if debugging, leave the test till after things are printed out. */ + +*code++ = OP_END; + +#ifndef DEBUG +if (code - codestart > length) errorcode = ERR23; +#endif + +/* Give an error if there's back reference to a non-existent capturing +subpattern. */ + +if (re->top_backref > re->top_bracket) errorcode = ERR15; + +/* Failed to compile, or error while post-processing */ + +if (errorcode != 0) + { + (pcre_free)(re); + PCRE_ERROR_RETURN: + *erroroffset = ptr - (const uschar *)pattern; + PCRE_EARLY_ERROR_RETURN: + *errorptr = error_texts[errorcode]; + if (errorcodeptr != NULL) *errorcodeptr = errorcode; + return NULL; + } + +/* If the anchored option was not passed, set the flag if we can determine that +the pattern is anchored by virtue of ^ characters or \A or anything else (such +as starting with .* when DOTALL is set). + +Otherwise, if we know what the first character has to be, save it, because that +speeds up unanchored matches no end. If not, see if we can set the +PCRE_STARTLINE flag. This is helpful for multiline matches when all branches +start with ^. and also when all branches start with .* for non-DOTALL matches. +*/ + +if ((options & PCRE_ANCHORED) == 0) + { + int temp_options = options; + if (is_anchored(codestart, &temp_options, 0, compile_block.backref_map)) + re->options |= PCRE_ANCHORED; + else + { + if (firstbyte < 0) + firstbyte = find_firstassertedchar(codestart, &temp_options, FALSE); + if (firstbyte >= 0) /* Remove caseless flag for non-caseable chars */ + { + int ch = firstbyte & 255; + re->first_byte = ((firstbyte & REQ_CASELESS) != 0 && + compile_block.fcc[ch] == ch)? ch : firstbyte; + re->options |= PCRE_FIRSTSET; + } + else if (is_startline(codestart, 0, compile_block.backref_map)) + re->options |= PCRE_STARTLINE; + } + } + +/* For an anchored pattern, we use the "required byte" only if it follows a +variable length item in the regex. Remove the caseless flag for non-caseable +bytes. */ + +if (reqbyte >= 0 && + ((re->options & PCRE_ANCHORED) == 0 || (reqbyte & REQ_VARY) != 0)) + { + int ch = reqbyte & 255; + re->req_byte = ((reqbyte & REQ_CASELESS) != 0 && + compile_block.fcc[ch] == ch)? (reqbyte & ~REQ_CASELESS) : reqbyte; + re->options |= PCRE_REQCHSET; + } + +/* Print out the compiled data for debugging */ + +#ifdef DEBUG + +printf("Length = %d top_bracket = %d top_backref = %d\n", + length, re->top_bracket, re->top_backref); + +if (re->options != 0) + { + printf("%s%s%s%s%s%s%s%s%s%s\n", + ((re->options & PCRE_NOPARTIAL) != 0)? "nopartial " : "", + ((re->options & PCRE_ANCHORED) != 0)? "anchored " : "", + ((re->options & PCRE_CASELESS) != 0)? "caseless " : "", + ((re->options & PCRE_ICHANGED) != 0)? "case state changed " : "", + ((re->options & PCRE_EXTENDED) != 0)? "extended " : "", + ((re->options & PCRE_MULTILINE) != 0)? "multiline " : "", + ((re->options & PCRE_DOTALL) != 0)? "dotall " : "", + ((re->options & PCRE_DOLLAR_ENDONLY) != 0)? "endonly " : "", + ((re->options & PCRE_EXTRA) != 0)? "extra " : "", + ((re->options & PCRE_UNGREEDY) != 0)? "ungreedy " : ""); + } + +if ((re->options & PCRE_FIRSTSET) != 0) + { + int ch = re->first_byte & 255; + const char *caseless = ((re->first_byte & REQ_CASELESS) == 0)? "" : " (caseless)"; + if (isprint(ch)) printf("First char = %c%s\n", ch, caseless); + else printf("First char = \\x%02x%s\n", ch, caseless); + } + +if ((re->options & PCRE_REQCHSET) != 0) + { + int ch = re->req_byte & 255; + const char *caseless = ((re->req_byte & REQ_CASELESS) == 0)? "" : " (caseless)"; + if (isprint(ch)) printf("Req char = %c%s\n", ch, caseless); + else printf("Req char = \\x%02x%s\n", ch, caseless); + } + +_pcre_printint(re, stdout); + +/* This check is done here in the debugging case so that the code that +was compiled can be seen. */ + +if (code - codestart > length) + { + (pcre_free)(re); + *errorptr = error_texts[ERR23]; + *erroroffset = ptr - (uschar *)pattern; + if (errorcodeptr != NULL) *errorcodeptr = ERR23; + return NULL; + } +#endif + +return (pcre *)re; +} + +/* End of pcre_compile.c */ diff --git a/ext/pcre/pcrelib/pcre_config.c b/ext/pcre/pcrelib/pcre_config.c new file mode 100644 index 000000000000..04029a9464c7 --- /dev/null +++ b/ext/pcre/pcrelib/pcre_config.c @@ -0,0 +1,112 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2005 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains the external function pcre_config(). */ + + +#include "pcre_internal.h" + + +/************************************************* +* Return info about what features are configured * +*************************************************/ + +/* This function has an extensible interface so that additional items can be +added compatibly. + +Arguments: + what what information is required + where where to put the information + +Returns: 0 if data returned, negative on error +*/ + +EXPORT int +pcre_config(int what, void *where) +{ +switch (what) + { + case PCRE_CONFIG_UTF8: +#ifdef SUPPORT_UTF8 + *((int *)where) = 1; +#else + *((int *)where) = 0; +#endif + break; + + case PCRE_CONFIG_UNICODE_PROPERTIES: +#ifdef SUPPORT_UCP + *((int *)where) = 1; +#else + *((int *)where) = 0; +#endif + break; + + case PCRE_CONFIG_NEWLINE: + *((int *)where) = NEWLINE; + break; + + case PCRE_CONFIG_LINK_SIZE: + *((int *)where) = LINK_SIZE; + break; + + case PCRE_CONFIG_POSIX_MALLOC_THRESHOLD: + *((int *)where) = POSIX_MALLOC_THRESHOLD; + break; + + case PCRE_CONFIG_MATCH_LIMIT: + *((unsigned int *)where) = MATCH_LIMIT; + break; + + case PCRE_CONFIG_STACKRECURSE: +#ifdef NO_RECURSE + *((int *)where) = 0; +#else + *((int *)where) = 1; +#endif + break; + + default: return PCRE_ERROR_BADOPTION; + } + +return 0; +} + +/* End of pcre_config.c */ diff --git a/ext/pcre/pcrelib/pcre_dfa_exec.c b/ext/pcre/pcrelib/pcre_dfa_exec.c new file mode 100644 index 000000000000..cb3ec186c6df --- /dev/null +++ b/ext/pcre/pcrelib/pcre_dfa_exec.c @@ -0,0 +1,1920 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2005 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains the external function pcre_dfa_exec(), which is an +alternative matching function that uses a DFA algorithm. This is NOT Perl- +compatible, but it has advantages in certain applications. */ + + +#include "pcre_internal.h" + + +/* For use to indent debugging output */ + +#define SP " " + + + +/************************************************* +* Code parameters and static tables * +*************************************************/ + +/* These are offsets that are used to turn the OP_TYPESTAR and friends opcodes +into others, under special conditions. A gap of 10 between the blocks should be +enough. */ + +#define OP_PROP_EXTRA (EXTRACT_BASIC_MAX+1) +#define OP_EXTUNI_EXTRA (EXTRACT_BASIC_MAX+11) + + +/* This table identifies those opcodes that are followed immediately by a +character that is to be tested in some way. This makes is possible to +centralize the loading of these characters. In the case of Type * etc, the +"character" is the opcode for \D, \d, \S, \s, \W, or \w, which will always be a +small value. */ + +static uschar coptable[] = { + 0, /* End */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* \A, \G, \B, \b, \D, \d, \S, \s, \W, \w */ + 0, 0, /* Any, Anybyte */ + 0, 0, 0, /* NOTPROP, PROP, EXTUNI */ + 0, 0, 0, 0, 0, /* \Z, \z, Opt, ^, $ */ + 1, /* Char */ + 1, /* Charnc */ + 1, /* not */ + /* Positive single-char repeats */ + 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */ + 3, 3, 3, /* upto, minupto, exact */ + /* Negative single-char repeats - only for chars < 256 */ + 1, 1, 1, 1, 1, 1, /* NOT *, *?, +, +?, ?, ?? */ + 3, 3, 3, /* NOT upto, minupto, exact */ + /* Positive type repeats */ + 1, 1, 1, 1, 1, 1, /* Type *, *?, +, +?, ?, ?? */ + 3, 3, 3, /* Type upto, minupto, exact */ + /* Character class & ref repeats */ + 0, 0, 0, 0, 0, 0, /* *, *?, +, +?, ?, ?? */ + 0, 0, /* CRRANGE, CRMINRANGE */ + 0, /* CLASS */ + 0, /* NCLASS */ + 0, /* XCLASS - variable length */ + 0, /* REF */ + 0, /* RECURSE */ + 0, /* CALLOUT */ + 0, /* Alt */ + 0, /* Ket */ + 0, /* KetRmax */ + 0, /* KetRmin */ + 0, /* Assert */ + 0, /* Assert not */ + 0, /* Assert behind */ + 0, /* Assert behind not */ + 0, /* Reverse */ + 0, /* Once */ + 0, /* COND */ + 0, /* CREF */ + 0, 0, /* BRAZERO, BRAMINZERO */ + 0, /* BRANUMBER */ + 0 /* BRA */ +}; + +/* These 2 tables allow for compact code for testing for \D, \d, \S, \s, \W, +and \w */ + +static uschar toptable1[] = { + 0, 0, 0, 0, 0, + ctype_digit, ctype_digit, + ctype_space, ctype_space, + ctype_word, ctype_word, + 0 /* OP_ANY */ +}; + +static uschar toptable2[] = { + 0, 0, 0, 0, 0, + ctype_digit, 0, + ctype_space, 0, + ctype_word, 0, + 1 /* OP_ANY */ +}; + + +/* Structure for holding data about a particular state, which is in effect the +current data for an active path through the match tree. It must consist +entirely of ints because the working vector we are passed, and which we put +these structures in, is a vector of ints. */ + +typedef struct stateblock { + int offset; /* Offset to opcode */ + int count; /* Count for repeats */ + int ims; /* ims flag bits */ + int data; /* Some use extra data */ +} stateblock; + +#define INTS_PER_STATEBLOCK (sizeof(stateblock)/sizeof(int)) + + +#ifdef DEBUG +/************************************************* +* Print character string * +*************************************************/ + +/* Character string printing function for debugging. + +Arguments: + p points to string + length number of bytes + f where to print + +Returns: nothing +*/ + +static void +pchars(unsigned char *p, int length, FILE *f) +{ +int c; +while (length-- > 0) + { + if (isprint(c = *(p++))) + fprintf(f, "%c", c); + else + fprintf(f, "\\x%02x", c); + } +} +#endif + + + +/************************************************* +* Execute a Regular Expression - DFA engine * +*************************************************/ + +/* This internal function applies a compiled pattern to a subject string, +starting at a given point, using a DFA engine. This function is called from the +external one, possibly multiple times if the pattern is not anchored. The +function calls itself recursively for some kinds of subpattern. + +Arguments: + md the match_data block with fixed information + this_start_code the opening bracket of this subexpression's code + current_subject where we currently are in the subject string + start_offset start offset in the subject string + offsets vector to contain the matching string offsets + offsetcount size of same + workspace vector of workspace + wscount size of same + ims the current ims flags + rlevel function call recursion level + recursing regex recursive call level + +Returns: > 0 => + = 0 => + -1 => failed to match + < -1 => some kind of unexpected problem + +The following macros are used for adding states to the two state vectors (one +for the current character, one for the following character). */ + +#define ADD_ACTIVE(x,y) \ + if (active_count++ < wscount) \ + { \ + next_active_state->offset = (x); \ + next_active_state->count = (y); \ + next_active_state->ims = ims; \ + next_active_state++; \ + DPRINTF(("%.*sADD_ACTIVE(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \ + } \ + else return PCRE_ERROR_DFA_WSSIZE + +#define ADD_ACTIVE_DATA(x,y,z) \ + if (active_count++ < wscount) \ + { \ + next_active_state->offset = (x); \ + next_active_state->count = (y); \ + next_active_state->ims = ims; \ + next_active_state->data = (z); \ + next_active_state++; \ + DPRINTF(("%.*sADD_ACTIVE_DATA(%d,%d,%d)\n", rlevel*2-2, SP, (x), (y), (z))); \ + } \ + else return PCRE_ERROR_DFA_WSSIZE + +#define ADD_NEW(x,y) \ + if (new_count++ < wscount) \ + { \ + next_new_state->offset = (x); \ + next_new_state->count = (y); \ + next_new_state->ims = ims; \ + next_new_state++; \ + DPRINTF(("%.*sADD_NEW(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \ + } \ + else return PCRE_ERROR_DFA_WSSIZE + +#define ADD_NEW_DATA(x,y,z) \ + if (new_count++ < wscount) \ + { \ + next_new_state->offset = (x); \ + next_new_state->count = (y); \ + next_new_state->ims = ims; \ + next_new_state->data = (z); \ + next_new_state++; \ + DPRINTF(("%.*sADD_NEW_DATA(%d,%d,%d)\n", rlevel*2-2, SP, (x), (y), (z))); \ + } \ + else return PCRE_ERROR_DFA_WSSIZE + +/* And now, here is the code */ + +static int +internal_dfa_exec( + dfa_match_data *md, + const uschar *this_start_code, + const uschar *current_subject, + int start_offset, + int *offsets, + int offsetcount, + int *workspace, + int wscount, + int ims, + int rlevel, + int recursing) +{ +stateblock *active_states, *new_states, *temp_states; +stateblock *next_active_state, *next_new_state; + +const uschar *ctypes, *lcc, *fcc; +const uschar *ptr; +const uschar *end_code; + +int active_count, new_count, match_count; + +/* Some fields in the md block are frequently referenced, so we load them into +independent variables in the hope that this will perform better. */ + +const uschar *start_subject = md->start_subject; +const uschar *end_subject = md->end_subject; +const uschar *start_code = md->start_code; + +BOOL utf8 = (md->poptions & PCRE_UTF8) != 0; + +rlevel++; +offsetcount &= (-2); + +wscount -= 2; +wscount = (wscount - (wscount % (INTS_PER_STATEBLOCK * 2))) / + (2 * INTS_PER_STATEBLOCK); + +DPRINTF(("\n%.*s---------------------\n" + "%.*sCall to internal_dfa_exec f=%d r=%d\n", + rlevel*2-2, SP, rlevel*2-2, SP, rlevel, recursing)); + +ctypes = md->tables + ctypes_offset; +lcc = md->tables + lcc_offset; +fcc = md->tables + fcc_offset; + +match_count = PCRE_ERROR_NOMATCH; /* A negative number */ + +active_states = (stateblock *)(workspace + 2); +next_new_state = new_states = active_states + wscount; +new_count = 0; + +/* The first thing in any (sub) pattern is a bracket of some sort. Push all +the alternative states onto the list, and find out where the end is. This +makes is possible to use this function recursively, when we want to stop at a +matching internal ket rather than at the end. + +If the first opcode in the first alternative is OP_REVERSE, we are dealing with +a backward assertion. In that case, we have to find out the maximum amount to +move back, and set up each alternative appropriately. */ + +if (this_start_code[1+LINK_SIZE] == OP_REVERSE) + { + int max_back = 0; + int gone_back; + + end_code = this_start_code; + do + { + int back = GET(end_code, 2+LINK_SIZE); + if (back > max_back) max_back = back; + end_code += GET(end_code, 1); + } + while (*end_code == OP_ALT); + + /* If we can't go back the amount required for the longest lookbehind + pattern, go back as far as we can; some alternatives may still be viable. */ + +#ifdef SUPPORT_UTF8 + /* In character mode we have to step back character by character */ + + if (utf8) + { + for (gone_back = 0; gone_back < max_back; gone_back++) + { + if (current_subject <= start_subject) break; + current_subject--; + while (current_subject > start_subject && + (*current_subject & 0xc0) == 0x80) + current_subject--; + } + } + else +#endif + + /* In byte-mode we can do this quickly. */ + + { + gone_back = (current_subject - max_back < start_subject)? + current_subject - start_subject : max_back; + current_subject -= gone_back; + } + + /* Now we can process the individual branches. */ + + end_code = this_start_code; + do + { + int back = GET(end_code, 2+LINK_SIZE); + if (back <= gone_back) + { + int bstate = end_code - start_code + 2 + 2*LINK_SIZE; + ADD_NEW_DATA(-bstate, 0, gone_back - back); + } + end_code += GET(end_code, 1); + } + while (*end_code == OP_ALT); + } + +/* This is the code for a "normal" subpattern (not a backward assertion). The +start of a whole pattern is always one of these. If we are at the top level, +we may be asked to restart matching from the same point that we reached for a +previous partial match. We still have to scan through the top-level branches to +find the end state. */ + +else + { + end_code = this_start_code; + + /* Restarting */ + + if (rlevel == 1 && (md->moptions & PCRE_DFA_RESTART) != 0) + { + do { end_code += GET(end_code, 1); } while (*end_code == OP_ALT); + new_count = workspace[1]; + if (!workspace[0]) + memcpy(new_states, active_states, new_count * sizeof(stateblock)); + } + + /* Not restarting */ + + else + { + do + { + ADD_NEW(end_code - start_code + 1 + LINK_SIZE, 0); + end_code += GET(end_code, 1); + } + while (*end_code == OP_ALT); + } + } + +workspace[0] = 0; /* Bit indicating which vector is current */ + +DPRINTF(("%.*sEnd state = %d\n", rlevel*2-2, SP, end_code - start_code)); + +/* Loop for scanning the subject */ + +ptr = current_subject; +for (;;) + { + int i, j; + int c, d, clen, dlen; + + /* Make the new state list into the active state list and empty the + new state list. */ + + temp_states = active_states; + active_states = new_states; + new_states = temp_states; + active_count = new_count; + new_count = 0; + + workspace[0] ^= 1; /* Remember for the restarting feature */ + workspace[1] = active_count; + +#ifdef DEBUG + printf("%.*sNext character: rest of subject = \"", rlevel*2-2, SP); + pchars((uschar *)ptr, strlen((char *)ptr), stdout); + printf("\"\n"); + + printf("%.*sActive states: ", rlevel*2-2, SP); + for (i = 0; i < active_count; i++) + printf("%d/%d ", active_states[i].offset, active_states[i].count); + printf("\n"); +#endif + + /* Set the pointers for adding new states */ + + next_active_state = active_states + active_count; + next_new_state = new_states; + + /* Load the current character from the subject outside the loop, as many + different states may want to look at it, and we assume that at least one + will. */ + + if (ptr < end_subject) + { + clen = 1; +#ifdef SUPPORT_UTF8 + if (utf8) { GETCHARLEN(c, ptr, clen); } else +#endif /* SUPPORT_UTF8 */ + c = *ptr; + } + else + { + clen = 0; /* At end subject */ + c = -1; + } + + /* Scan up the active states and act on each one. The result of an action + may be to add more states to the currently active list (e.g. on hitting a + parenthesis) or it may be to put states on the new list, for considering + when we move the character pointer on. */ + + for (i = 0; i < active_count; i++) + { + stateblock *current_state = active_states + i; + const uschar *code; + int state_offset = current_state->offset; + int count, codevalue; + int chartype, othercase; + +#ifdef DEBUG + printf ("%.*sProcessing state %d c=", rlevel*2-2, SP, state_offset); + if (c < 0) printf("-1\n"); + else if (c > 32 && c < 127) printf("'%c'\n", c); + else printf("0x%02x\n", c); +#endif + + /* This variable is referred to implicity in the ADD_xxx macros. */ + + ims = current_state->ims; + + /* A negative offset is a special case meaning "hold off going to this + (negated) state until the number of characters in the data field have + been skipped". */ + + if (state_offset < 0) + { + if (current_state->data > 0) + { + DPRINTF(("%.*sSkipping this character\n", rlevel*2-2, SP)); + ADD_NEW_DATA(state_offset, current_state->count, + current_state->data - 1); + continue; + } + else + { + current_state->offset = state_offset = -state_offset; + } + } + + /* Check for a duplicate state with the same count, and skip if found. */ + + for (j = 0; j < i; j++) + { + if (active_states[j].offset == state_offset && + active_states[j].count == current_state->count) + { + DPRINTF(("%.*sDuplicate state: skipped\n", rlevel*2-2, SP)); + goto NEXT_ACTIVE_STATE; + } + } + + /* The state offset is the offset to the opcode */ + + code = start_code + state_offset; + codevalue = *code; + if (codevalue >= OP_BRA) codevalue = OP_BRA; /* All brackets are equal */ + + /* If this opcode is followed by an inline character, load it. It is + tempting to test for the presence of a subject character here, but that + is wrong, because sometimes zero repetitions of the subject are + permitted. + + We also use this mechanism for opcodes such as OP_TYPEPLUS that take an + argument that is not a data character - but is always one byte long. + Unfortunately, we have to take special action to deal with \P, \p, and + \X in this case. To keep the other cases fast, convert these ones to new + opcodes. */ + + if (coptable[codevalue] > 0) + { + dlen = 1; +#ifdef SUPPORT_UTF8 + if (utf8) { GETCHARLEN(d, (code + coptable[codevalue]), dlen); } else +#endif /* SUPPORT_UTF8 */ + d = code[coptable[codevalue]]; + if (codevalue >= OP_TYPESTAR) + { + if (d == OP_ANYBYTE) return PCRE_ERROR_DFA_UITEM; + if (d >= OP_NOTPROP) + codevalue += (d == OP_EXTUNI)? OP_EXTUNI_EXTRA : OP_PROP_EXTRA; + } + } + else + { + dlen = 0; /* Not strictly necessary, but compilers moan */ + d = -1; /* if these variables are not set. */ + } + + + /* Now process the individual opcodes */ + + switch (codevalue) + { + +/* ========================================================================== */ + /* Reached a closing bracket. If not at the end of the pattern, carry + on with the next opcode. Otherwise, unless we have an empty string and + PCRE_NOTEMPTY is set, save the match data, shifting up all previous + matches so we always have the longest first. */ + + case OP_KET: + case OP_KETRMIN: + case OP_KETRMAX: + if (code != end_code) + { + ADD_ACTIVE(state_offset + 1 + LINK_SIZE, 0); + if (codevalue != OP_KET) + { + ADD_ACTIVE(state_offset - GET(code, 1), 0); + } + } + else if (ptr > current_subject || (md->moptions & PCRE_NOTEMPTY) == 0) + { + if (match_count < 0) match_count = (offsetcount >= 2)? 1 : 0; + else if (match_count > 0 && ++match_count * 2 >= offsetcount) + match_count = 0; + count = ((match_count == 0)? offsetcount : match_count * 2) - 2; + if (count > 0) memmove(offsets + 2, offsets, count * sizeof(int)); + if (offsetcount >= 2) + { + offsets[0] = current_subject - start_subject; + offsets[1] = ptr - start_subject; + DPRINTF(("%.*sSet matched string = \"%.*s\"\n", rlevel*2-2, SP, + offsets[1] - offsets[0], current_subject)); + } + if ((md->moptions & PCRE_DFA_SHORTEST) != 0) + { + DPRINTF(("%.*sEnd of internal_dfa_exec %d: returning %d\n" + "%.*s---------------------\n\n", rlevel*2-2, SP, rlevel, + match_count, rlevel*2-2, SP)); + return match_count; + } + } + break; + +/* ========================================================================== */ + /* These opcodes add to the current list of states without looking + at the current character. */ + + /*-----------------------------------------------------------------*/ + case OP_ALT: + do { code += GET(code, 1); } while (*code == OP_ALT); + ADD_ACTIVE(code - start_code, 0); + break; + + /*-----------------------------------------------------------------*/ + case OP_BRA: + do + { + ADD_ACTIVE(code - start_code + 1 + LINK_SIZE, 0); + code += GET(code, 1); + } + while (*code == OP_ALT); + break; + + /*-----------------------------------------------------------------*/ + case OP_BRAZERO: + case OP_BRAMINZERO: + ADD_ACTIVE(state_offset + 1, 0); + code += 1 + GET(code, 2); + while (*code == OP_ALT) code += GET(code, 1); + ADD_ACTIVE(code - start_code + 1 + LINK_SIZE, 0); + break; + + /*-----------------------------------------------------------------*/ + case OP_BRANUMBER: + ADD_ACTIVE(state_offset + 1 + LINK_SIZE, 0); + break; + + /*-----------------------------------------------------------------*/ + case OP_CIRC: + if ((ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0) || + ((ims & PCRE_MULTILINE) != 0 && ptr[-1] == NEWLINE)) + { ADD_ACTIVE(state_offset + 1, 0); } + break; + + /*-----------------------------------------------------------------*/ + case OP_EOD: + if (ptr >= end_subject) { ADD_ACTIVE(state_offset + 1, 0); } + break; + + /*-----------------------------------------------------------------*/ + case OP_OPT: + ims = code[1]; + ADD_ACTIVE(state_offset + 2, 0); + break; + + /*-----------------------------------------------------------------*/ + case OP_SOD: + if (ptr == start_subject) { ADD_ACTIVE(state_offset + 1, 0); } + break; + + /*-----------------------------------------------------------------*/ + case OP_SOM: + if (ptr == start_subject + start_offset) { ADD_ACTIVE(state_offset + 1, 0); } + break; + + +/* ========================================================================== */ + /* These opcodes inspect the next subject character, and sometimes + the previous one as well, but do not have an argument. The variable + clen contains the length of the current character and is zero if we are + at the end of the subject. */ + + /*-----------------------------------------------------------------*/ + case OP_ANY: + if (clen > 0 && (c != NEWLINE || (ims & PCRE_DOTALL) != 0)) + { ADD_NEW(state_offset + 1, 0); } + break; + + /*-----------------------------------------------------------------*/ + case OP_EODN: + if (clen == 0 || (c == NEWLINE && ptr + 1 == end_subject)) + { ADD_ACTIVE(state_offset + 1, 0); } + break; + + /*-----------------------------------------------------------------*/ + case OP_DOLL: + if ((md->moptions & PCRE_NOTEOL) == 0) + { + if (clen == 0 || (c == NEWLINE && (ptr + 1 == end_subject || + (ims & PCRE_MULTILINE) != 0))) + { ADD_ACTIVE(state_offset + 1, 0); } + } + else if (c == NEWLINE && (ims & PCRE_MULTILINE) != 0) + { ADD_ACTIVE(state_offset + 1, 0); } + break; + + /*-----------------------------------------------------------------*/ + + case OP_DIGIT: + case OP_WHITESPACE: + case OP_WORDCHAR: + if (clen > 0 && c < 256 && + ((ctypes[c] & toptable1[codevalue]) ^ toptable2[codevalue]) != 0) + { ADD_NEW(state_offset + 1, 0); } + break; + + /*-----------------------------------------------------------------*/ + case OP_NOT_DIGIT: + case OP_NOT_WHITESPACE: + case OP_NOT_WORDCHAR: + if (clen > 0 && (c >= 256 || + ((ctypes[c] & toptable1[codevalue]) ^ toptable2[codevalue]) != 0)) + { ADD_NEW(state_offset + 1, 0); } + break; + + /*-----------------------------------------------------------------*/ + case OP_WORD_BOUNDARY: + case OP_NOT_WORD_BOUNDARY: + { + int left_word, right_word; + + if (ptr > start_subject) + { + const uschar *temp = ptr - 1; +#ifdef SUPPORT_UTF8 + if (utf8) BACKCHAR(temp); +#endif + GETCHARTEST(d, temp); + left_word = d < 256 && (ctypes[d] & ctype_word) != 0; + } + else left_word = 0; + + if (clen > 0) right_word = c < 256 && (ctypes[c] & ctype_word) != 0; + else right_word = 0; + + if ((left_word == right_word) == (codevalue == OP_NOT_WORD_BOUNDARY)) + { ADD_ACTIVE(state_offset + 1, 0); } + } + break; + + +#ifdef SUPPORT_UCP + + /*-----------------------------------------------------------------*/ + /* Check the next character by Unicode property. We will get here only + if the support is in the binary; otherwise a compile-time error occurs. + */ + + case OP_PROP: + case OP_NOTPROP: + if (clen > 0) + { + int rqdtype, category; + category = ucp_findchar(c, &chartype, &othercase); + rqdtype = code[1]; + if (rqdtype >= 128) + { + if ((rqdtype - 128 == category) == (codevalue == OP_PROP)) + { ADD_NEW(state_offset + 2, 0); } + } + else + { + if ((rqdtype == chartype) == (codevalue == OP_PROP)) + { ADD_NEW(state_offset + 2, 0); } + } + } + break; +#endif + + + +/* ========================================================================== */ + /* These opcodes likewise inspect the subject character, but have an + argument that is not a data character. It is one of these opcodes: + OP_ANY, OP_DIGIT, OP_NOT_DIGIT, OP_WHITESPACE, OP_NOT_SPACE, OP_WORDCHAR, + OP_NOT_WORDCHAR. The value is loaded into d. */ + + case OP_TYPEPLUS: + case OP_TYPEMINPLUS: + count = current_state->count; /* Already matched */ + if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); } + if (clen > 0) + { + if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) || + (c < 256 && + (d != OP_ANY || c != '\n' || (ims & PCRE_DOTALL) != 0) && + ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0)) + { + count++; + ADD_NEW(state_offset, count); + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_TYPEQUERY: + case OP_TYPEMINQUERY: + ADD_ACTIVE(state_offset + 2, 0); + if (clen > 0) + { + if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) || + (c < 256 && + (d != OP_ANY || c != '\n' || (ims & PCRE_DOTALL) != 0) && + ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0)) + { + ADD_NEW(state_offset + 2, 0); + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_TYPESTAR: + case OP_TYPEMINSTAR: + ADD_ACTIVE(state_offset + 2, 0); + if (clen > 0) + { + if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) || + (c < 256 && + (d != OP_ANY || c != '\n' || (ims & PCRE_DOTALL) != 0) && + ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0)) + { + ADD_NEW(state_offset, 0); + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_TYPEEXACT: + case OP_TYPEUPTO: + case OP_TYPEMINUPTO: + if (codevalue != OP_TYPEEXACT) + { ADD_ACTIVE(state_offset + 4, 0); } + count = current_state->count; /* Number already matched */ + if (clen > 0) + { + if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) || + (c < 256 && + (d != OP_ANY || c != '\n' || (ims & PCRE_DOTALL) != 0) && + ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0)) + { + if (++count >= GET2(code, 1)) + { ADD_NEW(state_offset + 4, 0); } + else + { ADD_NEW(state_offset, count); } + } + } + break; + +/* ========================================================================== */ + /* These are virtual opcodes that are used when something like + OP_TYPEPLUS has OP_PROP, OP_NOTPROP, or OP_EXTUNI as its argument. It + keeps the code above fast for the other cases. The argument is in the + d variable. */ + + case OP_PROP_EXTRA + OP_TYPEPLUS: + case OP_PROP_EXTRA + OP_TYPEMINPLUS: + count = current_state->count; /* Already matched */ + if (count > 0) { ADD_ACTIVE(state_offset + 3, 0); } + if (clen > 0) + { + int category = ucp_findchar(c, &chartype, &othercase); + int rqdtype = code[2]; + if ((d == OP_PROP) == + (rqdtype == ((rqdtype >= 128)? (category + 128) : chartype))) + { count++; ADD_NEW(state_offset, count); } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_EXTUNI_EXTRA + OP_TYPEPLUS: + case OP_EXTUNI_EXTRA + OP_TYPEMINPLUS: + count = current_state->count; /* Already matched */ + if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); } + if (clen > 0 && ucp_findchar(c, &chartype, &othercase) != ucp_M) + { + const uschar *nptr = ptr + clen; + int ncount = 0; + while (nptr < end_subject) + { + int nd; + int ndlen = 1; + GETCHARLEN(nd, nptr, ndlen); + if (ucp_findchar(nd, &chartype, &othercase) != ucp_M) break; + ncount++; + nptr += ndlen; + } + count++; + ADD_NEW_DATA(-state_offset, count, ncount); + } + break; + + /*-----------------------------------------------------------------*/ + case OP_PROP_EXTRA + OP_TYPEQUERY: + case OP_PROP_EXTRA + OP_TYPEMINQUERY: + count = 3; + goto QS1; + + case OP_PROP_EXTRA + OP_TYPESTAR: + case OP_PROP_EXTRA + OP_TYPEMINSTAR: + count = 0; + + QS1: + + ADD_ACTIVE(state_offset + 3, 0); + if (clen > 0) + { + int category = ucp_findchar(c, &chartype, &othercase); + int rqdtype = code[2]; + if ((d == OP_PROP) == + (rqdtype == ((rqdtype >= 128)? (category + 128) : chartype))) + { ADD_NEW(state_offset + count, 0); } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_EXTUNI_EXTRA + OP_TYPEQUERY: + case OP_EXTUNI_EXTRA + OP_TYPEMINQUERY: + count = 2; + goto QS2; + + case OP_EXTUNI_EXTRA + OP_TYPESTAR: + case OP_EXTUNI_EXTRA + OP_TYPEMINSTAR: + count = 0; + + QS2: + + ADD_ACTIVE(state_offset + 2, 0); + if (clen > 0 && ucp_findchar(c, &chartype, &othercase) != ucp_M) + { + const uschar *nptr = ptr + clen; + int ncount = 0; + while (nptr < end_subject) + { + int nd; + int ndlen = 1; + GETCHARLEN(nd, nptr, ndlen); + if (ucp_findchar(nd, &chartype, &othercase) != ucp_M) break; + ncount++; + nptr += ndlen; + } + ADD_NEW_DATA(-(state_offset + count), 0, ncount); + } + break; + + /*-----------------------------------------------------------------*/ + case OP_PROP_EXTRA + OP_TYPEEXACT: + case OP_PROP_EXTRA + OP_TYPEUPTO: + case OP_PROP_EXTRA + OP_TYPEMINUPTO: + if (codevalue != OP_PROP_EXTRA + OP_TYPEEXACT) + { ADD_ACTIVE(state_offset + 5, 0); } + count = current_state->count; /* Number already matched */ + if (clen > 0) + { + int category = ucp_findchar(c, &chartype, &othercase); + int rqdtype = code[4]; + if ((d == OP_PROP) == + (rqdtype == ((rqdtype >= 128)? (category + 128) : chartype))) + { + if (++count >= GET2(code, 1)) + { ADD_NEW(state_offset + 5, 0); } + else + { ADD_NEW(state_offset, count); } + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_EXTUNI_EXTRA + OP_TYPEEXACT: + case OP_EXTUNI_EXTRA + OP_TYPEUPTO: + case OP_EXTUNI_EXTRA + OP_TYPEMINUPTO: + if (codevalue != OP_EXTUNI_EXTRA + OP_TYPEEXACT) + { ADD_ACTIVE(state_offset + 4, 0); } + count = current_state->count; /* Number already matched */ + if (clen > 0 && ucp_findchar(c, &chartype, &othercase) != ucp_M) + { + const uschar *nptr = ptr + clen; + int ncount = 0; + while (nptr < end_subject) + { + int nd; + int ndlen = 1; + GETCHARLEN(nd, nptr, ndlen); + if (ucp_findchar(nd, &chartype, &othercase) != ucp_M) break; + ncount++; + nptr += ndlen; + } + if (++count >= GET2(code, 1)) + { ADD_NEW_DATA(-(state_offset + 4), 0, ncount); } + else + { ADD_NEW_DATA(-state_offset, count, ncount); } + } + break; + +/* ========================================================================== */ + /* These opcodes are followed by a character that is usually compared + to the current subject character; it is loaded into d. We still get + here even if there is no subject character, because in some cases zero + repetitions are permitted. */ + + /*-----------------------------------------------------------------*/ + case OP_CHAR: + if (clen > 0 && c == d) { ADD_NEW(state_offset + dlen + 1, 0); } + break; + + /*-----------------------------------------------------------------*/ + case OP_CHARNC: + if (clen == 0) break; + +#ifdef SUPPORT_UTF8 + if (utf8) + { + if (c == d) { ADD_NEW(state_offset + dlen + 1, 0); } else + { + if (c < 128) othercase = fcc[c]; else + + /* If we have Unicode property support, we can use it to test the + other case of the character, if there is one. The result of + ucp_findchar() is < 0 if the char isn't found, and othercase is + returned as zero if there isn't another case. */ + +#ifdef SUPPORT_UCP + if (ucp_findchar(c, &chartype, &othercase) < 0) +#endif + othercase = -1; + + if (d == othercase) { ADD_NEW(state_offset + dlen + 1, 0); } + } + } + else +#endif /* SUPPORT_UTF8 */ + + /* Non-UTF-8 mode */ + { + if (lcc[c] == lcc[d]) { ADD_NEW(state_offset + 2, 0); } + } + break; + + +#ifdef SUPPORT_UCP + /*-----------------------------------------------------------------*/ + /* This is a tricky one because it can match more than one character. + Find out how many characters to skip, and then set up a negative state + to wait for them to pass before continuing. */ + + case OP_EXTUNI: + if (clen > 0 && ucp_findchar(c, &chartype, &othercase) != ucp_M) + { + const uschar *nptr = ptr + clen; + int ncount = 0; + while (nptr < end_subject) + { + int nclen = 1; + GETCHARLEN(c, nptr, nclen); + if (ucp_findchar(c, &chartype, &othercase) != ucp_M) break; + ncount++; + nptr += nclen; + } + ADD_NEW_DATA(-(state_offset + 1), 0, ncount); + } + break; +#endif + + /*-----------------------------------------------------------------*/ + /* Match a negated single character. This is only used for one-byte + characters, that is, we know that d < 256. The character we are + checking (c) can be multibyte. */ + + case OP_NOT: + if (clen > 0) + { + int otherd = ((ims & PCRE_CASELESS) != 0)? fcc[d] : d; + if (c != d && c != otherd) { ADD_NEW(state_offset + dlen + 1, 0); } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_PLUS: + case OP_MINPLUS: + case OP_NOTPLUS: + case OP_NOTMINPLUS: + count = current_state->count; /* Already matched */ + if (count > 0) { ADD_ACTIVE(state_offset + dlen + 1, 0); } + if (clen > 0) + { + int otherd = -1; + if ((ims & PCRE_CASELESS) != 0) + { +#ifdef SUPPORT_UTF8 + if (utf8 && c >= 128) + { +#ifdef SUPPORT_UCP + if (ucp_findchar(d, &chartype, &otherd) < 0) otherd = -1; +#endif /* SUPPORT_UCP */ + } + else +#endif /* SUPPORT_UTF8 */ + otherd = fcc[d]; + } + if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR)) + { count++; ADD_NEW(state_offset, count); } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_QUERY: + case OP_MINQUERY: + case OP_NOTQUERY: + case OP_NOTMINQUERY: + ADD_ACTIVE(state_offset + dlen + 1, 0); + if (clen > 0) + { + int otherd = -1; + if ((ims && PCRE_CASELESS) != 0) + { +#ifdef SUPPORT_UTF8 + if (utf8 && c >= 128) + { +#ifdef SUPPORT_UCP + if (ucp_findchar(c, &chartype, &otherd) < 0) otherd = -1; +#endif /* SUPPORT_UCP */ + } + else +#endif /* SUPPORT_UTF8 */ + otherd = fcc[d]; + } + if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR)) + { ADD_NEW(state_offset + dlen + 1, 0); } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_STAR: + case OP_MINSTAR: + case OP_NOTSTAR: + case OP_NOTMINSTAR: + ADD_ACTIVE(state_offset + dlen + 1, 0); + if (clen > 0) + { + int otherd = -1; + if ((ims && PCRE_CASELESS) != 0) + { +#ifdef SUPPORT_UTF8 + if (utf8 && c >= 128) + { +#ifdef SUPPORT_UCP + if (ucp_findchar(c, &chartype, &otherd) < 0) otherd = -1; +#endif /* SUPPORT_UCP */ + } + else +#endif /* SUPPORT_UTF8 */ + otherd = fcc[d]; + } + if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR)) + { ADD_NEW(state_offset, 0); } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_EXACT: + case OP_UPTO: + case OP_MINUPTO: + case OP_NOTEXACT: + case OP_NOTUPTO: + case OP_NOTMINUPTO: + if (codevalue != OP_EXACT && codevalue != OP_NOTEXACT) + { ADD_ACTIVE(state_offset + dlen + 3, 0); } + count = current_state->count; /* Number already matched */ + if (clen > 0) + { + int otherd = -1; + if ((ims & PCRE_CASELESS) != 0) + { +#ifdef SUPPORT_UTF8 + if (utf8 && c >= 128) + { +#ifdef SUPPORT_UCP + if (ucp_findchar(d, &chartype, &otherd) < 0) otherd = -1; +#endif /* SUPPORT_UCP */ + } + else +#endif /* SUPPORT_UTF8 */ + otherd = fcc[d]; + } + if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR)) + { + if (++count >= GET2(code, 1)) + { ADD_NEW(state_offset + dlen + 3, 0); } + else + { ADD_NEW(state_offset, count); } + } + } + break; + + +/* ========================================================================== */ + /* These are the class-handling opcodes */ + + case OP_CLASS: + case OP_NCLASS: + case OP_XCLASS: + { + BOOL isinclass = FALSE; + int next_state_offset; + const uschar *ecode; + + /* For a simple class, there is always just a 32-byte table, and we + can set isinclass from it. */ + + if (codevalue != OP_XCLASS) + { + ecode = code + 33; + if (clen > 0) + { + isinclass = (c > 255)? (codevalue == OP_NCLASS) : + ((code[1 + c/8] & (1 << (c&7))) != 0); + } + } + + /* An extended class may have a table or a list of single characters, + ranges, or both, and it may be positive or negative. There's a + function that sorts all this out. */ + + else + { + ecode = code + GET(code, 1); + if (clen > 0) isinclass = _pcre_xclass(c, code + 1 + LINK_SIZE); + } + + /* At this point, isinclass is set for all kinds of class, and ecode + points to the byte after the end of the class. If there is a + quantifier, this is where it will be. */ + + next_state_offset = ecode - start_code; + + switch (*ecode) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + ADD_ACTIVE(next_state_offset + 1, 0); + if (isinclass) { ADD_NEW(state_offset, 0); } + break; + + case OP_CRPLUS: + case OP_CRMINPLUS: + count = current_state->count; /* Already matched */ + if (count > 0) { ADD_ACTIVE(next_state_offset + 1, 0); } + if (isinclass) { count++; ADD_NEW(state_offset, count); } + break; + + case OP_CRQUERY: + case OP_CRMINQUERY: + ADD_ACTIVE(next_state_offset + 1, 0); + if (isinclass) { ADD_NEW(next_state_offset + 1, 0); } + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + count = current_state->count; /* Already matched */ + if (count >= GET2(ecode, 1)) + { ADD_ACTIVE(next_state_offset + 5, 0); } + if (isinclass) + { + if (++count >= GET2(ecode, 3)) + { ADD_NEW(next_state_offset + 5, 0); } + else + { ADD_NEW(state_offset, count); } + } + break; + + default: + if (isinclass) { ADD_NEW(next_state_offset, 0); } + break; + } + } + break; + +/* ========================================================================== */ + /* These are the opcodes for fancy brackets of various kinds. We have + to use recursion in order to handle them. */ + + case OP_ASSERT: + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + { + int rc; + int local_offsets[2]; + int local_workspace[1000]; + const uschar *endasscode = code + GET(code, 1); + + while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1); + + rc = internal_dfa_exec( + md, /* static match data */ + code, /* this subexpression's code */ + ptr, /* where we currently are */ + ptr - start_subject, /* start offset */ + local_offsets, /* offset vector */ + sizeof(local_offsets)/sizeof(int), /* size of same */ + local_workspace, /* workspace vector */ + sizeof(local_workspace)/sizeof(int), /* size of same */ + ims, /* the current ims flags */ + rlevel, /* function recursion level */ + recursing); /* pass on regex recursion */ + + if ((rc >= 0) == (codevalue == OP_ASSERT || codevalue == OP_ASSERTBACK)) + { ADD_ACTIVE(endasscode + LINK_SIZE + 1 - start_code, 0); } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_COND: + { + int local_offsets[1000]; + int local_workspace[1000]; + int condcode = code[LINK_SIZE+1]; + + /* The only supported version of OP_CREF is for the value 0xffff, which + means "test if in a recursion". */ + + if (condcode == OP_CREF) + { + int value = GET2(code, LINK_SIZE+2); + if (value != 0xffff) return PCRE_ERROR_DFA_UCOND; + if (recursing > 0) { ADD_ACTIVE(state_offset + LINK_SIZE + 4, 0); } + else { ADD_ACTIVE(state_offset + GET(code, 1) + LINK_SIZE + 1, 0); } + } + + /* Otherwise, the condition is an assertion */ + + else + { + int rc; + const uschar *asscode = code + LINK_SIZE + 1; + const uschar *endasscode = asscode + GET(asscode, 1); + + while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1); + + rc = internal_dfa_exec( + md, /* fixed match data */ + asscode, /* this subexpression's code */ + ptr, /* where we currently are */ + ptr - start_subject, /* start offset */ + local_offsets, /* offset vector */ + sizeof(local_offsets)/sizeof(int), /* size of same */ + local_workspace, /* workspace vector */ + sizeof(local_workspace)/sizeof(int), /* size of same */ + ims, /* the current ims flags */ + rlevel, /* function recursion level */ + recursing); /* pass on regex recursion */ + + if ((rc >= 0) == + (condcode == OP_ASSERT || condcode == OP_ASSERTBACK)) + { ADD_ACTIVE(endasscode + LINK_SIZE + 1 - start_code, 0); } + else + { ADD_ACTIVE(state_offset + GET(code, 1) + LINK_SIZE + 1, 0); } + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_RECURSE: + { + int local_offsets[1000]; + int local_workspace[1000]; + int rc; + + DPRINTF(("%.*sStarting regex recursion %d\n", rlevel*2-2, SP, + recursing + 1)); + + rc = internal_dfa_exec( + md, /* fixed match data */ + start_code + GET(code, 1), /* this subexpression's code */ + ptr, /* where we currently are */ + ptr - start_subject, /* start offset */ + local_offsets, /* offset vector */ + sizeof(local_offsets)/sizeof(int), /* size of same */ + local_workspace, /* workspace vector */ + sizeof(local_workspace)/sizeof(int), /* size of same */ + ims, /* the current ims flags */ + rlevel, /* function recursion level */ + recursing + 1); /* regex recurse level */ + + DPRINTF(("%.*sReturn from regex recursion %d: rc=%d\n", rlevel*2-2, SP, + recursing + 1, rc)); + + /* Ran out of internal offsets */ + + if (rc == 0) return PCRE_ERROR_DFA_RECURSE; + + /* For each successful matched substring, set up the next state with a + count of characters to skip before trying it. Note that the count is in + characters, not bytes. */ + + if (rc > 0) + { + for (rc = rc*2 - 2; rc >= 0; rc -= 2) + { + const uschar *p = start_subject + local_offsets[rc]; + const uschar *pp = start_subject + local_offsets[rc+1]; + int charcount = local_offsets[rc+1] - local_offsets[rc]; + while (p < pp) if ((*p++ & 0xc0) == 0x80) charcount--; + if (charcount > 0) + { + ADD_NEW_DATA(-(state_offset + LINK_SIZE + 1), 0, (charcount - 1)); + } + else + { + ADD_ACTIVE(state_offset + LINK_SIZE + 1, 0); + } + } + } + else if (rc != PCRE_ERROR_NOMATCH) return rc; + } + break; + + /*-----------------------------------------------------------------*/ + case OP_ONCE: + { + int local_offsets[2]; + int local_workspace[1000]; + + int rc = internal_dfa_exec( + md, /* fixed match data */ + code, /* this subexpression's code */ + ptr, /* where we currently are */ + ptr - start_subject, /* start offset */ + local_offsets, /* offset vector */ + sizeof(local_offsets)/sizeof(int), /* size of same */ + local_workspace, /* workspace vector */ + sizeof(local_workspace)/sizeof(int), /* size of same */ + ims, /* the current ims flags */ + rlevel, /* function recursion level */ + recursing); /* pass on regex recursion */ + + if (rc >= 0) + { + const uschar *end_subpattern = code; + int charcount = local_offsets[1] - local_offsets[0]; + int next_state_offset, repeat_state_offset; + + do { end_subpattern += GET(end_subpattern, 1); } + while (*end_subpattern == OP_ALT); + next_state_offset = end_subpattern - start_code + LINK_SIZE + 1; + + /* If the end of this subpattern is KETRMAX or KETRMIN, we must + arrange for the repeat state also to be added to the relevant list. + Calculate the offset, or set -1 for no repeat. */ + + repeat_state_offset = (*end_subpattern == OP_KETRMAX || + *end_subpattern == OP_KETRMIN)? + end_subpattern - start_code - GET(end_subpattern, 1) : -1; + + /* If we have matched an empty string, add the next state at the + current character pointer. This is important so that the duplicate + checking kicks in, which is what breaks infinite loops that match an + empty string. */ + + if (charcount == 0) + { + ADD_ACTIVE(next_state_offset, 0); + } + + /* Optimization: if there are no more active states, and there + are no new states yet set up, then skip over the subject string + right here, to save looping. Otherwise, set up the new state to swing + into action when the end of the substring is reached. */ + + else if (i + 1 >= active_count && new_count == 0) + { + ptr += charcount; + clen = 0; + ADD_NEW(next_state_offset, 0); + + /* If we are adding a repeat state at the new character position, + we must fudge things so that it is the only current state. + Otherwise, it might be a duplicate of one we processed before, and + that would cause it to be skipped. */ + + if (repeat_state_offset >= 0) + { + next_active_state = active_states; + active_count = 0; + i = -1; + ADD_ACTIVE(repeat_state_offset, 0); + } + } + else + { + const uschar *p = start_subject + local_offsets[0]; + const uschar *pp = start_subject + local_offsets[1]; + while (p < pp) if ((*p++ & 0xc0) == 0x80) charcount--; + ADD_NEW_DATA(-next_state_offset, 0, (charcount - 1)); + if (repeat_state_offset >= 0) + { ADD_NEW_DATA(-repeat_state_offset, 0, (charcount - 1)); } + } + + } + else if (rc != PCRE_ERROR_NOMATCH) return rc; + } + break; + + +/* ========================================================================== */ + /* Handle callouts */ + + case OP_CALLOUT: + if (pcre_callout != NULL) + { + int rrc; + pcre_callout_block cb; + cb.version = 1; /* Version 1 of the callout block */ + cb.callout_number = code[1]; + cb.offset_vector = offsets; + cb.subject = (char *)start_subject; + cb.subject_length = end_subject - start_subject; + cb.start_match = current_subject - start_subject; + cb.current_position = ptr - start_subject; + cb.pattern_position = GET(code, 2); + cb.next_item_length = GET(code, 2 + LINK_SIZE); + cb.capture_top = 1; + cb.capture_last = -1; + cb.callout_data = md->callout_data; + if ((rrc = (*pcre_callout)(&cb)) < 0) return rrc; /* Abandon */ + if (rrc == 0) { ADD_ACTIVE(state_offset + 2 + 2*LINK_SIZE, 0); } + } + break; + + +/* ========================================================================== */ + default: /* Unsupported opcode */ + return PCRE_ERROR_DFA_UITEM; + } + + NEXT_ACTIVE_STATE: continue; + + } /* End of loop scanning active states */ + + /* We have finished the processing at the current subject character. If no + new states have been set for the next character, we have found all the + matches that we are going to find. If we are at the top level and partial + matching has been requested, check for appropriate conditions. */ + + if (new_count <= 0) + { + if (match_count < 0 && /* No matches found */ + rlevel == 1 && /* Top level match function */ + (md->moptions & PCRE_PARTIAL) != 0 && /* Want partial matching */ + ptr >= end_subject && /* Reached end of subject */ + ptr > current_subject) /* Matched non-empty string */ + { + if (offsetcount >= 2) + { + offsets[0] = current_subject - start_subject; + offsets[1] = end_subject - start_subject; + } + match_count = PCRE_ERROR_PARTIAL; + } + + DPRINTF(("%.*sEnd of internal_dfa_exec %d: returning %d\n" + "%.*s---------------------\n\n", rlevel*2-2, SP, rlevel, match_count, + rlevel*2-2, SP)); + return match_count; + } + + /* One or more states are active for the next character. */ + + ptr += clen; /* Advance to next subject character */ + } /* Loop to move along the subject string */ + +/* Control never gets here, but we must keep the compiler happy. */ + +DPRINTF(("%.*s+++ Unexpected end of internal_dfa_exec %d +++\n" + "%.*s---------------------\n\n", rlevel*2-2, SP, rlevel, rlevel*2-2, SP)); +return PCRE_ERROR_NOMATCH; +} + + + + +/************************************************* +* Execute a Regular Expression - DFA engine * +*************************************************/ + +/* This external function applies a compiled re to a subject string using a DFA +engine. This function calls the internal function multiple times if the pattern +is not anchored. + +Arguments: + argument_re points to the compiled expression + extra_data points to extra data or is NULL (not currently used) + subject points to the subject string + length length of subject string (may contain binary zeros) + start_offset where to start in the subject string + options option bits + offsets vector of match offsets + offsetcount size of same + workspace workspace vector + wscount size of same + +Returns: > 0 => number of match offset pairs placed in offsets + = 0 => offsets overflowed; longest matches are present + -1 => failed to match + < -1 => some kind of unexpected problem +*/ + +EXPORT int +pcre_dfa_exec(const pcre *argument_re, const pcre_extra *extra_data, + const char *subject, int length, int start_offset, int options, int *offsets, + int offsetcount, int *workspace, int wscount) +{ +real_pcre *re = (real_pcre *)argument_re; +dfa_match_data match_block; +BOOL utf8, anchored, startline, firstline; +const uschar *current_subject, *end_subject, *lcc; + +pcre_study_data internal_study; +const pcre_study_data *study = NULL; +real_pcre internal_re; + +const uschar *req_byte_ptr; +const uschar *start_bits = NULL; +BOOL first_byte_caseless = FALSE; +BOOL req_byte_caseless = FALSE; +int first_byte = -1; +int req_byte = -1; +int req_byte2 = -1; + +/* Plausibility checks */ + +if ((options & ~PUBLIC_DFA_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION; +if (re == NULL || subject == NULL || workspace == NULL || + (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL; +if (offsetcount < 0) return PCRE_ERROR_BADCOUNT; +if (wscount < 20) return PCRE_ERROR_DFA_WSSIZE; + +/* We need to find the pointer to any study data before we test for byte +flipping, so we scan the extra_data block first. This may set two fields in the +match block, so we must initialize them beforehand. However, the other fields +in the match block must not be set until after the byte flipping. */ + +match_block.tables = re->tables; +match_block.callout_data = NULL; + +if (extra_data != NULL) + { + unsigned int flags = extra_data->flags; + if ((flags & PCRE_EXTRA_STUDY_DATA) != 0) + study = (const pcre_study_data *)extra_data->study_data; + if ((flags & PCRE_EXTRA_MATCH_LIMIT) != 0) return PCRE_ERROR_DFA_UMLIMIT; + if ((flags & PCRE_EXTRA_CALLOUT_DATA) != 0) + match_block.callout_data = extra_data->callout_data; + if ((flags & PCRE_EXTRA_TABLES) != 0) + match_block.tables = extra_data->tables; + } + +/* Check that the first field in the block is the magic number. If it is not, +test for a regex that was compiled on a host of opposite endianness. If this is +the case, flipped values are put in internal_re and internal_study if there was +study data too. */ + +if (re->magic_number != MAGIC_NUMBER) + { + re = _pcre_try_flipped(re, &internal_re, study, &internal_study); + if (re == NULL) return PCRE_ERROR_BADMAGIC; + if (study != NULL) study = &internal_study; + } + +/* Set some local values */ + +current_subject = (const unsigned char *)subject + start_offset; +end_subject = (const unsigned char *)subject + length; +req_byte_ptr = current_subject - 1; + +utf8 = (re->options & PCRE_UTF8) != 0; +anchored = (options & PCRE_ANCHORED) != 0 || (re->options & PCRE_ANCHORED) != 0; + +/* The remaining fixed data for passing around. */ + +match_block.start_code = (const uschar *)argument_re + + re->name_table_offset + re->name_count * re->name_entry_size; +match_block.start_subject = (const unsigned char *)subject; +match_block.end_subject = end_subject; +match_block.moptions = options; +match_block.poptions = re->options; + +/* Check a UTF-8 string if required. Unfortunately there's no way of passing +back the character offset. */ + +#ifdef SUPPORT_UTF8 +if (utf8 && (options & PCRE_NO_UTF8_CHECK) == 0) + { + if (_pcre_valid_utf8((uschar *)subject, length) >= 0) + return PCRE_ERROR_BADUTF8; + if (start_offset > 0 && start_offset < length) + { + int tb = ((uschar *)subject)[start_offset]; + if (tb > 127) + { + tb &= 0xc0; + if (tb != 0 && tb != 0xc0) return PCRE_ERROR_BADUTF8_OFFSET; + } + } + } +#endif + +/* If the exec call supplied NULL for tables, use the inbuilt ones. This +is a feature that makes it possible to save compiled regex and re-use them +in other programs later. */ + +if (match_block.tables == NULL) match_block.tables = _pcre_default_tables; + +/* The lower casing table and the "must be at the start of a line" flag are +used in a loop when finding where to start. */ + +lcc = match_block.tables + lcc_offset; +startline = (re->options & PCRE_STARTLINE) != 0; +firstline = (re->options & PCRE_FIRSTLINE) != 0; + +/* Set up the first character to match, if available. The first_byte value is +never set for an anchored regular expression, but the anchoring may be forced +at run time, so we have to test for anchoring. The first char may be unset for +an unanchored pattern, of course. If there's no first char and the pattern was +studied, there may be a bitmap of possible first characters. */ + +if (!anchored) + { + if ((re->options & PCRE_FIRSTSET) != 0) + { + first_byte = re->first_byte & 255; + if ((first_byte_caseless = ((re->first_byte & REQ_CASELESS) != 0)) == TRUE) + first_byte = lcc[first_byte]; + } + else + { + if (startline && study != NULL && + (study->options & PCRE_STUDY_MAPPED) != 0) + start_bits = study->start_bits; + } + } + +/* For anchored or unanchored matches, there may be a "last known required +character" set. */ + +if ((re->options & PCRE_REQCHSET) != 0) + { + req_byte = re->req_byte & 255; + req_byte_caseless = (re->req_byte & REQ_CASELESS) != 0; + req_byte2 = (match_block.tables + fcc_offset)[req_byte]; /* case flipped */ + } + +/* Call the main matching function, looping for a non-anchored regex after a +failed match. Unless restarting, optimize by moving to the first match +character if possible, when not anchored. Then unless wanting a partial match, +check for a required later character. */ + +for (;;) + { + int rc; + + if ((options & PCRE_DFA_RESTART) == 0) + { + const uschar *save_end_subject = end_subject; + + /* Advance to a unique first char if possible. If firstline is TRUE, the + start of the match is constrained to the first line of a multiline string. + Implement this by temporarily adjusting end_subject so that we stop scanning + at a newline. If the match fails at the newline, later code breaks this loop. + */ + + if (firstline) + { + const uschar *t = current_subject; + while (t < save_end_subject && *t != '\n') t++; + end_subject = t; + } + + if (first_byte >= 0) + { + if (first_byte_caseless) + while (current_subject < end_subject && + lcc[*current_subject] != first_byte) + current_subject++; + else + while (current_subject < end_subject && *current_subject != first_byte) + current_subject++; + } + + /* Or to just after \n for a multiline match if possible */ + + else if (startline) + { + if (current_subject > match_block.start_subject + start_offset) + { + while (current_subject < end_subject && current_subject[-1] != NEWLINE) + current_subject++; + } + } + + /* Or to a non-unique first char after study */ + + else if (start_bits != NULL) + { + while (current_subject < end_subject) + { + register unsigned int c = *current_subject; + if ((start_bits[c/8] & (1 << (c&7))) == 0) current_subject++; + else break; + } + } + + /* Restore fudged end_subject */ + + end_subject = save_end_subject; + } + + /* If req_byte is set, we know that that character must appear in the subject + for the match to succeed. If the first character is set, req_byte must be + later in the subject; otherwise the test starts at the match point. This + optimization can save a huge amount of work in patterns with nested unlimited + repeats that aren't going to match. Writing separate code for cased/caseless + versions makes it go faster, as does using an autoincrement and backing off + on a match. + + HOWEVER: when the subject string is very, very long, searching to its end can + take a long time, and give bad performance on quite ordinary patterns. This + showed up when somebody was matching /^C/ on a 32-megabyte string... so we + don't do this when the string is sufficiently long. + + ALSO: this processing is disabled when partial matching is requested. + */ + + if (req_byte >= 0 && + end_subject - current_subject < REQ_BYTE_MAX && + (options & PCRE_PARTIAL) == 0) + { + register const uschar *p = current_subject + ((first_byte >= 0)? 1 : 0); + + /* We don't need to repeat the search if we haven't yet reached the + place we found it at last time. */ + + if (p > req_byte_ptr) + { + if (req_byte_caseless) + { + while (p < end_subject) + { + register int pp = *p++; + if (pp == req_byte || pp == req_byte2) { p--; break; } + } + } + else + { + while (p < end_subject) + { + if (*p++ == req_byte) { p--; break; } + } + } + + /* If we can't find the required character, break the matching loop, + which will cause a return or PCRE_ERROR_NOMATCH. */ + + if (p >= end_subject) break; + + /* If we have found the required character, save the point where we + found it, so that we don't search again next time round the loop if + the start hasn't passed this character yet. */ + + req_byte_ptr = p; + } + } + + /* OK, now we can do the business */ + + rc = internal_dfa_exec( + &match_block, /* fixed match data */ + match_block.start_code, /* this subexpression's code */ + current_subject, /* where we currently are */ + start_offset, /* start offset in subject */ + offsets, /* offset vector */ + offsetcount, /* size of same */ + workspace, /* workspace vector */ + wscount, /* size of same */ + re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL), /* ims flags */ + 0, /* function recurse level */ + 0); /* regex recurse level */ + + /* Anything other than "no match" means we are done, always; otherwise, carry + on only if not anchored. */ + + if (rc != PCRE_ERROR_NOMATCH || anchored) return rc; + + /* Advance to the next subject character unless we are at the end of a line + and firstline is set. */ + + if (firstline && *current_subject == NEWLINE) break; + current_subject++; + +#ifdef SUPPORT_UTF8 + if (utf8) + { + while (current_subject < end_subject && (*current_subject & 0xc0) == 0x80) + current_subject++; + } +#endif + + if (current_subject > end_subject) break; + } + +return PCRE_ERROR_NOMATCH; +} + +/* End of pcre_dfa_exec.c */ diff --git a/ext/pcre/pcrelib/pcre_exec.c b/ext/pcre/pcrelib/pcre_exec.c new file mode 100644 index 000000000000..65173e2ba241 --- /dev/null +++ b/ext/pcre/pcrelib/pcre_exec.c @@ -0,0 +1,3632 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2005 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains pcre_exec(), the externally visible function that does +pattern matching using an NFA algorithm, trying to mimic Perl as closely as +possible. There are also some static supporting functions. */ + + +#include "pcre_internal.h" + + +/* Structure for building a chain of data that actually lives on the +stack, for holding the values of the subject pointer at the start of each +subpattern, so as to detect when an empty string has been matched by a +subpattern - to break infinite loops. When NO_RECURSE is set, these blocks +are on the heap, not on the stack. */ + +typedef struct eptrblock { + struct eptrblock *epb_prev; + const uschar *epb_saved_eptr; +} eptrblock; + +/* Flag bits for the match() function */ + +#define match_condassert 0x01 /* Called to check a condition assertion */ +#define match_isgroup 0x02 /* Set if start of bracketed group */ + +/* Non-error returns from the match() function. Error returns are externally +defined PCRE_ERROR_xxx codes, which are all negative. */ + +#define MATCH_MATCH 1 +#define MATCH_NOMATCH 0 + +/* Maximum number of ints of offset to save on the stack for recursive calls. +If the offset vector is bigger, malloc is used. This should be a multiple of 3, +because the offset vector is always a multiple of 3 long. */ + +#define REC_STACK_SAVE_MAX 30 + +/* Min and max values for the common repeats; for the maxima, 0 => infinity */ + +static const char rep_min[] = { 0, 0, 1, 1, 0, 0 }; +static const char rep_max[] = { 0, 0, 0, 0, 1, 1 }; + + + +#ifdef DEBUG +/************************************************* +* Debugging function to print chars * +*************************************************/ + +/* Print a sequence of chars in printable format, stopping at the end of the +subject if the requested. + +Arguments: + p points to characters + length number to print + is_subject TRUE if printing from within md->start_subject + md pointer to matching data block, if is_subject is TRUE + +Returns: nothing +*/ + +static void +pchars(const uschar *p, int length, BOOL is_subject, match_data *md) +{ +int c; +if (is_subject && length > md->end_subject - p) length = md->end_subject - p; +while (length-- > 0) + if (isprint(c = *(p++))) printf("%c", c); else printf("\\x%02x", c); +} +#endif + + + +/************************************************* +* Match a back-reference * +*************************************************/ + +/* If a back reference hasn't been set, the length that is passed is greater +than the number of characters left in the string, so the match fails. + +Arguments: + offset index into the offset vector + eptr points into the subject + length length to be matched + md points to match data block + ims the ims flags + +Returns: TRUE if matched +*/ + +static BOOL +match_ref(int offset, register const uschar *eptr, int length, match_data *md, + unsigned long int ims) +{ +const uschar *p = md->start_subject + md->offset_vector[offset]; + +#ifdef DEBUG +if (eptr >= md->end_subject) + printf("matching subject "); +else + { + printf("matching subject "); + pchars(eptr, length, TRUE, md); + } +printf(" against backref "); +pchars(p, length, FALSE, md); +printf("\n"); +#endif + +/* Always fail if not enough characters left */ + +if (length > md->end_subject - eptr) return FALSE; + +/* Separate the caselesss case for speed */ + +if ((ims & PCRE_CASELESS) != 0) + { + while (length-- > 0) + if (md->lcc[*p++] != md->lcc[*eptr++]) return FALSE; + } +else + { while (length-- > 0) if (*p++ != *eptr++) return FALSE; } + +return TRUE; +} + + + +/*************************************************************************** +**************************************************************************** + RECURSION IN THE match() FUNCTION + +The match() function is highly recursive. Some regular expressions can cause +it to recurse thousands of times. I was writing for Unix, so I just let it +call itself recursively. This uses the stack for saving everything that has +to be saved for a recursive call. On Unix, the stack can be large, and this +works fine. + +It turns out that on non-Unix systems there are problems with programs that +use a lot of stack. (This despite the fact that every last chip has oodles +of memory these days, and techniques for extending the stack have been known +for decades.) So.... + +There is a fudge, triggered by defining NO_RECURSE, which avoids recursive +calls by keeping local variables that need to be preserved in blocks of memory +obtained from malloc instead instead of on the stack. Macros are used to +achieve this so that the actual code doesn't look very different to what it +always used to. +**************************************************************************** +***************************************************************************/ + + +/* These versions of the macros use the stack, as normal */ + +#ifndef NO_RECURSE +#define REGISTER register +#define RMATCH(rx,ra,rb,rc,rd,re,rf,rg) rx = match(ra,rb,rc,rd,re,rf,rg) +#define RRETURN(ra) return ra +#else + + +/* These versions of the macros manage a private stack on the heap. Note +that the rd argument of RMATCH isn't actually used. It's the md argument of +match(), which never changes. */ + +#define REGISTER + +#define RMATCH(rx,ra,rb,rc,rd,re,rf,rg)\ + {\ + heapframe *newframe = (pcre_stack_malloc)(sizeof(heapframe));\ + if (setjmp(frame->Xwhere) == 0)\ + {\ + newframe->Xeptr = ra;\ + newframe->Xecode = rb;\ + newframe->Xoffset_top = rc;\ + newframe->Xims = re;\ + newframe->Xeptrb = rf;\ + newframe->Xflags = rg;\ + newframe->Xprevframe = frame;\ + frame = newframe;\ + DPRINTF(("restarting from line %d\n", __LINE__));\ + goto HEAP_RECURSE;\ + }\ + else\ + {\ + DPRINTF(("longjumped back to line %d\n", __LINE__));\ + frame = md->thisframe;\ + rx = frame->Xresult;\ + }\ + } + +#define RRETURN(ra)\ + {\ + heapframe *newframe = frame;\ + frame = newframe->Xprevframe;\ + (pcre_stack_free)(newframe);\ + if (frame != NULL)\ + {\ + frame->Xresult = ra;\ + md->thisframe = frame;\ + longjmp(frame->Xwhere, 1);\ + }\ + return ra;\ + } + + +/* Structure for remembering the local variables in a private frame */ + +typedef struct heapframe { + struct heapframe *Xprevframe; + + /* Function arguments that may change */ + + const uschar *Xeptr; + const uschar *Xecode; + int Xoffset_top; + long int Xims; + eptrblock *Xeptrb; + int Xflags; + + /* Function local variables */ + + const uschar *Xcallpat; + const uschar *Xcharptr; + const uschar *Xdata; + const uschar *Xnext; + const uschar *Xpp; + const uschar *Xprev; + const uschar *Xsaved_eptr; + + recursion_info Xnew_recursive; + + BOOL Xcur_is_word; + BOOL Xcondition; + BOOL Xminimize; + BOOL Xprev_is_word; + + unsigned long int Xoriginal_ims; + +#ifdef SUPPORT_UCP + int Xprop_type; + int Xprop_fail_result; + int Xprop_category; + int Xprop_chartype; + int Xprop_othercase; + int Xprop_test_against; + int *Xprop_test_variable; +#endif + + int Xctype; + int Xfc; + int Xfi; + int Xlength; + int Xmax; + int Xmin; + int Xnumber; + int Xoffset; + int Xop; + int Xsave_capture_last; + int Xsave_offset1, Xsave_offset2, Xsave_offset3; + int Xstacksave[REC_STACK_SAVE_MAX]; + + eptrblock Xnewptrb; + + /* Place to pass back result, and where to jump back to */ + + int Xresult; + jmp_buf Xwhere; + +} heapframe; + +#endif + + +/*************************************************************************** +***************************************************************************/ + + + +/************************************************* +* Match from current position * +*************************************************/ + +/* On entry ecode points to the first opcode, and eptr to the first character +in the subject string, while eptrb holds the value of eptr at the start of the +last bracketed group - used for breaking infinite loops matching zero-length +strings. This function is called recursively in many circumstances. Whenever it +returns a negative (error) response, the outer incarnation must also return the +same response. + +Performance note: It might be tempting to extract commonly used fields from the +md structure (e.g. utf8, end_subject) into individual variables to improve +performance. Tests using gcc on a SPARC disproved this; in the first case, it +made performance worse. + +Arguments: + eptr pointer in subject + ecode position in code + offset_top current top pointer + md pointer to "static" info for the match + ims current /i, /m, and /s options + eptrb pointer to chain of blocks containing eptr at start of + brackets - for testing for empty matches + flags can contain + match_condassert - this is an assertion condition + match_isgroup - this is the start of a bracketed group + +Returns: MATCH_MATCH if matched ) these values are >= 0 + MATCH_NOMATCH if failed to match ) + a negative PCRE_ERROR_xxx value if aborted by an error condition + (e.g. stopped by recursion limit) +*/ + +static int +match(REGISTER const uschar *eptr, REGISTER const uschar *ecode, + int offset_top, match_data *md, unsigned long int ims, eptrblock *eptrb, + int flags) +{ +/* These variables do not need to be preserved over recursion in this function, +so they can be ordinary variables in all cases. Mark them with "register" +because they are used a lot in loops. */ + +register int rrc; /* Returns from recursive calls */ +register int i; /* Used for loops not involving calls to RMATCH() */ +register int c; /* Character values not kept over RMATCH() calls */ +register BOOL utf8; /* Local copy of UTF-8 flag for speed */ + +/* When recursion is not being used, all "local" variables that have to be +preserved over calls to RMATCH() are part of a "frame" which is obtained from +heap storage. Set up the top-level frame here; others are obtained from the +heap whenever RMATCH() does a "recursion". See the macro definitions above. */ + +#ifdef NO_RECURSE +heapframe *frame = (pcre_stack_malloc)(sizeof(heapframe)); +frame->Xprevframe = NULL; /* Marks the top level */ + +/* Copy in the original argument variables */ + +frame->Xeptr = eptr; +frame->Xecode = ecode; +frame->Xoffset_top = offset_top; +frame->Xims = ims; +frame->Xeptrb = eptrb; +frame->Xflags = flags; + +/* This is where control jumps back to to effect "recursion" */ + +HEAP_RECURSE: + +/* Macros make the argument variables come from the current frame */ + +#define eptr frame->Xeptr +#define ecode frame->Xecode +#define offset_top frame->Xoffset_top +#define ims frame->Xims +#define eptrb frame->Xeptrb +#define flags frame->Xflags + +/* Ditto for the local variables */ + +#ifdef SUPPORT_UTF8 +#define charptr frame->Xcharptr +#endif +#define callpat frame->Xcallpat +#define data frame->Xdata +#define next frame->Xnext +#define pp frame->Xpp +#define prev frame->Xprev +#define saved_eptr frame->Xsaved_eptr + +#define new_recursive frame->Xnew_recursive + +#define cur_is_word frame->Xcur_is_word +#define condition frame->Xcondition +#define minimize frame->Xminimize +#define prev_is_word frame->Xprev_is_word + +#define original_ims frame->Xoriginal_ims + +#ifdef SUPPORT_UCP +#define prop_type frame->Xprop_type +#define prop_fail_result frame->Xprop_fail_result +#define prop_category frame->Xprop_category +#define prop_chartype frame->Xprop_chartype +#define prop_othercase frame->Xprop_othercase +#define prop_test_against frame->Xprop_test_against +#define prop_test_variable frame->Xprop_test_variable +#endif + +#define ctype frame->Xctype +#define fc frame->Xfc +#define fi frame->Xfi +#define length frame->Xlength +#define max frame->Xmax +#define min frame->Xmin +#define number frame->Xnumber +#define offset frame->Xoffset +#define op frame->Xop +#define save_capture_last frame->Xsave_capture_last +#define save_offset1 frame->Xsave_offset1 +#define save_offset2 frame->Xsave_offset2 +#define save_offset3 frame->Xsave_offset3 +#define stacksave frame->Xstacksave + +#define newptrb frame->Xnewptrb + +/* When recursion is being used, local variables are allocated on the stack and +get preserved during recursion in the normal way. In this environment, fi and +i, and fc and c, can be the same variables. */ + +#else +#define fi i +#define fc c + + +#ifdef SUPPORT_UTF8 /* Many of these variables are used ony */ +const uschar *charptr; /* small blocks of the code. My normal */ +#endif /* style of coding would have declared */ +const uschar *callpat; /* them within each of those blocks. */ +const uschar *data; /* However, in order to accommodate the */ +const uschar *next; /* version of this code that uses an */ +const uschar *pp; /* external "stack" implemented on the */ +const uschar *prev; /* heap, it is easier to declare them */ +const uschar *saved_eptr; /* all here, so the declarations can */ + /* be cut out in a block. The only */ +recursion_info new_recursive; /* declarations within blocks below are */ + /* for variables that do not have to */ +BOOL cur_is_word; /* be preserved over a recursive call */ +BOOL condition; /* to RMATCH(). */ +BOOL minimize; +BOOL prev_is_word; + +unsigned long int original_ims; + +#ifdef SUPPORT_UCP +int prop_type; +int prop_fail_result; +int prop_category; +int prop_chartype; +int prop_othercase; +int prop_test_against; +int *prop_test_variable; +#endif + +int ctype; +int length; +int max; +int min; +int number; +int offset; +int op; +int save_capture_last; +int save_offset1, save_offset2, save_offset3; +int stacksave[REC_STACK_SAVE_MAX]; + +eptrblock newptrb; +#endif + +/* These statements are here to stop the compiler complaining about unitialized +variables. */ + +#ifdef SUPPORT_UCP +prop_fail_result = 0; +prop_test_against = 0; +prop_test_variable = NULL; +#endif + +/* OK, now we can get on with the real code of the function. Recursion is +specified by the macros RMATCH and RRETURN. When NO_RECURSE is *not* defined, +these just turn into a recursive call to match() and a "return", respectively. +However, RMATCH isn't like a function call because it's quite a complicated +macro. It has to be used in one particular way. This shouldn't, however, impact +performance when true recursion is being used. */ + +if (md->match_call_count++ >= md->match_limit) RRETURN(PCRE_ERROR_MATCHLIMIT); + +original_ims = ims; /* Save for resetting on ')' */ +utf8 = md->utf8; /* Local copy of the flag */ + +/* At the start of a bracketed group, add the current subject pointer to the +stack of such pointers, to be re-instated at the end of the group when we hit +the closing ket. When match() is called in other circumstances, we don't add to +this stack. */ + +if ((flags & match_isgroup) != 0) + { + newptrb.epb_prev = eptrb; + newptrb.epb_saved_eptr = eptr; + eptrb = &newptrb; + } + +/* Now start processing the operations. */ + +for (;;) + { + op = *ecode; + minimize = FALSE; + + /* For partial matching, remember if we ever hit the end of the subject after + matching at least one subject character. */ + + if (md->partial && + eptr >= md->end_subject && + eptr > md->start_match) + md->hitend = TRUE; + + /* Opening capturing bracket. If there is space in the offset vector, save + the current subject position in the working slot at the top of the vector. We + mustn't change the current values of the data slot, because they may be set + from a previous iteration of this group, and be referred to by a reference + inside the group. + + If the bracket fails to match, we need to restore this value and also the + values of the final offsets, in case they were set by a previous iteration of + the same bracket. + + If there isn't enough space in the offset vector, treat this as if it were a + non-capturing bracket. Don't worry about setting the flag for the error case + here; that is handled in the code for KET. */ + + if (op > OP_BRA) + { + number = op - OP_BRA; + + /* For extended extraction brackets (large number), we have to fish out the + number from a dummy opcode at the start. */ + + if (number > EXTRACT_BASIC_MAX) + number = GET2(ecode, 2+LINK_SIZE); + offset = number << 1; + +#ifdef DEBUG + printf("start bracket %d subject=", number); + pchars(eptr, 16, TRUE, md); + printf("\n"); +#endif + + if (offset < md->offset_max) + { + save_offset1 = md->offset_vector[offset]; + save_offset2 = md->offset_vector[offset+1]; + save_offset3 = md->offset_vector[md->offset_end - number]; + save_capture_last = md->capture_last; + + DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3)); + md->offset_vector[md->offset_end - number] = eptr - md->start_subject; + + do + { + RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, + match_isgroup); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + md->capture_last = save_capture_last; + ecode += GET(ecode, 1); + } + while (*ecode == OP_ALT); + + DPRINTF(("bracket %d failed\n", number)); + + md->offset_vector[offset] = save_offset1; + md->offset_vector[offset+1] = save_offset2; + md->offset_vector[md->offset_end - number] = save_offset3; + + RRETURN(MATCH_NOMATCH); + } + + /* Insufficient room for saving captured contents */ + + else op = OP_BRA; + } + + /* Other types of node can be handled by a switch */ + + switch(op) + { + case OP_BRA: /* Non-capturing bracket: optimized */ + DPRINTF(("start bracket 0\n")); + do + { + RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, + match_isgroup); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + ecode += GET(ecode, 1); + } + while (*ecode == OP_ALT); + DPRINTF(("bracket 0 failed\n")); + RRETURN(MATCH_NOMATCH); + + /* Conditional group: compilation checked that there are no more than + two branches. If the condition is false, skipping the first branch takes us + past the end if there is only one branch, but that's OK because that is + exactly what going to the ket would do. */ + + case OP_COND: + if (ecode[LINK_SIZE+1] == OP_CREF) /* Condition extract or recurse test */ + { + offset = GET2(ecode, LINK_SIZE+2) << 1; /* Doubled ref number */ + condition = (offset == CREF_RECURSE * 2)? + (md->recursive != NULL) : + (offset < offset_top && md->offset_vector[offset] >= 0); + RMATCH(rrc, eptr, ecode + (condition? + (LINK_SIZE + 4) : (LINK_SIZE + 1 + GET(ecode, 1))), + offset_top, md, ims, eptrb, match_isgroup); + RRETURN(rrc); + } + + /* The condition is an assertion. Call match() to evaluate it - setting + the final argument TRUE causes it to stop at the end of an assertion. */ + + else + { + RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, + match_condassert | match_isgroup); + if (rrc == MATCH_MATCH) + { + ecode += 1 + LINK_SIZE + GET(ecode, LINK_SIZE+2); + while (*ecode == OP_ALT) ecode += GET(ecode, 1); + } + else if (rrc != MATCH_NOMATCH) + { + RRETURN(rrc); /* Need braces because of following else */ + } + else ecode += GET(ecode, 1); + RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, + match_isgroup); + RRETURN(rrc); + } + /* Control never reaches here */ + + /* Skip over conditional reference or large extraction number data if + encountered. */ + + case OP_CREF: + case OP_BRANUMBER: + ecode += 3; + break; + + /* End of the pattern. If we are in a recursion, we should restore the + offsets appropriately and continue from after the call. */ + + case OP_END: + if (md->recursive != NULL && md->recursive->group_num == 0) + { + recursion_info *rec = md->recursive; + DPRINTF(("Hit the end in a (?0) recursion\n")); + md->recursive = rec->prevrec; + memmove(md->offset_vector, rec->offset_save, + rec->saved_max * sizeof(int)); + md->start_match = rec->save_start; + ims = original_ims; + ecode = rec->after_call; + break; + } + + /* Otherwise, if PCRE_NOTEMPTY is set, fail if we have matched an empty + string - backtracking will then try other alternatives, if any. */ + + if (md->notempty && eptr == md->start_match) RRETURN(MATCH_NOMATCH); + md->end_match_ptr = eptr; /* Record where we ended */ + md->end_offset_top = offset_top; /* and how many extracts were taken */ + RRETURN(MATCH_MATCH); + + /* Change option settings */ + + case OP_OPT: + ims = ecode[1]; + ecode += 2; + DPRINTF(("ims set to %02lx\n", ims)); + break; + + /* Assertion brackets. Check the alternative branches in turn - the + matching won't pass the KET for an assertion. If any one branch matches, + the assertion is true. Lookbehind assertions have an OP_REVERSE item at the + start of each branch to move the current point backwards, so the code at + this level is identical to the lookahead case. */ + + case OP_ASSERT: + case OP_ASSERTBACK: + do + { + RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, + match_isgroup); + if (rrc == MATCH_MATCH) break; + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + ecode += GET(ecode, 1); + } + while (*ecode == OP_ALT); + if (*ecode == OP_KET) RRETURN(MATCH_NOMATCH); + + /* If checking an assertion for a condition, return MATCH_MATCH. */ + + if ((flags & match_condassert) != 0) RRETURN(MATCH_MATCH); + + /* Continue from after the assertion, updating the offsets high water + mark, since extracts may have been taken during the assertion. */ + + do ecode += GET(ecode,1); while (*ecode == OP_ALT); + ecode += 1 + LINK_SIZE; + offset_top = md->end_offset_top; + continue; + + /* Negative assertion: all branches must fail to match */ + + case OP_ASSERT_NOT: + case OP_ASSERTBACK_NOT: + do + { + RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, + match_isgroup); + if (rrc == MATCH_MATCH) RRETURN(MATCH_NOMATCH); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + ecode += GET(ecode,1); + } + while (*ecode == OP_ALT); + + if ((flags & match_condassert) != 0) RRETURN(MATCH_MATCH); + + ecode += 1 + LINK_SIZE; + continue; + + /* Move the subject pointer back. This occurs only at the start of + each branch of a lookbehind assertion. If we are too close to the start to + move back, this match function fails. When working with UTF-8 we move + back a number of characters, not bytes. */ + + case OP_REVERSE: +#ifdef SUPPORT_UTF8 + if (utf8) + { + c = GET(ecode,1); + for (i = 0; i < c; i++) + { + eptr--; + if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH); + BACKCHAR(eptr) + } + } + else +#endif + + /* No UTF-8 support, or not in UTF-8 mode: count is byte count */ + + { + eptr -= GET(ecode,1); + if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH); + } + + /* Skip to next op code */ + + ecode += 1 + LINK_SIZE; + break; + + /* The callout item calls an external function, if one is provided, passing + details of the match so far. This is mainly for debugging, though the + function is able to force a failure. */ + + case OP_CALLOUT: + if (pcre_callout != NULL) + { + pcre_callout_block cb; + cb.version = 1; /* Version 1 of the callout block */ + cb.callout_number = ecode[1]; + cb.offset_vector = md->offset_vector; + cb.subject = (const char *)md->start_subject; + cb.subject_length = md->end_subject - md->start_subject; + cb.start_match = md->start_match - md->start_subject; + cb.current_position = eptr - md->start_subject; + cb.pattern_position = GET(ecode, 2); + cb.next_item_length = GET(ecode, 2 + LINK_SIZE); + cb.capture_top = offset_top/2; + cb.capture_last = md->capture_last; + cb.callout_data = md->callout_data; + if ((rrc = (*pcre_callout)(&cb)) > 0) RRETURN(MATCH_NOMATCH); + if (rrc < 0) RRETURN(rrc); + } + ecode += 2 + 2*LINK_SIZE; + break; + + /* Recursion either matches the current regex, or some subexpression. The + offset data is the offset to the starting bracket from the start of the + whole pattern. (This is so that it works from duplicated subpatterns.) + + If there are any capturing brackets started but not finished, we have to + save their starting points and reinstate them after the recursion. However, + we don't know how many such there are (offset_top records the completed + total) so we just have to save all the potential data. There may be up to + 65535 such values, which is too large to put on the stack, but using malloc + for small numbers seems expensive. As a compromise, the stack is used when + there are no more than REC_STACK_SAVE_MAX values to store; otherwise malloc + is used. A problem is what to do if the malloc fails ... there is no way of + returning to the top level with an error. Save the top REC_STACK_SAVE_MAX + values on the stack, and accept that the rest may be wrong. + + There are also other values that have to be saved. We use a chained + sequence of blocks that actually live on the stack. Thanks to Robin Houston + for the original version of this logic. */ + + case OP_RECURSE: + { + callpat = md->start_code + GET(ecode, 1); + new_recursive.group_num = *callpat - OP_BRA; + + /* For extended extraction brackets (large number), we have to fish out + the number from a dummy opcode at the start. */ + + if (new_recursive.group_num > EXTRACT_BASIC_MAX) + new_recursive.group_num = GET2(callpat, 2+LINK_SIZE); + + /* Add to "recursing stack" */ + + new_recursive.prevrec = md->recursive; + md->recursive = &new_recursive; + + /* Find where to continue from afterwards */ + + ecode += 1 + LINK_SIZE; + new_recursive.after_call = ecode; + + /* Now save the offset data. */ + + new_recursive.saved_max = md->offset_end; + if (new_recursive.saved_max <= REC_STACK_SAVE_MAX) + new_recursive.offset_save = stacksave; + else + { + new_recursive.offset_save = + (int *)(pcre_malloc)(new_recursive.saved_max * sizeof(int)); + if (new_recursive.offset_save == NULL) RRETURN(PCRE_ERROR_NOMEMORY); + } + + memcpy(new_recursive.offset_save, md->offset_vector, + new_recursive.saved_max * sizeof(int)); + new_recursive.save_start = md->start_match; + md->start_match = eptr; + + /* OK, now we can do the recursion. For each top-level alternative we + restore the offset and recursion data. */ + + DPRINTF(("Recursing into group %d\n", new_recursive.group_num)); + do + { + RMATCH(rrc, eptr, callpat + 1 + LINK_SIZE, offset_top, md, ims, + eptrb, match_isgroup); + if (rrc == MATCH_MATCH) + { + md->recursive = new_recursive.prevrec; + if (new_recursive.offset_save != stacksave) + (pcre_free)(new_recursive.offset_save); + RRETURN(MATCH_MATCH); + } + else if (rrc != MATCH_NOMATCH) RRETURN(rrc); + + md->recursive = &new_recursive; + memcpy(md->offset_vector, new_recursive.offset_save, + new_recursive.saved_max * sizeof(int)); + callpat += GET(callpat, 1); + } + while (*callpat == OP_ALT); + + DPRINTF(("Recursion didn't match\n")); + md->recursive = new_recursive.prevrec; + if (new_recursive.offset_save != stacksave) + (pcre_free)(new_recursive.offset_save); + RRETURN(MATCH_NOMATCH); + } + /* Control never reaches here */ + + /* "Once" brackets are like assertion brackets except that after a match, + the point in the subject string is not moved back. Thus there can never be + a move back into the brackets. Friedl calls these "atomic" subpatterns. + Check the alternative branches in turn - the matching won't pass the KET + for this kind of subpattern. If any one branch matches, we carry on as at + the end of a normal bracket, leaving the subject pointer. */ + + case OP_ONCE: + { + prev = ecode; + saved_eptr = eptr; + + do + { + RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, + eptrb, match_isgroup); + if (rrc == MATCH_MATCH) break; + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + ecode += GET(ecode,1); + } + while (*ecode == OP_ALT); + + /* If hit the end of the group (which could be repeated), fail */ + + if (*ecode != OP_ONCE && *ecode != OP_ALT) RRETURN(MATCH_NOMATCH); + + /* Continue as from after the assertion, updating the offsets high water + mark, since extracts may have been taken. */ + + do ecode += GET(ecode,1); while (*ecode == OP_ALT); + + offset_top = md->end_offset_top; + eptr = md->end_match_ptr; + + /* For a non-repeating ket, just continue at this level. This also + happens for a repeating ket if no characters were matched in the group. + This is the forcible breaking of infinite loops as implemented in Perl + 5.005. If there is an options reset, it will get obeyed in the normal + course of events. */ + + if (*ecode == OP_KET || eptr == saved_eptr) + { + ecode += 1+LINK_SIZE; + break; + } + + /* The repeating kets try the rest of the pattern or restart from the + preceding bracket, in the appropriate order. We need to reset any options + that changed within the bracket before re-running it, so check the next + opcode. */ + + if (ecode[1+LINK_SIZE] == OP_OPT) + { + ims = (ims & ~PCRE_IMS) | ecode[4]; + DPRINTF(("ims set to %02lx at group repeat\n", ims)); + } + + if (*ecode == OP_KETRMIN) + { + RMATCH(rrc, eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + RMATCH(rrc, eptr, prev, offset_top, md, ims, eptrb, match_isgroup); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + } + else /* OP_KETRMAX */ + { + RMATCH(rrc, eptr, prev, offset_top, md, ims, eptrb, match_isgroup); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + RMATCH(rrc, eptr, ecode + 1+LINK_SIZE, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + } + } + RRETURN(MATCH_NOMATCH); + + /* An alternation is the end of a branch; scan along to find the end of the + bracketed group and go to there. */ + + case OP_ALT: + do ecode += GET(ecode,1); while (*ecode == OP_ALT); + break; + + /* BRAZERO and BRAMINZERO occur just before a bracket group, indicating + that it may occur zero times. It may repeat infinitely, or not at all - + i.e. it could be ()* or ()? in the pattern. Brackets with fixed upper + repeat limits are compiled as a number of copies, with the optional ones + preceded by BRAZERO or BRAMINZERO. */ + + case OP_BRAZERO: + { + next = ecode+1; + RMATCH(rrc, eptr, next, offset_top, md, ims, eptrb, match_isgroup); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + do next += GET(next,1); while (*next == OP_ALT); + ecode = next + 1+LINK_SIZE; + } + break; + + case OP_BRAMINZERO: + { + next = ecode+1; + do next += GET(next,1); while (*next == OP_ALT); + RMATCH(rrc, eptr, next + 1+LINK_SIZE, offset_top, md, ims, eptrb, + match_isgroup); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + ecode++; + } + break; + + /* End of a group, repeated or non-repeating. If we are at the end of + an assertion "group", stop matching and return MATCH_MATCH, but record the + current high water mark for use by positive assertions. Do this also + for the "once" (not-backup up) groups. */ + + case OP_KET: + case OP_KETRMIN: + case OP_KETRMAX: + { + prev = ecode - GET(ecode, 1); + saved_eptr = eptrb->epb_saved_eptr; + + /* Back up the stack of bracket start pointers. */ + + eptrb = eptrb->epb_prev; + + if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT || + *prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT || + *prev == OP_ONCE) + { + md->end_match_ptr = eptr; /* For ONCE */ + md->end_offset_top = offset_top; + RRETURN(MATCH_MATCH); + } + + /* In all other cases except a conditional group we have to check the + group number back at the start and if necessary complete handling an + extraction by setting the offsets and bumping the high water mark. */ + + if (*prev != OP_COND) + { + number = *prev - OP_BRA; + + /* For extended extraction brackets (large number), we have to fish out + the number from a dummy opcode at the start. */ + + if (number > EXTRACT_BASIC_MAX) number = GET2(prev, 2+LINK_SIZE); + offset = number << 1; + +#ifdef DEBUG + printf("end bracket %d", number); + printf("\n"); +#endif + + /* Test for a numbered group. This includes groups called as a result + of recursion. Note that whole-pattern recursion is coded as a recurse + into group 0, so it won't be picked up here. Instead, we catch it when + the OP_END is reached. */ + + if (number > 0) + { + md->capture_last = number; + if (offset >= md->offset_max) md->offset_overflow = TRUE; else + { + md->offset_vector[offset] = + md->offset_vector[md->offset_end - number]; + md->offset_vector[offset+1] = eptr - md->start_subject; + if (offset_top <= offset) offset_top = offset + 2; + } + + /* Handle a recursively called group. Restore the offsets + appropriately and continue from after the call. */ + + if (md->recursive != NULL && md->recursive->group_num == number) + { + recursion_info *rec = md->recursive; + DPRINTF(("Recursion (%d) succeeded - continuing\n", number)); + md->recursive = rec->prevrec; + md->start_match = rec->save_start; + memcpy(md->offset_vector, rec->offset_save, + rec->saved_max * sizeof(int)); + ecode = rec->after_call; + ims = original_ims; + break; + } + } + } + + /* Reset the value of the ims flags, in case they got changed during + the group. */ + + ims = original_ims; + DPRINTF(("ims reset to %02lx\n", ims)); + + /* For a non-repeating ket, just continue at this level. This also + happens for a repeating ket if no characters were matched in the group. + This is the forcible breaking of infinite loops as implemented in Perl + 5.005. If there is an options reset, it will get obeyed in the normal + course of events. */ + + if (*ecode == OP_KET || eptr == saved_eptr) + { + ecode += 1 + LINK_SIZE; + break; + } + + /* The repeating kets try the rest of the pattern or restart from the + preceding bracket, in the appropriate order. */ + + if (*ecode == OP_KETRMIN) + { + RMATCH(rrc, eptr, ecode + 1+LINK_SIZE, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + RMATCH(rrc, eptr, prev, offset_top, md, ims, eptrb, match_isgroup); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + } + else /* OP_KETRMAX */ + { + RMATCH(rrc, eptr, prev, offset_top, md, ims, eptrb, match_isgroup); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + RMATCH(rrc, eptr, ecode + 1+LINK_SIZE, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + } + } + + RRETURN(MATCH_NOMATCH); + + /* Start of subject unless notbol, or after internal newline if multiline */ + + case OP_CIRC: + if (md->notbol && eptr == md->start_subject) RRETURN(MATCH_NOMATCH); + if ((ims & PCRE_MULTILINE) != 0) + { + if (eptr != md->start_subject && eptr[-1] != NEWLINE) + RRETURN(MATCH_NOMATCH); + ecode++; + break; + } + /* ... else fall through */ + + /* Start of subject assertion */ + + case OP_SOD: + if (eptr != md->start_subject) RRETURN(MATCH_NOMATCH); + ecode++; + break; + + /* Start of match assertion */ + + case OP_SOM: + if (eptr != md->start_subject + md->start_offset) RRETURN(MATCH_NOMATCH); + ecode++; + break; + + /* Assert before internal newline if multiline, or before a terminating + newline unless endonly is set, else end of subject unless noteol is set. */ + + case OP_DOLL: + if ((ims & PCRE_MULTILINE) != 0) + { + if (eptr < md->end_subject) + { if (*eptr != NEWLINE) RRETURN(MATCH_NOMATCH); } + else + { if (md->noteol) RRETURN(MATCH_NOMATCH); } + ecode++; + break; + } + else + { + if (md->noteol) RRETURN(MATCH_NOMATCH); + if (!md->endonly) + { + if (eptr < md->end_subject - 1 || + (eptr == md->end_subject - 1 && *eptr != NEWLINE)) + RRETURN(MATCH_NOMATCH); + ecode++; + break; + } + } + /* ... else fall through */ + + /* End of subject assertion (\z) */ + + case OP_EOD: + if (eptr < md->end_subject) RRETURN(MATCH_NOMATCH); + ecode++; + break; + + /* End of subject or ending \n assertion (\Z) */ + + case OP_EODN: + if (eptr < md->end_subject - 1 || + (eptr == md->end_subject - 1 && *eptr != NEWLINE)) RRETURN(MATCH_NOMATCH); + ecode++; + break; + + /* Word boundary assertions */ + + case OP_NOT_WORD_BOUNDARY: + case OP_WORD_BOUNDARY: + { + + /* Find out if the previous and current characters are "word" characters. + It takes a bit more work in UTF-8 mode. Characters > 255 are assumed to + be "non-word" characters. */ + +#ifdef SUPPORT_UTF8 + if (utf8) + { + if (eptr == md->start_subject) prev_is_word = FALSE; else + { + const uschar *lastptr = eptr - 1; + while((*lastptr & 0xc0) == 0x80) lastptr--; + GETCHAR(c, lastptr); + prev_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0; + } + if (eptr >= md->end_subject) cur_is_word = FALSE; else + { + GETCHAR(c, eptr); + cur_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0; + } + } + else +#endif + + /* More streamlined when not in UTF-8 mode */ + + { + prev_is_word = (eptr != md->start_subject) && + ((md->ctypes[eptr[-1]] & ctype_word) != 0); + cur_is_word = (eptr < md->end_subject) && + ((md->ctypes[*eptr] & ctype_word) != 0); + } + + /* Now see if the situation is what we want */ + + if ((*ecode++ == OP_WORD_BOUNDARY)? + cur_is_word == prev_is_word : cur_is_word != prev_is_word) + RRETURN(MATCH_NOMATCH); + } + break; + + /* Match a single character type; inline for speed */ + + case OP_ANY: + if ((ims & PCRE_DOTALL) == 0 && eptr < md->end_subject && *eptr == NEWLINE) + RRETURN(MATCH_NOMATCH); + if (eptr++ >= md->end_subject) RRETURN(MATCH_NOMATCH); +#ifdef SUPPORT_UTF8 + if (utf8) + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; +#endif + ecode++; + break; + + /* Match a single byte, even in UTF-8 mode. This opcode really does match + any byte, even newline, independent of the setting of PCRE_DOTALL. */ + + case OP_ANYBYTE: + if (eptr++ >= md->end_subject) RRETURN(MATCH_NOMATCH); + ecode++; + break; + + case OP_NOT_DIGIT: + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(c, eptr); + if ( +#ifdef SUPPORT_UTF8 + c < 256 && +#endif + (md->ctypes[c] & ctype_digit) != 0 + ) + RRETURN(MATCH_NOMATCH); + ecode++; + break; + + case OP_DIGIT: + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(c, eptr); + if ( +#ifdef SUPPORT_UTF8 + c >= 256 || +#endif + (md->ctypes[c] & ctype_digit) == 0 + ) + RRETURN(MATCH_NOMATCH); + ecode++; + break; + + case OP_NOT_WHITESPACE: + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(c, eptr); + if ( +#ifdef SUPPORT_UTF8 + c < 256 && +#endif + (md->ctypes[c] & ctype_space) != 0 + ) + RRETURN(MATCH_NOMATCH); + ecode++; + break; + + case OP_WHITESPACE: + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(c, eptr); + if ( +#ifdef SUPPORT_UTF8 + c >= 256 || +#endif + (md->ctypes[c] & ctype_space) == 0 + ) + RRETURN(MATCH_NOMATCH); + ecode++; + break; + + case OP_NOT_WORDCHAR: + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(c, eptr); + if ( +#ifdef SUPPORT_UTF8 + c < 256 && +#endif + (md->ctypes[c] & ctype_word) != 0 + ) + RRETURN(MATCH_NOMATCH); + ecode++; + break; + + case OP_WORDCHAR: + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(c, eptr); + if ( +#ifdef SUPPORT_UTF8 + c >= 256 || +#endif + (md->ctypes[c] & ctype_word) == 0 + ) + RRETURN(MATCH_NOMATCH); + ecode++; + break; + +#ifdef SUPPORT_UCP + /* Check the next character by Unicode property. We will get here only + if the support is in the binary; otherwise a compile-time error occurs. */ + + case OP_PROP: + case OP_NOTPROP: + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(c, eptr); + { + int chartype, rqdtype; + int othercase; + int category = ucp_findchar(c, &chartype, &othercase); + + rqdtype = *(++ecode); + ecode++; + + if (rqdtype >= 128) + { + if ((rqdtype - 128 != category) == (op == OP_PROP)) + RRETURN(MATCH_NOMATCH); + } + else + { + if ((rqdtype != chartype) == (op == OP_PROP)) + RRETURN(MATCH_NOMATCH); + } + } + break; + + /* Match an extended Unicode sequence. We will get here only if the support + is in the binary; otherwise a compile-time error occurs. */ + + case OP_EXTUNI: + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(c, eptr); + { + int chartype; + int othercase; + int category = ucp_findchar(c, &chartype, &othercase); + if (category == ucp_M) RRETURN(MATCH_NOMATCH); + while (eptr < md->end_subject) + { + int len = 1; + if (!utf8) c = *eptr; else + { + GETCHARLEN(c, eptr, len); + } + category = ucp_findchar(c, &chartype, &othercase); + if (category != ucp_M) break; + eptr += len; + } + } + ecode++; + break; +#endif + + + /* Match a back reference, possibly repeatedly. Look past the end of the + item to see if there is repeat information following. The code is similar + to that for character classes, but repeated for efficiency. Then obey + similar code to character type repeats - written out again for speed. + However, if the referenced string is the empty string, always treat + it as matched, any number of times (otherwise there could be infinite + loops). */ + + case OP_REF: + { + offset = GET2(ecode, 1) << 1; /* Doubled ref number */ + ecode += 3; /* Advance past item */ + + /* If the reference is unset, set the length to be longer than the amount + of subject left; this ensures that every attempt at a match fails. We + can't just fail here, because of the possibility of quantifiers with zero + minima. */ + + length = (offset >= offset_top || md->offset_vector[offset] < 0)? + md->end_subject - eptr + 1 : + md->offset_vector[offset+1] - md->offset_vector[offset]; + + /* Set up for repetition, or handle the non-repeated case */ + + switch (*ecode) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRPLUS: + case OP_CRMINPLUS: + case OP_CRQUERY: + case OP_CRMINQUERY: + c = *ecode++ - OP_CRSTAR; + minimize = (c & 1) != 0; + min = rep_min[c]; /* Pick up values from tables; */ + max = rep_max[c]; /* zero for max => infinity */ + if (max == 0) max = INT_MAX; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + minimize = (*ecode == OP_CRMINRANGE); + min = GET2(ecode, 1); + max = GET2(ecode, 3); + if (max == 0) max = INT_MAX; + ecode += 5; + break; + + default: /* No repeat follows */ + if (!match_ref(offset, eptr, length, md, ims)) RRETURN(MATCH_NOMATCH); + eptr += length; + continue; /* With the main loop */ + } + + /* If the length of the reference is zero, just continue with the + main loop. */ + + if (length == 0) continue; + + /* First, ensure the minimum number of matches are present. We get back + the length of the reference string explicitly rather than passing the + address of eptr, so that eptr can be a register variable. */ + + for (i = 1; i <= min; i++) + { + if (!match_ref(offset, eptr, length, md, ims)) RRETURN(MATCH_NOMATCH); + eptr += length; + } + + /* If min = max, continue at the same level without recursion. + They are not both allowed to be zero. */ + + if (min == max) continue; + + /* If minimizing, keep trying and advancing the pointer */ + + if (minimize) + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || !match_ref(offset, eptr, length, md, ims)) + RRETURN(MATCH_NOMATCH); + eptr += length; + } + /* Control never gets here */ + } + + /* If maximizing, find the longest string and work backwards */ + + else + { + pp = eptr; + for (i = min; i < max; i++) + { + if (!match_ref(offset, eptr, length, md, ims)) break; + eptr += length; + } + while (eptr >= pp) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + eptr -= length; + } + RRETURN(MATCH_NOMATCH); + } + } + /* Control never gets here */ + + + + /* Match a bit-mapped character class, possibly repeatedly. This op code is + used when all the characters in the class have values in the range 0-255, + and either the matching is caseful, or the characters are in the range + 0-127 when UTF-8 processing is enabled. The only difference between + OP_CLASS and OP_NCLASS occurs when a data character outside the range is + encountered. + + First, look past the end of the item to see if there is repeat information + following. Then obey similar code to character type repeats - written out + again for speed. */ + + case OP_NCLASS: + case OP_CLASS: + { + data = ecode + 1; /* Save for matching */ + ecode += 33; /* Advance past the item */ + + switch (*ecode) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRPLUS: + case OP_CRMINPLUS: + case OP_CRQUERY: + case OP_CRMINQUERY: + c = *ecode++ - OP_CRSTAR; + minimize = (c & 1) != 0; + min = rep_min[c]; /* Pick up values from tables; */ + max = rep_max[c]; /* zero for max => infinity */ + if (max == 0) max = INT_MAX; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + minimize = (*ecode == OP_CRMINRANGE); + min = GET2(ecode, 1); + max = GET2(ecode, 3); + if (max == 0) max = INT_MAX; + ecode += 5; + break; + + default: /* No repeat follows */ + min = max = 1; + break; + } + + /* First, ensure the minimum number of matches are present. */ + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (utf8) + { + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINC(c, eptr); + if (c > 255) + { + if (op == OP_CLASS) RRETURN(MATCH_NOMATCH); + } + else + { + if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); + } + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + c = *eptr++; + if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); + } + } + + /* If max == min we can continue with the main loop without the + need to recurse. */ + + if (min == max) continue; + + /* If minimizing, keep testing the rest of the expression and advancing + the pointer while it matches the class. */ + + if (minimize) + { +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (utf8) + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINC(c, eptr); + if (c > 255) + { + if (op == OP_CLASS) RRETURN(MATCH_NOMATCH); + } + else + { + if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); + } + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + c = *eptr++; + if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); + } + } + /* Control never gets here */ + } + + /* If maximizing, find the longest possible run, then work backwards. */ + + else + { + pp = eptr; + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (utf8) + { + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + if (c > 255) + { + if (op == OP_CLASS) break; + } + else + { + if ((data[c/8] & (1 << (c&7))) == 0) break; + } + eptr += len; + } + for (;;) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr); + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) break; + c = *eptr; + if ((data[c/8] & (1 << (c&7))) == 0) break; + eptr++; + } + while (eptr >= pp) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + eptr--; + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + } + } + + RRETURN(MATCH_NOMATCH); + } + } + /* Control never gets here */ + + + /* Match an extended character class. This opcode is encountered only + in UTF-8 mode, because that's the only time it is compiled. */ + +#ifdef SUPPORT_UTF8 + case OP_XCLASS: + { + data = ecode + 1 + LINK_SIZE; /* Save for matching */ + ecode += GET(ecode, 1); /* Advance past the item */ + + switch (*ecode) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRPLUS: + case OP_CRMINPLUS: + case OP_CRQUERY: + case OP_CRMINQUERY: + c = *ecode++ - OP_CRSTAR; + minimize = (c & 1) != 0; + min = rep_min[c]; /* Pick up values from tables; */ + max = rep_max[c]; /* zero for max => infinity */ + if (max == 0) max = INT_MAX; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + minimize = (*ecode == OP_CRMINRANGE); + min = GET2(ecode, 1); + max = GET2(ecode, 3); + if (max == 0) max = INT_MAX; + ecode += 5; + break; + + default: /* No repeat follows */ + min = max = 1; + break; + } + + /* First, ensure the minimum number of matches are present. */ + + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINC(c, eptr); + if (!_pcre_xclass(c, data)) RRETURN(MATCH_NOMATCH); + } + + /* If max == min we can continue with the main loop without the + need to recurse. */ + + if (min == max) continue; + + /* If minimizing, keep testing the rest of the expression and advancing + the pointer while it matches the class. */ + + if (minimize) + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINC(c, eptr); + if (!_pcre_xclass(c, data)) RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + } + + /* If maximizing, find the longest possible run, then work backwards. */ + + else + { + pp = eptr; + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + if (!_pcre_xclass(c, data)) break; + eptr += len; + } + for(;;) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr) + } + RRETURN(MATCH_NOMATCH); + } + + /* Control never gets here */ + } +#endif /* End of XCLASS */ + + /* Match a single character, casefully */ + + case OP_CHAR: +#ifdef SUPPORT_UTF8 + if (utf8) + { + length = 1; + ecode++; + GETCHARLEN(fc, ecode, length); + if (length > md->end_subject - eptr) RRETURN(MATCH_NOMATCH); + while (length-- > 0) if (*ecode++ != *eptr++) RRETURN(MATCH_NOMATCH); + } + else +#endif + + /* Non-UTF-8 mode */ + { + if (md->end_subject - eptr < 1) RRETURN(MATCH_NOMATCH); + if (ecode[1] != *eptr++) RRETURN(MATCH_NOMATCH); + ecode += 2; + } + break; + + /* Match a single character, caselessly */ + + case OP_CHARNC: +#ifdef SUPPORT_UTF8 + if (utf8) + { + length = 1; + ecode++; + GETCHARLEN(fc, ecode, length); + + if (length > md->end_subject - eptr) RRETURN(MATCH_NOMATCH); + + /* If the pattern character's value is < 128, we have only one byte, and + can use the fast lookup table. */ + + if (fc < 128) + { + if (md->lcc[*ecode++] != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH); + } + + /* Otherwise we must pick up the subject character */ + + else + { + int dc; + GETCHARINC(dc, eptr); + ecode += length; + + /* If we have Unicode property support, we can use it to test the other + case of the character, if there is one. The result of ucp_findchar() is + < 0 if the char isn't found, and othercase is returned as zero if there + isn't one. */ + + if (fc != dc) + { +#ifdef SUPPORT_UCP + int chartype; + int othercase; + if (ucp_findchar(fc, &chartype, &othercase) < 0 || dc != othercase) +#endif + RRETURN(MATCH_NOMATCH); + } + } + } + else +#endif /* SUPPORT_UTF8 */ + + /* Non-UTF-8 mode */ + { + if (md->end_subject - eptr < 1) RRETURN(MATCH_NOMATCH); + if (md->lcc[ecode[1]] != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH); + ecode += 2; + } + break; + + /* Match a single character repeatedly; different opcodes share code. */ + + case OP_EXACT: + min = max = GET2(ecode, 1); + ecode += 3; + goto REPEATCHAR; + + case OP_UPTO: + case OP_MINUPTO: + min = 0; + max = GET2(ecode, 1); + minimize = *ecode == OP_MINUPTO; + ecode += 3; + goto REPEATCHAR; + + case OP_STAR: + case OP_MINSTAR: + case OP_PLUS: + case OP_MINPLUS: + case OP_QUERY: + case OP_MINQUERY: + c = *ecode++ - OP_STAR; + minimize = (c & 1) != 0; + min = rep_min[c]; /* Pick up values from tables; */ + max = rep_max[c]; /* zero for max => infinity */ + if (max == 0) max = INT_MAX; + + /* Common code for all repeated single-character matches. We can give + up quickly if there are fewer than the minimum number of characters left in + the subject. */ + + REPEATCHAR: +#ifdef SUPPORT_UTF8 + if (utf8) + { + length = 1; + charptr = ecode; + GETCHARLEN(fc, ecode, length); + if (min * length > md->end_subject - eptr) RRETURN(MATCH_NOMATCH); + ecode += length; + + /* Handle multibyte character matching specially here. There is + support for caseless matching if UCP support is present. */ + + if (length > 1) + { + int oclength = 0; + uschar occhars[8]; + +#ifdef SUPPORT_UCP + int othercase; + int chartype; + if ((ims & PCRE_CASELESS) != 0 && + ucp_findchar(fc, &chartype, &othercase) >= 0 && + othercase > 0) + oclength = _pcre_ord2utf8(othercase, occhars); +#endif /* SUPPORT_UCP */ + + for (i = 1; i <= min; i++) + { + if (memcmp(eptr, charptr, length) == 0) eptr += length; + /* Need braces because of following else */ + else if (oclength == 0) { RRETURN(MATCH_NOMATCH); } + else + { + if (memcmp(eptr, occhars, oclength) != 0) RRETURN(MATCH_NOMATCH); + eptr += oclength; + } + } + + if (min == max) continue; + + if (minimize) + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + if (memcmp(eptr, charptr, length) == 0) eptr += length; + /* Need braces because of following else */ + else if (oclength == 0) { RRETURN(MATCH_NOMATCH); } + else + { + if (memcmp(eptr, occhars, oclength) != 0) RRETURN(MATCH_NOMATCH); + eptr += oclength; + } + } + /* Control never gets here */ + } + else + { + pp = eptr; + for (i = min; i < max; i++) + { + if (eptr > md->end_subject - length) break; + if (memcmp(eptr, charptr, length) == 0) eptr += length; + else if (oclength == 0) break; + else + { + if (memcmp(eptr, occhars, oclength) != 0) break; + eptr += oclength; + } + } + while (eptr >= pp) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + eptr -= length; + } + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + } + + /* If the length of a UTF-8 character is 1, we fall through here, and + obey the code as for non-UTF-8 characters below, though in this case the + value of fc will always be < 128. */ + } + else +#endif /* SUPPORT_UTF8 */ + + /* When not in UTF-8 mode, load a single-byte character. */ + { + if (min > md->end_subject - eptr) RRETURN(MATCH_NOMATCH); + fc = *ecode++; + } + + /* The value of fc at this point is always less than 256, though we may or + may not be in UTF-8 mode. The code is duplicated for the caseless and + caseful cases, for speed, since matching characters is likely to be quite + common. First, ensure the minimum number of matches are present. If min = + max, continue at the same level without recursing. Otherwise, if + minimizing, keep trying the rest of the expression and advancing one + matching character if failing, up to the maximum. Alternatively, if + maximizing, find the maximum number of characters and work backwards. */ + + DPRINTF(("matching %c{%d,%d} against subject %.*s\n", fc, min, max, + max, eptr)); + + if ((ims & PCRE_CASELESS) != 0) + { + fc = md->lcc[fc]; + for (i = 1; i <= min; i++) + if (fc != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH); + if (min == max) continue; + if (minimize) + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || eptr >= md->end_subject || + fc != md->lcc[*eptr++]) + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + } + else + { + pp = eptr; + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || fc != md->lcc[*eptr]) break; + eptr++; + } + while (eptr >= pp) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + eptr--; + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + } + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + } + + /* Caseful comparisons (includes all multi-byte characters) */ + + else + { + for (i = 1; i <= min; i++) if (fc != *eptr++) RRETURN(MATCH_NOMATCH); + if (min == max) continue; + if (minimize) + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || eptr >= md->end_subject || fc != *eptr++) + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + } + else + { + pp = eptr; + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || fc != *eptr) break; + eptr++; + } + while (eptr >= pp) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + eptr--; + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + } + RRETURN(MATCH_NOMATCH); + } + } + /* Control never gets here */ + + /* Match a negated single one-byte character. The character we are + checking can be multibyte. */ + + case OP_NOT: + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + ecode++; + GETCHARINCTEST(c, eptr); + if ((ims & PCRE_CASELESS) != 0) + { +#ifdef SUPPORT_UTF8 + if (c < 256) +#endif + c = md->lcc[c]; + if (md->lcc[*ecode++] == c) RRETURN(MATCH_NOMATCH); + } + else + { + if (*ecode++ == c) RRETURN(MATCH_NOMATCH); + } + break; + + /* Match a negated single one-byte character repeatedly. This is almost a + repeat of the code for a repeated single character, but I haven't found a + nice way of commoning these up that doesn't require a test of the + positive/negative option for each character match. Maybe that wouldn't add + very much to the time taken, but character matching *is* what this is all + about... */ + + case OP_NOTEXACT: + min = max = GET2(ecode, 1); + ecode += 3; + goto REPEATNOTCHAR; + + case OP_NOTUPTO: + case OP_NOTMINUPTO: + min = 0; + max = GET2(ecode, 1); + minimize = *ecode == OP_NOTMINUPTO; + ecode += 3; + goto REPEATNOTCHAR; + + case OP_NOTSTAR: + case OP_NOTMINSTAR: + case OP_NOTPLUS: + case OP_NOTMINPLUS: + case OP_NOTQUERY: + case OP_NOTMINQUERY: + c = *ecode++ - OP_NOTSTAR; + minimize = (c & 1) != 0; + min = rep_min[c]; /* Pick up values from tables; */ + max = rep_max[c]; /* zero for max => infinity */ + if (max == 0) max = INT_MAX; + + /* Common code for all repeated single-byte matches. We can give up quickly + if there are fewer than the minimum number of bytes left in the + subject. */ + + REPEATNOTCHAR: + if (min > md->end_subject - eptr) RRETURN(MATCH_NOMATCH); + fc = *ecode++; + + /* The code is duplicated for the caseless and caseful cases, for speed, + since matching characters is likely to be quite common. First, ensure the + minimum number of matches are present. If min = max, continue at the same + level without recursing. Otherwise, if minimizing, keep trying the rest of + the expression and advancing one matching character if failing, up to the + maximum. Alternatively, if maximizing, find the maximum number of + characters and work backwards. */ + + DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", fc, min, max, + max, eptr)); + + if ((ims & PCRE_CASELESS) != 0) + { + fc = md->lcc[fc]; + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (utf8) + { + register int d; + for (i = 1; i <= min; i++) + { + GETCHARINC(d, eptr); + if (d < 256) d = md->lcc[d]; + if (fc == d) RRETURN(MATCH_NOMATCH); + } + } + else +#endif + + /* Not UTF-8 mode */ + { + for (i = 1; i <= min; i++) + if (fc == md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH); + } + + if (min == max) continue; + + if (minimize) + { +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (utf8) + { + register int d; + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + GETCHARINC(d, eptr); + if (d < 256) d = md->lcc[d]; + if (fi >= max || eptr >= md->end_subject || fc == d) + RRETURN(MATCH_NOMATCH); + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || eptr >= md->end_subject || fc == md->lcc[*eptr++]) + RRETURN(MATCH_NOMATCH); + } + } + /* Control never gets here */ + } + + /* Maximize case */ + + else + { + pp = eptr; + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (utf8) + { + register int d; + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(d, eptr, len); + if (d < 256) d = md->lcc[d]; + if (fc == d) break; + eptr += len; + } + for(;;) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr); + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || fc == md->lcc[*eptr]) break; + eptr++; + } + while (eptr >= pp) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + eptr--; + } + } + + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + } + + /* Caseful comparisons */ + + else + { +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (utf8) + { + register int d; + for (i = 1; i <= min; i++) + { + GETCHARINC(d, eptr); + if (fc == d) RRETURN(MATCH_NOMATCH); + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (i = 1; i <= min; i++) + if (fc == *eptr++) RRETURN(MATCH_NOMATCH); + } + + if (min == max) continue; + + if (minimize) + { +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (utf8) + { + register int d; + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + GETCHARINC(d, eptr); + if (fi >= max || eptr >= md->end_subject || fc == d) + RRETURN(MATCH_NOMATCH); + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || eptr >= md->end_subject || fc == *eptr++) + RRETURN(MATCH_NOMATCH); + } + } + /* Control never gets here */ + } + + /* Maximize case */ + + else + { + pp = eptr; + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (utf8) + { + register int d; + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(d, eptr, len); + if (fc == d) break; + eptr += len; + } + for(;;) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr); + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || fc == *eptr) break; + eptr++; + } + while (eptr >= pp) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + eptr--; + } + } + + RRETURN(MATCH_NOMATCH); + } + } + /* Control never gets here */ + + /* Match a single character type repeatedly; several different opcodes + share code. This is very similar to the code for single characters, but we + repeat it in the interests of efficiency. */ + + case OP_TYPEEXACT: + min = max = GET2(ecode, 1); + minimize = TRUE; + ecode += 3; + goto REPEATTYPE; + + case OP_TYPEUPTO: + case OP_TYPEMINUPTO: + min = 0; + max = GET2(ecode, 1); + minimize = *ecode == OP_TYPEMINUPTO; + ecode += 3; + goto REPEATTYPE; + + case OP_TYPESTAR: + case OP_TYPEMINSTAR: + case OP_TYPEPLUS: + case OP_TYPEMINPLUS: + case OP_TYPEQUERY: + case OP_TYPEMINQUERY: + c = *ecode++ - OP_TYPESTAR; + minimize = (c & 1) != 0; + min = rep_min[c]; /* Pick up values from tables; */ + max = rep_max[c]; /* zero for max => infinity */ + if (max == 0) max = INT_MAX; + + /* Common code for all repeated single character type matches. Note that + in UTF-8 mode, '.' matches a character of any length, but for the other + character types, the valid characters are all one-byte long. */ + + REPEATTYPE: + ctype = *ecode++; /* Code for the character type */ + +#ifdef SUPPORT_UCP + if (ctype == OP_PROP || ctype == OP_NOTPROP) + { + prop_fail_result = ctype == OP_NOTPROP; + prop_type = *ecode++; + if (prop_type >= 128) + { + prop_test_against = prop_type - 128; + prop_test_variable = &prop_category; + } + else + { + prop_test_against = prop_type; + prop_test_variable = &prop_chartype; + } + } + else prop_type = -1; +#endif + + /* First, ensure the minimum number of matches are present. Use inline + code for maximizing the speed, and do the type test once at the start + (i.e. keep it out of the loop). Also we can test that there are at least + the minimum number of bytes before we start. This isn't as effective in + UTF-8 mode, but it does no harm. Separate the UTF-8 code completely as that + is tidier. Also separate the UCP code, which can be the same for both UTF-8 + and single-bytes. */ + + if (min > md->end_subject - eptr) RRETURN(MATCH_NOMATCH); + if (min > 0) + { +#ifdef SUPPORT_UCP + if (prop_type > 0) + { + for (i = 1; i <= min; i++) + { + GETCHARINC(c, eptr); + prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase); + if ((*prop_test_variable == prop_test_against) == prop_fail_result) + RRETURN(MATCH_NOMATCH); + } + } + + /* Match extended Unicode sequences. We will get here only if the + support is in the binary; otherwise a compile-time error occurs. */ + + else if (ctype == OP_EXTUNI) + { + for (i = 1; i <= min; i++) + { + GETCHARINCTEST(c, eptr); + prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase); + if (prop_category == ucp_M) RRETURN(MATCH_NOMATCH); + while (eptr < md->end_subject) + { + int len = 1; + if (!utf8) c = *eptr; else + { + GETCHARLEN(c, eptr, len); + } + prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase); + if (prop_category != ucp_M) break; + eptr += len; + } + } + } + + else +#endif /* SUPPORT_UCP */ + +/* Handle all other cases when the coding is UTF-8 */ + +#ifdef SUPPORT_UTF8 + if (utf8) switch(ctype) + { + case OP_ANY: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject || + (*eptr++ == NEWLINE && (ims & PCRE_DOTALL) == 0)) + RRETURN(MATCH_NOMATCH); + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; + } + break; + + case OP_ANYBYTE: + eptr += min; + break; + + case OP_NOT_DIGIT: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINC(c, eptr); + if (c < 128 && (md->ctypes[c] & ctype_digit) != 0) + RRETURN(MATCH_NOMATCH); + } + break; + + case OP_DIGIT: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject || + *eptr >= 128 || (md->ctypes[*eptr++] & ctype_digit) == 0) + RRETURN(MATCH_NOMATCH); + /* No need to skip more bytes - we know it's a 1-byte character */ + } + break; + + case OP_NOT_WHITESPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject || + (*eptr < 128 && (md->ctypes[*eptr++] & ctype_space) != 0)) + RRETURN(MATCH_NOMATCH); + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; + } + break; + + case OP_WHITESPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject || + *eptr >= 128 || (md->ctypes[*eptr++] & ctype_space) == 0) + RRETURN(MATCH_NOMATCH); + /* No need to skip more bytes - we know it's a 1-byte character */ + } + break; + + case OP_NOT_WORDCHAR: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject || + (*eptr < 128 && (md->ctypes[*eptr++] & ctype_word) != 0)) + RRETURN(MATCH_NOMATCH); + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; + } + break; + + case OP_WORDCHAR: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject || + *eptr >= 128 || (md->ctypes[*eptr++] & ctype_word) == 0) + RRETURN(MATCH_NOMATCH); + /* No need to skip more bytes - we know it's a 1-byte character */ + } + break; + + default: + RRETURN(PCRE_ERROR_INTERNAL); + } /* End switch(ctype) */ + + else +#endif /* SUPPORT_UTF8 */ + + /* Code for the non-UTF-8 case for minimum matching of operators other + than OP_PROP and OP_NOTPROP. */ + + switch(ctype) + { + case OP_ANY: + if ((ims & PCRE_DOTALL) == 0) + { + for (i = 1; i <= min; i++) + if (*eptr++ == NEWLINE) RRETURN(MATCH_NOMATCH); + } + else eptr += min; + break; + + case OP_ANYBYTE: + eptr += min; + break; + + case OP_NOT_DIGIT: + for (i = 1; i <= min; i++) + if ((md->ctypes[*eptr++] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH); + break; + + case OP_DIGIT: + for (i = 1; i <= min; i++) + if ((md->ctypes[*eptr++] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH); + break; + + case OP_NOT_WHITESPACE: + for (i = 1; i <= min; i++) + if ((md->ctypes[*eptr++] & ctype_space) != 0) RRETURN(MATCH_NOMATCH); + break; + + case OP_WHITESPACE: + for (i = 1; i <= min; i++) + if ((md->ctypes[*eptr++] & ctype_space) == 0) RRETURN(MATCH_NOMATCH); + break; + + case OP_NOT_WORDCHAR: + for (i = 1; i <= min; i++) + if ((md->ctypes[*eptr++] & ctype_word) != 0) + RRETURN(MATCH_NOMATCH); + break; + + case OP_WORDCHAR: + for (i = 1; i <= min; i++) + if ((md->ctypes[*eptr++] & ctype_word) == 0) + RRETURN(MATCH_NOMATCH); + break; + + default: + RRETURN(PCRE_ERROR_INTERNAL); + } + } + + /* If min = max, continue at the same level without recursing */ + + if (min == max) continue; + + /* If minimizing, we have to test the rest of the pattern before each + subsequent match. Again, separate the UTF-8 case for speed, and also + separate the UCP cases. */ + + if (minimize) + { +#ifdef SUPPORT_UCP + if (prop_type > 0) + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINC(c, eptr); + prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase); + if ((*prop_test_variable == prop_test_against) == prop_fail_result) + RRETURN(MATCH_NOMATCH); + } + } + + /* Match extended Unicode sequences. We will get here only if the + support is in the binary; otherwise a compile-time error occurs. */ + + else if (ctype == OP_EXTUNI) + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(c, eptr); + prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase); + if (prop_category == ucp_M) RRETURN(MATCH_NOMATCH); + while (eptr < md->end_subject) + { + int len = 1; + if (!utf8) c = *eptr; else + { + GETCHARLEN(c, eptr, len); + } + prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase); + if (prop_category != ucp_M) break; + eptr += len; + } + } + } + + else +#endif /* SUPPORT_UCP */ + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (utf8) + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + + GETCHARINC(c, eptr); + switch(ctype) + { + case OP_ANY: + if ((ims & PCRE_DOTALL) == 0 && c == NEWLINE) RRETURN(MATCH_NOMATCH); + break; + + case OP_ANYBYTE: + break; + + case OP_NOT_DIGIT: + if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) + RRETURN(MATCH_NOMATCH); + break; + + case OP_DIGIT: + if (c >= 256 || (md->ctypes[c] & ctype_digit) == 0) + RRETURN(MATCH_NOMATCH); + break; + + case OP_NOT_WHITESPACE: + if (c < 256 && (md->ctypes[c] & ctype_space) != 0) + RRETURN(MATCH_NOMATCH); + break; + + case OP_WHITESPACE: + if (c >= 256 || (md->ctypes[c] & ctype_space) == 0) + RRETURN(MATCH_NOMATCH); + break; + + case OP_NOT_WORDCHAR: + if (c < 256 && (md->ctypes[c] & ctype_word) != 0) + RRETURN(MATCH_NOMATCH); + break; + + case OP_WORDCHAR: + if (c >= 256 || (md->ctypes[c] & ctype_word) == 0) + RRETURN(MATCH_NOMATCH); + break; + + default: + RRETURN(PCRE_ERROR_INTERNAL); + } + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (fi = min;; fi++) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH); + c = *eptr++; + switch(ctype) + { + case OP_ANY: + if ((ims & PCRE_DOTALL) == 0 && c == NEWLINE) RRETURN(MATCH_NOMATCH); + break; + + case OP_ANYBYTE: + break; + + case OP_NOT_DIGIT: + if ((md->ctypes[c] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH); + break; + + case OP_DIGIT: + if ((md->ctypes[c] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH); + break; + + case OP_NOT_WHITESPACE: + if ((md->ctypes[c] & ctype_space) != 0) RRETURN(MATCH_NOMATCH); + break; + + case OP_WHITESPACE: + if ((md->ctypes[c] & ctype_space) == 0) RRETURN(MATCH_NOMATCH); + break; + + case OP_NOT_WORDCHAR: + if ((md->ctypes[c] & ctype_word) != 0) RRETURN(MATCH_NOMATCH); + break; + + case OP_WORDCHAR: + if ((md->ctypes[c] & ctype_word) == 0) RRETURN(MATCH_NOMATCH); + break; + + default: + RRETURN(PCRE_ERROR_INTERNAL); + } + } + } + /* Control never gets here */ + } + + /* If maximizing it is worth using inline code for speed, doing the type + test once at the start (i.e. keep it out of the loop). Again, keep the + UTF-8 and UCP stuff separate. */ + + else + { + pp = eptr; /* Remember where we started */ + +#ifdef SUPPORT_UCP + if (prop_type > 0) + { + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase); + if ((*prop_test_variable == prop_test_against) == prop_fail_result) + break; + eptr+= len; + } + + /* eptr is now past the end of the maximum run */ + + for(;;) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr); + } + } + + /* Match extended Unicode sequences. We will get here only if the + support is in the binary; otherwise a compile-time error occurs. */ + + else if (ctype == OP_EXTUNI) + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) break; + GETCHARINCTEST(c, eptr); + prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase); + if (prop_category == ucp_M) break; + while (eptr < md->end_subject) + { + int len = 1; + if (!utf8) c = *eptr; else + { + GETCHARLEN(c, eptr, len); + } + prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase); + if (prop_category != ucp_M) break; + eptr += len; + } + } + + /* eptr is now past the end of the maximum run */ + + for(;;) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + for (;;) /* Move back over one extended */ + { + int len = 1; + BACKCHAR(eptr); + if (!utf8) c = *eptr; else + { + GETCHARLEN(c, eptr, len); + } + prop_category = ucp_findchar(c, &prop_chartype, &prop_othercase); + if (prop_category != ucp_M) break; + eptr--; + } + } + } + + else +#endif /* SUPPORT_UCP */ + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + + if (utf8) + { + switch(ctype) + { + case OP_ANY: + + /* Special code is required for UTF8, but when the maximum is unlimited + we don't need it, so we repeat the non-UTF8 code. This is probably + worth it, because .* is quite a common idiom. */ + + if (max < INT_MAX) + { + if ((ims & PCRE_DOTALL) == 0) + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || *eptr == NEWLINE) break; + eptr++; + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; + } + } + else + { + for (i = min; i < max; i++) + { + eptr++; + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; + } + } + } + + /* Handle unlimited UTF-8 repeat */ + + else + { + if ((ims & PCRE_DOTALL) == 0) + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || *eptr == NEWLINE) break; + eptr++; + } + break; + } + else + { + c = max - min; + if (c > md->end_subject - eptr) c = md->end_subject - eptr; + eptr += c; + } + } + break; + + /* The byte case is the same as non-UTF8 */ + + case OP_ANYBYTE: + c = max - min; + if (c > md->end_subject - eptr) c = md->end_subject - eptr; + eptr += c; + break; + + case OP_NOT_DIGIT: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) break; + eptr+= len; + } + break; + + case OP_DIGIT: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + if (c >= 256 ||(md->ctypes[c] & ctype_digit) == 0) break; + eptr+= len; + } + break; + + case OP_NOT_WHITESPACE: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + if (c < 256 && (md->ctypes[c] & ctype_space) != 0) break; + eptr+= len; + } + break; + + case OP_WHITESPACE: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + if (c >= 256 ||(md->ctypes[c] & ctype_space) == 0) break; + eptr+= len; + } + break; + + case OP_NOT_WORDCHAR: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + if (c < 256 && (md->ctypes[c] & ctype_word) != 0) break; + eptr+= len; + } + break; + + case OP_WORDCHAR: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) break; + GETCHARLEN(c, eptr, len); + if (c >= 256 || (md->ctypes[c] & ctype_word) == 0) break; + eptr+= len; + } + break; + + default: + RRETURN(PCRE_ERROR_INTERNAL); + } + + /* eptr is now past the end of the maximum run */ + + for(;;) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr); + } + } + else +#endif + + /* Not UTF-8 mode */ + { + switch(ctype) + { + case OP_ANY: + if ((ims & PCRE_DOTALL) == 0) + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || *eptr == NEWLINE) break; + eptr++; + } + break; + } + /* For DOTALL case, fall through and treat as \C */ + + case OP_ANYBYTE: + c = max - min; + if (c > md->end_subject - eptr) c = md->end_subject - eptr; + eptr += c; + break; + + case OP_NOT_DIGIT: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) != 0) + break; + eptr++; + } + break; + + case OP_DIGIT: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) == 0) + break; + eptr++; + } + break; + + case OP_NOT_WHITESPACE: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) != 0) + break; + eptr++; + } + break; + + case OP_WHITESPACE: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) == 0) + break; + eptr++; + } + break; + + case OP_NOT_WORDCHAR: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) != 0) + break; + eptr++; + } + break; + + case OP_WORDCHAR: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) == 0) + break; + eptr++; + } + break; + + default: + RRETURN(PCRE_ERROR_INTERNAL); + } + + /* eptr is now past the end of the maximum run */ + + while (eptr >= pp) + { + RMATCH(rrc, eptr, ecode, offset_top, md, ims, eptrb, 0); + eptr--; + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + } + } + + /* Get here if we can't make it match with any permitted repetitions */ + + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + + /* There's been some horrible disaster. Since all codes > OP_BRA are + for capturing brackets, and there shouldn't be any gaps between 0 and + OP_BRA, arrival here can only mean there is something seriously wrong + in the code above or the OP_xxx definitions. */ + + default: + DPRINTF(("Unknown opcode %d\n", *ecode)); + RRETURN(PCRE_ERROR_UNKNOWN_NODE); + } + + /* Do not stick any code in here without much thought; it is assumed + that "continue" in the code above comes out to here to repeat the main + loop. */ + + } /* End of main loop */ +/* Control never reaches here */ +} + + +/*************************************************************************** +**************************************************************************** + RECURSION IN THE match() FUNCTION + +Undefine all the macros that were defined above to handle this. */ + +#ifdef NO_RECURSE +#undef eptr +#undef ecode +#undef offset_top +#undef ims +#undef eptrb +#undef flags + +#undef callpat +#undef charptr +#undef data +#undef next +#undef pp +#undef prev +#undef saved_eptr + +#undef new_recursive + +#undef cur_is_word +#undef condition +#undef minimize +#undef prev_is_word + +#undef original_ims + +#undef ctype +#undef length +#undef max +#undef min +#undef number +#undef offset +#undef op +#undef save_capture_last +#undef save_offset1 +#undef save_offset2 +#undef save_offset3 +#undef stacksave + +#undef newptrb + +#endif + +/* These two are defined as macros in both cases */ + +#undef fc +#undef fi + +/*************************************************************************** +***************************************************************************/ + + + +/************************************************* +* Execute a Regular Expression * +*************************************************/ + +/* This function applies a compiled re to a subject string and picks out +portions of the string if it matches. Two elements in the vector are set for +each substring: the offsets to the start and end of the substring. + +Arguments: + argument_re points to the compiled expression + extra_data points to extra data or is NULL + subject points to the subject string + length length of subject string (may contain binary zeros) + start_offset where to start in the subject string + options option bits + offsets points to a vector of ints to be filled in with offsets + offsetcount the number of elements in the vector + +Returns: > 0 => success; value is the number of elements filled in + = 0 => success, but offsets is not big enough + -1 => failed to match + < -1 => some kind of unexpected problem +*/ + +EXPORT int +pcre_exec(const pcre *argument_re, const pcre_extra *extra_data, + const char *subject, int length, int start_offset, int options, int *offsets, + int offsetcount) +{ +int rc, resetcount, ocount; +int first_byte = -1; +int req_byte = -1; +int req_byte2 = -1; +unsigned long int ims = 0; +BOOL using_temporary_offsets = FALSE; +BOOL anchored; +BOOL startline; +BOOL firstline; +BOOL first_byte_caseless = FALSE; +BOOL req_byte_caseless = FALSE; +match_data match_block; +const uschar *tables; +const uschar *start_bits = NULL; +const uschar *start_match = (const uschar *)subject + start_offset; +const uschar *end_subject; +const uschar *req_byte_ptr = start_match - 1; + +pcre_study_data internal_study; +const pcre_study_data *study; + +real_pcre internal_re; +const real_pcre *external_re = (const real_pcre *)argument_re; +const real_pcre *re = external_re; + +/* Plausibility checks */ + +if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION; +if (re == NULL || subject == NULL || + (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL; +if (offsetcount < 0) return PCRE_ERROR_BADCOUNT; + +/* Fish out the optional data from the extra_data structure, first setting +the default values. */ + +study = NULL; +match_block.match_limit = MATCH_LIMIT; +match_block.callout_data = NULL; + +/* The table pointer is always in native byte order. */ + +tables = external_re->tables; + +if (extra_data != NULL) + { + register unsigned int flags = extra_data->flags; + if ((flags & PCRE_EXTRA_STUDY_DATA) != 0) + study = (const pcre_study_data *)extra_data->study_data; + if ((flags & PCRE_EXTRA_MATCH_LIMIT) != 0) + match_block.match_limit = extra_data->match_limit; + if ((flags & PCRE_EXTRA_CALLOUT_DATA) != 0) + match_block.callout_data = extra_data->callout_data; + if ((flags & PCRE_EXTRA_TABLES) != 0) tables = extra_data->tables; + } + +/* If the exec call supplied NULL for tables, use the inbuilt ones. This +is a feature that makes it possible to save compiled regex and re-use them +in other programs later. */ + +if (tables == NULL) tables = _pcre_default_tables; + +/* Check that the first field in the block is the magic number. If it is not, +test for a regex that was compiled on a host of opposite endianness. If this is +the case, flipped values are put in internal_re and internal_study if there was +study data too. */ + +if (re->magic_number != MAGIC_NUMBER) + { + re = _pcre_try_flipped(re, &internal_re, study, &internal_study); + if (re == NULL) return PCRE_ERROR_BADMAGIC; + if (study != NULL) study = &internal_study; + } + +/* Set up other data */ + +anchored = ((re->options | options) & PCRE_ANCHORED) != 0; +startline = (re->options & PCRE_STARTLINE) != 0; +firstline = (re->options & PCRE_FIRSTLINE) != 0; + +/* The code starts after the real_pcre block and the capture name table. */ + +match_block.start_code = (const uschar *)external_re + re->name_table_offset + + re->name_count * re->name_entry_size; + +match_block.start_subject = (const uschar *)subject; +match_block.start_offset = start_offset; +match_block.end_subject = match_block.start_subject + length; +end_subject = match_block.end_subject; + +match_block.endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0; +match_block.utf8 = (re->options & PCRE_UTF8) != 0; + +match_block.notbol = (options & PCRE_NOTBOL) != 0; +match_block.noteol = (options & PCRE_NOTEOL) != 0; +match_block.notempty = (options & PCRE_NOTEMPTY) != 0; +match_block.partial = (options & PCRE_PARTIAL) != 0; +match_block.hitend = FALSE; + +match_block.recursive = NULL; /* No recursion at top level */ + +match_block.lcc = tables + lcc_offset; +match_block.ctypes = tables + ctypes_offset; + +/* Partial matching is supported only for a restricted set of regexes at the +moment. */ + +if (match_block.partial && (re->options & PCRE_NOPARTIAL) != 0) + return PCRE_ERROR_BADPARTIAL; + +/* Check a UTF-8 string if required. Unfortunately there's no way of passing +back the character offset. */ + +#ifdef SUPPORT_UTF8 +if (match_block.utf8 && (options & PCRE_NO_UTF8_CHECK) == 0) + { + if (_pcre_valid_utf8((uschar *)subject, length) >= 0) + return PCRE_ERROR_BADUTF8; + if (start_offset > 0 && start_offset < length) + { + int tb = ((uschar *)subject)[start_offset]; + if (tb > 127) + { + tb &= 0xc0; + if (tb != 0 && tb != 0xc0) return PCRE_ERROR_BADUTF8_OFFSET; + } + } + } +#endif + +/* The ims options can vary during the matching as a result of the presence +of (?ims) items in the pattern. They are kept in a local variable so that +restoring at the exit of a group is easy. */ + +ims = re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL); + +/* If the expression has got more back references than the offsets supplied can +hold, we get a temporary chunk of working store to use during the matching. +Otherwise, we can use the vector supplied, rounding down its size to a multiple +of 3. */ + +ocount = offsetcount - (offsetcount % 3); + +if (re->top_backref > 0 && re->top_backref >= ocount/3) + { + ocount = re->top_backref * 3 + 3; + match_block.offset_vector = (int *)(pcre_malloc)(ocount * sizeof(int)); + if (match_block.offset_vector == NULL) return PCRE_ERROR_NOMEMORY; + using_temporary_offsets = TRUE; + DPRINTF(("Got memory to hold back references\n")); + } +else match_block.offset_vector = offsets; + +match_block.offset_end = ocount; +match_block.offset_max = (2*ocount)/3; +match_block.offset_overflow = FALSE; +match_block.capture_last = -1; + +/* Compute the minimum number of offsets that we need to reset each time. Doing +this makes a huge difference to execution time when there aren't many brackets +in the pattern. */ + +resetcount = 2 + re->top_bracket * 2; +if (resetcount > offsetcount) resetcount = ocount; + +/* Reset the working variable associated with each extraction. These should +never be used unless previously set, but they get saved and restored, and so we +initialize them to avoid reading uninitialized locations. */ + +if (match_block.offset_vector != NULL) + { + register int *iptr = match_block.offset_vector + ocount; + register int *iend = iptr - resetcount/2 + 1; + while (--iptr >= iend) *iptr = -1; + } + +/* Set up the first character to match, if available. The first_byte value is +never set for an anchored regular expression, but the anchoring may be forced +at run time, so we have to test for anchoring. The first char may be unset for +an unanchored pattern, of course. If there's no first char and the pattern was +studied, there may be a bitmap of possible first characters. */ + +if (!anchored) + { + if ((re->options & PCRE_FIRSTSET) != 0) + { + first_byte = re->first_byte & 255; + if ((first_byte_caseless = ((re->first_byte & REQ_CASELESS) != 0)) == TRUE) + first_byte = match_block.lcc[first_byte]; + } + else + if (!startline && study != NULL && + (study->options & PCRE_STUDY_MAPPED) != 0) + start_bits = study->start_bits; + } + +/* For anchored or unanchored matches, there may be a "last known required +character" set. */ + +if ((re->options & PCRE_REQCHSET) != 0) + { + req_byte = re->req_byte & 255; + req_byte_caseless = (re->req_byte & REQ_CASELESS) != 0; + req_byte2 = (tables + fcc_offset)[req_byte]; /* case flipped */ + } + +/* Loop for handling unanchored repeated matching attempts; for anchored regexs +the loop runs just once. */ + +do + { + const uschar *save_end_subject = end_subject; + + /* Reset the maximum number of extractions we might see. */ + + if (match_block.offset_vector != NULL) + { + register int *iptr = match_block.offset_vector; + register int *iend = iptr + resetcount; + while (iptr < iend) *iptr++ = -1; + } + + /* Advance to a unique first char if possible. If firstline is TRUE, the + start of the match is constrained to the first line of a multiline string. + Implement this by temporarily adjusting end_subject so that we stop scanning + at a newline. If the match fails at the newline, later code breaks this loop. + */ + + if (firstline) + { + const uschar *t = start_match; + while (t < save_end_subject && *t != '\n') t++; + end_subject = t; + } + + /* Now test for a unique first byte */ + + if (first_byte >= 0) + { + if (first_byte_caseless) + while (start_match < end_subject && + match_block.lcc[*start_match] != first_byte) + start_match++; + else + while (start_match < end_subject && *start_match != first_byte) + start_match++; + } + + /* Or to just after \n for a multiline match if possible */ + + else if (startline) + { + if (start_match > match_block.start_subject + start_offset) + { + while (start_match < end_subject && start_match[-1] != NEWLINE) + start_match++; + } + } + + /* Or to a non-unique first char after study */ + + else if (start_bits != NULL) + { + while (start_match < end_subject) + { + register unsigned int c = *start_match; + if ((start_bits[c/8] & (1 << (c&7))) == 0) start_match++; else break; + } + } + + /* Restore fudged end_subject */ + + end_subject = save_end_subject; + +#ifdef DEBUG /* Sigh. Some compilers never learn. */ + printf(">>>> Match against: "); + pchars(start_match, end_subject - start_match, TRUE, &match_block); + printf("\n"); +#endif + + /* If req_byte is set, we know that that character must appear in the subject + for the match to succeed. If the first character is set, req_byte must be + later in the subject; otherwise the test starts at the match point. This + optimization can save a huge amount of backtracking in patterns with nested + unlimited repeats that aren't going to match. Writing separate code for + cased/caseless versions makes it go faster, as does using an autoincrement + and backing off on a match. + + HOWEVER: when the subject string is very, very long, searching to its end can + take a long time, and give bad performance on quite ordinary patterns. This + showed up when somebody was matching /^C/ on a 32-megabyte string... so we + don't do this when the string is sufficiently long. + + ALSO: this processing is disabled when partial matching is requested. + */ + + if (req_byte >= 0 && + end_subject - start_match < REQ_BYTE_MAX && + !match_block.partial) + { + register const uschar *p = start_match + ((first_byte >= 0)? 1 : 0); + + /* We don't need to repeat the search if we haven't yet reached the + place we found it at last time. */ + + if (p > req_byte_ptr) + { + if (req_byte_caseless) + { + while (p < end_subject) + { + register int pp = *p++; + if (pp == req_byte || pp == req_byte2) { p--; break; } + } + } + else + { + while (p < end_subject) + { + if (*p++ == req_byte) { p--; break; } + } + } + + /* If we can't find the required character, break the matching loop */ + + if (p >= end_subject) break; + + /* If we have found the required character, save the point where we + found it, so that we don't search again next time round the loop if + the start hasn't passed this character yet. */ + + req_byte_ptr = p; + } + } + + /* When a match occurs, substrings will be set for all internal extractions; + we just need to set up the whole thing as substring 0 before returning. If + there were too many extractions, set the return code to zero. In the case + where we had to get some local store to hold offsets for backreferences, copy + those back references that we can. In this case there need not be overflow + if certain parts of the pattern were not used. */ + + match_block.start_match = start_match; + match_block.match_call_count = 0; + + rc = match(start_match, match_block.start_code, 2, &match_block, ims, NULL, + match_isgroup); + + /* When the result is no match, if the subject's first character was a + newline and the PCRE_FIRSTLINE option is set, break (which will return + PCRE_ERROR_NOMATCH). The option requests that a match occur before the first + newline in the subject. Otherwise, advance the pointer to the next character + and continue - but the continuation will actually happen only when the + pattern is not anchored. */ + + if (rc == MATCH_NOMATCH) + { + if (firstline && *start_match == NEWLINE) break; + start_match++; +#ifdef SUPPORT_UTF8 + if (match_block.utf8) + while(start_match < end_subject && (*start_match & 0xc0) == 0x80) + start_match++; +#endif + continue; + } + + if (rc != MATCH_MATCH) + { + DPRINTF((">>>> error: returning %d\n", rc)); + return rc; + } + + /* We have a match! Copy the offset information from temporary store if + necessary */ + + if (using_temporary_offsets) + { + if (offsetcount >= 4) + { + memcpy(offsets + 2, match_block.offset_vector + 2, + (offsetcount - 2) * sizeof(int)); + DPRINTF(("Copied offsets from temporary memory\n")); + } + if (match_block.end_offset_top > offsetcount) + match_block.offset_overflow = TRUE; + + DPRINTF(("Freeing temporary memory\n")); + (pcre_free)(match_block.offset_vector); + } + + rc = match_block.offset_overflow? 0 : match_block.end_offset_top/2; + + if (offsetcount < 2) rc = 0; else + { + offsets[0] = start_match - match_block.start_subject; + offsets[1] = match_block.end_match_ptr - match_block.start_subject; + } + + DPRINTF((">>>> returning %d\n", rc)); + return rc; + } + +/* This "while" is the end of the "do" above */ + +while (!anchored && start_match <= end_subject); + +if (using_temporary_offsets) + { + DPRINTF(("Freeing temporary memory\n")); + (pcre_free)(match_block.offset_vector); + } + +if (match_block.partial && match_block.hitend) + { + DPRINTF((">>>> returning PCRE_ERROR_PARTIAL\n")); + return PCRE_ERROR_PARTIAL; + } +else + { + DPRINTF((">>>> returning PCRE_ERROR_NOMATCH\n")); + return PCRE_ERROR_NOMATCH; + } +} + +/* End of pcre_exec.c */ diff --git a/ext/pcre/pcrelib/pcre_fullinfo.c b/ext/pcre/pcrelib/pcre_fullinfo.c new file mode 100644 index 000000000000..ac80e65e2a1b --- /dev/null +++ b/ext/pcre/pcrelib/pcre_fullinfo.c @@ -0,0 +1,149 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/*PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2005 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains the external function pcre_fullinfo(), which returns +information about a compiled pattern. */ + + +#include "pcre_internal.h" + + +/************************************************* +* Return info about compiled pattern * +*************************************************/ + +/* This is a newer "info" function which has an extensible interface so +that additional items can be added compatibly. + +Arguments: + argument_re points to compiled code + extra_data points extra data, or NULL + what what information is required + where where to put the information + +Returns: 0 if data returned, negative on error +*/ + +EXPORT int +pcre_fullinfo(const pcre *argument_re, const pcre_extra *extra_data, int what, + void *where) +{ +real_pcre internal_re; +pcre_study_data internal_study; +const real_pcre *re = (const real_pcre *)argument_re; +const pcre_study_data *study = NULL; + +if (re == NULL || where == NULL) return PCRE_ERROR_NULL; + +if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_STUDY_DATA) != 0) + study = (const pcre_study_data *)extra_data->study_data; + +if (re->magic_number != MAGIC_NUMBER) + { + re = _pcre_try_flipped(re, &internal_re, study, &internal_study); + if (re == NULL) return PCRE_ERROR_BADMAGIC; + if (study != NULL) study = &internal_study; + } + +switch (what) + { + case PCRE_INFO_OPTIONS: + *((unsigned long int *)where) = re->options & PUBLIC_OPTIONS; + break; + + case PCRE_INFO_SIZE: + *((size_t *)where) = re->size; + break; + + case PCRE_INFO_STUDYSIZE: + *((size_t *)where) = (study == NULL)? 0 : study->size; + break; + + case PCRE_INFO_CAPTURECOUNT: + *((int *)where) = re->top_bracket; + break; + + case PCRE_INFO_BACKREFMAX: + *((int *)where) = re->top_backref; + break; + + case PCRE_INFO_FIRSTBYTE: + *((int *)where) = + ((re->options & PCRE_FIRSTSET) != 0)? re->first_byte : + ((re->options & PCRE_STARTLINE) != 0)? -1 : -2; + break; + + /* Make sure we pass back the pointer to the bit vector in the external + block, not the internal copy (with flipped integer fields). */ + + case PCRE_INFO_FIRSTTABLE: + *((const uschar **)where) = + (study != NULL && (study->options & PCRE_STUDY_MAPPED) != 0)? + ((const pcre_study_data *)extra_data->study_data)->start_bits : NULL; + break; + + case PCRE_INFO_LASTLITERAL: + *((int *)where) = + ((re->options & PCRE_REQCHSET) != 0)? re->req_byte : -1; + break; + + case PCRE_INFO_NAMEENTRYSIZE: + *((int *)where) = re->name_entry_size; + break; + + case PCRE_INFO_NAMECOUNT: + *((int *)where) = re->name_count; + break; + + case PCRE_INFO_NAMETABLE: + *((const uschar **)where) = (const uschar *)re + re->name_table_offset; + break; + + case PCRE_INFO_DEFAULT_TABLES: + *((const uschar **)where) = (const uschar *)(_pcre_default_tables); + break; + + default: return PCRE_ERROR_BADOPTION; + } + +return 0; +} + +/* End of pcre_fullinfo.c */ diff --git a/ext/pcre/pcrelib/get.c b/ext/pcre/pcrelib/pcre_get.c similarity index 85% rename from ext/pcre/pcrelib/get.c rename to ext/pcre/pcrelib/pcre_get.c index 8556d9508d7d..fc4a14ac14f8 100644 --- a/ext/pcre/pcrelib/get.c +++ b/ext/pcre/pcrelib/pcre_get.c @@ -2,45 +2,48 @@ * Perl-Compatible Regular Expressions * *************************************************/ -/* -This is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. See -the file Tech.Notes for some information on the internals. +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. -Written by: Philip Hazel - - Copyright (c) 1997-2004 University of Cambridge + Written by Philip Hazel + Copyright (c) 1997-2005 University of Cambridge ----------------------------------------------------------------------------- -Permission is granted to anyone to use this software for any purpose on any -computer system, and to redistribute it freely, subject to the following -restrictions: - -1. This software is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -2. The origin of this software must not be misrepresented, either by - explicit claim or by omission. - -3. Altered versions must be plainly marked as such, and must not be - misrepresented as being the original software. - -4. If PCRE is embedded in any software that is released under the GNU - General Purpose Licence (GPL), then the terms of that licence shall - supersede any condition above with which it is incompatible. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------------------- */ + /* This module contains some convenience functions for extracting substrings from the subject string after a regex match has succeeded. The original idea -for these functions came from Scott Wimer . */ - +for these functions came from Scott Wimer. */ -/* Include the internals header, which itself includes Standard C headers plus -the external pcre header. */ -#include "internal.h" +#include "pcre_internal.h" /************************************************* @@ -346,4 +349,4 @@ pcre_free_substring(const char *pointer) (pcre_free)((void *)pointer); } -/* End of get.c */ +/* End of pcre_get.c */ diff --git a/ext/pcre/pcrelib/pcre_globals.c b/ext/pcre/pcrelib/pcre_globals.c new file mode 100644 index 000000000000..1a839802ba02 --- /dev/null +++ b/ext/pcre/pcrelib/pcre_globals.c @@ -0,0 +1,69 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2005 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains global variables that are exported by the PCRE library. +PCRE is thread-clean and doesn't use any global variables in the normal sense. +However, it calls memory allocation and freeing functions via the four +indirections below, and it can optionally do callouts, using the fifth +indirection. These values can be changed by the caller, but are shared between +all threads. However, when compiling for Virtual Pascal, things are done +differently, and global variables are not used (see pcre.in). */ + + +#include "pcre_internal.h" + + +#ifndef VPCOMPAT +#ifdef __cplusplus +extern "C" void *(*pcre_malloc)(size_t) = malloc; +extern "C" void (*pcre_free)(void *) = free; +extern "C" void *(*pcre_stack_malloc)(size_t) = malloc; +extern "C" void (*pcre_stack_free)(void *) = free; +extern "C" int (*pcre_callout)(pcre_callout_block *) = NULL; +#else +void *(*pcre_malloc)(size_t) = malloc; +void (*pcre_free)(void *) = free; +void *(*pcre_stack_malloc)(size_t) = malloc; +void (*pcre_stack_free)(void *) = free; +int (*pcre_callout)(pcre_callout_block *) = NULL; +#endif +#endif + +/* End of pcre_globals.c */ diff --git a/ext/pcre/pcrelib/pcre_info.c b/ext/pcre/pcrelib/pcre_info.c new file mode 100644 index 000000000000..228949d0cd2a --- /dev/null +++ b/ext/pcre/pcrelib/pcre_info.c @@ -0,0 +1,89 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2005 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains the external function pcre_info(), which gives some +information about a compiled pattern. However, use of this function is now +deprecated, as it has been superseded by pcre_fullinfo(). */ + + +#include "pcre_internal.h" + + +/************************************************* +* (Obsolete) Return info about compiled pattern * +*************************************************/ + +/* This is the original "info" function. It picks potentially useful data out +of the private structure, but its interface was too rigid. It remains for +backwards compatibility. The public options are passed back in an int - though +the re->options field has been expanded to a long int, all the public options +at the low end of it, and so even on 16-bit systems this will still be OK. +Therefore, I haven't changed the API for pcre_info(). + +Arguments: + argument_re points to compiled code + optptr where to pass back the options + first_byte where to pass back the first character, + or -1 if multiline and all branches start ^, + or -2 otherwise + +Returns: number of capturing subpatterns + or negative values on error +*/ + +EXPORT int +pcre_info(const pcre *argument_re, int *optptr, int *first_byte) +{ +real_pcre internal_re; +const real_pcre *re = (const real_pcre *)argument_re; +if (re == NULL) return PCRE_ERROR_NULL; +if (re->magic_number != MAGIC_NUMBER) + { + re = _pcre_try_flipped(re, &internal_re, NULL, NULL); + if (re == NULL) return PCRE_ERROR_BADMAGIC; + } +if (optptr != NULL) *optptr = (int)(re->options & PUBLIC_OPTIONS); +if (first_byte != NULL) + *first_byte = ((re->options & PCRE_FIRSTSET) != 0)? re->first_byte : + ((re->options & PCRE_STARTLINE) != 0)? -1 : -2; +return re->top_bracket; +} + +/* End of pcre_info.c */ diff --git a/ext/pcre/pcrelib/pcre_internal.h b/ext/pcre/pcrelib/pcre_internal.h new file mode 100644 index 000000000000..bffab024cb3b --- /dev/null +++ b/ext/pcre/pcrelib/pcre_internal.h @@ -0,0 +1,909 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2005 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +/* This header contains definitions that are shared between the different +modules, but which are not relevant to the exported API. This includes some +functions whose names all begin with "_pcre_". */ + + +/* Define DEBUG to get debugging output on stdout. */ + +/**** +#define DEBUG +****/ + +/* Use a macro for debugging printing, 'cause that eliminates the use of #ifdef +inline, and there are *still* stupid compilers about that don't like indented +pre-processor statements, or at least there were when I first wrote this. After +all, it had only been about 10 years then... */ + +#ifdef DEBUG +#define DPRINTF(p) printf p +#else +#define DPRINTF(p) /*nothing*/ +#endif + + +/* Get the definitions provided by running "configure" */ + +#ifdef PHP_WIN32 +# include "config.w32.h" +#else +# include +#endif + +/* Standard C headers plus the external interface definition. The only time +setjmp and stdarg are used is when NO_RECURSE is set. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef PCRE_SPY +#define PCRE_DEFINITION /* Win32 __declspec(export) trigger for .dll */ +#endif + +/* We need to have types that specify unsigned 16-bit and 32-bit integers. We +cannot determine these outside the compilation (e.g. by running a program as +part of "configure") because PCRE is often cross-compiled for use on other +systems. Instead we make use of the maximum sizes that are available at +preprocessor time in standard C environments. */ + +#if USHRT_MAX == 65535 + typedef unsigned short pcre_uint16; +#elif UINT_MAX == 65535 + typedef unsigned int pcre_uint16; +#else + #error Cannot determine a type for 16-bit unsigned integers +#endif + +#if UINT_MAX == 4294967295 + typedef unsigned int pcre_uint32; +#elif ULONG_MAX == 4294967295 + typedef unsigned long int pcre_uint32; +#else + #error Cannot determine a type for 32-bit unsigned integers +#endif + +/* All character handling must be done as unsigned characters. Otherwise there +are problems with top-bit-set characters and functions such as isspace(). +However, we leave the interface to the outside world as char *, because that +should make things easier for callers. We define a short type for unsigned char +to save lots of typing. I tried "uchar", but it causes problems on Digital +Unix, where it is defined in sys/types, so use "uschar" instead. */ + +typedef unsigned char uschar; + +/* Include the public PCRE header */ + +#include "pcre.h" + +/* Include the (copy of) the public ucp header, changing the external name into +a private one. This does no harm, even if we aren't compiling UCP support. */ + +#define ucp_findchar _pcre_ucp_findchar +#include "ucp.h" + +/* When compiling for use with the Virtual Pascal compiler, these functions +need to have their names changed. PCRE must be compiled with the -DVPCOMPAT +option on the command line. */ + +#ifdef VPCOMPAT +#define strncmp(s1,s2,m) _strncmp(s1,s2,m) +#define memcpy(d,s,n) _memcpy(d,s,n) +#define memmove(d,s,n) _memmove(d,s,n) +#define memset(s,c,n) _memset(s,c,n) +#else /* VPCOMPAT */ + +/* To cope with SunOS4 and other systems that lack memmove() but have bcopy(), +define a macro for memmove() if HAVE_MEMMOVE is false, provided that HAVE_BCOPY +is set. Otherwise, include an emulating function for those systems that have +neither (there some non-Unix environments where this is the case). This assumes +that all calls to memmove are moving strings upwards in store, which is the +case in PCRE. */ + +#if ! HAVE_MEMMOVE +#undef memmove /* some systems may have a macro */ +#if HAVE_BCOPY +#define memmove(a, b, c) bcopy(b, a, c) +#else /* HAVE_BCOPY */ +void * +pcre_memmove(unsigned char *dest, const unsigned char *src, size_t n) +{ +int i; +dest += n; +src += n; +for (i = 0; i < n; ++i) *(--dest) = *(--src); +} +#define memmove(a, b, c) pcre_memmove(a, b, c) +#endif /* not HAVE_BCOPY */ +#endif /* not HAVE_MEMMOVE */ +#endif /* not VPCOMPAT */ + + +/* PCRE keeps offsets in its compiled code as 2-byte quantities (always stored +in big-endian order) by default. These are used, for example, to link from the +start of a subpattern to its alternatives and its end. The use of 2 bytes per +offset limits the size of the compiled regex to around 64K, which is big enough +for almost everybody. However, I received a request for an even bigger limit. +For this reason, and also to make the code easier to maintain, the storing and +loading of offsets from the byte string is now handled by the macros that are +defined here. + +The macros are controlled by the value of LINK_SIZE. This defaults to 2 in +the config.h file, but can be overridden by using -D on the command line. This +is automated on Unix systems via the "configure" command. */ + +#if LINK_SIZE == 2 + +#define PUT(a,n,d) \ + (a[n] = (d) >> 8), \ + (a[(n)+1] = (d) & 255) + +#define GET(a,n) \ + (((a)[n] << 8) | (a)[(n)+1]) + +#define MAX_PATTERN_SIZE (1 << 16) + + +#elif LINK_SIZE == 3 + +#define PUT(a,n,d) \ + (a[n] = (d) >> 16), \ + (a[(n)+1] = (d) >> 8), \ + (a[(n)+2] = (d) & 255) + +#define GET(a,n) \ + (((a)[n] << 16) | ((a)[(n)+1] << 8) | (a)[(n)+2]) + +#define MAX_PATTERN_SIZE (1 << 24) + + +#elif LINK_SIZE == 4 + +#define PUT(a,n,d) \ + (a[n] = (d) >> 24), \ + (a[(n)+1] = (d) >> 16), \ + (a[(n)+2] = (d) >> 8), \ + (a[(n)+3] = (d) & 255) + +#define GET(a,n) \ + (((a)[n] << 24) | ((a)[(n)+1] << 16) | ((a)[(n)+2] << 8) | (a)[(n)+3]) + +#define MAX_PATTERN_SIZE (1 << 30) /* Keep it positive */ + + +#else +#error LINK_SIZE must be either 2, 3, or 4 +#endif + + +/* Convenience macro defined in terms of the others */ + +#define PUTINC(a,n,d) PUT(a,n,d), a += LINK_SIZE + + +/* PCRE uses some other 2-byte quantities that do not change when the size of +offsets changes. There are used for repeat counts and for other things such as +capturing parenthesis numbers in back references. */ + +#define PUT2(a,n,d) \ + a[n] = (d) >> 8; \ + a[(n)+1] = (d) & 255 + +#define GET2(a,n) \ + (((a)[n] << 8) | (a)[(n)+1]) + +#define PUT2INC(a,n,d) PUT2(a,n,d), a += 2 + + +/* When UTF-8 encoding is being used, a character is no longer just a single +byte. The macros for character handling generate simple sequences when used in +byte-mode, and more complicated ones for UTF-8 characters. */ + +#ifndef SUPPORT_UTF8 +#define GETCHAR(c, eptr) c = *eptr; +#define GETCHARTEST(c, eptr) c = *eptr; +#define GETCHARINC(c, eptr) c = *eptr++; +#define GETCHARINCTEST(c, eptr) c = *eptr++; +#define GETCHARLEN(c, eptr, len) c = *eptr; +#define BACKCHAR(eptr) + +#else /* SUPPORT_UTF8 */ + +/* Get the next UTF-8 character, not advancing the pointer. This is called when +we know we are in UTF-8 mode. */ + +#define GETCHAR(c, eptr) \ + c = *eptr; \ + if ((c & 0xc0) == 0xc0) \ + { \ + int gcii; \ + int gcaa = _pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ + int gcss = 6*gcaa; \ + c = (c & _pcre_utf8_table3[gcaa]) << gcss; \ + for (gcii = 1; gcii <= gcaa; gcii++) \ + { \ + gcss -= 6; \ + c |= (eptr[gcii] & 0x3f) << gcss; \ + } \ + } + +/* Get the next UTF-8 character, testing for UTF-8 mode, and not advancing the +pointer. */ + +#define GETCHARTEST(c, eptr) \ + c = *eptr; \ + if (utf8 && (c & 0xc0) == 0xc0) \ + { \ + int gcii; \ + int gcaa = _pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ + int gcss = 6*gcaa; \ + c = (c & _pcre_utf8_table3[gcaa]) << gcss; \ + for (gcii = 1; gcii <= gcaa; gcii++) \ + { \ + gcss -= 6; \ + c |= (eptr[gcii] & 0x3f) << gcss; \ + } \ + } + +/* Get the next UTF-8 character, advancing the pointer. This is called when we +know we are in UTF-8 mode. */ + +#define GETCHARINC(c, eptr) \ + c = *eptr++; \ + if ((c & 0xc0) == 0xc0) \ + { \ + int gcaa = _pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ + int gcss = 6*gcaa; \ + c = (c & _pcre_utf8_table3[gcaa]) << gcss; \ + while (gcaa-- > 0) \ + { \ + gcss -= 6; \ + c |= (*eptr++ & 0x3f) << gcss; \ + } \ + } + +/* Get the next character, testing for UTF-8 mode, and advancing the pointer */ + +#define GETCHARINCTEST(c, eptr) \ + c = *eptr++; \ + if (utf8 && (c & 0xc0) == 0xc0) \ + { \ + int gcaa = _pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ + int gcss = 6*gcaa; \ + c = (c & _pcre_utf8_table3[gcaa]) << gcss; \ + while (gcaa-- > 0) \ + { \ + gcss -= 6; \ + c |= (*eptr++ & 0x3f) << gcss; \ + } \ + } + +/* Get the next UTF-8 character, not advancing the pointer, incrementing length +if there are extra bytes. This is called when we know we are in UTF-8 mode. */ + +#define GETCHARLEN(c, eptr, len) \ + c = *eptr; \ + if ((c & 0xc0) == 0xc0) \ + { \ + int gcii; \ + int gcaa = _pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ + int gcss = 6*gcaa; \ + c = (c & _pcre_utf8_table3[gcaa]) << gcss; \ + for (gcii = 1; gcii <= gcaa; gcii++) \ + { \ + gcss -= 6; \ + c |= (eptr[gcii] & 0x3f) << gcss; \ + } \ + len += gcaa; \ + } + +/* If the pointer is not at the start of a character, move it back until +it is. Called only in UTF-8 mode. */ + +#define BACKCHAR(eptr) while((*eptr & 0xc0) == 0x80) eptr--; + +#endif + + +/* In case there is no definition of offsetof() provided - though any proper +Standard C system should have one. */ + +#ifndef offsetof +#define offsetof(p_type,field) ((size_t)&(((p_type *)0)->field)) +#endif + + +/* These are the public options that can change during matching. */ + +#define PCRE_IMS (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL) + +/* Private options flags start at the most significant end of the four bytes, +but skip the top bit so we can use ints for convenience without getting tangled +with negative values. The public options defined in pcre.h start at the least +significant end. Make sure they don't overlap! */ + +#define PCRE_FIRSTSET 0x40000000 /* first_byte is set */ +#define PCRE_REQCHSET 0x20000000 /* req_byte is set */ +#define PCRE_STARTLINE 0x10000000 /* start after \n for multiline */ +#define PCRE_ICHANGED 0x08000000 /* i option changes within regex */ +#define PCRE_NOPARTIAL 0x04000000 /* can't use partial with this regex */ + +/* Options for the "extra" block produced by pcre_study(). */ + +#define PCRE_STUDY_MAPPED 0x01 /* a map of starting chars exists */ + +/* Masks for identifying the public options that are permitted at compile +time, run time, or study time, respectively. */ + +#define PUBLIC_OPTIONS \ + (PCRE_CASELESS|PCRE_EXTENDED|PCRE_ANCHORED|PCRE_MULTILINE| \ + PCRE_DOTALL|PCRE_DOLLAR_ENDONLY|PCRE_EXTRA|PCRE_UNGREEDY|PCRE_UTF8| \ + PCRE_NO_AUTO_CAPTURE|PCRE_NO_UTF8_CHECK|PCRE_AUTO_CALLOUT|PCRE_FIRSTLINE) + +#define PUBLIC_EXEC_OPTIONS \ + (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY|PCRE_NO_UTF8_CHECK| \ + PCRE_PARTIAL) + +#define PUBLIC_DFA_EXEC_OPTIONS \ + (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY|PCRE_NO_UTF8_CHECK| \ + PCRE_PARTIAL|PCRE_DFA_SHORTEST|PCRE_DFA_RESTART) + +#define PUBLIC_STUDY_OPTIONS 0 /* None defined */ + +/* Magic number to provide a small check against being handed junk. Also used +to detect whether a pattern was compiled on a host of different endianness. */ + +#define MAGIC_NUMBER 0x50435245UL /* 'PCRE' */ + +/* Negative values for the firstchar and reqchar variables */ + +#define REQ_UNSET (-2) +#define REQ_NONE (-1) + +/* The maximum remaining length of subject we are prepared to search for a +req_byte match. */ + +#define REQ_BYTE_MAX 1000 + +/* Flags added to firstbyte or reqbyte; a "non-literal" item is either a +variable-length repeat, or a anything other than literal characters. */ + +#define REQ_CASELESS 0x0100 /* indicates caselessness */ +#define REQ_VARY 0x0200 /* reqbyte followed non-literal item */ + +/* Miscellaneous definitions */ + +typedef int BOOL; + +#define FALSE 0 +#define TRUE 1 + +/* Escape items that are just an encoding of a particular data value. Note that +ESC_n is defined as yet another macro, which is set in config.h to either \n +(the default) or \r (which some people want). */ + +#ifndef ESC_e +#define ESC_e 27 +#endif + +#ifndef ESC_f +#define ESC_f '\f' +#endif + +#ifndef ESC_n +#define ESC_n NEWLINE +#endif + +#ifndef ESC_r +#define ESC_r '\r' +#endif + +/* We can't officially use ESC_t because it is a POSIX reserved identifier +(presumably because of all the others like size_t). */ + +#ifndef ESC_tee +#define ESC_tee '\t' +#endif + +/* These are escaped items that aren't just an encoding of a particular data +value such as \n. They must have non-zero values, as check_escape() returns +their negation. Also, they must appear in the same order as in the opcode +definitions below, up to ESC_z. There's a dummy for OP_ANY because it +corresponds to "." rather than an escape sequence. The final one must be +ESC_REF as subsequent values are used for \1, \2, \3, etc. There is are two +tests in the code for an escape greater than ESC_b and less than ESC_Z to +detect the types that may be repeated. These are the types that consume +characters. If any new escapes are put in between that don't consume a +character, that code will have to change. */ + +enum { ESC_A = 1, ESC_G, ESC_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s, ESC_W, + ESC_w, ESC_dum1, ESC_C, ESC_P, ESC_p, ESC_X, ESC_Z, ESC_z, ESC_E, + ESC_Q, ESC_REF }; + +/* Flag bits and data types for the extended class (OP_XCLASS) for classes that +contain UTF-8 characters with values greater than 255. */ + +#define XCL_NOT 0x01 /* Flag: this is a negative class */ +#define XCL_MAP 0x02 /* Flag: a 32-byte map is present */ + +#define XCL_END 0 /* Marks end of individual items */ +#define XCL_SINGLE 1 /* Single item (one multibyte char) follows */ +#define XCL_RANGE 2 /* A range (two multibyte chars) follows */ +#define XCL_PROP 3 /* Unicode property (one property code) follows */ +#define XCL_NOTPROP 4 /* Unicode inverted property (ditto) */ + + +/* Opcode table: OP_BRA must be last, as all values >= it are used for brackets +that extract substrings. Starting from 1 (i.e. after OP_END), the values up to +OP_EOD must correspond in order to the list of escapes immediately above. +Note that whenever this list is updated, the two macro definitions that follow +must also be updated to match. */ + +enum { + OP_END, /* 0 End of pattern */ + + /* Values corresponding to backslashed metacharacters */ + + OP_SOD, /* 1 Start of data: \A */ + OP_SOM, /* 2 Start of match (subject + offset): \G */ + OP_NOT_WORD_BOUNDARY, /* 3 \B */ + OP_WORD_BOUNDARY, /* 4 \b */ + OP_NOT_DIGIT, /* 5 \D */ + OP_DIGIT, /* 6 \d */ + OP_NOT_WHITESPACE, /* 7 \S */ + OP_WHITESPACE, /* 8 \s */ + OP_NOT_WORDCHAR, /* 9 \W */ + OP_WORDCHAR, /* 10 \w */ + OP_ANY, /* 11 Match any character */ + OP_ANYBYTE, /* 12 Match any byte (\C); different to OP_ANY for UTF-8 */ + OP_NOTPROP, /* 13 \P (not Unicode property) */ + OP_PROP, /* 14 \p (Unicode property) */ + OP_EXTUNI, /* 15 \X (extended Unicode sequence */ + OP_EODN, /* 16 End of data or \n at end of data: \Z. */ + OP_EOD, /* 17 End of data: \z */ + + OP_OPT, /* 18 Set runtime options */ + OP_CIRC, /* 19 Start of line - varies with multiline switch */ + OP_DOLL, /* 20 End of line - varies with multiline switch */ + OP_CHAR, /* 21 Match one character, casefully */ + OP_CHARNC, /* 22 Match one character, caselessly */ + OP_NOT, /* 23 Match anything but the following char */ + + OP_STAR, /* 24 The maximizing and minimizing versions of */ + OP_MINSTAR, /* 25 all these opcodes must come in pairs, with */ + OP_PLUS, /* 26 the minimizing one second. */ + OP_MINPLUS, /* 27 This first set applies to single characters */ + OP_QUERY, /* 28 */ + OP_MINQUERY, /* 29 */ + OP_UPTO, /* 30 From 0 to n matches */ + OP_MINUPTO, /* 31 */ + OP_EXACT, /* 32 Exactly n matches */ + + OP_NOTSTAR, /* 33 The maximizing and minimizing versions of */ + OP_NOTMINSTAR, /* 34 all these opcodes must come in pairs, with */ + OP_NOTPLUS, /* 35 the minimizing one second. */ + OP_NOTMINPLUS, /* 36 This set applies to "not" single characters */ + OP_NOTQUERY, /* 37 */ + OP_NOTMINQUERY, /* 38 */ + OP_NOTUPTO, /* 39 From 0 to n matches */ + OP_NOTMINUPTO, /* 40 */ + OP_NOTEXACT, /* 41 Exactly n matches */ + + OP_TYPESTAR, /* 42 The maximizing and minimizing versions of */ + OP_TYPEMINSTAR, /* 43 all these opcodes must come in pairs, with */ + OP_TYPEPLUS, /* 44 the minimizing one second. These codes must */ + OP_TYPEMINPLUS, /* 45 be in exactly the same order as those above. */ + OP_TYPEQUERY, /* 46 This set applies to character types such as \d */ + OP_TYPEMINQUERY, /* 47 */ + OP_TYPEUPTO, /* 48 From 0 to n matches */ + OP_TYPEMINUPTO, /* 49 */ + OP_TYPEEXACT, /* 50 Exactly n matches */ + + OP_CRSTAR, /* 51 The maximizing and minimizing versions of */ + OP_CRMINSTAR, /* 52 all these opcodes must come in pairs, with */ + OP_CRPLUS, /* 53 the minimizing one second. These codes must */ + OP_CRMINPLUS, /* 54 be in exactly the same order as those above. */ + OP_CRQUERY, /* 55 These are for character classes and back refs */ + OP_CRMINQUERY, /* 56 */ + OP_CRRANGE, /* 57 These are different to the three sets above. */ + OP_CRMINRANGE, /* 58 */ + + OP_CLASS, /* 59 Match a character class, chars < 256 only */ + OP_NCLASS, /* 60 Same, but the bitmap was created from a negative + class - the difference is relevant only when a UTF-8 + character > 255 is encountered. */ + + OP_XCLASS, /* 61 Extended class for handling UTF-8 chars within the + class. This does both positive and negative. */ + + OP_REF, /* 62 Match a back reference */ + OP_RECURSE, /* 63 Match a numbered subpattern (possibly recursive) */ + OP_CALLOUT, /* 64 Call out to external function if provided */ + + OP_ALT, /* 65 Start of alternation */ + OP_KET, /* 66 End of group that doesn't have an unbounded repeat */ + OP_KETRMAX, /* 67 These two must remain together and in this */ + OP_KETRMIN, /* 68 order. They are for groups the repeat for ever. */ + + /* The assertions must come before ONCE and COND */ + + OP_ASSERT, /* 69 Positive lookahead */ + OP_ASSERT_NOT, /* 70 Negative lookahead */ + OP_ASSERTBACK, /* 71 Positive lookbehind */ + OP_ASSERTBACK_NOT, /* 72 Negative lookbehind */ + OP_REVERSE, /* 73 Move pointer back - used in lookbehind assertions */ + + /* ONCE and COND must come after the assertions, with ONCE first, as there's + a test for >= ONCE for a subpattern that isn't an assertion. */ + + OP_ONCE, /* 74 Once matched, don't back up into the subpattern */ + OP_COND, /* 75 Conditional group */ + OP_CREF, /* 76 Used to hold an extraction string number (cond ref) */ + + OP_BRAZERO, /* 77 These two must remain together and in this */ + OP_BRAMINZERO, /* 78 order. */ + + OP_BRANUMBER, /* 79 Used for extracting brackets whose number is greater + than can fit into an opcode. */ + + OP_BRA /* 80 This and greater values are used for brackets that + extract substrings up to EXTRACT_BASIC_MAX. After + that, use is made of OP_BRANUMBER. */ +}; + +/* WARNING WARNING WARNING: There is an implicit assumption in pcre.c and +study.c that all opcodes are less than 128 in value. This makes handling UTF-8 +character sequences easier. */ + +/* The highest extraction number before we have to start using additional +bytes. (Originally PCRE didn't have support for extraction counts highter than +this number.) The value is limited by the number of opcodes left after OP_BRA, +i.e. 255 - OP_BRA. We actually set it a bit lower to leave room for additional +opcodes. */ + +#define EXTRACT_BASIC_MAX 100 + + +/* This macro defines textual names for all the opcodes. These are used only +for debugging. The macro is referenced only in pcre_printint.c. */ + +#define OP_NAME_LIST \ + "End", "\\A", "\\G", "\\B", "\\b", "\\D", "\\d", \ + "\\S", "\\s", "\\W", "\\w", "Any", "Anybyte", \ + "notprop", "prop", "extuni", \ + "\\Z", "\\z", \ + "Opt", "^", "$", "char", "charnc", "not", \ + "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \ + "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \ + "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \ + "*", "*?", "+", "+?", "?", "??", "{", "{", \ + "class", "nclass", "xclass", "Ref", "Recurse", "Callout", \ + "Alt", "Ket", "KetRmax", "KetRmin", "Assert", "Assert not", \ + "AssertB", "AssertB not", "Reverse", "Once", "Cond", "Cond ref",\ + "Brazero", "Braminzero", "Branumber", "Bra" + + +/* This macro defines the length of fixed length operations in the compiled +regex. The lengths are used when searching for specific things, and also in the +debugging printing of a compiled regex. We use a macro so that it can be +defined close to the definitions of the opcodes themselves. + +As things have been extended, some of these are no longer fixed lenths, but are +minima instead. For example, the length of a single-character repeat may vary +in UTF-8 mode. The code that uses this table must know about such things. */ + +#define OP_LENGTHS \ + 1, /* End */ \ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* \A, \G, \B, \B, \D, \d, \S, \s, \W, \w */ \ + 1, 1, /* Any, Anybyte */ \ + 2, 2, 1, /* NOTPROP, PROP, EXTUNI */ \ + 1, 1, 2, 1, 1, /* \Z, \z, Opt, ^, $ */ \ + 2, /* Char - the minimum length */ \ + 2, /* Charnc - the minimum length */ \ + 2, /* not */ \ + /* Positive single-char repeats ** These are */ \ + 2, 2, 2, 2, 2, 2, /* *, *?, +, +?, ?, ?? ** minima in */ \ + 4, 4, 4, /* upto, minupto, exact ** UTF-8 mode */ \ + /* Negative single-char repeats - only for chars < 256 */ \ + 2, 2, 2, 2, 2, 2, /* NOT *, *?, +, +?, ?, ?? */ \ + 4, 4, 4, /* NOT upto, minupto, exact */ \ + /* Positive type repeats */ \ + 2, 2, 2, 2, 2, 2, /* Type *, *?, +, +?, ?, ?? */ \ + 4, 4, 4, /* Type upto, minupto, exact */ \ + /* Character class & ref repeats */ \ + 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */ \ + 5, 5, /* CRRANGE, CRMINRANGE */ \ + 33, /* CLASS */ \ + 33, /* NCLASS */ \ + 0, /* XCLASS - variable length */ \ + 3, /* REF */ \ + 1+LINK_SIZE, /* RECURSE */ \ + 2+2*LINK_SIZE, /* CALLOUT */ \ + 1+LINK_SIZE, /* Alt */ \ + 1+LINK_SIZE, /* Ket */ \ + 1+LINK_SIZE, /* KetRmax */ \ + 1+LINK_SIZE, /* KetRmin */ \ + 1+LINK_SIZE, /* Assert */ \ + 1+LINK_SIZE, /* Assert not */ \ + 1+LINK_SIZE, /* Assert behind */ \ + 1+LINK_SIZE, /* Assert behind not */ \ + 1+LINK_SIZE, /* Reverse */ \ + 1+LINK_SIZE, /* Once */ \ + 1+LINK_SIZE, /* COND */ \ + 3, /* CREF */ \ + 1, 1, /* BRAZERO, BRAMINZERO */ \ + 3, /* BRANUMBER */ \ + 1+LINK_SIZE /* BRA */ \ + + +/* A magic value for OP_CREF to indicate the "in recursion" condition. */ + +#define CREF_RECURSE 0xffff + +/* Error code numbers. They are given names so that they can more easily be +tracked. */ + +enum { ERR0, ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9, + ERR10, ERR11, ERR12, ERR13, ERR14, ERR15, ERR16, ERR17, ERR18, ERR19, + ERR20, ERR21, ERR22, ERR23, ERR24, ERR25, ERR26, ERR27, ERR28, ERR29, + ERR30, ERR31, ERR32, ERR33, ERR34, ERR35, ERR36, ERR37, ERR38, ERR39, + ERR40, ERR41, ERR42, ERR43, ERR44, ERR45, ERR46, ERR47 }; + +/* The real format of the start of the pcre block; the index of names and the +code vector run on as long as necessary after the end. We store an explicit +offset to the name table so that if a regex is compiled on one host, saved, and +then run on another where the size of pointers is different, all might still +be well. For the case of compiled-on-4 and run-on-8, we include an extra +pointer that is always NULL. For future-proofing, a few dummy fields were +originally included - even though you can never get this planning right - but +there is only one left now. + +NOTE NOTE NOTE: +Because people can now save and re-use compiled patterns, any additions to this +structure should be made at the end, and something earlier (e.g. a new +flag in the options or one of the dummy fields) should indicate that the new +fields are present. Currently PCRE always sets the dummy fields to zero. +NOTE NOTE NOTE: +*/ + +typedef struct real_pcre { + pcre_uint32 magic_number; + pcre_uint32 size; /* Total that was malloced */ + pcre_uint32 options; + pcre_uint32 dummy1; /* For future use, maybe */ + + pcre_uint16 top_bracket; + pcre_uint16 top_backref; + pcre_uint16 first_byte; + pcre_uint16 req_byte; + pcre_uint16 name_table_offset; /* Offset to name table that follows */ + pcre_uint16 name_entry_size; /* Size of any name items */ + pcre_uint16 name_count; /* Number of name items */ + pcre_uint16 ref_count; /* Reference count */ + + const unsigned char *tables; /* Pointer to tables or NULL for std */ + const unsigned char *nullpad; /* NULL padding */ +} real_pcre; + +/* The format of the block used to store data from pcre_study(). The same +remark (see NOTE above) about extending this structure applies. */ + +typedef struct pcre_study_data { + pcre_uint32 size; /* Total that was malloced */ + pcre_uint32 options; + uschar start_bits[32]; +} pcre_study_data; + +/* Structure for passing "static" information around between the functions +doing the compiling, so that they are thread-safe. */ + +typedef struct compile_data { + const uschar *lcc; /* Points to lower casing table */ + const uschar *fcc; /* Points to case-flipping table */ + const uschar *cbits; /* Points to character type table */ + const uschar *ctypes; /* Points to table of type maps */ + const uschar *start_code; /* The start of the compiled code */ + const uschar *start_pattern; /* The start of the pattern */ + uschar *name_table; /* The name/number table */ + int names_found; /* Number of entries so far */ + int name_entry_size; /* Size of each entry */ + int top_backref; /* Maximum back reference */ + unsigned int backref_map; /* Bitmap of low back refs */ + int req_varyopt; /* "After variable item" flag for reqbyte */ + BOOL nopartial; /* Set TRUE if partial won't work */ +} compile_data; + +/* Structure for maintaining a chain of pointers to the currently incomplete +branches, for testing for left recursion. */ + +typedef struct branch_chain { + struct branch_chain *outer; + uschar *current; +} branch_chain; + +/* Structure for items in a linked list that represents an explicit recursive +call within the pattern. */ + +typedef struct recursion_info { + struct recursion_info *prevrec; /* Previous recursion record (or NULL) */ + int group_num; /* Number of group that was called */ + const uschar *after_call; /* "Return value": points after the call in the expr */ + const uschar *save_start; /* Old value of md->start_match */ + int *offset_save; /* Pointer to start of saved offsets */ + int saved_max; /* Number of saved offsets */ +} recursion_info; + +/* When compiling in a mode that doesn't use recursive calls to match(), +a structure is used to remember local variables on the heap. It is defined in +pcre.c, close to the match() function, so that it is easy to keep it in step +with any changes of local variable. However, the pointer to the current frame +must be saved in some "static" place over a longjmp(). We declare the +structure here so that we can put a pointer in the match_data structure. +NOTE: This isn't used for a "normal" compilation of pcre. */ + +struct heapframe; + +/* Structure for passing "static" information around between the functions +doing traditional NFA matching, so that they are thread-safe. */ + +typedef struct match_data { + unsigned long int match_call_count; /* As it says */ + unsigned long int match_limit;/* As it says */ + int *offset_vector; /* Offset vector */ + int offset_end; /* One past the end */ + int offset_max; /* The maximum usable for return data */ + const uschar *lcc; /* Points to lower casing table */ + const uschar *ctypes; /* Points to table of type maps */ + BOOL offset_overflow; /* Set if too many extractions */ + BOOL notbol; /* NOTBOL flag */ + BOOL noteol; /* NOTEOL flag */ + BOOL utf8; /* UTF8 flag */ + BOOL endonly; /* Dollar not before final \n */ + BOOL notempty; /* Empty string match not wanted */ + BOOL partial; /* PARTIAL flag */ + BOOL hitend; /* Hit the end of the subject at some point */ + const uschar *start_code; /* For use when recursing */ + const uschar *start_subject; /* Start of the subject string */ + const uschar *end_subject; /* End of the subject string */ + const uschar *start_match; /* Start of this match attempt */ + const uschar *end_match_ptr; /* Subject position at end match */ + int end_offset_top; /* Highwater mark at end of match */ + int capture_last; /* Most recent capture number */ + int start_offset; /* The start offset value */ + recursion_info *recursive; /* Linked list of recursion data */ + void *callout_data; /* To pass back to callouts */ + struct heapframe *thisframe; /* Used only when compiling for no recursion */ +} match_data; + +/* A similar structure is used for the same purpose by the DFA matching +functions. */ + +typedef struct dfa_match_data { + const uschar *start_code; /* Start of the compiled pattern */ + const uschar *start_subject; /* Start of the subject string */ + const uschar *end_subject; /* End of subject string */ + const uschar *tables; /* Character tables */ + int moptions; /* Match options */ + int poptions; /* Pattern options */ + void *callout_data; /* To pass back to callouts */ +} dfa_match_data; + +/* Bit definitions for entries in the pcre_ctypes table. */ + +#define ctype_space 0x01 +#define ctype_letter 0x02 +#define ctype_digit 0x04 +#define ctype_xdigit 0x08 +#define ctype_word 0x10 /* alphameric or '_' */ +#define ctype_meta 0x80 /* regexp meta char or zero (end pattern) */ + +/* Offsets for the bitmap tables in pcre_cbits. Each table contains a set +of bits for a class map. Some classes are built by combining these tables. */ + +#define cbit_space 0 /* [:space:] or \s */ +#define cbit_xdigit 32 /* [:xdigit:] */ +#define cbit_digit 64 /* [:digit:] or \d */ +#define cbit_upper 96 /* [:upper:] */ +#define cbit_lower 128 /* [:lower:] */ +#define cbit_word 160 /* [:word:] or \w */ +#define cbit_graph 192 /* [:graph:] */ +#define cbit_print 224 /* [:print:] */ +#define cbit_punct 256 /* [:punct:] */ +#define cbit_cntrl 288 /* [:cntrl:] */ +#define cbit_length 320 /* Length of the cbits table */ + +/* Offsets of the various tables from the base tables pointer, and +total length. */ + +#define lcc_offset 0 +#define fcc_offset 256 +#define cbits_offset 512 +#define ctypes_offset (cbits_offset + cbit_length) +#define tables_length (ctypes_offset + 256) + +/* Layout of the UCP type table that translates property names into codes for +ucp_findchar(). */ + +typedef struct { + const char *name; + int value; +} ucp_type_table; + + +/* Internal shared data tables. These are tables that are used by more than one +of the exported public functions. They have to be "external" in the C sense, +but are not part of the PCRE public API. The data for these tables is in the +pcre_tables.c module. */ + +extern const int _pcre_utf8_table1[]; +extern const int _pcre_utf8_table2[]; +extern const int _pcre_utf8_table3[]; +extern const uschar _pcre_utf8_table4[]; + +extern const int _pcre_utf8_table1_size; + +extern const ucp_type_table _pcre_utt[]; +extern const int _pcre_utt_size; + +extern const uschar _pcre_default_tables[]; + +extern const uschar _pcre_OP_lengths[]; + + +/* Internal shared functions. These are functions that are used by more than +one of the exported public functions. They have to be "external" in the C +sense, but are not part of the PCRE public API. */ + +extern int _pcre_ord2utf8(int, uschar *); +extern void _pcre_printint(pcre *, FILE *); +extern real_pcre * _pcre_try_flipped(const real_pcre *, real_pcre *, + const pcre_study_data *, pcre_study_data *); +extern int _pcre_ucp_findchar(const int, int *, int *); +extern int _pcre_valid_utf8(const uschar *, int); +extern BOOL _pcre_xclass(int, const uschar *); + +/* End of pcre_internal.h */ diff --git a/ext/pcre/pcrelib/maketables.c b/ext/pcre/pcrelib/pcre_maketables.c similarity index 62% rename from ext/pcre/pcrelib/maketables.c rename to ext/pcre/pcrelib/pcre_maketables.c index 8cfcd729c9c2..c4954b264817 100644 --- a/ext/pcre/pcrelib/maketables.c +++ b/ext/pcre/pcrelib/pcre_maketables.c @@ -2,48 +2,53 @@ * Perl-Compatible Regular Expressions * *************************************************/ -/* -PCRE is a library of functions to support regular expressions whose syntax +/* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. -Written by: Philip Hazel - - Copyright (c) 1997-2004 University of Cambridge + Written by Philip Hazel + Copyright (c) 1997-2005 University of Cambridge ----------------------------------------------------------------------------- -Permission is granted to anyone to use this software for any purpose on any -computer system, and to redistribute it freely, subject to the following -restrictions: - -1. This software is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -2. The origin of this software must not be misrepresented, either by - explicit claim or by omission. - -3. Altered versions must be plainly marked as such, and must not be - misrepresented as being the original software. - -4. If PCRE is embedded in any software that is released under the GNU - General Purpose Licence (GPL), then the terms of that licence shall - supersede any condition above with which it is incompatible. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------------------- - -See the file Tech.Notes for some information on the internals. */ -/* This file is compiled on its own as part of the PCRE library. However, -it is also included in the compilation of dftables.c, in which case the macro -DFTABLES is defined. */ +/* This module contains the external function pcre_maketables(), which builds +character tables for PCRE in the current locale. The file is compiled on its +own as part of the PCRE library. However, it is also included in the +compilation of dftables.c, in which case the macro DFTABLES is defined. */ + #ifndef DFTABLES -#include "internal.h" +#include "pcre_internal.h" #endif - /************************************************* * Create PCRE character tables * *************************************************/ @@ -137,4 +142,4 @@ for (i = 0; i < 256; i++) return yield; } -/* End of maketables.c */ +/* End of pcre_maketables.c */ diff --git a/ext/pcre/pcrelib/pcre_ord2utf8.c b/ext/pcre/pcrelib/pcre_ord2utf8.c new file mode 100644 index 000000000000..f6a06fc6eafe --- /dev/null +++ b/ext/pcre/pcrelib/pcre_ord2utf8.c @@ -0,0 +1,78 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2005 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This file contains a private PCRE function that converts an ordinal +character value into a UTF8 string. */ + + +#include "pcre_internal.h" + + +/************************************************* +* Convert character value to UTF-8 * +*************************************************/ + +/* This function takes an integer value in the range 0 - 0x7fffffff +and encodes it as a UTF-8 character in 0 to 6 bytes. + +Arguments: + cvalue the character value + buffer pointer to buffer for result - at least 6 bytes long + +Returns: number of characters placed in the buffer +*/ + +EXPORT int +_pcre_ord2utf8(int cvalue, uschar *buffer) +{ +register int i, j; +for (i = 0; i < _pcre_utf8_table1_size; i++) + if (cvalue <= _pcre_utf8_table1[i]) break; +buffer += i; +for (j = i; j > 0; j--) + { + *buffer-- = 0x80 | (cvalue & 0x3f); + cvalue >>= 6; + } +*buffer = _pcre_utf8_table2[i] | cvalue; +return i + 1; +} + +/* End of pcre_ord2utf8.c */ diff --git a/ext/pcre/pcrelib/pcre_printint.c b/ext/pcre/pcrelib/pcre_printint.c new file mode 100644 index 000000000000..d18f39925272 --- /dev/null +++ b/ext/pcre/pcrelib/pcre_printint.c @@ -0,0 +1,451 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2005 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains an PCRE private debugging function for printing out the +internal form of a compiled regular expression, along with some supporting +local functions. */ + + +#include "pcre_internal.h" + + +static const char *OP_names[] = { OP_NAME_LIST }; + + +/************************************************* +* Print single- or multi-byte character * +*************************************************/ + +static int +print_char(FILE *f, uschar *ptr, BOOL utf8) +{ +int c = *ptr; + +if (!utf8 || (c & 0xc0) != 0xc0) + { + if (isprint(c)) fprintf(f, "%c", c); else fprintf(f, "\\x%02x", c); + return 0; + } +else + { + int i; + int a = _pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */ + int s = 6*a; + c = (c & _pcre_utf8_table3[a]) << s; + for (i = 1; i <= a; i++) + { + /* This is a check for malformed UTF-8; it should only occur if the sanity + check has been turned off. Rather than swallow random bytes, just stop if + we hit a bad one. Print it with \X instead of \x as an indication. */ + + if ((ptr[i] & 0xc0) != 0x80) + { + fprintf(f, "\\X{%x}", c); + return i - 1; + } + + /* The byte is OK */ + + s -= 6; + c |= (ptr[i] & 0x3f) << s; + } + if (c < 128) fprintf(f, "\\x%02x", c); else fprintf(f, "\\x{%x}", c); + return a; + } +} + + + +/************************************************* +* Find Unicode property name * +*************************************************/ + +static const char * +get_ucpname(int property) +{ +#ifdef SUPPORT_UCP +int i; +for (i = _pcre_utt_size; i >= 0; i--) + { + if (property == _pcre_utt[i].value) break; + } +return (i >= 0)? _pcre_utt[i].name : "??"; +#else +return "??"; +#endif +} + + + +/************************************************* +* Print compiled regex * +*************************************************/ + +/* Make this function work for a regex with integers either byte order. +However, we assume that what we are passed is a compiled regex. */ + +EXPORT void +_pcre_printint(pcre *external_re, FILE *f) +{ +real_pcre *re = (real_pcre *)external_re; +uschar *codestart, *code; +BOOL utf8; + +unsigned int options = re->options; +int offset = re->name_table_offset; +int count = re->name_count; +int size = re->name_entry_size; + +if (re->magic_number != MAGIC_NUMBER) + { + offset = ((offset << 8) & 0xff00) | ((offset >> 8) & 0xff); + count = ((count << 8) & 0xff00) | ((count >> 8) & 0xff); + size = ((size << 8) & 0xff00) | ((size >> 8) & 0xff); + options = ((options << 24) & 0xff000000) | + ((options << 8) & 0x00ff0000) | + ((options >> 8) & 0x0000ff00) | + ((options >> 24) & 0x000000ff); + } + +code = codestart = (uschar *)re + offset + count * size; +utf8 = (options & PCRE_UTF8) != 0; + +for(;;) + { + uschar *ccode; + int c; + int extra = 0; + + fprintf(f, "%3d ", (int)(code - codestart)); + + if (*code >= OP_BRA) + { + if (*code - OP_BRA > EXTRACT_BASIC_MAX) + fprintf(f, "%3d Bra extra\n", GET(code, 1)); + else + fprintf(f, "%3d Bra %d\n", GET(code, 1), *code - OP_BRA); + code += _pcre_OP_lengths[OP_BRA]; + continue; + } + + switch(*code) + { + case OP_END: + fprintf(f, " %s\n", OP_names[*code]); + fprintf(f, "------------------------------------------------------------------\n"); + return; + + case OP_OPT: + fprintf(f, " %.2x %s", code[1], OP_names[*code]); + break; + + case OP_CHAR: + { + fprintf(f, " "); + do + { + code++; + code += 1 + print_char(f, code, utf8); + } + while (*code == OP_CHAR); + fprintf(f, "\n"); + continue; + } + break; + + case OP_CHARNC: + { + fprintf(f, " NC "); + do + { + code++; + code += 1 + print_char(f, code, utf8); + } + while (*code == OP_CHARNC); + fprintf(f, "\n"); + continue; + } + break; + + case OP_KETRMAX: + case OP_KETRMIN: + case OP_ALT: + case OP_KET: + case OP_ASSERT: + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + case OP_ONCE: + case OP_COND: + case OP_REVERSE: + fprintf(f, "%3d %s", GET(code, 1), OP_names[*code]); + break; + + case OP_BRANUMBER: + printf("%3d %s", GET2(code, 1), OP_names[*code]); + break; + + case OP_CREF: + if (GET2(code, 1) == CREF_RECURSE) + fprintf(f, " Cond recurse"); + else + fprintf(f, "%3d %s", GET2(code,1), OP_names[*code]); + break; + + case OP_STAR: + case OP_MINSTAR: + case OP_PLUS: + case OP_MINPLUS: + case OP_QUERY: + case OP_MINQUERY: + case OP_TYPESTAR: + case OP_TYPEMINSTAR: + case OP_TYPEPLUS: + case OP_TYPEMINPLUS: + case OP_TYPEQUERY: + case OP_TYPEMINQUERY: + fprintf(f, " "); + if (*code >= OP_TYPESTAR) + { + fprintf(f, "%s", OP_names[code[1]]); + if (code[1] == OP_PROP || code[1] == OP_NOTPROP) + { + fprintf(f, " %s ", get_ucpname(code[2])); + extra = 1; + } + } + else extra = print_char(f, code+1, utf8); + fprintf(f, "%s", OP_names[*code]); + break; + + case OP_EXACT: + case OP_UPTO: + case OP_MINUPTO: + fprintf(f, " "); + extra = print_char(f, code+3, utf8); + fprintf(f, "{"); + if (*code != OP_EXACT) fprintf(f, ","); + fprintf(f, "%d}", GET2(code,1)); + if (*code == OP_MINUPTO) fprintf(f, "?"); + break; + + case OP_TYPEEXACT: + case OP_TYPEUPTO: + case OP_TYPEMINUPTO: + fprintf(f, " %s", OP_names[code[3]]); + if (code[3] == OP_PROP || code[3] == OP_NOTPROP) + { + fprintf(f, " %s ", get_ucpname(code[4])); + extra = 1; + } + fprintf(f, "{"); + if (*code != OP_TYPEEXACT) fprintf(f, "0,"); + fprintf(f, "%d}", GET2(code,1)); + if (*code == OP_TYPEMINUPTO) fprintf(f, "?"); + break; + + case OP_NOT: + if (isprint(c = code[1])) fprintf(f, " [^%c]", c); + else fprintf(f, " [^\\x%02x]", c); + break; + + case OP_NOTSTAR: + case OP_NOTMINSTAR: + case OP_NOTPLUS: + case OP_NOTMINPLUS: + case OP_NOTQUERY: + case OP_NOTMINQUERY: + if (isprint(c = code[1])) fprintf(f, " [^%c]", c); + else fprintf(f, " [^\\x%02x]", c); + fprintf(f, "%s", OP_names[*code]); + break; + + case OP_NOTEXACT: + case OP_NOTUPTO: + case OP_NOTMINUPTO: + if (isprint(c = code[3])) fprintf(f, " [^%c]{", c); + else fprintf(f, " [^\\x%02x]{", c); + if (*code != OP_NOTEXACT) fprintf(f, "0,"); + fprintf(f, "%d}", GET2(code,1)); + if (*code == OP_NOTMINUPTO) fprintf(f, "?"); + break; + + case OP_RECURSE: + fprintf(f, "%3d %s", GET(code, 1), OP_names[*code]); + break; + + case OP_REF: + fprintf(f, " \\%d", GET2(code,1)); + ccode = code + _pcre_OP_lengths[*code]; + goto CLASS_REF_REPEAT; + + case OP_CALLOUT: + fprintf(f, " %s %d %d %d", OP_names[*code], code[1], GET(code,2), + GET(code, 2 + LINK_SIZE)); + break; + + case OP_PROP: + case OP_NOTPROP: + fprintf(f, " %s %s", OP_names[*code], get_ucpname(code[1])); + break; + + /* OP_XCLASS can only occur in UTF-8 mode. However, there's no harm in + having this code always here, and it makes it less messy without all those + #ifdefs. */ + + case OP_CLASS: + case OP_NCLASS: + case OP_XCLASS: + { + int i, min, max; + BOOL printmap; + + fprintf(f, " ["); + + if (*code == OP_XCLASS) + { + extra = GET(code, 1); + ccode = code + LINK_SIZE + 1; + printmap = (*ccode & XCL_MAP) != 0; + if ((*ccode++ & XCL_NOT) != 0) fprintf(f, "^"); + } + else + { + printmap = TRUE; + ccode = code + 1; + } + + /* Print a bit map */ + + if (printmap) + { + for (i = 0; i < 256; i++) + { + if ((ccode[i/8] & (1 << (i&7))) != 0) + { + int j; + for (j = i+1; j < 256; j++) + if ((ccode[j/8] & (1 << (j&7))) == 0) break; + if (i == '-' || i == ']') fprintf(f, "\\"); + if (isprint(i)) fprintf(f, "%c", i); else fprintf(f, "\\x%02x", i); + if (--j > i) + { + if (j != i + 1) fprintf(f, "-"); + if (j == '-' || j == ']') fprintf(f, "\\"); + if (isprint(j)) fprintf(f, "%c", j); else fprintf(f, "\\x%02x", j); + } + i = j; + } + } + ccode += 32; + } + + /* For an XCLASS there is always some additional data */ + + if (*code == OP_XCLASS) + { + int ch; + while ((ch = *ccode++) != XCL_END) + { + if (ch == XCL_PROP) + { + fprintf(f, "\\p{%s}", get_ucpname(*ccode++)); + } + else if (ch == XCL_NOTPROP) + { + fprintf(f, "\\P{%s}", get_ucpname(*ccode++)); + } + else + { + ccode += 1 + print_char(f, ccode, TRUE); + if (ch == XCL_RANGE) + { + fprintf(f, "-"); + ccode += 1 + print_char(f, ccode, TRUE); + } + } + } + } + + /* Indicate a non-UTF8 class which was created by negation */ + + fprintf(f, "]%s", (*code == OP_NCLASS)? " (neg)" : ""); + + /* Handle repeats after a class or a back reference */ + + CLASS_REF_REPEAT: + switch(*ccode) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRPLUS: + case OP_CRMINPLUS: + case OP_CRQUERY: + case OP_CRMINQUERY: + fprintf(f, "%s", OP_names[*ccode]); + extra += _pcre_OP_lengths[*ccode]; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + min = GET2(ccode,1); + max = GET2(ccode,3); + if (max == 0) fprintf(f, "{%d,}", min); + else fprintf(f, "{%d,%d}", min, max); + if (*ccode == OP_CRMINRANGE) fprintf(f, "?"); + extra += _pcre_OP_lengths[*ccode]; + break; + } + } + break; + + /* Anything else is just an item with no data*/ + + default: + fprintf(f, " %s", OP_names[*code]); + break; + } + + code += _pcre_OP_lengths[*code] + extra; + fprintf(f, "\n"); + } +} + +/* End of pcre_printint.c */ diff --git a/ext/pcre/pcrelib/pcre_refcount.c b/ext/pcre/pcrelib/pcre_refcount.c new file mode 100644 index 000000000000..35a7ee869113 --- /dev/null +++ b/ext/pcre/pcrelib/pcre_refcount.c @@ -0,0 +1,77 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2005 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains the external function pcre_refcount(), which is an +auxiliary function that can be used to maintain a reference count in a compiled +pattern data block. This might be helpful in applications where the block is +shared by different users. */ + +#include "pcre_internal.h" + + +/************************************************* +* Maintain reference count * +*************************************************/ + +/* The reference count is a 16-bit field, initialized to zero. It is not +possible to transfer a non-zero count from one host to a different host that +has a different byte order - though I can't see why anyone in their right mind +would ever want to do that! + +Arguments: + argument_re points to compiled code + adjust value to add to the count + +Returns: the (possibly updated) count value (a non-negative number), or + a negative error number +*/ + +EXPORT int +pcre_refcount(pcre *argument_re, int adjust) +{ +real_pcre *re = (real_pcre *)argument_re; +if (re == NULL) return PCRE_ERROR_NULL; +re->ref_count = (-adjust > re->ref_count)? 0 : + (adjust + re->ref_count > 65535)? 65535 : + re->ref_count + adjust; +return re->ref_count; +} + +/* End of pcre_refcount.c */ diff --git a/ext/pcre/pcrelib/pcre_scanner.cc b/ext/pcre/pcrelib/pcre_scanner.cc new file mode 100644 index 000000000000..4a66fdf0ba2a --- /dev/null +++ b/ext/pcre/pcrelib/pcre_scanner.cc @@ -0,0 +1,169 @@ +// Copyright (c) 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: Sanjay Ghemawat + +#include +#include // for count() +#include +#include "config.h" +#include "pcre_scanner.h" + +using std::vector; + +namespace pcrecpp { + +Scanner::Scanner() + : data_(), + input_(data_), + skip_(NULL), + should_skip_(false), + save_comments_(false), + comments_(NULL), + comments_offset_(0) { +} + +Scanner::Scanner(const string& in) + : data_(in), + input_(data_), + skip_(NULL), + should_skip_(false), + save_comments_(false), + comments_(NULL), + comments_offset_(0) { +} + +Scanner::~Scanner() { + delete skip_; + delete comments_; +} + +void Scanner::Skip(const char* re) { + delete skip_; + if (re != NULL) { + skip_ = new RE(re); + should_skip_ = true; + ConsumeSkip(); + } else { + skip_ = NULL; + should_skip_ = false; + } +} + +void Scanner::DisableSkip() { + assert(skip_ != NULL); + should_skip_ = false; +} + +void Scanner::EnableSkip() { + assert(skip_ != NULL); + should_skip_ = true; + ConsumeSkip(); +} + +int Scanner::LineNumber() const { + // TODO: Make it more efficient by keeping track of the last point + // where we computed line numbers and counting newlines since then. + return 1 + std::count(data_.data(), input_.data(), '\n'); +} + +int Scanner::Offset() const { + return input_.data() - data_.c_str(); +} + +bool Scanner::LookingAt(const RE& re) const { + int consumed; + return re.DoMatch(input_, RE::ANCHOR_START, &consumed, 0, 0); +} + + +bool Scanner::Consume(const RE& re, + const Arg& arg0, + const Arg& arg1, + const Arg& arg2) { + const bool result = re.Consume(&input_, arg0, arg1, arg2); + if (result && should_skip_) ConsumeSkip(); + return result; +} + +// helper function to consume *skip_ and honour save_comments_ +void Scanner::ConsumeSkip() { + if (save_comments_) { + if (NULL == comments_) { + comments_ = new vector; + } + const char *start_data = input_.data(); + skip_->Consume(&input_); + // already pointing one past end, so no need to +1 + int length = input_.data() - start_data; + if (length > 0) { + comments_->push_back(StringPiece(start_data, length)); + } + } else { + skip_->Consume(&input_); + } +} + + +void Scanner::GetComments(int start, int end, vector *ranges) { + // short circuit out if we've not yet initialized comments_ + // (e.g., when save_comments is false) + if (!comments_) { + return; + } + // TODO: if we guarantee that comments_ will contain StringPieces + // that are ordered by their start, then we can do a binary search + // for the first StringPiece at or past start and then scan for the + // ones contained in the range, quit early (use equal_range or + // lower_bound) + for (vector::const_iterator it = comments_->begin(); + it != comments_->end(); ++it) { + if ((it->data() >= data_.c_str() + start && + it->data() + it->size() <= data_.c_str() + end)) { + ranges->push_back(*it); + } + } +} + + +void Scanner::GetNextComments(vector *ranges) { + // short circuit out if we've not yet initialized comments_ + // (e.g., when save_comments is false) + if (!comments_) { + return; + } + for (vector::const_iterator it = + comments_->begin() + comments_offset_; + it != comments_->end(); ++it) { + ranges->push_back(*it); + ++comments_offset_; + } +} + +} // namespace pcrecpp diff --git a/ext/pcre/pcrelib/pcre_scanner.h b/ext/pcre/pcrelib/pcre_scanner.h new file mode 100644 index 000000000000..a73b72fd2d1c --- /dev/null +++ b/ext/pcre/pcrelib/pcre_scanner.h @@ -0,0 +1,163 @@ +// Copyright (c) 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: Sanjay Ghemawat +// +// Regular-expression based scanner for parsing an input stream. +// +// Example 1: parse a sequence of "var = number" entries from input: +// +// Scanner scanner(input); +// string var; +// int number; +// scanner.Skip("\\s+"); // Skip any white space we encounter +// while (scanner.Consume("(\\w+) = (\\d+)", &var, &number)) { +// ...; +// } + +#ifndef _PCRE_SCANNER_H +#define _PCRE_SCANNER_H + +#include +#include +#include +#include +#include + +namespace pcrecpp { + +class Scanner { + public: + Scanner(); + explicit Scanner(const std::string& input); + ~Scanner(); + + // Return current line number. The returned line-number is + // one-based. I.e. it returns 1 + the number of consumed newlines. + // + // Note: this method may be slow. It may take time proportional to + // the size of the input. + int LineNumber() const; + + // Return the byte-offset that the scanner is looking in the + // input data; + int Offset() const; + + // Return true iff the start of the remaining input matches "re" + bool LookingAt(const RE& re) const; + + // Return true iff all of the following are true + // a. the start of the remaining input matches "re", + // b. if any arguments are supplied, matched sub-patterns can be + // parsed and stored into the arguments. + // If it returns true, it skips over the matched input and any + // following input that matches the "skip" regular expression. + bool Consume(const RE& re, + const Arg& arg0 = no_arg, + const Arg& arg1 = no_arg, + const Arg& arg2 = no_arg + // TODO: Allow more arguments? + ); + + // Set the "skip" regular expression. If after consuming some data, + // a prefix of the input matches this RE, it is automatically + // skipped. For example, a programming language scanner would use + // a skip RE that matches white space and comments. + // + // scanner.Skip("(\\s|//.*|/[*](.|\n)*?[*]/)*"); + // + // You can pass NULL for "re" if you do not want any data to be skipped. + void Skip(const char* re); + + // Temporarily pause "skip"ing. This + // Skip("Foo"); code ; DisableSkip(); code; EnableSkip() + // is similar to + // Skip("Foo"); code ; Skip(NULL); code ; Skip("Foo"); + // but avoids creating/deleting new RE objects. + void DisableSkip(); + + // Reenable previously paused skipping. Any prefix of the input + // that matches the skip pattern is immediately dropped. + void EnableSkip(); + + /***** Special wrappers around SetSkip() for some common idioms *****/ + + // Arranges to skip whitespace, C comments, C++ comments. + // The overall RE is a repeated disjunction of the following REs: + // \\s whitespace + // //.*\n C++ comment + // /[*](.|\n)*?[*]/ C comment (x*? means minimal repetitions of x) + void SkipCXXComments() { + Skip("((\\s|//.*\n|/[*](.|\n)*?[*]/)*)"); + } + + void set_save_comments(bool comments) { + save_comments_ = comments; + } + + bool save_comments() { + return save_comments_; + } + + // Append to vector ranges the comments found in the + // byte range [start,end] (inclusive) of the input data. + // Only comments that were extracted entirely within that + // range are returned: no range splitting of atomically-extracted + // comments is performed. + void GetComments(int start, int end, std::vector *ranges); + + // Append to vector ranges the comments added + // since the last time this was called. This + // functionality is provided for efficiency when + // interleaving scanning with parsing. + void GetNextComments(std::vector *ranges); + + private: + std::string data_; // All the input data + StringPiece input_; // Unprocessed input + RE* skip_; // If non-NULL, RE for skipping input + bool should_skip_; // If true, use skip_ + bool save_comments_; // If true, aggregate the skip expression + + // the skipped comments + // TODO: later consider requiring that the StringPieces be added + // in order by their start position + std::vector *comments_; + + // the offset into comments_ that has been returned by GetNextComments + int comments_offset_; + + // helper function to consume *skip_ and honour + // save_comments_ + void ConsumeSkip(); +}; + +} // namespace pcrecpp + +#endif /* _PCRE_SCANNER_H */ diff --git a/ext/pcre/pcrelib/pcre_scanner_unittest.cc b/ext/pcre/pcrelib/pcre_scanner_unittest.cc new file mode 100644 index 000000000000..e000a078d592 --- /dev/null +++ b/ext/pcre/pcrelib/pcre_scanner_unittest.cc @@ -0,0 +1,125 @@ +// Copyright (c) 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: Greg J. Badros +// +// Unittest for scanner, especially GetNextComments and GetComments() +// functionality. + +#include +#include +#include +#include + +// Dies with a fatal error if the two values are not equal. +#define CHECK_EQ(a, b) do { \ + if ( (a) != (b) ) { \ + fprintf(stderr, "%s:%d: Check failed because %s != %s\n", \ + __FILE__, __LINE__, #a, #b); \ + exit(1); \ + } \ +} while (0) + +using std::vector; +using pcrecpp::StringPiece; +using pcrecpp::Scanner; + +static void TestScanner() { + const char input[] = "\n" + "alpha = 1; // this sets alpha\n" + "bravo = 2; // bravo is set here\n" + "gamma = 33; /* and here is gamma */\n"; + + const char *re = "(\\w+) = (\\d+);"; + + Scanner s(input); + string var; + int number; + s.SkipCXXComments(); + s.set_save_comments(true); + vector comments; + + s.Consume(re, &var, &number); + CHECK_EQ(var, "alpha"); + CHECK_EQ(number, 1); + s.GetNextComments(&comments); + CHECK_EQ(comments.size(), 1); + CHECK_EQ(comments[0].as_string(), " // this sets alpha\n"); + comments.resize(0); + + s.Consume(re, &var, &number); + CHECK_EQ(var, "bravo"); + CHECK_EQ(number, 2); + s.GetNextComments(&comments); + CHECK_EQ(comments.size(), 1); + CHECK_EQ(comments[0].as_string(), " // bravo is set here\n"); + comments.resize(0); + + s.Consume(re, &var, &number); + CHECK_EQ(var, "gamma"); + CHECK_EQ(number, 33); + s.GetNextComments(&comments); + CHECK_EQ(comments.size(), 1); + CHECK_EQ(comments[0].as_string(), " /* and here is gamma */\n"); + comments.resize(0); + + s.GetComments(0, sizeof(input), &comments); + CHECK_EQ(comments.size(), 3); + CHECK_EQ(comments[0].as_string(), " // this sets alpha\n"); + CHECK_EQ(comments[1].as_string(), " // bravo is set here\n"); + CHECK_EQ(comments[2].as_string(), " /* and here is gamma */\n"); + comments.resize(0); + + s.GetComments(0, strchr(input, '/') - input, &comments); + CHECK_EQ(comments.size(), 0); + comments.resize(0); + + s.GetComments(strchr(input, '/') - input - 1, sizeof(input), + &comments); + CHECK_EQ(comments.size(), 3); + CHECK_EQ(comments[0].as_string(), " // this sets alpha\n"); + CHECK_EQ(comments[1].as_string(), " // bravo is set here\n"); + CHECK_EQ(comments[2].as_string(), " /* and here is gamma */\n"); + comments.resize(0); + + s.GetComments(strchr(input, '/') - input - 1, + strchr(input + 1, '\n') - input + 1, &comments); + CHECK_EQ(comments.size(), 1); + CHECK_EQ(comments[0].as_string(), " // this sets alpha\n"); + comments.resize(0); +} + +int main(int argc, char** argv) { + TestScanner(); + + // Done + printf("OK\n"); + + return 0; +} diff --git a/ext/pcre/pcrelib/pcre_stringpiece.cc b/ext/pcre/pcrelib/pcre_stringpiece.cc new file mode 100644 index 000000000000..dbdb509b3b64 --- /dev/null +++ b/ext/pcre/pcrelib/pcre_stringpiece.cc @@ -0,0 +1,39 @@ +// Copyright (c) 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wilsonh@google.com (Wilson Hsieh) +// + +#include +#include "config.h" +#include "pcre_stringpiece.h" + +std::ostream& operator<<(std::ostream& o, const pcrecpp::StringPiece& piece) { + return (o << piece.as_string()); +} diff --git a/ext/pcre/pcrelib/pcre_stringpiece.h b/ext/pcre/pcrelib/pcre_stringpiece.h new file mode 100644 index 000000000000..89d5449651a4 --- /dev/null +++ b/ext/pcre/pcrelib/pcre_stringpiece.h @@ -0,0 +1,172 @@ +// Copyright (c) 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: Sanjay Ghemawat +// +// A string like object that points into another piece of memory. +// Useful for providing an interface that allows clients to easily +// pass in either a "const char*" or a "string". +// +// Arghh! I wish C++ literals were automatically of type "string". + +#ifndef _PCRE_STRINGPIECE_H +#define _PCRE_STRINGPIECE_H + +#include +#include +#include // for ostream forward-declaration + +#if 1 +#define HAVE_TYPE_TRAITS +#include +#elif 0 +#define HAVE_TYPE_TRAITS +#include +#endif + +using std::string; + +namespace pcrecpp { + +class StringPiece { + private: + const char* ptr_; + int length_; + + public: + // We provide non-explicit singleton constructors so users can pass + // in a "const char*" or a "string" wherever a "StringPiece" is + // expected. + StringPiece() + : ptr_(NULL), length_(0) { } + StringPiece(const char* str) + : ptr_(str), length_(static_cast(strlen(str))) { } + StringPiece(const string& str) + : ptr_(str.data()), length_(static_cast(str.size())) { } + StringPiece(const char* offset, int len) + : ptr_(offset), length_(len) { } + + // data() may return a pointer to a buffer with embedded NULs, and the + // returned buffer may or may not be null terminated. Therefore it is + // typically a mistake to pass data() to a routine that expects a NUL + // terminated string. Use "as_string().c_str()" if you really need to do + // this. Or better yet, change your routine so it does not rely on NUL + // termination. + const char* data() const { return ptr_; } + int size() const { return length_; } + bool empty() const { return length_ == 0; } + + void clear() { ptr_ = NULL; length_ = 0; } + void set(const char* buffer, int len) { ptr_ = buffer; length_ = len; } + void set(const char* str) { + ptr_ = str; + length_ = static_cast(strlen(str)); + } + void set(const void* buffer, int len) { + ptr_ = reinterpret_cast(buffer); + length_ = len; + } + + char operator[](int i) const { return ptr_[i]; } + + void remove_prefix(int n) { + ptr_ += n; + length_ -= n; + } + + void remove_suffix(int n) { + length_ -= n; + } + + bool operator==(const StringPiece& x) const { + return ((length_ == x.length_) && + (memcmp(ptr_, x.ptr_, length_) == 0)); + } + bool operator!=(const StringPiece& x) const { + return !(*this == x); + } + +#define STRINGPIECE_BINARY_PREDICATE(cmp,auxcmp) \ + bool operator cmp (const StringPiece& x) const { \ + int r = memcmp(ptr_, x.ptr_, length_ < x.length_ ? length_ : x.length_); \ + return ((r auxcmp 0) || ((r == 0) && (length_ cmp x.length_))); \ + } + STRINGPIECE_BINARY_PREDICATE(<, <); + STRINGPIECE_BINARY_PREDICATE(<=, <); + STRINGPIECE_BINARY_PREDICATE(>=, >); + STRINGPIECE_BINARY_PREDICATE(>, >); +#undef STRINGPIECE_BINARY_PREDICATE + + int compare(const StringPiece& x) const { + int r = memcmp(ptr_, x.ptr_, length_ < x.length_ ? length_ : x.length_); + if (r == 0) { + if (length_ < x.length_) r = -1; + else if (length_ > x.length_) r = +1; + } + return r; + } + + string as_string() const { + return string(data(), size()); + } + + void CopyToString(string* target) const { + target->assign(ptr_, length_); + } + + // Does "this" start with "x" + bool starts_with(const StringPiece& x) const { + return ((length_ >= x.length_) && (memcmp(ptr_, x.ptr_, x.length_) == 0)); + } +}; + +} // namespace pcrecpp + +// ------------------------------------------------------------------ +// Functions used to create STL containers that use StringPiece +// Remember that a StringPiece's lifetime had better be less than +// that of the underlying string or char*. If it is not, then you +// cannot safely store a StringPiece into an STL container +// ------------------------------------------------------------------ + +#ifdef HAVE_TYPE_TRAITS +// This makes vector really fast for some STL implementations +template<> struct __type_traits { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; +#endif + +// allow StringPiece to be logged +std::ostream& operator<<(std::ostream& o, const pcrecpp::StringPiece& piece); + +#endif /* _PCRE_STRINGPIECE_H */ diff --git a/ext/pcre/pcrelib/pcre_stringpiece_unittest.cc b/ext/pcre/pcrelib/pcre_stringpiece_unittest.cc new file mode 100644 index 000000000000..d6a89e8c7a29 --- /dev/null +++ b/ext/pcre/pcrelib/pcre_stringpiece_unittest.cc @@ -0,0 +1,145 @@ +// Copyright 2003 and onwards Google Inc. +// Author: Sanjay Ghemawat + +#include +#include +#include // for make_pair +#include + +// CHECK dies with a fatal error if condition is not true. It is *not* +// controlled by NDEBUG, so the check will be executed regardless of +// compilation mode. Therefore, it is safe to do things like: +// CHECK(fp->Write(x) == 4) +#define CHECK(condition) do { \ + if (!(condition)) { \ + fprintf(stderr, "%s:%d: Check failed: %s\n", \ + __FILE__, __LINE__, #condition); \ + exit(1); \ + } \ +} while (0) + +using std::map; +using std::make_pair; +using pcrecpp::StringPiece; + +static void CheckSTLComparator() { + string s1("foo"); + string s2("bar"); + string s3("baz"); + + StringPiece p1(s1); + StringPiece p2(s2); + StringPiece p3(s3); + + typedef map TestMap; + TestMap map; + + map.insert(make_pair(p1, 0)); + map.insert(make_pair(p2, 1)); + map.insert(make_pair(p3, 2)); + CHECK(map.size() == 3); + + TestMap::const_iterator iter = map.begin(); + CHECK(iter->second == 1); + ++iter; + CHECK(iter->second == 2); + ++iter; + CHECK(iter->second == 0); + ++iter; + CHECK(iter == map.end()); + + TestMap::iterator new_iter = map.find("zot"); + CHECK(new_iter == map.end()); + + new_iter = map.find("bar"); + CHECK(new_iter != map.end()); + + map.erase(new_iter); + CHECK(map.size() == 2); + + iter = map.begin(); + CHECK(iter->second == 2); + ++iter; + CHECK(iter->second == 0); + ++iter; + CHECK(iter == map.end()); +} + +static void CheckComparisonOperators() { +#define CMP_Y(op, x, y) \ + CHECK( (StringPiece((x)) op StringPiece((y)))); \ + CHECK( (StringPiece((x)).compare(StringPiece((y))) op 0)) + +#define CMP_N(op, x, y) \ + CHECK(!(StringPiece((x)) op StringPiece((y)))); \ + CHECK(!(StringPiece((x)).compare(StringPiece((y))) op 0)) + + CMP_Y(==, "", ""); + CMP_Y(==, "a", "a"); + CMP_Y(==, "aa", "aa"); + CMP_N(==, "a", ""); + CMP_N(==, "", "a"); + CMP_N(==, "a", "b"); + CMP_N(==, "a", "aa"); + CMP_N(==, "aa", "a"); + + CMP_N(!=, "", ""); + CMP_N(!=, "a", "a"); + CMP_N(!=, "aa", "aa"); + CMP_Y(!=, "a", ""); + CMP_Y(!=, "", "a"); + CMP_Y(!=, "a", "b"); + CMP_Y(!=, "a", "aa"); + CMP_Y(!=, "aa", "a"); + + CMP_Y(<, "a", "b"); + CMP_Y(<, "a", "aa"); + CMP_Y(<, "aa", "b"); + CMP_Y(<, "aa", "bb"); + CMP_N(<, "a", "a"); + CMP_N(<, "b", "a"); + CMP_N(<, "aa", "a"); + CMP_N(<, "b", "aa"); + CMP_N(<, "bb", "aa"); + + CMP_Y(<=, "a", "a"); + CMP_Y(<=, "a", "b"); + CMP_Y(<=, "a", "aa"); + CMP_Y(<=, "aa", "b"); + CMP_Y(<=, "aa", "bb"); + CMP_N(<=, "b", "a"); + CMP_N(<=, "aa", "a"); + CMP_N(<=, "b", "aa"); + CMP_N(<=, "bb", "aa"); + + CMP_N(>=, "a", "b"); + CMP_N(>=, "a", "aa"); + CMP_N(>=, "aa", "b"); + CMP_N(>=, "aa", "bb"); + CMP_Y(>=, "a", "a"); + CMP_Y(>=, "b", "a"); + CMP_Y(>=, "aa", "a"); + CMP_Y(>=, "b", "aa"); + CMP_Y(>=, "bb", "aa"); + + CMP_N(>, "a", "a"); + CMP_N(>, "a", "b"); + CMP_N(>, "a", "aa"); + CMP_N(>, "aa", "b"); + CMP_N(>, "aa", "bb"); + CMP_Y(>, "b", "a"); + CMP_Y(>, "aa", "a"); + CMP_Y(>, "b", "aa"); + CMP_Y(>, "bb", "aa"); + +#undef CMP_Y +#undef CMP_N +} + +int main(int argc, char** argv) { + CheckComparisonOperators(); + CheckSTLComparator(); + + printf("OK\n"); + return 0; +} diff --git a/ext/pcre/pcrelib/study.c b/ext/pcre/pcrelib/pcre_study.c similarity index 83% rename from ext/pcre/pcrelib/study.c rename to ext/pcre/pcrelib/pcre_study.c index 4484a3f992e9..7c10c049171a 100644 --- a/ext/pcre/pcrelib/study.c +++ b/ext/pcre/pcrelib/pcre_study.c @@ -2,42 +2,47 @@ * Perl-Compatible Regular Expressions * *************************************************/ -/* -This is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. See -the file Tech.Notes for some information on the internals. +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. -Written by: Philip Hazel - - Copyright (c) 1997-2004 University of Cambridge + Written by Philip Hazel + Copyright (c) 1997-2005 University of Cambridge ----------------------------------------------------------------------------- -Permission is granted to anyone to use this software for any purpose on any -computer system, and to redistribute it freely, subject to the following -restrictions: - -1. This software is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -2. The origin of this software must not be misrepresented, either by - explicit claim or by omission. - -3. Altered versions must be plainly marked as such, and must not be - misrepresented as being the original software. - -4. If PCRE is embedded in any software that is released under the GNU - General Purpose Licence (GPL), then the terms of that licence shall - supersede any condition above with which it is incompatible. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------------------- */ -/* Include the internals header, which itself includes Standard C headers plus -the external pcre header. */ +/* This module contains the external function pcre_study(), along with local +supporting functions. */ -#include "internal.h" +#include "pcre_internal.h" /************************************************* @@ -57,7 +62,7 @@ Returns: nothing */ static void -set_bit(uschar *start_bits, int c, BOOL caseless, compile_data *cd) +set_bit(uschar *start_bits, unsigned int c, BOOL caseless, compile_data *cd) { start_bits[c/8] |= (1 << (c&7)); if (caseless && (cd->ctypes[c] & ctype_letter) != 0) @@ -123,7 +128,7 @@ do /* Skip over callout */ case OP_CALLOUT: - tcode += 2; + tcode += 2 + 2*LINK_SIZE; break; /* Skip over extended extraction bracket number */ @@ -186,11 +191,10 @@ do /* At least one single char sets the bit and stops */ case OP_EXACT: /* Fall through */ - tcode++; - - case OP_CHARS: /* Fall through */ - tcode++; + tcode += 2; + case OP_CHAR: + case OP_CHARNC: case OP_PLUS: case OP_MINPLUS: set_bit(start_bits, tcode[1], caseless, cd); @@ -403,8 +407,9 @@ pcre_study(const pcre *external_re, int options, const char **errorptr) uschar start_bits[32]; pcre_extra *extra; pcre_study_data *study; +const uschar *tables; const real_pcre *re = (const real_pcre *)external_re; -uschar *code = (uschar *)re + sizeof(real_pcre) + +uschar *code = (uschar *)re + re->name_table_offset + (re->name_count * re->name_entry_size); compile_data compile_block; @@ -429,12 +434,17 @@ at present. */ if ((re->options & (PCRE_ANCHORED|PCRE_FIRSTSET|PCRE_STARTLINE)) != 0) return NULL; -/* Set the character tables in the block which is passed around */ +/* Set the character tables in the block that is passed around */ + +tables = re->tables; +if (tables == NULL) + (void)pcre_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES, + (void *)(&tables)); -compile_block.lcc = re->tables + lcc_offset; -compile_block.fcc = re->tables + fcc_offset; -compile_block.cbits = re->tables + cbits_offset; -compile_block.ctypes = re->tables + ctypes_offset; +compile_block.lcc = tables + lcc_offset; +compile_block.fcc = tables + fcc_offset; +compile_block.cbits = tables + cbits_offset; +compile_block.ctypes = tables + ctypes_offset; /* See if we can find a fixed set of initial characters for the pattern. */ @@ -469,4 +479,4 @@ memcpy(study->start_bits, start_bits, sizeof(start_bits)); return extra; } -/* End of study.c */ +/* End of pcre_study.c */ diff --git a/ext/pcre/pcrelib/pcre_tables.c b/ext/pcre/pcrelib/pcre_tables.c new file mode 100644 index 000000000000..4f442eae033e --- /dev/null +++ b/ext/pcre/pcrelib/pcre_tables.c @@ -0,0 +1,129 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2005 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains some fixed tables that are used by more than one of the +PCRE code modules. */ + + +#include "pcre_internal.h" + + +/* Table of sizes for the fixed-length opcodes. It's defined in a macro so that +the definition is next to the definition of the opcodes in internal.h. */ + +const uschar _pcre_OP_lengths[] = { OP_LENGTHS }; + + + +/************************************************* +* Tables for UTF-8 support * +*************************************************/ + +/* These are the breakpoints for different numbers of bytes in a UTF-8 +character. */ + +const int _pcre_utf8_table1[] = + { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff}; + +const int _pcre_utf8_table1_size = sizeof(_pcre_utf8_table1)/sizeof(int); + +/* These are the indicator bits and the mask for the data bits to set in the +first byte of a character, indexed by the number of additional bytes. */ + +const int _pcre_utf8_table2[] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}; +const int _pcre_utf8_table3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01}; + +/* Table of the number of extra characters, indexed by the first character +masked with 0x3f. The highest number for a valid UTF-8 character is in fact +0x3d. */ + +const uschar _pcre_utf8_table4[] = { + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 }; + +/* This table translates Unicode property names into code values for the +ucp_findchar() function. It is used by pcretest as well as by the library +functions. */ + +const ucp_type_table _pcre_utt[] = { + { "C", 128 + ucp_C }, + { "Cc", ucp_Cc }, + { "Cf", ucp_Cf }, + { "Cn", ucp_Cn }, + { "Co", ucp_Co }, + { "Cs", ucp_Cs }, + { "L", 128 + ucp_L }, + { "Ll", ucp_Ll }, + { "Lm", ucp_Lm }, + { "Lo", ucp_Lo }, + { "Lt", ucp_Lt }, + { "Lu", ucp_Lu }, + { "M", 128 + ucp_M }, + { "Mc", ucp_Mc }, + { "Me", ucp_Me }, + { "Mn", ucp_Mn }, + { "N", 128 + ucp_N }, + { "Nd", ucp_Nd }, + { "Nl", ucp_Nl }, + { "No", ucp_No }, + { "P", 128 + ucp_P }, + { "Pc", ucp_Pc }, + { "Pd", ucp_Pd }, + { "Pe", ucp_Pe }, + { "Pf", ucp_Pf }, + { "Pi", ucp_Pi }, + { "Po", ucp_Po }, + { "Ps", ucp_Ps }, + { "S", 128 + ucp_S }, + { "Sc", ucp_Sc }, + { "Sk", ucp_Sk }, + { "Sm", ucp_Sm }, + { "So", ucp_So }, + { "Z", 128 + ucp_Z }, + { "Zl", ucp_Zl }, + { "Zp", ucp_Zp }, + { "Zs", ucp_Zs } +}; + +const int _pcre_utt_size = sizeof(_pcre_utt)/sizeof(ucp_type_table); + +/* End of pcre_tables.c */ diff --git a/ext/pcre/pcrelib/pcre_try_flipped.c b/ext/pcre/pcrelib/pcre_try_flipped.c new file mode 100644 index 000000000000..a07bb23db061 --- /dev/null +++ b/ext/pcre/pcrelib/pcre_try_flipped.c @@ -0,0 +1,132 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2005 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains an internal function that tests a compiled pattern to +see if it was compiled with the opposite endianness. If so, it uses an +auxiliary local function to flip the appropriate bytes. */ + + +#include "pcre_internal.h" + + +/************************************************* +* Flip bytes in an integer * +*************************************************/ + +/* This function is called when the magic number in a regex doesn't match, in +order to flip its bytes to see if we are dealing with a pattern that was +compiled on a host of different endianness. If so, this function is used to +flip other byte values. + +Arguments: + value the number to flip + n the number of bytes to flip (assumed to be 2 or 4) + +Returns: the flipped value +*/ + +static long int +byteflip(long int value, int n) +{ +if (n == 2) return ((value & 0x00ff) << 8) | ((value & 0xff00) >> 8); +return ((value & 0x000000ff) << 24) | + ((value & 0x0000ff00) << 8) | + ((value & 0x00ff0000) >> 8) | + ((value & 0xff000000) >> 24); +} + + + +/************************************************* +* Test for a byte-flipped compiled regex * +*************************************************/ + +/* This function is called from pcre_exec(), pcre_dfa_exec(), and also from +pcre_fullinfo(). Its job is to test whether the regex is byte-flipped - that +is, it was compiled on a system of opposite endianness. The function is called +only when the native MAGIC_NUMBER test fails. If the regex is indeed flipped, +we flip all the relevant values into a different data block, and return it. + +Arguments: + re points to the regex + study points to study data, or NULL + internal_re points to a new regex block + internal_study points to a new study block + +Returns: the new block if is is indeed a byte-flipped regex + NULL if it is not +*/ + +EXPORT real_pcre * +_pcre_try_flipped(const real_pcre *re, real_pcre *internal_re, + const pcre_study_data *study, pcre_study_data *internal_study) +{ +if (byteflip(re->magic_number, sizeof(re->magic_number)) != MAGIC_NUMBER) + return NULL; + +*internal_re = *re; /* To copy other fields */ +internal_re->size = byteflip(re->size, sizeof(re->size)); +internal_re->options = byteflip(re->options, sizeof(re->options)); +internal_re->top_bracket = + (pcre_uint16)byteflip(re->top_bracket, sizeof(re->top_bracket)); +internal_re->top_backref = + (pcre_uint16)byteflip(re->top_backref, sizeof(re->top_backref)); +internal_re->first_byte = + (pcre_uint16)byteflip(re->first_byte, sizeof(re->first_byte)); +internal_re->req_byte = + (pcre_uint16)byteflip(re->req_byte, sizeof(re->req_byte)); +internal_re->name_table_offset = + (pcre_uint16)byteflip(re->name_table_offset, sizeof(re->name_table_offset)); +internal_re->name_entry_size = + (pcre_uint16)byteflip(re->name_entry_size, sizeof(re->name_entry_size)); +internal_re->name_count = + (pcre_uint16)byteflip(re->name_count, sizeof(re->name_count)); + +if (study != NULL) + { + *internal_study = *study; /* To copy other fields */ + internal_study->size = byteflip(study->size, sizeof(study->size)); + internal_study->options = byteflip(study->options, sizeof(study->options)); + } + +return internal_re; +} + +/* End of pcre_tryflipped.c */ diff --git a/ext/pcre/pcrelib/pcre_ucp_findchar.c b/ext/pcre/pcrelib/pcre_ucp_findchar.c new file mode 100644 index 000000000000..9f8de0663e96 --- /dev/null +++ b/ext/pcre/pcrelib/pcre_ucp_findchar.c @@ -0,0 +1,53 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2005 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module compiles code for supporting the use of Unicode character +properties. We use the (embryonic at the time of writing) UCP library, by +including some of its files, copies of which have been put in the PCRE +distribution. There is a macro in pcre_internal.h that changes the name +ucp_findchar into _pcre_ucp_findchar. */ + + +#include "pcre_internal.h" + +#include "ucp_findchar.c" + + +/* End of pcre_ucp_findchar.c */ diff --git a/ext/pcre/pcrelib/pcre_valid_utf8.c b/ext/pcre/pcrelib/pcre_valid_utf8.c new file mode 100644 index 000000000000..72f0f5e6e206 --- /dev/null +++ b/ext/pcre/pcrelib/pcre_valid_utf8.c @@ -0,0 +1,130 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2005 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains an internal function for validating UTF-8 character +strings. */ + + +#include "pcre_internal.h" + + +/************************************************* +* Validate a UTF-8 string * +*************************************************/ + +/* This function is called (optionally) at the start of compile or match, to +validate that a supposed UTF-8 string is actually valid. The early check means +that subsequent code can assume it is dealing with a valid string. The check +can be turned off for maximum performance, but the consequences of supplying +an invalid string are then undefined. + +Arguments: + string points to the string + length length of string, or -1 if the string is zero-terminated + +Returns: < 0 if the string is a valid UTF-8 string + >= 0 otherwise; the value is the offset of the bad byte +*/ + +EXPORT int +_pcre_valid_utf8(const uschar *string, int length) +{ +register const uschar *p; + +if (length < 0) + { + for (p = string; *p != 0; p++); + length = p - string; + } + +for (p = string; length-- > 0; p++) + { + register int ab; + register int c = *p; + if (c < 128) continue; + if ((c & 0xc0) != 0xc0) return p - string; + ab = _pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */ + if (length < ab) return p - string; + length -= ab; + + /* Check top bits in the second byte */ + if ((*(++p) & 0xc0) != 0x80) return p - string; + + /* Check for overlong sequences for each different length */ + switch (ab) + { + /* Check for xx00 000x */ + case 1: + if ((c & 0x3e) == 0) return p - string; + continue; /* We know there aren't any more bytes to check */ + + /* Check for 1110 0000, xx0x xxxx */ + case 2: + if (c == 0xe0 && (*p & 0x20) == 0) return p - string; + break; + + /* Check for 1111 0000, xx00 xxxx */ + case 3: + if (c == 0xf0 && (*p & 0x30) == 0) return p - string; + break; + + /* Check for 1111 1000, xx00 0xxx */ + case 4: + if (c == 0xf8 && (*p & 0x38) == 0) return p - string; + break; + + /* Check for leading 0xfe or 0xff, and then for 1111 1100, xx00 00xx */ + case 5: + if (c == 0xfe || c == 0xff || + (c == 0xfc && (*p & 0x3c) == 0)) return p - string; + break; + } + + /* Check for valid bytes after the 2nd, if any; all must start 10 */ + while (--ab > 0) + { + if ((*(++p) & 0xc0) != 0x80) return p - string; + } + } + +return -1; +} + +/* End of pcre_valid_utf8.c */ diff --git a/ext/pcre/pcrelib/pcre_version.c b/ext/pcre/pcrelib/pcre_version.c new file mode 100644 index 000000000000..d296eea809c9 --- /dev/null +++ b/ext/pcre/pcrelib/pcre_version.c @@ -0,0 +1,61 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2005 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains the external function pcre_version(), which returns a +string that identifies the PCRE version that is in use. */ + + +#include "pcre_internal.h" + + +/************************************************* +* Return version string * +*************************************************/ + +#define STRING(a) # a +#define XSTRING(s) STRING(s) + +EXPORT const char * +pcre_version(void) +{ +return XSTRING(PCRE_MAJOR) "." XSTRING(PCRE_MINOR) " " XSTRING(PCRE_DATE); +} + +/* End of pcre_version.c */ diff --git a/ext/pcre/pcrelib/pcre_xclass.c b/ext/pcre/pcrelib/pcre_xclass.c new file mode 100644 index 000000000000..40d2654da088 --- /dev/null +++ b/ext/pcre/pcrelib/pcre_xclass.c @@ -0,0 +1,121 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2005 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains an internal function that is used to match an extended +class (one that contains characters whose values are > 255). It is used by both +pcre_exec() and pcre_def_exec(). */ + + +#include "pcre_internal.h" + + +/************************************************* +* Match character against an XCLASS * +*************************************************/ + +/* This function is called to match a character against an extended class that +might contain values > 255. + +Arguments: + c the character + data points to the flag byte of the XCLASS data + +Returns: TRUE if character matches, else FALSE +*/ + +EXPORT BOOL +_pcre_xclass(int c, const uschar *data) +{ +int t; +BOOL negated = (*data & XCL_NOT) != 0; + +/* Character values < 256 are matched against a bitmap, if one is present. If +not, we still carry on, because there may be ranges that start below 256 in the +additional data. */ + +if (c < 256) + { + if ((*data & XCL_MAP) != 0 && (data[1 + c/8] & (1 << (c&7))) != 0) + return !negated; /* char found */ + } + +/* First skip the bit map if present. Then match against the list of Unicode +properties or large chars or ranges that end with a large char. We won't ever +encounter XCL_PROP or XCL_NOTPROP when UCP support is not compiled. */ + +if ((*data++ & XCL_MAP) != 0) data += 32; + +while ((t = *data++) != XCL_END) + { + int x, y; + if (t == XCL_SINGLE) + { + GETCHARINC(x, data); + if (c == x) return !negated; + } + else if (t == XCL_RANGE) + { + GETCHARINC(x, data); + GETCHARINC(y, data); + if (c >= x && c <= y) return !negated; + } + +#ifdef SUPPORT_UCP + else /* XCL_PROP & XCL_NOTPROP */ + { + int chartype, othercase; + int rqdtype = *data++; + int category = ucp_findchar(c, &chartype, &othercase); + if (rqdtype >= 128) + { + if ((rqdtype - 128 == category) == (t == XCL_PROP)) return !negated; + } + else + { + if ((rqdtype == chartype) == (t == XCL_PROP)) return !negated; + } + } +#endif /* SUPPORT_UCP */ + } + +return negated; /* char did not match */ +} + +/* End of pcre_xclass.c */ diff --git a/ext/pcre/pcrelib/pcrecpp.cc b/ext/pcre/pcrelib/pcrecpp.cc new file mode 100644 index 000000000000..0ffd221d2335 --- /dev/null +++ b/ext/pcre/pcrelib/pcrecpp.cc @@ -0,0 +1,770 @@ +// Copyright (c) 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: Sanjay Ghemawat + +#include +#include +#include +#include /* for SHRT_MIN, USHRT_MAX, etc */ +#include +#include +#include +#include +#include "config.h" +// We need this to compile the proper dll on windows/msys. This is copied +// from pcre_internal.h. It would probably be better just to include that. +#define PCRE_DEFINITION /* Win32 __declspec(export) trigger for .dll */ +#include "pcre.h" +#include "pcre_stringpiece.h" +#include "pcrecpp.h" + + +namespace pcrecpp { + +// Maximum number of args we can set +static const int kMaxArgs = 16; +static const int kVecSize = (1 + kMaxArgs) * 3; // results + PCRE workspace + +// Special object that stands-in for no argument +Arg no_arg((void*)NULL); + +// If a regular expression has no error, its error_ field points here +static const string empty_string; + +// If the user doesn't ask for any options, we just use this one +static RE_Options default_options; + +void RE::Init(const char* pat, const RE_Options* options) { + pattern_ = pat; + if (options == NULL) { + options_ = default_options; + } else { + options_ = *options; + } + error_ = &empty_string; + re_full_ = NULL; + re_partial_ = NULL; + + re_partial_ = Compile(UNANCHORED); + if (re_partial_ != NULL) { + // Check for complicated patterns. The following change is + // conservative in that it may treat some "simple" patterns + // as "complex" (e.g., if the vertical bar is in a character + // class or is escaped). But it seems good enough. + if (strchr(pat, '|') == NULL) { + // Simple pattern: we can use position-based checks to perform + // fully anchored matches + re_full_ = re_partial_; + } else { + // We need a special pattern for anchored matches + re_full_ = Compile(ANCHOR_BOTH); + } + } +} + +RE::~RE() { + if (re_full_ != NULL && re_full_ != re_partial_) (*pcre_free)(re_full_); + if (re_partial_ != NULL) (*pcre_free)(re_partial_); + if (error_ != &empty_string) delete error_; +} + +pcre* RE::Compile(Anchor anchor) { + // First, convert RE_Options into pcre options + int pcre_options = 0; + pcre_options = options_.all_options(); + + // Special treatment for anchoring. This is needed because at + // runtime pcre only provides an option for anchoring at the + // beginning of a string (unless you use offset). + // + // There are three types of anchoring we want: + // UNANCHORED Compile the original pattern, and use + // a pcre unanchored match. + // ANCHOR_START Compile the original pattern, and use + // a pcre anchored match. + // ANCHOR_BOTH Tack a "\z" to the end of the original pattern + // and use a pcre anchored match. + + const char* compile_error; + int eoffset; + pcre* re; + if (anchor != ANCHOR_BOTH) { + re = pcre_compile(pattern_.c_str(), pcre_options, + &compile_error, &eoffset, NULL); + } else { + // Tack a '\z' at the end of RE. Parenthesize it first so that + // the '\z' applies to all top-level alternatives in the regexp. + string wrapped = "(?:"; // A non-counting grouping operator + wrapped += pattern_; + wrapped += ")\\z"; + re = pcre_compile(wrapped.c_str(), pcre_options, + &compile_error, &eoffset, NULL); + } + if (re == NULL) { + if (error_ == &empty_string) error_ = new string(compile_error); + } + return re; +} + +/***** Matching interfaces *****/ + +bool RE::FullMatch(const StringPiece& text, + const Arg& ptr1, + const Arg& ptr2, + const Arg& ptr3, + const Arg& ptr4, + const Arg& ptr5, + const Arg& ptr6, + const Arg& ptr7, + const Arg& ptr8, + const Arg& ptr9, + const Arg& ptr10, + const Arg& ptr11, + const Arg& ptr12, + const Arg& ptr13, + const Arg& ptr14, + const Arg& ptr15, + const Arg& ptr16) const { + const Arg* args[kMaxArgs]; + int n = 0; + if (&ptr1 == &no_arg) goto done; args[n++] = &ptr1; + if (&ptr2 == &no_arg) goto done; args[n++] = &ptr2; + if (&ptr3 == &no_arg) goto done; args[n++] = &ptr3; + if (&ptr4 == &no_arg) goto done; args[n++] = &ptr4; + if (&ptr5 == &no_arg) goto done; args[n++] = &ptr5; + if (&ptr6 == &no_arg) goto done; args[n++] = &ptr6; + if (&ptr7 == &no_arg) goto done; args[n++] = &ptr7; + if (&ptr8 == &no_arg) goto done; args[n++] = &ptr8; + if (&ptr9 == &no_arg) goto done; args[n++] = &ptr9; + if (&ptr10 == &no_arg) goto done; args[n++] = &ptr10; + if (&ptr11 == &no_arg) goto done; args[n++] = &ptr11; + if (&ptr12 == &no_arg) goto done; args[n++] = &ptr12; + if (&ptr13 == &no_arg) goto done; args[n++] = &ptr13; + if (&ptr14 == &no_arg) goto done; args[n++] = &ptr14; + if (&ptr15 == &no_arg) goto done; args[n++] = &ptr15; + if (&ptr16 == &no_arg) goto done; args[n++] = &ptr16; + done: + + int consumed; + int vec[kVecSize]; + return DoMatchImpl(text, ANCHOR_BOTH, &consumed, args, n, vec, kVecSize); +} + +bool RE::PartialMatch(const StringPiece& text, + const Arg& ptr1, + const Arg& ptr2, + const Arg& ptr3, + const Arg& ptr4, + const Arg& ptr5, + const Arg& ptr6, + const Arg& ptr7, + const Arg& ptr8, + const Arg& ptr9, + const Arg& ptr10, + const Arg& ptr11, + const Arg& ptr12, + const Arg& ptr13, + const Arg& ptr14, + const Arg& ptr15, + const Arg& ptr16) const { + const Arg* args[kMaxArgs]; + int n = 0; + if (&ptr1 == &no_arg) goto done; args[n++] = &ptr1; + if (&ptr2 == &no_arg) goto done; args[n++] = &ptr2; + if (&ptr3 == &no_arg) goto done; args[n++] = &ptr3; + if (&ptr4 == &no_arg) goto done; args[n++] = &ptr4; + if (&ptr5 == &no_arg) goto done; args[n++] = &ptr5; + if (&ptr6 == &no_arg) goto done; args[n++] = &ptr6; + if (&ptr7 == &no_arg) goto done; args[n++] = &ptr7; + if (&ptr8 == &no_arg) goto done; args[n++] = &ptr8; + if (&ptr9 == &no_arg) goto done; args[n++] = &ptr9; + if (&ptr10 == &no_arg) goto done; args[n++] = &ptr10; + if (&ptr11 == &no_arg) goto done; args[n++] = &ptr11; + if (&ptr12 == &no_arg) goto done; args[n++] = &ptr12; + if (&ptr13 == &no_arg) goto done; args[n++] = &ptr13; + if (&ptr14 == &no_arg) goto done; args[n++] = &ptr14; + if (&ptr15 == &no_arg) goto done; args[n++] = &ptr15; + if (&ptr16 == &no_arg) goto done; args[n++] = &ptr16; + done: + + int consumed; + int vec[kVecSize]; + return DoMatchImpl(text, UNANCHORED, &consumed, args, n, vec, kVecSize); +} + +bool RE::Consume(StringPiece* input, + const Arg& ptr1, + const Arg& ptr2, + const Arg& ptr3, + const Arg& ptr4, + const Arg& ptr5, + const Arg& ptr6, + const Arg& ptr7, + const Arg& ptr8, + const Arg& ptr9, + const Arg& ptr10, + const Arg& ptr11, + const Arg& ptr12, + const Arg& ptr13, + const Arg& ptr14, + const Arg& ptr15, + const Arg& ptr16) const { + const Arg* args[kMaxArgs]; + int n = 0; + if (&ptr1 == &no_arg) goto done; args[n++] = &ptr1; + if (&ptr2 == &no_arg) goto done; args[n++] = &ptr2; + if (&ptr3 == &no_arg) goto done; args[n++] = &ptr3; + if (&ptr4 == &no_arg) goto done; args[n++] = &ptr4; + if (&ptr5 == &no_arg) goto done; args[n++] = &ptr5; + if (&ptr6 == &no_arg) goto done; args[n++] = &ptr6; + if (&ptr7 == &no_arg) goto done; args[n++] = &ptr7; + if (&ptr8 == &no_arg) goto done; args[n++] = &ptr8; + if (&ptr9 == &no_arg) goto done; args[n++] = &ptr9; + if (&ptr10 == &no_arg) goto done; args[n++] = &ptr10; + if (&ptr11 == &no_arg) goto done; args[n++] = &ptr11; + if (&ptr12 == &no_arg) goto done; args[n++] = &ptr12; + if (&ptr13 == &no_arg) goto done; args[n++] = &ptr13; + if (&ptr14 == &no_arg) goto done; args[n++] = &ptr14; + if (&ptr15 == &no_arg) goto done; args[n++] = &ptr15; + if (&ptr16 == &no_arg) goto done; args[n++] = &ptr16; + done: + + int consumed; + int vec[kVecSize]; + if (DoMatchImpl(*input, ANCHOR_START, &consumed, + args, n, vec, kVecSize)) { + input->remove_prefix(consumed); + return true; + } else { + return false; + } +} + +bool RE::FindAndConsume(StringPiece* input, + const Arg& ptr1, + const Arg& ptr2, + const Arg& ptr3, + const Arg& ptr4, + const Arg& ptr5, + const Arg& ptr6, + const Arg& ptr7, + const Arg& ptr8, + const Arg& ptr9, + const Arg& ptr10, + const Arg& ptr11, + const Arg& ptr12, + const Arg& ptr13, + const Arg& ptr14, + const Arg& ptr15, + const Arg& ptr16) const { + const Arg* args[kMaxArgs]; + int n = 0; + if (&ptr1 == &no_arg) goto done; args[n++] = &ptr1; + if (&ptr2 == &no_arg) goto done; args[n++] = &ptr2; + if (&ptr3 == &no_arg) goto done; args[n++] = &ptr3; + if (&ptr4 == &no_arg) goto done; args[n++] = &ptr4; + if (&ptr5 == &no_arg) goto done; args[n++] = &ptr5; + if (&ptr6 == &no_arg) goto done; args[n++] = &ptr6; + if (&ptr7 == &no_arg) goto done; args[n++] = &ptr7; + if (&ptr8 == &no_arg) goto done; args[n++] = &ptr8; + if (&ptr9 == &no_arg) goto done; args[n++] = &ptr9; + if (&ptr10 == &no_arg) goto done; args[n++] = &ptr10; + if (&ptr11 == &no_arg) goto done; args[n++] = &ptr11; + if (&ptr12 == &no_arg) goto done; args[n++] = &ptr12; + if (&ptr13 == &no_arg) goto done; args[n++] = &ptr13; + if (&ptr14 == &no_arg) goto done; args[n++] = &ptr14; + if (&ptr15 == &no_arg) goto done; args[n++] = &ptr15; + if (&ptr16 == &no_arg) goto done; args[n++] = &ptr16; + done: + + int consumed; + int vec[kVecSize]; + if (DoMatchImpl(*input, UNANCHORED, &consumed, + args, n, vec, kVecSize)) { + input->remove_prefix(consumed); + return true; + } else { + return false; + } +} + +bool RE::Replace(const StringPiece& rewrite, + string *str) const { + int vec[kVecSize]; + int matches = TryMatch(*str, 0, UNANCHORED, vec, kVecSize); + if (matches == 0) + return false; + + string s; + if (!Rewrite(&s, rewrite, *str, vec, matches)) + return false; + + assert(vec[0] >= 0); + assert(vec[1] >= 0); + str->replace(vec[0], vec[1] - vec[0], s); + return true; +} + +int RE::GlobalReplace(const StringPiece& rewrite, + string *str) const { + int count = 0; + int vec[kVecSize]; + string out; + int start = 0; + int lastend = -1; + + for (; start <= static_cast(str->length()); count++) { + int matches = TryMatch(*str, start, UNANCHORED, vec, kVecSize); + if (matches <= 0) + break; + int matchstart = vec[0], matchend = vec[1]; + assert(matchstart >= start); + assert(matchend >= matchstart); + if (matchstart == matchend && matchstart == lastend) { + // advance one character if we matched an empty string at the same + // place as the last match occurred + if (start < static_cast(str->length())) + out.push_back((*str)[start]); + start++; + } else { + out.append(*str, start, matchstart - start); + Rewrite(&out, rewrite, *str, vec, matches); + start = matchend; + lastend = matchend; + count++; + } + } + + if (count == 0) + return 0; + + if (start < static_cast(str->length())) + out.append(*str, start, str->length() - start); + swap(out, *str); + return count; +} + +bool RE::Extract(const StringPiece& rewrite, + const StringPiece& text, + string *out) const { + int vec[kVecSize]; + int matches = TryMatch(text, 0, UNANCHORED, vec, kVecSize); + if (matches == 0) + return false; + out->erase(); + return Rewrite(out, rewrite, text, vec, matches); +} + +/***** Actual matching and rewriting code *****/ + +int RE::TryMatch(const StringPiece& text, + int startpos, + Anchor anchor, + int *vec, + int vecsize) const { + pcre* re = (anchor == ANCHOR_BOTH) ? re_full_ : re_partial_; + if (re == NULL) { + //fprintf(stderr, "Matching against invalid re: %s\n", error_->c_str()); + return 0; + } + + pcre_extra extra = { 0 }; + if (options_.match_limit() > 0) { + extra.flags = PCRE_EXTRA_MATCH_LIMIT; + extra.match_limit = options_.match_limit(); + } + int rc = pcre_exec(re, // The regular expression object + &extra, + text.data(), + text.size(), + startpos, + (anchor == UNANCHORED) ? 0 : PCRE_ANCHORED, + vec, + vecsize); + + // Handle errors + if (rc == PCRE_ERROR_NOMATCH) { + return 0; + } else if (rc < 0) { + //fprintf(stderr, "Unexpected return code: %d when matching '%s'\n", + // re, pattern_.c_str()); + return 0; + } else if (rc == 0) { + // pcre_exec() returns 0 as a special case when the number of + // capturing subpatterns exceeds the size of the vector. + // When this happens, there is a match and the output vector + // is filled, but we miss out on the positions of the extra subpatterns. + rc = vecsize / 2; + } + + if ((anchor == ANCHOR_BOTH) && (re_full_ == re_partial_)) { + // We need an extra check to make sure that the match extended + // to the end of the input string + assert(vec[0] == 0); // PCRE_ANCHORED forces starting match + if (vec[1] != text.size()) return 0; // Did not get ending match + } + + return rc; +} + +bool RE::DoMatchImpl(const StringPiece& text, + Anchor anchor, + int* consumed, + const Arg* const* args, + int n, + int* vec, + int vecsize) const { + assert((1 + n) * 3 <= vecsize); // results + PCRE workspace + int matches = TryMatch(text, 0, anchor, vec, vecsize); + assert(matches >= 0); // TryMatch never returns negatives + if (matches == 0) + return false; + + *consumed = vec[1]; + + if (args == NULL) { + // We are not interested in results + return true; + } + + // If we got here, we must have matched the whole pattern. + // We do not need (can not do) any more checks on the value of 'matches' here + // -- see the comment for TryMatch. + for (int i = 0; i < n; i++) { + const int start = vec[2*(i+1)]; + const int limit = vec[2*(i+1)+1]; + if (!args[i]->Parse(text.data() + start, limit-start)) { + // TODO: Should we indicate what the error was? + return false; + } + } + + return true; +} + +bool RE::DoMatch(const StringPiece& text, + Anchor anchor, + int* consumed, + const Arg* const args[], + int n) const { + assert(n >= 0); + size_t const vecsize = (1 + n) * 3; // results + PCRE workspace + // (as for kVecSize) + int space[21]; // use stack allocation for small vecsize (common case) + int* vec = vecsize <= 21 ? space : new int[vecsize]; + bool retval = DoMatchImpl(text, anchor, consumed, args, n, vec, vecsize); + if (vec != space) delete [] vec; + return retval; +} + +bool RE::Rewrite(string *out, const StringPiece &rewrite, + const StringPiece &text, int *vec, int veclen) const { + for (const char *s = rewrite.data(), *end = s + rewrite.size(); + s < end; s++) { + int c = *s; + if (c == '\\') { + c = *++s; + if (isdigit(c)) { + int n = (c - '0'); + if (n >= veclen) { + //fprintf(stderr, requested group %d in regexp %.*s\n", + // n, rewrite.size(), rewrite.data()); + return false; + } + int start = vec[2 * n]; + if (start >= 0) + out->append(text.data() + start, vec[2 * n + 1] - start); + } else if (c == '\\') { + out->push_back('\\'); + } else { + //fprintf(stderr, "invalid rewrite pattern: %.*s\n", + // rewrite.size(), rewrite.data()); + return false; + } + } else { + out->push_back(c); + } + } + return true; +} + +// Return the number of capturing subpatterns, or -1 if the +// regexp wasn't valid on construction. +int RE::NumberOfCapturingGroups() { + if (re_partial_ == NULL) return -1; + + int result; + int pcre_retval = pcre_fullinfo(re_partial_, // The regular expression object + NULL, // We did not study the pattern + PCRE_INFO_CAPTURECOUNT, + &result); + assert(pcre_retval == 0); + return result; +} + +/***** Parsers for various types *****/ + +bool Arg::parse_null(const char* str, int n, void* dest) { + // We fail if somebody asked us to store into a non-NULL void* pointer + return (dest == NULL); +} + +bool Arg::parse_string(const char* str, int n, void* dest) { + reinterpret_cast(dest)->assign(str, n); + return true; +} + +bool Arg::parse_stringpiece(const char* str, int n, void* dest) { + reinterpret_cast(dest)->set(str, n); + return true; +} + +bool Arg::parse_char(const char* str, int n, void* dest) { + if (n != 1) return false; + *(reinterpret_cast(dest)) = str[0]; + return true; +} + +bool Arg::parse_uchar(const char* str, int n, void* dest) { + if (n != 1) return false; + *(reinterpret_cast(dest)) = str[0]; + return true; +} + +// Largest number spec that we are willing to parse +static const int kMaxNumberLength = 32; + +// REQUIRES "buf" must have length at least kMaxNumberLength+1 +// REQUIRES "n > 0" +// Copies "str" into "buf" and null-terminates if necessary. +// Returns one of: +// a. "str" if no termination is needed +// b. "buf" if the string was copied and null-terminated +// c. "" if the input was invalid and has no hope of being parsed +static const char* TerminateNumber(char* buf, const char* str, int n) { + if ((n > 0) && isspace(*str)) { + // We are less forgiving than the strtoxxx() routines and do not + // allow leading spaces. + return ""; + } + + // See if the character right after the input text may potentially + // look like a digit. + if (isdigit(str[n]) || + ((str[n] >= 'a') && (str[n] <= 'f')) || + ((str[n] >= 'A') && (str[n] <= 'F'))) { + if (n > kMaxNumberLength) return ""; // Input too big to be a valid number + memcpy(buf, str, n); + buf[n] = '\0'; + return buf; + } else { + // We can parse right out of the supplied string, so return it. + return str; + } +} + +bool Arg::parse_long_radix(const char* str, + int n, + void* dest, + int radix) { + if (n == 0) return false; + char buf[kMaxNumberLength+1]; + str = TerminateNumber(buf, str, n); + char* end; + errno = 0; + long r = strtol(str, &end, radix); + if (end != str + n) return false; // Leftover junk + if (errno) return false; + *(reinterpret_cast(dest)) = r; + return true; +} + +bool Arg::parse_ulong_radix(const char* str, + int n, + void* dest, + int radix) { + if (n == 0) return false; + char buf[kMaxNumberLength+1]; + str = TerminateNumber(buf, str, n); + char* end; + errno = 0; + unsigned long r = strtoul(str, &end, radix); + if (end != str + n) return false; // Leftover junk + if (errno) return false; + *(reinterpret_cast(dest)) = r; + return true; +} + +bool Arg::parse_short_radix(const char* str, + int n, + void* dest, + int radix) { + long r; + if (!parse_long_radix(str, n, &r, radix)) return false; // Could not parse + if (r < SHRT_MIN || r > SHRT_MAX) return false; // Out of range + *(reinterpret_cast(dest)) = r; + return true; +} + +bool Arg::parse_ushort_radix(const char* str, + int n, + void* dest, + int radix) { + unsigned long r; + if (!parse_ulong_radix(str, n, &r, radix)) return false; // Could not parse + if (r > USHRT_MAX) return false; // Out of range + *(reinterpret_cast(dest)) = r; + return true; +} + +bool Arg::parse_int_radix(const char* str, + int n, + void* dest, + int radix) { + long r; + if (!parse_long_radix(str, n, &r, radix)) return false; // Could not parse + if (r < INT_MIN || r > INT_MAX) return false; // Out of range + *(reinterpret_cast(dest)) = r; + return true; +} + +bool Arg::parse_uint_radix(const char* str, + int n, + void* dest, + int radix) { + unsigned long r; + if (!parse_ulong_radix(str, n, &r, radix)) return false; // Could not parse + if (r > UINT_MAX) return false; // Out of range + *(reinterpret_cast(dest)) = r; + return true; +} + +bool Arg::parse_longlong_radix(const char* str, + int n, + void* dest, + int radix) { +#ifndef HAVE_LONG_LONG + return false; +#else + if (n == 0) return false; + char buf[kMaxNumberLength+1]; + str = TerminateNumber(buf, str, n); + char* end; + errno = 0; +#if defined HAVE_STRTOQ + long long r = strtoq(str, &end, radix); +#elif defined HAVE_STRTOLL + long long r = strtoll(str, &end, radix); +#else +#error parse_longlong_radix: cannot convert input to a long-long +#endif + if (end != str + n) return false; // Leftover junk + if (errno) return false; + *(reinterpret_cast(dest)) = r; + return true; +#endif /* HAVE_LONG_LONG */ +} + +bool Arg::parse_ulonglong_radix(const char* str, + int n, + void* dest, + int radix) { +#ifndef HAVE_UNSIGNED_LONG_LONG + return false; +#else + if (n == 0) return false; + char buf[kMaxNumberLength+1]; + str = TerminateNumber(buf, str, n); + char* end; + errno = 0; +#if defined HAVE_STRTOQ + unsigned long long r = strtouq(str, &end, radix); +#elif defined HAVE_STRTOLL + unsigned long long r = strtoull(str, &end, radix); +#else +#error parse_ulonglong_radix: cannot convert input to a long-long +#endif + if (end != str + n) return false; // Leftover junk + if (errno) return false; + *(reinterpret_cast(dest)) = r; + return true; +#endif /* HAVE_UNSIGNED_LONG_LONG */ +} + +bool Arg::parse_double(const char* str, int n, void* dest) { + if (n == 0) return false; + static const int kMaxLength = 200; + char buf[kMaxLength]; + if (n >= kMaxLength) return false; + memcpy(buf, str, n); + buf[n] = '\0'; + errno = 0; + char* end; + double r = strtod(buf, &end); + if (end != buf + n) return false; // Leftover junk + if (errno) return false; + *(reinterpret_cast(dest)) = r; + return true; +} + +bool Arg::parse_float(const char* str, int n, void* dest) { + double r; + if (!parse_double(str, n, &r)) return false; + *(reinterpret_cast(dest)) = static_cast(r); + return true; +} + + +#define DEFINE_INTEGER_PARSERS(name) \ + bool Arg::parse_##name(const char* str, int n, void* dest) { \ + return parse_##name##_radix(str, n, dest, 10); \ + } \ + bool Arg::parse_##name##_hex(const char* str, int n, void* dest) { \ + return parse_##name##_radix(str, n, dest, 16); \ + } \ + bool Arg::parse_##name##_octal(const char* str, int n, void* dest) { \ + return parse_##name##_radix(str, n, dest, 8); \ + } \ + bool Arg::parse_##name##_cradix(const char* str, int n, void* dest) { \ + return parse_##name##_radix(str, n, dest, 0); \ + } + +DEFINE_INTEGER_PARSERS(short); +DEFINE_INTEGER_PARSERS(ushort); +DEFINE_INTEGER_PARSERS(int); +DEFINE_INTEGER_PARSERS(uint); +DEFINE_INTEGER_PARSERS(long); +DEFINE_INTEGER_PARSERS(ulong); +DEFINE_INTEGER_PARSERS(longlong); +DEFINE_INTEGER_PARSERS(ulonglong); + +#undef DEFINE_INTEGER_PARSERS + +} // namespace pcrecpp diff --git a/ext/pcre/pcrelib/pcrecpp.h b/ext/pcre/pcrelib/pcrecpp.h new file mode 100644 index 000000000000..ef9d9b2b58c0 --- /dev/null +++ b/ext/pcre/pcrelib/pcrecpp.h @@ -0,0 +1,786 @@ +// Copyright (c) 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: Sanjay Ghemawat +// Support for PCRE_XXX modifiers added by Giuseppe Maxia, July 2005 + +#ifndef _PCRE_REGEXP_H +#define _PCRE_REGEXP_H + +// C++ interface to the pcre regular-expression library. RE supports +// Perl-style regular expressions (with extensions like \d, \w, \s, +// ...). +// +// ----------------------------------------------------------------------- +// REGEXP SYNTAX: +// +// This module is part of the pcre library and hence supports its syntax +// for regular expressions. +// +// The syntax is pretty similar to Perl's. For those not familiar +// with Perl's regular expressions, here are some examples of the most +// commonly used extensions: +// +// "hello (\\w+) world" -- \w matches a "word" character +// "version (\\d+)" -- \d matches a digit +// "hello\\s+world" -- \s matches any whitespace character +// "\\b(\\w+)\\b" -- \b matches empty string at a word boundary +// "(?i)hello" -- (?i) turns on case-insensitive matching +// "/\\*(.*?)\\*/" -- .*? matches . minimum no. of times possible +// +// ----------------------------------------------------------------------- +// MATCHING INTERFACE: +// +// The "FullMatch" operation checks that supplied text matches a +// supplied pattern exactly. +// +// Example: successful match +// pcrecpp::RE re("h.*o"); +// re.FullMatch("hello"); +// +// Example: unsuccessful match (requires full match): +// pcrecpp::RE re("e"); +// !re.FullMatch("hello"); +// +// Example: creating a temporary RE object: +// pcrecpp::RE("h.*o").FullMatch("hello"); +// +// You can pass in a "const char*" or a "string" for "text". The +// examples below tend to use a const char*. +// +// You can, as in the different examples above, store the RE object +// explicitly in a variable or use a temporary RE object. The +// examples below use one mode or the other arbitrarily. Either +// could correctly be used for any of these examples. +// +// ----------------------------------------------------------------------- +// MATCHING WITH SUB-STRING EXTRACTION: +// +// You can supply extra pointer arguments to extract matched subpieces. +// +// Example: extracts "ruby" into "s" and 1234 into "i" +// int i; +// string s; +// pcrecpp::RE re("(\\w+):(\\d+)"); +// re.FullMatch("ruby:1234", &s, &i); +// +// Example: does not try to extract any extra sub-patterns +// re.FullMatch("ruby:1234", &s); +// +// Example: does not try to extract into NULL +// re.FullMatch("ruby:1234", NULL, &i); +// +// Example: integer overflow causes failure +// !re.FullMatch("ruby:1234567891234", NULL, &i); +// +// Example: fails because there aren't enough sub-patterns: +// !pcrecpp::RE("\\w+:\\d+").FullMatch("ruby:1234", &s); +// +// Example: fails because string cannot be stored in integer +// !pcrecpp::RE("(.*)").FullMatch("ruby", &i); +// +// The provided pointer arguments can be pointers to any scalar numeric +// type, or one of +// string (matched piece is copied to string) +// StringPiece (StringPiece is mutated to point to matched piece) +// T (where "bool T::ParseFrom(const char*, int)" exists) +// NULL (the corresponding matched sub-pattern is not copied) +// +// ----------------------------------------------------------------------- +// DO_MATCH +// +// The matching interface supports at most 16 arguments per call. +// If you need more, consider using the more general interface +// pcrecpp::RE::DoMatch(). See pcrecpp.h for the signature for DoMatch. +// +// ----------------------------------------------------------------------- +// PARTIAL MATCHES +// +// You can use the "PartialMatch" operation when you want the pattern +// to match any substring of the text. +// +// Example: simple search for a string: +// pcrecpp::RE("ell").PartialMatch("hello"); +// +// Example: find first number in a string: +// int number; +// pcrecpp::RE re("(\\d+)"); +// re.PartialMatch("x*100 + 20", &number); +// assert(number == 100); +// +// ----------------------------------------------------------------------- +// UTF-8 AND THE MATCHING INTERFACE: +// +// By default, pattern and text are plain text, one byte per character. +// The UTF8 flag, passed to the constructor, causes both pattern +// and string to be treated as UTF-8 text, still a byte stream but +// potentially multiple bytes per character. In practice, the text +// is likelier to be UTF-8 than the pattern, but the match returned +// may depend on the UTF8 flag, so always use it when matching +// UTF8 text. E.g., "." will match one byte normally but with UTF8 +// set may match up to three bytes of a multi-byte character. +// +// Example: +// pcrecpp::RE_Options options; +// options.set_utf8(); +// pcrecpp::RE re(utf8_pattern, options); +// re.FullMatch(utf8_string); +// +// Example: using the convenience function UTF8(): +// pcrecpp::RE re(utf8_pattern, pcrecpp::UTF8()); +// re.FullMatch(utf8_string); +// +// NOTE: The UTF8 option is ignored if pcre was not configured with the +// --enable-utf8 flag. +// +// ----------------------------------------------------------------------- +// PASSING MODIFIERS TO THE REGULAR EXPRESSION ENGINE +// +// PCRE defines some modifiers to change the behavior of the regular +// expression engine. +// The C++ wrapper defines an auxiliary class, RE_Options, as a vehicle +// to pass such modifiers to a RE class. +// +// Currently, the following modifiers are supported +// +// modifier description Perl corresponding +// +// PCRE_CASELESS case insensitive match /i +// PCRE_MULTILINE multiple lines match /m +// PCRE_DOTALL dot matches newlines /s +// PCRE_DOLLAR_ENDONLY $ matches only at end N/A +// PCRE_EXTRA strict escape parsing N/A +// PCRE_EXTENDED ignore whitespaces /x +// PCRE_UTF8 handles UTF8 chars built-in +// PCRE_UNGREEDY reverses * and *? N/A +// PCRE_NO_AUTO_CAPTURE disables matching parens N/A (*) +// +// (For a full account on how each modifier works, please check the +// PCRE API reference manual). +// +// (*) Both Perl and PCRE allow non matching parentheses by means of the +// "?:" modifier within the pattern itself. e.g. (?:ab|cd) does not +// capture, while (ab|cd) does. +// +// For each modifier, there are two member functions whose name is made +// out of the modifier in lowercase, without the "PCRE_" prefix. For +// instance, PCRE_CASELESS is handled by +// bool caseless(), +// which returns true if the modifier is set, and +// RE_Options & set_caseless(bool), +// which sets or unsets the modifier. +// +// Moreover, PCRE_CONFIG_MATCH_LIMIT can be accessed through the +// set_match_limit() and match_limit() member functions. +// Setting match_limit to a non-zero value will limit the executation of +// pcre to keep it from doing bad things like blowing the stack or taking +// an eternity to return a result. A value of 5000 is good enough to stop +// stack blowup in a 2MB thread stack. Setting match_limit to zero will +// disable match limiting. +// +// Normally, to pass one or more modifiers to a RE class, you declare +// a RE_Options object, set the appropriate options, and pass this +// object to a RE constructor. Example: +// +// RE_options opt; +// opt.set_caseless(true); +// +// if (RE("HELLO", opt).PartialMatch("hello world")) ... +// +// RE_options has two constructors. The default constructor takes no +// arguments and creates a set of flags that are off by default. +// +// The optional parameter 'option_flags' is to facilitate transfer +// of legacy code from C programs. This lets you do +// RE(pattern, RE_Options(PCRE_CASELESS|PCRE_MULTILINE)).PartialMatch(str); +// +// But new code is better off doing +// RE(pattern, +// RE_Options().set_caseless(true).set_multiline(true)).PartialMatch(str); +// (See below) +// +// If you are going to pass one of the most used modifiers, there are some +// convenience functions that return a RE_Options class with the +// appropriate modifier already set: +// CASELESS(), UTF8(), MULTILINE(), DOTALL(), EXTENDED() +// +// If you need to set several options at once, and you don't want to go +// through the pains of declaring a RE_Options object and setting several +// options, there is a parallel method that give you such ability on the +// fly. You can concatenate several set_xxxxx member functions, since each +// of them returns a reference to its class object. e.g.: to pass +// PCRE_CASELESS, PCRE_EXTENDED, and PCRE_MULTILINE to a RE with one +// statement, you may write +// +// RE(" ^ xyz \\s+ .* blah$", RE_Options() +// .set_caseless(true) +// .set_extended(true) +// .set_multiline(true)).PartialMatch(sometext); +// +// ----------------------------------------------------------------------- +// SCANNING TEXT INCREMENTALLY +// +// The "Consume" operation may be useful if you want to repeatedly +// match regular expressions at the front of a string and skip over +// them as they match. This requires use of the "StringPiece" type, +// which represents a sub-range of a real string. Like RE, StringPiece +// is defined in the pcrecpp namespace. +// +// Example: read lines of the form "var = value" from a string. +// string contents = ...; // Fill string somehow +// pcrecpp::StringPiece input(contents); // Wrap in a StringPiece +// +// string var; +// int value; +// pcrecpp::RE re("(\\w+) = (\\d+)\n"); +// while (re.Consume(&input, &var, &value)) { +// ...; +// } +// +// Each successful call to "Consume" will set "var/value", and also +// advance "input" so it points past the matched text. +// +// The "FindAndConsume" operation is similar to "Consume" but does not +// anchor your match at the beginning of the string. For example, you +// could extract all words from a string by repeatedly calling +// pcrecpp::RE("(\\w+)").FindAndConsume(&input, &word) +// +// ----------------------------------------------------------------------- +// PARSING HEX/OCTAL/C-RADIX NUMBERS +// +// By default, if you pass a pointer to a numeric value, the +// corresponding text is interpreted as a base-10 number. You can +// instead wrap the pointer with a call to one of the operators Hex(), +// Octal(), or CRadix() to interpret the text in another base. The +// CRadix operator interprets C-style "0" (base-8) and "0x" (base-16) +// prefixes, but defaults to base-10. +// +// Example: +// int a, b, c, d; +// pcrecpp::RE re("(.*) (.*) (.*) (.*)"); +// re.FullMatch("100 40 0100 0x40", +// pcrecpp::Octal(&a), pcrecpp::Hex(&b), +// pcrecpp::CRadix(&c), pcrecpp::CRadix(&d)); +// will leave 64 in a, b, c, and d. +// +// ----------------------------------------------------------------------- +// REPLACING PARTS OF STRINGS +// +// You can replace the first match of "pattern" in "str" with +// "rewrite". Within "rewrite", backslash-escaped digits (\1 to \9) +// can be used to insert text matching corresponding parenthesized +// group from the pattern. \0 in "rewrite" refers to the entire +// matching text. E.g., +// +// string s = "yabba dabba doo"; +// pcrecpp::RE("b+").Replace("d", &s); +// +// will leave "s" containing "yada dabba doo". The result is true if +// the pattern matches and a replacement occurs, or false otherwise. +// +// GlobalReplace() is like Replace(), except that it replaces all +// occurrences of the pattern in the string with the rewrite. +// Replacements are not subject to re-matching. E.g., +// +// string s = "yabba dabba doo"; +// pcrecpp::RE("b+").GlobalReplace("d", &s); +// +// will leave "s" containing "yada dada doo". It returns the number +// of replacements made. +// +// Extract() is like Replace(), except that if the pattern matches, +// "rewrite" is copied into "out" (an additional argument) with +// substitutions. The non-matching portions of "text" are ignored. +// Returns true iff a match occurred and the extraction happened +// successfully. If no match occurs, the string is left unaffected. + + +#include +// These aren't technically needed here, but we include them +// anyway so folks who include pcrecpp.h don't have to include +// all these other header files as well. +#include +#include + +namespace pcrecpp { + +#define PCRE_SET_OR_CLEAR(b, o) \ + if (b) all_options_ |= (o); else all_options_ &= ~(o); \ + return *this + +#define PCRE_IS_SET(o) \ + (all_options_ & o) == o + +// We convert user-passed pointers into special Arg objects +class Arg; +extern Arg no_arg; + +/***** Compiling regular expressions: the RE class *****/ + +// RE_Options allow you to set options to be passed along to pcre, +// along with other options we put on top of pcre. +// Only 9 modifiers, plus match_limit are supported now. +class RE_Options { + public: + // constructor + RE_Options() : match_limit_(0), all_options_(0) {} + + // alternative constructor. + // To facilitate transfer of legacy code from C programs + // + // This lets you do + // RE(pattern, RE_Options(PCRE_CASELESS|PCRE_MULTILINE)).PartialMatch(str); + // But new code is better off doing + // RE(pattern, + // RE_Options().set_caseless(true).set_multiline(true)).PartialMatch(str); + RE_Options(int option_flags) : match_limit_(0), all_options_ (option_flags) {} + // we're fine with the default destructor, copy constructor, etc. + + // accessors and mutators + int match_limit() const { return match_limit_; }; + RE_Options &set_match_limit(int limit) { + match_limit_ = limit; + return *this; + } + + bool caseless() const { + return PCRE_IS_SET(PCRE_CASELESS); + } + RE_Options &set_caseless(bool x) { + PCRE_SET_OR_CLEAR(x, PCRE_CASELESS); + } + + bool multiline() const { + return PCRE_IS_SET(PCRE_MULTILINE); + } + RE_Options &set_multiline(bool x) { + PCRE_SET_OR_CLEAR(x, PCRE_MULTILINE); + } + + bool dotall() const { + return PCRE_IS_SET(PCRE_DOTALL); + } + RE_Options &set_dotall(bool x) { + PCRE_SET_OR_CLEAR(x,PCRE_DOTALL); + } + + bool extended() const { + return PCRE_IS_SET(PCRE_EXTENDED); + } + RE_Options &set_extended(bool x) { + PCRE_SET_OR_CLEAR(x,PCRE_EXTENDED); + } + + bool dollar_endonly() const { + return PCRE_IS_SET(PCRE_DOLLAR_ENDONLY); + } + RE_Options &set_dollar_endonly(bool x) { + PCRE_SET_OR_CLEAR(x,PCRE_DOLLAR_ENDONLY); + } + + bool extra() const { + return PCRE_IS_SET( PCRE_EXTRA); + } + RE_Options &set_extra(bool x) { + PCRE_SET_OR_CLEAR(x, PCRE_EXTRA); + } + + bool ungreedy() const { + return PCRE_IS_SET(PCRE_UNGREEDY); + } + RE_Options &set_ungreedy(bool x) { + PCRE_SET_OR_CLEAR(x, PCRE_UNGREEDY); + } + + bool utf8() const { + return PCRE_IS_SET(PCRE_UTF8); + } + RE_Options &set_utf8(bool x) { + PCRE_SET_OR_CLEAR(x, PCRE_UTF8); + } + + bool no_auto_capture() const { + return PCRE_IS_SET(PCRE_NO_AUTO_CAPTURE); + } + RE_Options &set_no_auto_capture(bool x) { + PCRE_SET_OR_CLEAR(x, PCRE_NO_AUTO_CAPTURE); + } + + RE_Options &set_all_options(int opt) { + all_options_ = opt; + return *this; + } + int all_options() const { + return all_options_ ; + } + + // TODO: add other pcre flags + + private: + int match_limit_; + int all_options_; +}; + +// These functions return some common RE_Options +static inline RE_Options UTF8() { + return RE_Options().set_utf8(true); +} + +static inline RE_Options CASELESS() { + return RE_Options().set_caseless(true); +} +static inline RE_Options MULTILINE() { + return RE_Options().set_multiline(true); +} + +static inline RE_Options DOTALL() { + return RE_Options().set_dotall(true); +} + +static inline RE_Options EXTENDED() { + return RE_Options().set_extended(true); +} + +// Interface for regular expression matching. Also corresponds to a +// pre-compiled regular expression. An "RE" object is safe for +// concurrent use by multiple threads. +class RE { + public: + // We provide implicit conversions from strings so that users can + // pass in a string or a "const char*" wherever an "RE" is expected. + RE(const char* pat) { Init(pat, NULL); } + RE(const char *pat, const RE_Options& option) { Init(pat, &option); } + RE(const string& pat) { Init(pat.c_str(), NULL); } + RE(const string& pat, const RE_Options& option) { Init(pat.c_str(), &option); } + + ~RE(); + + // The string specification for this RE. E.g. + // RE re("ab*c?d+"); + // re.pattern(); // "ab*c?d+" + const string& pattern() const { return pattern_; } + + // If RE could not be created properly, returns an error string. + // Else returns the empty string. + const string& error() const { return *error_; } + + /***** The useful part: the matching interface *****/ + + // This is provided so one can do pattern.ReplaceAll() just as + // easily as ReplaceAll(pattern-text, ....) + + bool FullMatch(const StringPiece& text, + const Arg& ptr1 = no_arg, + const Arg& ptr2 = no_arg, + const Arg& ptr3 = no_arg, + const Arg& ptr4 = no_arg, + const Arg& ptr5 = no_arg, + const Arg& ptr6 = no_arg, + const Arg& ptr7 = no_arg, + const Arg& ptr8 = no_arg, + const Arg& ptr9 = no_arg, + const Arg& ptr10 = no_arg, + const Arg& ptr11 = no_arg, + const Arg& ptr12 = no_arg, + const Arg& ptr13 = no_arg, + const Arg& ptr14 = no_arg, + const Arg& ptr15 = no_arg, + const Arg& ptr16 = no_arg) const; + + bool PartialMatch(const StringPiece& text, + const Arg& ptr1 = no_arg, + const Arg& ptr2 = no_arg, + const Arg& ptr3 = no_arg, + const Arg& ptr4 = no_arg, + const Arg& ptr5 = no_arg, + const Arg& ptr6 = no_arg, + const Arg& ptr7 = no_arg, + const Arg& ptr8 = no_arg, + const Arg& ptr9 = no_arg, + const Arg& ptr10 = no_arg, + const Arg& ptr11 = no_arg, + const Arg& ptr12 = no_arg, + const Arg& ptr13 = no_arg, + const Arg& ptr14 = no_arg, + const Arg& ptr15 = no_arg, + const Arg& ptr16 = no_arg) const; + + bool Consume(StringPiece* input, + const Arg& ptr1 = no_arg, + const Arg& ptr2 = no_arg, + const Arg& ptr3 = no_arg, + const Arg& ptr4 = no_arg, + const Arg& ptr5 = no_arg, + const Arg& ptr6 = no_arg, + const Arg& ptr7 = no_arg, + const Arg& ptr8 = no_arg, + const Arg& ptr9 = no_arg, + const Arg& ptr10 = no_arg, + const Arg& ptr11 = no_arg, + const Arg& ptr12 = no_arg, + const Arg& ptr13 = no_arg, + const Arg& ptr14 = no_arg, + const Arg& ptr15 = no_arg, + const Arg& ptr16 = no_arg) const; + + bool FindAndConsume(StringPiece* input, + const Arg& ptr1 = no_arg, + const Arg& ptr2 = no_arg, + const Arg& ptr3 = no_arg, + const Arg& ptr4 = no_arg, + const Arg& ptr5 = no_arg, + const Arg& ptr6 = no_arg, + const Arg& ptr7 = no_arg, + const Arg& ptr8 = no_arg, + const Arg& ptr9 = no_arg, + const Arg& ptr10 = no_arg, + const Arg& ptr11 = no_arg, + const Arg& ptr12 = no_arg, + const Arg& ptr13 = no_arg, + const Arg& ptr14 = no_arg, + const Arg& ptr15 = no_arg, + const Arg& ptr16 = no_arg) const; + + bool Replace(const StringPiece& rewrite, + string *str) const; + + int GlobalReplace(const StringPiece& rewrite, + string *str) const; + + bool Extract(const StringPiece &rewrite, + const StringPiece &text, + string *out) const; + + /***** Generic matching interface *****/ + + // Type of match (TODO: Should be restructured as part of RE_Options) + enum Anchor { + UNANCHORED, // No anchoring + ANCHOR_START, // Anchor at start only + ANCHOR_BOTH // Anchor at start and end + }; + + // General matching routine. Stores the length of the match in + // "*consumed" if successful. + bool DoMatch(const StringPiece& text, + Anchor anchor, + int* consumed, + const Arg* const* args, int n) const; + + // Return the number of capturing subpatterns, or -1 if the + // regexp wasn't valid on construction. + int NumberOfCapturingGroups(); + + private: + + void Init(const char* pattern, const RE_Options* options); + + // Match against "text", filling in "vec" (up to "vecsize" * 2/3) with + // pairs of integers for the beginning and end positions of matched + // text. The first pair corresponds to the entire matched text; + // subsequent pairs correspond, in order, to parentheses-captured + // matches. Returns the number of pairs (one more than the number of + // the last subpattern with a match) if matching was successful + // and zero if the match failed. + // I.e. for RE("(foo)|(bar)|(baz)") it will return 2, 3, and 4 when matching + // against "foo", "bar", and "baz" respectively. + // When matching RE("(foo)|hello") against "hello", it will return 1. + // But the values for all subpattern are filled in into "vec". + int TryMatch(const StringPiece& text, + int startpos, + Anchor anchor, + int *vec, + int vecsize) const; + + // Append the "rewrite" string, with backslash subsitutions from "text" + // and "vec", to string "out". + bool Rewrite(string *out, + const StringPiece& rewrite, + const StringPiece& text, + int *vec, + int veclen) const; + + // internal implementation for DoMatch + bool DoMatchImpl(const StringPiece& text, + Anchor anchor, + int* consumed, + const Arg* const args[], + int n, + int* vec, + int vecsize) const; + + // Compile the regexp for the specified anchoring mode + pcre* Compile(Anchor anchor); + + string pattern_; + RE_Options options_; + pcre* re_full_; // For full matches + pcre* re_partial_; // For partial matches + const string* error_; // Error indicator (or points to empty string) + int match_limit_; // limit on execution resources + + // Don't allow the default copy or assignment constructors -- + // they're expensive and too easy to do by accident. + RE(const RE&); + void operator=(const RE&); +}; + + +/***** Implementation details *****/ + +// Hex/Octal/Binary? + +// Special class for parsing into objects that define a ParseFrom() method +template +class _RE_MatchObject { + public: + static inline bool Parse(const char* str, int n, void* dest) { + T* object = reinterpret_cast(dest); + return object->ParseFrom(str, n); + } +}; + +class Arg { + public: + // Empty constructor so we can declare arrays of Arg + Arg(); + + // Constructor specially designed for NULL arguments + Arg(void*); + + typedef bool (*Parser)(const char* str, int n, void* dest); + +// Type-specific parsers +#define PCRE_MAKE_PARSER(type,name) \ + Arg(type* p) : arg_(p), parser_(name) { } \ + Arg(type* p, Parser parser) : arg_(p), parser_(parser) { } + + + PCRE_MAKE_PARSER(char, parse_char); + PCRE_MAKE_PARSER(unsigned char, parse_uchar); + PCRE_MAKE_PARSER(short, parse_short); + PCRE_MAKE_PARSER(unsigned short, parse_ushort); + PCRE_MAKE_PARSER(int, parse_int); + PCRE_MAKE_PARSER(unsigned int, parse_uint); + PCRE_MAKE_PARSER(long, parse_long); + PCRE_MAKE_PARSER(unsigned long, parse_ulong); +#if 1 + PCRE_MAKE_PARSER(long long, parse_longlong); +#endif +#if 1 + PCRE_MAKE_PARSER(unsigned long long, parse_ulonglong); +#endif + PCRE_MAKE_PARSER(float, parse_float); + PCRE_MAKE_PARSER(double, parse_double); + PCRE_MAKE_PARSER(string, parse_string); + PCRE_MAKE_PARSER(StringPiece, parse_stringpiece); + +#undef PCRE_MAKE_PARSER + + // Generic constructor + template Arg(T*, Parser parser); + // Generic constructor template + template Arg(T* p) + : arg_(p), parser_(_RE_MatchObject::Parse) { + } + + // Parse the data + bool Parse(const char* str, int n) const; + + private: + void* arg_; + Parser parser_; + + static bool parse_null (const char* str, int n, void* dest); + static bool parse_char (const char* str, int n, void* dest); + static bool parse_uchar (const char* str, int n, void* dest); + static bool parse_float (const char* str, int n, void* dest); + static bool parse_double (const char* str, int n, void* dest); + static bool parse_string (const char* str, int n, void* dest); + static bool parse_stringpiece (const char* str, int n, void* dest); + +#define PCRE_DECLARE_INTEGER_PARSER(name) \ + private: \ + static bool parse_ ## name(const char* str, int n, void* dest); \ + static bool parse_ ## name ## _radix( \ + const char* str, int n, void* dest, int radix); \ + public: \ + static bool parse_ ## name ## _hex(const char* str, int n, void* dest); \ + static bool parse_ ## name ## _octal(const char* str, int n, void* dest); \ + static bool parse_ ## name ## _cradix(const char* str, int n, void* dest) + + PCRE_DECLARE_INTEGER_PARSER(short); + PCRE_DECLARE_INTEGER_PARSER(ushort); + PCRE_DECLARE_INTEGER_PARSER(int); + PCRE_DECLARE_INTEGER_PARSER(uint); + PCRE_DECLARE_INTEGER_PARSER(long); + PCRE_DECLARE_INTEGER_PARSER(ulong); + PCRE_DECLARE_INTEGER_PARSER(longlong); + PCRE_DECLARE_INTEGER_PARSER(ulonglong); + +#undef PCRE_DECLARE_INTEGER_PARSER +}; + +inline Arg::Arg() : arg_(NULL), parser_(parse_null) { } +inline Arg::Arg(void* p) : arg_(p), parser_(parse_null) { } + +inline bool Arg::Parse(const char* str, int n) const { + return (*parser_)(str, n, arg_); +} + +// This part of the parser, appropriate only for ints, deals with bases +#define MAKE_INTEGER_PARSER(type, name) \ + inline Arg Hex(type* ptr) { \ + return Arg(ptr, Arg::parse_ ## name ## _hex); } \ + inline Arg Octal(type* ptr) { \ + return Arg(ptr, Arg::parse_ ## name ## _octal); } \ + inline Arg CRadix(type* ptr) { \ + return Arg(ptr, Arg::parse_ ## name ## _cradix); } + +MAKE_INTEGER_PARSER(short, short); +MAKE_INTEGER_PARSER(unsigned short, ushort); +MAKE_INTEGER_PARSER(int, int); +MAKE_INTEGER_PARSER(unsigned int, uint); +MAKE_INTEGER_PARSER(long, long); +MAKE_INTEGER_PARSER(unsigned long, ulong); +#if 1 +MAKE_INTEGER_PARSER(long long, longlong); +#endif +#if 1 +MAKE_INTEGER_PARSER(unsigned long long, ulonglong); +#endif + +#undef PCRE_IS_SET +#undef PCRE_SET_OR_CLEAR +#undef MAKE_INTEGER_PARSER + +} // namespace pcrecpp + + +#endif /* _PCRE_REGEXP_H */ diff --git a/ext/pcre/pcrelib/pcrecpp_unittest.cc b/ext/pcre/pcrelib/pcrecpp_unittest.cc new file mode 100644 index 000000000000..6a03744a7dbe --- /dev/null +++ b/ext/pcre/pcrelib/pcrecpp_unittest.cc @@ -0,0 +1,1042 @@ +// Copyright (c) 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: Sanjay Ghemawat +// +// TODO: Test extractions for PartialMatch/Consume + +#include +#include +#include "config.h" +#include "pcrecpp.h" + +using pcrecpp::StringPiece; +using pcrecpp::RE; +using pcrecpp::RE_Options; +using pcrecpp::Hex; +using pcrecpp::Octal; +using pcrecpp::CRadix; + +static bool VERBOSE_TEST = false; + +// CHECK dies with a fatal error if condition is not true. It is *not* +// controlled by NDEBUG, so the check will be executed regardless of +// compilation mode. Therefore, it is safe to do things like: +// CHECK_EQ(fp->Write(x), 4) +#define CHECK(condition) do { \ + if (!(condition)) { \ + fprintf(stderr, "%s:%d: Check failed: %s\n", \ + __FILE__, __LINE__, #condition); \ + exit(1); \ + } \ +} while (0) + +#define CHECK_EQ(a, b) CHECK(a == b) + +static void Timing1(int num_iters) { + // Same pattern lots of times + RE pattern("ruby:\\d+"); + StringPiece p("ruby:1234"); + for (int j = num_iters; j > 0; j--) { + CHECK(pattern.FullMatch(p)); + } +} + +static void Timing2(int num_iters) { + // Same pattern lots of times + RE pattern("ruby:(\\d+)"); + int i; + for (int j = num_iters; j > 0; j--) { + CHECK(pattern.FullMatch("ruby:1234", &i)); + CHECK_EQ(i, 1234); + } +} + +static void Timing3(int num_iters) { + string text_string; + for (int j = num_iters; j > 0; j--) { + text_string += "this is another line\n"; + } + + RE line_matcher(".*\n"); + string line; + StringPiece text(text_string); + int counter = 0; + while (line_matcher.Consume(&text)) { + counter++; + } + printf("Matched %d lines\n", counter); +} + +#if 0 // uncomment this if you have a way of defining VirtualProcessSize() + +static void LeakTest() { + // Check for memory leaks + unsigned long long initial_size = 0; + for (int i = 0; i < 100000; i++) { + if (i == 50000) { + initial_size = VirtualProcessSize(); + printf("Size after 50000: %llu\n", initial_size); + } + char buf[100]; + snprintf(buf, sizeof(buf), "pat%09d", i); + RE newre(buf); + } + uint64 final_size = VirtualProcessSize(); + printf("Size after 100000: %llu\n", final_size); + const double growth = double(final_size - initial_size) / final_size; + printf("Growth: %0.2f%%", growth * 100); + CHECK(growth < 0.02); // Allow < 2% growth +} + +#endif + +static void RadixTests() { + printf("Testing hex\n"); + +#define CHECK_HEX(type, value) \ + do { \ + type v; \ + CHECK(RE("([0-9a-fA-F]+)[uUlL]*").FullMatch(#value, Hex(&v))); \ + CHECK_EQ(v, 0x ## value); \ + CHECK(RE("([0-9a-fA-FxX]+)[uUlL]*").FullMatch("0x" #value, CRadix(&v))); \ + CHECK_EQ(v, 0x ## value); \ + } while(0) + + CHECK_HEX(short, 2bad); + CHECK_HEX(unsigned short, 2badU); + CHECK_HEX(int, dead); + CHECK_HEX(unsigned int, deadU); + CHECK_HEX(long, 7eadbeefL); + CHECK_HEX(unsigned long, deadbeefUL); +#ifdef HAVE_LONG_LONG + CHECK_HEX(long long, 12345678deadbeefLL); +#endif +#ifdef HAVE_UNSIGNED_LONG_LONG + CHECK_HEX(unsigned long long, cafebabedeadbeefULL); +#endif + +#undef CHECK_HEX + + printf("Testing octal\n"); + +#define CHECK_OCTAL(type, value) \ + do { \ + type v; \ + CHECK(RE("([0-7]+)[uUlL]*").FullMatch(#value, Octal(&v))); \ + CHECK_EQ(v, 0 ## value); \ + CHECK(RE("([0-9a-fA-FxX]+)[uUlL]*").FullMatch("0" #value, CRadix(&v))); \ + CHECK_EQ(v, 0 ## value); \ + } while(0) + + CHECK_OCTAL(short, 77777); + CHECK_OCTAL(unsigned short, 177777U); + CHECK_OCTAL(int, 17777777777); + CHECK_OCTAL(unsigned int, 37777777777U); + CHECK_OCTAL(long, 17777777777L); + CHECK_OCTAL(unsigned long, 37777777777UL); +#ifdef HAVE_LONG_LONG + CHECK_OCTAL(long long, 777777777777777777777LL); +#endif +#ifdef HAVE_UNSIGNED_LONG_LONG + CHECK_OCTAL(unsigned long long, 1777777777777777777777ULL); +#endif + +#undef CHECK_OCTAL + + printf("Testing decimal\n"); + +#define CHECK_DECIMAL(type, value) \ + do { \ + type v; \ + CHECK(RE("(-?[0-9]+)[uUlL]*").FullMatch(#value, &v)); \ + CHECK_EQ(v, value); \ + CHECK(RE("(-?[0-9a-fA-FxX]+)[uUlL]*").FullMatch(#value, CRadix(&v))); \ + CHECK_EQ(v, value); \ + } while(0) + + CHECK_DECIMAL(short, -1); + CHECK_DECIMAL(unsigned short, 9999); + CHECK_DECIMAL(int, -1000); + CHECK_DECIMAL(unsigned int, 12345U); + CHECK_DECIMAL(long, -10000000L); + CHECK_DECIMAL(unsigned long, 3083324652U); +#ifdef HAVE_LONG_LONG + CHECK_DECIMAL(long long, -100000000000000LL); +#endif +#ifdef HAVE_UNSIGNED_LONG_LONG + CHECK_DECIMAL(unsigned long long, 1234567890987654321ULL); +#endif + +#undef CHECK_DECIMAL + +} + +static void TestReplace() { + printf("Testing Replace\n"); + + struct ReplaceTest { + const char *regexp; + const char *rewrite; + const char *original; + const char *single; + const char *global; + }; + static const ReplaceTest tests[] = { + { "(qu|[b-df-hj-np-tv-z]*)([a-z]+)", + "\\2\\1ay", + "the quick brown fox jumps over the lazy dogs.", + "ethay quick brown fox jumps over the lazy dogs.", + "ethay ickquay ownbray oxfay umpsjay overay ethay azylay ogsday." }, + { "\\w+", + "\\0-NOSPAM", + "paul.haahr@google.com", + "paul-NOSPAM.haahr@google.com", + "paul-NOSPAM.haahr-NOSPAM@google-NOSPAM.com-NOSPAM" }, + { "^", + "(START)", + "foo", + "(START)foo", + "(START)foo" }, + { "^", + "(START)", + "", + "(START)", + "(START)" }, + { "$", + "(END)", + "", + "(END)", + "(END)" }, + { "b", + "bb", + "ababababab", + "abbabababab", + "abbabbabbabbabb" }, + { "b", + "bb", + "bbbbbb", + "bbbbbbb", + "bbbbbbbbbbbb" }, + { "b+", + "bb", + "bbbbbb", + "bb", + "bb" }, + { "b*", + "bb", + "bbbbbb", + "bb", + "bb" }, + { "b*", + "bb", + "aaaaa", + "bbaaaaa", + "bbabbabbabbabbabb" }, + { "", NULL, NULL, NULL, NULL } + }; + + for (const ReplaceTest *t = tests; t->original != NULL; ++t) { + string one(t->original); + CHECK(RE(t->regexp).Replace(t->rewrite, &one)); + CHECK_EQ(one, t->single); + string all(t->original); + CHECK(RE(t->regexp).GlobalReplace(t->rewrite, &all) > 0); + CHECK_EQ(all, t->global); + } +} + +static void TestExtract() { + printf("Testing Extract\n"); + + string s; + + CHECK(RE("(.*)@([^.]*)").Extract("\\2!\\1", "boris@kremvax.ru", &s)); + CHECK_EQ(s, "kremvax!boris"); + + // check the RE interface as well + CHECK(RE(".*").Extract("'\\0'", "foo", &s)); + CHECK_EQ(s, "'foo'"); + CHECK(!RE("bar").Extract("'\\0'", "baz", &s)); + CHECK_EQ(s, "'foo'"); +} + +static void TestConsume() { + printf("Testing Consume\n"); + + string word; + + string s(" aaa b!@#$@#$cccc"); + StringPiece input(s); + + RE r("\\s*(\\w+)"); // matches a word, possibly proceeded by whitespace + CHECK(r.Consume(&input, &word)); + CHECK_EQ(word, "aaa"); + CHECK(r.Consume(&input, &word)); + CHECK_EQ(word, "b"); + CHECK(! r.Consume(&input, &word)); +} + +static void TestFindAndConsume() { + printf("Testing FindAndConsume\n"); + + string word; + + string s(" aaa b!@#$@#$cccc"); + StringPiece input(s); + + RE r("(\\w+)"); // matches a word + CHECK(r.FindAndConsume(&input, &word)); + CHECK_EQ(word, "aaa"); + CHECK(r.FindAndConsume(&input, &word)); + CHECK_EQ(word, "b"); + CHECK(r.FindAndConsume(&input, &word)); + CHECK_EQ(word, "cccc"); + CHECK(! r.FindAndConsume(&input, &word)); +} + +static void TestMatchNumberPeculiarity() { + printf("Testing match-number peculiaraity\n"); + + string word1; + string word2; + string word3; + + RE r("(foo)|(bar)|(baz)"); + CHECK(r.PartialMatch("foo", &word1, &word2, &word3)); + CHECK_EQ(word1, "foo"); + CHECK_EQ(word2, ""); + CHECK_EQ(word3, ""); + CHECK(r.PartialMatch("bar", &word1, &word2, &word3)); + CHECK_EQ(word1, ""); + CHECK_EQ(word2, "bar"); + CHECK_EQ(word3, ""); + CHECK(r.PartialMatch("baz", &word1, &word2, &word3)); + CHECK_EQ(word1, ""); + CHECK_EQ(word2, ""); + CHECK_EQ(word3, "baz"); + CHECK(!r.PartialMatch("f", &word1, &word2, &word3)); + + string a; + CHECK(RE("(foo)|hello").FullMatch("hello", &a)); + CHECK_EQ(a, ""); +} + +static void TestRecursion(int size, const char *pattern, int match_limit) { + printf("Testing recursion\n"); + + // Fill up a string repeating the pattern given + string domain; + domain.resize(size); + int patlen = strlen(pattern); + for (int i = 0; i < size; ++i) { + domain[i] = pattern[i % patlen]; + } + // Just make sure it doesn't crash due to too much recursion. + RE_Options options; + options.set_match_limit(match_limit); + RE re("([a-zA-Z0-9]|-)+(\\.([a-zA-Z0-9]|-)+)*(\\.)?", options); + re.FullMatch(domain); +} + +// +// Options tests contributed by +// Giuseppe Maxia, CTO, Stardata s.r.l. +// July 2005 +// +static void GetOneOptionResult( + const char *option_name, + const char *regex, + const char *str, + RE_Options options, + bool full, + string expected) { + + printf("Testing Option <%s>\n", option_name); + if(VERBOSE_TEST) + printf("/%s/ finds \"%s\" within \"%s\" \n", + regex, + expected.c_str(), + str); + string captured(""); + if (full) + RE(regex,options).FullMatch(str, &captured); + else + RE(regex,options).PartialMatch(str, &captured); + CHECK_EQ(captured, expected); +} + +static void TestOneOption( + const char *option_name, + const char *regex, + const char *str, + RE_Options options, + bool full, + bool assertive = true) { + + printf("Testing Option <%s>\n", option_name); + if (VERBOSE_TEST) + printf("'%s' %s /%s/ \n", + str, + (assertive? "matches" : "doesn't match"), + regex); + if (assertive) { + if (full) + CHECK(RE(regex,options).FullMatch(str)); + else + CHECK(RE(regex,options).PartialMatch(str)); + } else { + if (full) + CHECK(!RE(regex,options).FullMatch(str)); + else + CHECK(!RE(regex,options).PartialMatch(str)); + } +} + +static void Test_CASELESS() { + RE_Options options; + RE_Options options2; + + options.set_caseless(true); + TestOneOption("CASELESS (class)", "HELLO", "hello", options, false); + TestOneOption("CASELESS (class2)", "HELLO", "hello", options2.set_caseless(true), false); + TestOneOption("CASELESS (class)", "^[A-Z]+$", "Hello", options, false); + + TestOneOption("CASELESS (function)", "HELLO", "hello", pcrecpp::CASELESS(), false); + TestOneOption("CASELESS (function)", "^[A-Z]+$", "Hello", pcrecpp::CASELESS(), false); + options.set_caseless(false); + TestOneOption("no CASELESS", "HELLO", "hello", options, false, false); +} + +static void Test_MULTILINE() { + RE_Options options; + RE_Options options2; + const char *str = "HELLO\n" "cruel\n" "world\n"; + + options.set_multiline(true); + TestOneOption("MULTILINE (class)", "^cruel$", str, options, false); + TestOneOption("MULTILINE (class2)", "^cruel$", str, options2.set_multiline(true), false); + TestOneOption("MULTILINE (function)", "^cruel$", str, pcrecpp::MULTILINE(), false); + options.set_multiline(false); + TestOneOption("no MULTILINE", "^cruel$", str, options, false, false); +} + +static void Test_DOTALL() { + RE_Options options; + RE_Options options2; + const char *str = "HELLO\n" "cruel\n" "world"; + + options.set_dotall(true); + TestOneOption("DOTALL (class)", "HELLO.*world", str, options, true); + TestOneOption("DOTALL (class2)", "HELLO.*world", str, options2.set_dotall(true), true); + TestOneOption("DOTALL (function)", "HELLO.*world", str, pcrecpp::DOTALL(), true); + options.set_dotall(false); + TestOneOption("no DOTALL", "HELLO.*world", str, options, true, false); +} + +static void Test_DOLLAR_ENDONLY() { + RE_Options options; + RE_Options options2; + const char *str = "HELLO world\n"; + + TestOneOption("no DOLLAR_ENDONLY", "world$", str, options, false); + options.set_dollar_endonly(true); + TestOneOption("DOLLAR_ENDONLY 1", "world$", str, options, false, false); + TestOneOption("DOLLAR_ENDONLY 2", "world$", str, options2.set_dollar_endonly(true), false, false); +} + +static void Test_EXTRA() { + RE_Options options; + const char *str = "HELLO"; + + options.set_extra(true); + TestOneOption("EXTRA 1", "\\HELL\\O", str, options, true, false ); + TestOneOption("EXTRA 2", "\\HELL\\O", str, RE_Options().set_extra(true), true, false ); + options.set_extra(false); + TestOneOption("no EXTRA", "\\HELL\\O", str, options, true ); +} + +static void Test_EXTENDED() { + RE_Options options; + RE_Options options2; + const char *str = "HELLO world"; + + options.set_extended(true); + TestOneOption("EXTENDED (class)", "HELLO world", str, options, false, false); + TestOneOption("EXTENDED (class2)", "HELLO world", str, options2.set_extended(true), false, false); + TestOneOption("EXTENDED (class)", + "^ HE L{2} O " + "\\s+ " + "\\w+ $ ", + str, + options, + false); + + TestOneOption("EXTENDED (function)", "HELLO world", str, pcrecpp::EXTENDED(), false, false); + TestOneOption("EXTENDED (function)", + "^ HE L{2} O " + "\\s+ " + "\\w+ $ ", + str, + pcrecpp::EXTENDED(), + false); + + options.set_extended(false); + TestOneOption("no EXTENDED", "HELLO world", str, options, false); +} + +static void Test_NO_AUTO_CAPTURE() { + RE_Options options; + const char *str = "HELLO world"; + string captured; + + printf("Testing Option \n"); + if (VERBOSE_TEST) + printf("parentheses capture text\n"); + RE re("(world|universe)$", options); + CHECK(re.Extract("\\1", str , &captured)); + CHECK_EQ(captured, "world"); + options.set_no_auto_capture(true); + printf("testing Option \n"); + if (VERBOSE_TEST) + printf("parentheses do not capture text\n"); + re.Extract("\\1",str, &captured ); + CHECK_EQ(captured, "world"); +} + +static void Test_UNGREEDY() { + RE_Options options; + const char *str = "HELLO, 'this' is the 'world'"; + + options.set_ungreedy(true); + GetOneOptionResult("UNGREEDY 1", "('.*')", str, options, false, "'this'" ); + GetOneOptionResult("UNGREEDY 2", "('.*')", str, RE_Options().set_ungreedy(true), false, "'this'" ); + GetOneOptionResult("UNGREEDY", "('.*?')", str, options, false, "'this' is the 'world'" ); + + options.set_ungreedy(false); + GetOneOptionResult("no UNGREEDY", "('.*')", str, options, false, "'this' is the 'world'" ); + GetOneOptionResult("no UNGREEDY", "('.*?')", str, options, false, "'this'" ); +} + +static void Test_all_options() { + const char *str = "HELLO\n" "cruel\n" "world"; + RE_Options options; + options.set_all_options(PCRE_CASELESS | PCRE_DOTALL); + + TestOneOption("all_options (CASELESS|DOTALL)", "^hello.*WORLD", str , options, false); + options.set_all_options(0); + TestOneOption("all_options (0)", "^hello.*WORLD", str , options, false, false); + options.set_all_options(PCRE_MULTILINE | PCRE_EXTENDED); + + TestOneOption("all_options (MULTILINE|EXTENDED)", " ^ c r u e l $ ", str, options, false); + TestOneOption("all_options (MULTILINE|EXTENDED) with constructor", + " ^ c r u e l $ ", + str, + RE_Options(PCRE_MULTILINE | PCRE_EXTENDED), + false); + + TestOneOption("all_options (MULTILINE|EXTENDED) with concatenation", + " ^ c r u e l $ ", + str, + RE_Options() + .set_multiline(true) + .set_extended(true), + false); + + options.set_all_options(0); + TestOneOption("all_options (0)", "^ c r u e l $", str, options, false, false); + +} + +static void TestOptions() { + printf("Testing Options\n"); + Test_CASELESS(); + Test_MULTILINE(); + Test_DOTALL(); + Test_DOLLAR_ENDONLY(); + Test_EXTENDED(); + Test_NO_AUTO_CAPTURE(); + Test_UNGREEDY(); + Test_EXTRA(); + Test_all_options(); +} + +int main(int argc, char** argv) { + // Treat any flag as --help + if (argc > 1 && argv[1][0] == '-') { + printf("Usage: %s [timing1|timing2|timing3 num-iters]\n" + " If 'timingX ###' is specified, run the given timing test\n" + " with the given number of iterations, rather than running\n" + " the default corectness test.\n", argv[0]); + return 0; + } + + if (argc > 1) { + if ( argc == 2 || atoi(argv[2]) == 0) { + printf("timing mode needs a num-iters argument\n"); + return 1; + } + if (!strcmp(argv[1], "timing1")) + Timing1(atoi(argv[2])); + else if (!strcmp(argv[1], "timing2")) + Timing2(atoi(argv[2])); + else if (!strcmp(argv[1], "timing3")) + Timing3(atoi(argv[2])); + else + printf("Unknown argument '%s'\n", argv[1]); + return 0; + } + + printf("Testing FullMatch\n"); + + int i; + string s; + + /***** FullMatch with no args *****/ + + CHECK(RE("h.*o").FullMatch("hello")); + CHECK(!RE("h.*o").FullMatch("othello")); + CHECK(!RE("h.*o").FullMatch("hello!")); + + /***** FullMatch with args *****/ + + // Zero-arg + CHECK(RE("\\d+").FullMatch("1001")); + + // Single-arg + CHECK(RE("(\\d+)").FullMatch("1001", &i)); + CHECK_EQ(i, 1001); + CHECK(RE("(-?\\d+)").FullMatch("-123", &i)); + CHECK_EQ(i, -123); + CHECK(!RE("()\\d+").FullMatch("10", &i)); + CHECK(!RE("(\\d+)").FullMatch("1234567890123456789012345678901234567890", + &i)); + + // Digits surrounding integer-arg + CHECK(RE("1(\\d*)4").FullMatch("1234", &i)); + CHECK_EQ(i, 23); + CHECK(RE("(\\d)\\d+").FullMatch("1234", &i)); + CHECK_EQ(i, 1); + CHECK(RE("(-\\d)\\d+").FullMatch("-1234", &i)); + CHECK_EQ(i, -1); + CHECK(RE("(\\d)").PartialMatch("1234", &i)); + CHECK_EQ(i, 1); + CHECK(RE("(-\\d)").PartialMatch("-1234", &i)); + CHECK_EQ(i, -1); + + // String-arg + CHECK(RE("h(.*)o").FullMatch("hello", &s)); + CHECK_EQ(s, string("ell")); + + // StringPiece-arg + StringPiece sp; + CHECK(RE("(\\w+):(\\d+)").FullMatch("ruby:1234", &sp, &i)); + CHECK_EQ(sp.size(), 4); + CHECK(memcmp(sp.data(), "ruby", 4) == 0); + CHECK_EQ(i, 1234); + + // Multi-arg + CHECK(RE("(\\w+):(\\d+)").FullMatch("ruby:1234", &s, &i)); + CHECK_EQ(s, string("ruby")); + CHECK_EQ(i, 1234); + + // Ignored arg + CHECK(RE("(\\w+)(:)(\\d+)").FullMatch("ruby:1234", &s, (void*)NULL, &i)); + CHECK_EQ(s, string("ruby")); + CHECK_EQ(i, 1234); + + // Type tests + { + char c; + CHECK(RE("(H)ello").FullMatch("Hello", &c)); + CHECK_EQ(c, 'H'); + } + { + unsigned char c; + CHECK(RE("(H)ello").FullMatch("Hello", &c)); + CHECK_EQ(c, static_cast('H')); + } + { + short v; + CHECK(RE("(-?\\d+)").FullMatch("100", &v)); CHECK_EQ(v, 100); + CHECK(RE("(-?\\d+)").FullMatch("-100", &v)); CHECK_EQ(v, -100); + CHECK(RE("(-?\\d+)").FullMatch("32767", &v)); CHECK_EQ(v, 32767); + CHECK(RE("(-?\\d+)").FullMatch("-32768", &v)); CHECK_EQ(v, -32768); + CHECK(!RE("(-?\\d+)").FullMatch("-32769", &v)); + CHECK(!RE("(-?\\d+)").FullMatch("32768", &v)); + } + { + unsigned short v; + CHECK(RE("(\\d+)").FullMatch("100", &v)); CHECK_EQ(v, 100); + CHECK(RE("(\\d+)").FullMatch("32767", &v)); CHECK_EQ(v, 32767); + CHECK(RE("(\\d+)").FullMatch("65535", &v)); CHECK_EQ(v, 65535); + CHECK(!RE("(\\d+)").FullMatch("65536", &v)); + } + { + int v; + static const int max_value = 0x7fffffff; + static const int min_value = -max_value - 1; + CHECK(RE("(-?\\d+)").FullMatch("100", &v)); CHECK_EQ(v, 100); + CHECK(RE("(-?\\d+)").FullMatch("-100", &v)); CHECK_EQ(v, -100); + CHECK(RE("(-?\\d+)").FullMatch("2147483647", &v)); CHECK_EQ(v, max_value); + CHECK(RE("(-?\\d+)").FullMatch("-2147483648", &v)); CHECK_EQ(v, min_value); + CHECK(!RE("(-?\\d+)").FullMatch("-2147483649", &v)); + CHECK(!RE("(-?\\d+)").FullMatch("2147483648", &v)); + } + { + unsigned int v; + static const unsigned int max_value = 0xfffffffful; + CHECK(RE("(\\d+)").FullMatch("100", &v)); CHECK_EQ(v, 100); + CHECK(RE("(\\d+)").FullMatch("4294967295", &v)); CHECK_EQ(v, max_value); + CHECK(!RE("(\\d+)").FullMatch("4294967296", &v)); + } +#ifdef HAVE_LONG_LONG + { + long long v; + static const long long max_value = 0x7fffffffffffffffLL; + static const long long min_value = -max_value - 1; + char buf[32]; + + CHECK(RE("(-?\\d+)").FullMatch("100", &v)); CHECK_EQ(v, 100); + CHECK(RE("(-?\\d+)").FullMatch("-100",&v)); CHECK_EQ(v, -100); + + snprintf(buf, sizeof(buf), "%lld", max_value); + CHECK(RE("(-?\\d+)").FullMatch(buf,&v)); CHECK_EQ(v, max_value); + + snprintf(buf, sizeof(buf), "%lld", min_value); + CHECK(RE("(-?\\d+)").FullMatch(buf,&v)); CHECK_EQ(v, min_value); + + snprintf(buf, sizeof(buf), "%lld", max_value); + assert(buf[strlen(buf)-1] != '9'); + buf[strlen(buf)-1]++; + CHECK(!RE("(-?\\d+)").FullMatch(buf, &v)); + + snprintf(buf, sizeof(buf), "%lld", min_value); + assert(buf[strlen(buf)-1] != '9'); + buf[strlen(buf)-1]++; + CHECK(!RE("(-?\\d+)").FullMatch(buf, &v)); + } +#endif +#if defined HAVE_UNSIGNED_LONG_LONG && defined HAVE_LONG_LONG + { + unsigned long long v; + long long v2; + static const unsigned long long max_value = 0xffffffffffffffffULL; + char buf[32]; + + CHECK(RE("(-?\\d+)").FullMatch("100",&v)); CHECK_EQ(v, 100); + CHECK(RE("(-?\\d+)").FullMatch("-100",&v2)); CHECK_EQ(v2, -100); + + snprintf(buf, sizeof(buf), "%llu", max_value); + CHECK(RE("(-?\\d+)").FullMatch(buf,&v)); CHECK_EQ(v, max_value); + + assert(buf[strlen(buf)-1] != '9'); + buf[strlen(buf)-1]++; + CHECK(!RE("(-?\\d+)").FullMatch(buf, &v)); + } +#endif + { + float v; + CHECK(RE("(.*)").FullMatch("100", &v)); + CHECK(RE("(.*)").FullMatch("-100.", &v)); + CHECK(RE("(.*)").FullMatch("1e23", &v)); + } + { + double v; + CHECK(RE("(.*)").FullMatch("100", &v)); + CHECK(RE("(.*)").FullMatch("-100.", &v)); + CHECK(RE("(.*)").FullMatch("1e23", &v)); + } + + // Check that matching is fully anchored + CHECK(!RE("(\\d+)").FullMatch("x1001", &i)); + CHECK(!RE("(\\d+)").FullMatch("1001x", &i)); + CHECK(RE("x(\\d+)").FullMatch("x1001", &i)); CHECK_EQ(i, 1001); + CHECK(RE("(\\d+)x").FullMatch("1001x", &i)); CHECK_EQ(i, 1001); + + // Braces + CHECK(RE("[0-9a-f+.-]{5,}").FullMatch("0abcd")); + CHECK(RE("[0-9a-f+.-]{5,}").FullMatch("0abcde")); + CHECK(!RE("[0-9a-f+.-]{5,}").FullMatch("0abc")); + + // Complicated RE + CHECK(RE("foo|bar|[A-Z]").FullMatch("foo")); + CHECK(RE("foo|bar|[A-Z]").FullMatch("bar")); + CHECK(RE("foo|bar|[A-Z]").FullMatch("X")); + CHECK(!RE("foo|bar|[A-Z]").FullMatch("XY")); + + // Check full-match handling (needs '$' tacked on internally) + CHECK(RE("fo|foo").FullMatch("fo")); + CHECK(RE("fo|foo").FullMatch("foo")); + CHECK(RE("fo|foo$").FullMatch("fo")); + CHECK(RE("fo|foo$").FullMatch("foo")); + CHECK(RE("foo$").FullMatch("foo")); + CHECK(!RE("foo\\$").FullMatch("foo$bar")); + CHECK(!RE("fo|bar").FullMatch("fox")); + + // Uncomment the following if we change the handling of '$' to + // prevent it from matching a trailing newline + if (false) { + // Check that we don't get bitten by pcre's special handling of a + // '\n' at the end of the string matching '$' + CHECK(!RE("foo$").PartialMatch("foo\n")); + } + + // Number of args + int a[16]; + CHECK(RE("").FullMatch("")); + + memset(a, 0, sizeof(0)); + CHECK(RE("(\\d){1}").FullMatch("1", + &a[0])); + CHECK_EQ(a[0], 1); + + memset(a, 0, sizeof(0)); + CHECK(RE("(\\d)(\\d)").FullMatch("12", + &a[0], &a[1])); + CHECK_EQ(a[0], 1); + CHECK_EQ(a[1], 2); + + memset(a, 0, sizeof(0)); + CHECK(RE("(\\d)(\\d)(\\d)").FullMatch("123", + &a[0], &a[1], &a[2])); + CHECK_EQ(a[0], 1); + CHECK_EQ(a[1], 2); + CHECK_EQ(a[2], 3); + + memset(a, 0, sizeof(0)); + CHECK(RE("(\\d)(\\d)(\\d)(\\d)").FullMatch("1234", + &a[0], &a[1], &a[2], &a[3])); + CHECK_EQ(a[0], 1); + CHECK_EQ(a[1], 2); + CHECK_EQ(a[2], 3); + CHECK_EQ(a[3], 4); + + memset(a, 0, sizeof(0)); + CHECK(RE("(\\d)(\\d)(\\d)(\\d)(\\d)").FullMatch("12345", + &a[0], &a[1], &a[2], + &a[3], &a[4])); + CHECK_EQ(a[0], 1); + CHECK_EQ(a[1], 2); + CHECK_EQ(a[2], 3); + CHECK_EQ(a[3], 4); + CHECK_EQ(a[4], 5); + + memset(a, 0, sizeof(0)); + CHECK(RE("(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)").FullMatch("123456", + &a[0], &a[1], &a[2], + &a[3], &a[4], &a[5])); + CHECK_EQ(a[0], 1); + CHECK_EQ(a[1], 2); + CHECK_EQ(a[2], 3); + CHECK_EQ(a[3], 4); + CHECK_EQ(a[4], 5); + CHECK_EQ(a[5], 6); + + memset(a, 0, sizeof(0)); + CHECK(RE("(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)").FullMatch("1234567", + &a[0], &a[1], &a[2], &a[3], + &a[4], &a[5], &a[6])); + CHECK_EQ(a[0], 1); + CHECK_EQ(a[1], 2); + CHECK_EQ(a[2], 3); + CHECK_EQ(a[3], 4); + CHECK_EQ(a[4], 5); + CHECK_EQ(a[5], 6); + CHECK_EQ(a[6], 7); + + memset(a, 0, sizeof(0)); + CHECK(RE("(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)" + "(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)").FullMatch( + "1234567890123456", + &a[0], &a[1], &a[2], &a[3], + &a[4], &a[5], &a[6], &a[7], + &a[8], &a[9], &a[10], &a[11], + &a[12], &a[13], &a[14], &a[15])); + CHECK_EQ(a[0], 1); + CHECK_EQ(a[1], 2); + CHECK_EQ(a[2], 3); + CHECK_EQ(a[3], 4); + CHECK_EQ(a[4], 5); + CHECK_EQ(a[5], 6); + CHECK_EQ(a[6], 7); + CHECK_EQ(a[7], 8); + CHECK_EQ(a[8], 9); + CHECK_EQ(a[9], 0); + CHECK_EQ(a[10], 1); + CHECK_EQ(a[11], 2); + CHECK_EQ(a[12], 3); + CHECK_EQ(a[13], 4); + CHECK_EQ(a[14], 5); + CHECK_EQ(a[15], 6); + + /***** PartialMatch *****/ + + printf("Testing PartialMatch\n"); + + CHECK(RE("h.*o").PartialMatch("hello")); + CHECK(RE("h.*o").PartialMatch("othello")); + CHECK(RE("h.*o").PartialMatch("hello!")); + CHECK(RE("((((((((((((((((((((x))))))))))))))))))))").PartialMatch("x")); + + RadixTests(); + TestReplace(); + TestExtract(); + TestConsume(); + TestFindAndConsume(); + TestMatchNumberPeculiarity(); + + // Check the pattern() accessor + { + const string kPattern = "http://([^/]+)/.*"; + const RE re(kPattern); + CHECK_EQ(kPattern, re.pattern()); + } + + // Check RE error field. + { + RE re("foo"); + CHECK(re.error().empty()); // Must have no error + } + +#ifdef SUPPORT_UTF8 + // Check UTF-8 handling + { + printf("Testing UTF-8 handling\n"); + + // Three Japanese characters (nihongo) + const char utf8_string[] = { + 0xe6, 0x97, 0xa5, // 65e5 + 0xe6, 0x9c, 0xac, // 627c + 0xe8, 0xaa, 0x9e, // 8a9e + 0 + }; + const char utf8_pattern[] = { + '.', + 0xe6, 0x9c, 0xac, // 627c + '.', + 0 + }; + + // Both should match in either mode, bytes or UTF-8 + RE re_test1("........."); + CHECK(re_test1.FullMatch(utf8_string)); + RE re_test2("...", pcrecpp::UTF8()); + CHECK(re_test2.FullMatch(utf8_string)); + + // Check that '.' matches one byte or UTF-8 character + // according to the mode. + string ss; + RE re_test3("(.)"); + CHECK(re_test3.PartialMatch(utf8_string, &ss)); + CHECK_EQ(ss, string("\xe6")); + RE re_test4("(.)", pcrecpp::UTF8()); + CHECK(re_test4.PartialMatch(utf8_string, &ss)); + CHECK_EQ(ss, string("\xe6\x97\xa5")); + + // Check that string matches itself in either mode + RE re_test5(utf8_string); + CHECK(re_test5.FullMatch(utf8_string)); + RE re_test6(utf8_string, pcrecpp::UTF8()); + CHECK(re_test6.FullMatch(utf8_string)); + + // Check that pattern matches string only in UTF8 mode + RE re_test7(utf8_pattern); + CHECK(!re_test7.FullMatch(utf8_string)); + RE re_test8(utf8_pattern, pcrecpp::UTF8()); + CHECK(re_test8.FullMatch(utf8_string)); + } + + // Check that ungreedy, UTF8 regular expressions don't match when they + // oughtn't -- see bug 82246. + { + // This code always worked. + const char* pattern = "\\w+X"; + const string target = "a aX"; + RE match_sentence(pattern); + RE match_sentence_re(pattern, pcrecpp::UTF8()); + + CHECK(!match_sentence.FullMatch(target)); + CHECK(!match_sentence_re.FullMatch(target)); + } + + { + const char* pattern = "(?U)\\w+X"; + const string target = "a aX"; + RE match_sentence(pattern); + RE match_sentence_re(pattern, pcrecpp::UTF8()); + + CHECK(!match_sentence.FullMatch(target)); + CHECK(!match_sentence_re.FullMatch(target)); + } +#endif /* def SUPPORT_UTF8 */ + + printf("Testing error reporting\n"); + + { RE re("a\\1"); CHECK(!re.error().empty()); } + { + RE re("a[x"); + CHECK(!re.error().empty()); + } + { + RE re("a[z-a]"); + CHECK(!re.error().empty()); + } + { + RE re("a[[:foobar:]]"); + CHECK(!re.error().empty()); + } + { + RE re("a(b"); + CHECK(!re.error().empty()); + } + { + RE re("a\\"); + CHECK(!re.error().empty()); + } + + // Test that recursion is stopped: there will be some errors reported + int matchlimit = 5000; + int bytes = 15 * 1024; // enough to crash if there was no match limit + TestRecursion(bytes, ".", matchlimit); + TestRecursion(bytes, "a", matchlimit); + TestRecursion(bytes, "a.", matchlimit); + TestRecursion(bytes, "ab.", matchlimit); + TestRecursion(bytes, "abc.", matchlimit); + + // Test Options + if (getenv("VERBOSE_TEST") != NULL) + VERBOSE_TEST = true; + TestOptions(); + + // Done + printf("OK\n"); + + return 0; +} diff --git a/ext/pcre/pcrelib/pcredemo.c b/ext/pcre/pcrelib/pcredemo.c new file mode 100644 index 000000000000..3817203b5fda --- /dev/null +++ b/ext/pcre/pcrelib/pcredemo.c @@ -0,0 +1,324 @@ +/************************************************* +* PCRE DEMONSTRATION PROGRAM * +*************************************************/ + +/* This is a demonstration program to illustrate the most straightforward ways +of calling the PCRE regular expression library from a C program. See the +pcresample documentation for a short discussion. + +Compile thuswise: + gcc -Wall pcredemo.c -I/usr/local/include -L/usr/local/lib \ + -R/usr/local/lib -lpcre + +Replace "/usr/local/include" and "/usr/local/lib" with wherever the include and +library files for PCRE are installed on your system. Only some operating +systems (e.g. Solaris) use the -R option. +*/ + + +#include +#include +#include + +#define OVECCOUNT 30 /* should be a multiple of 3 */ + + +int main(int argc, char **argv) +{ +pcre *re; +const char *error; +char *pattern; +char *subject; +unsigned char *name_table; +int erroffset; +int find_all; +int namecount; +int name_entry_size; +int ovector[OVECCOUNT]; +int subject_length; +int rc, i; + + +/************************************************************************** +* First, sort out the command line. There is only one possible option at * +* the moment, "-g" to request repeated matching to find all occurrences, * +* like Perl's /g option. We set the variable find_all to a non-zero value * +* if the -g option is present. Apart from that, there must be exactly two * +* arguments. * +**************************************************************************/ + +find_all = 0; +for (i = 1; i < argc; i++) + { + if (strcmp(argv[i], "-g") == 0) find_all = 1; + else break; + } + +/* After the options, we require exactly two arguments, which are the pattern, +and the subject string. */ + +if (argc - i != 2) + { + printf("Two arguments required: a regex and a subject string\n"); + return 1; + } + +pattern = argv[i]; +subject = argv[i+1]; +subject_length = (int)strlen(subject); + + +/************************************************************************* +* Now we are going to compile the regular expression pattern, and handle * +* and errors that are detected. * +*************************************************************************/ + +re = pcre_compile( + pattern, /* the pattern */ + 0, /* default options */ + &error, /* for error message */ + &erroffset, /* for error offset */ + NULL); /* use default character tables */ + +/* Compilation failed: print the error message and exit */ + +if (re == NULL) + { + printf("PCRE compilation failed at offset %d: %s\n", erroffset, error); + return 1; + } + + +/************************************************************************* +* If the compilation succeeded, we call PCRE again, in order to do a * +* pattern match against the subject string. This does just ONE match. If * +* further matching is needed, it will be done below. * +*************************************************************************/ + +rc = pcre_exec( + re, /* the compiled pattern */ + NULL, /* no extra data - we didn't study the pattern */ + subject, /* the subject string */ + subject_length, /* the length of the subject */ + 0, /* start at offset 0 in the subject */ + 0, /* default options */ + ovector, /* output vector for substring information */ + OVECCOUNT); /* number of elements in the output vector */ + +/* Matching failed: handle error cases */ + +if (rc < 0) + { + switch(rc) + { + case PCRE_ERROR_NOMATCH: printf("No match\n"); break; + /* + Handle other special cases if you like + */ + default: printf("Matching error %d\n", rc); break; + } + free(re); /* Release memory used for the compiled pattern */ + return 1; + } + +/* Match succeded */ + +printf("\nMatch succeeded at offset %d\n", ovector[0]); + + +/************************************************************************* +* We have found the first match within the subject string. If the output * +* vector wasn't big enough, set its size to the maximum. Then output any * +* substrings that were captured. * +*************************************************************************/ + +/* The output vector wasn't big enough */ + +if (rc == 0) + { + rc = OVECCOUNT/3; + printf("ovector only has room for %d captured substrings\n", rc - 1); + } + +/* Show substrings stored in the output vector by number. Obviously, in a real +application you might want to do things other than print them. */ + +for (i = 0; i < rc; i++) + { + char *substring_start = subject + ovector[2*i]; + int substring_length = ovector[2*i+1] - ovector[2*i]; + printf("%2d: %.*s\n", i, substring_length, substring_start); + } + + +/************************************************************************** +* That concludes the basic part of this demonstration program. We have * +* compiled a pattern, and performed a single match. The code that follows * +* first shows how to access named substrings, and then how to code for * +* repeated matches on the same subject. * +**************************************************************************/ + +/* See if there are any named substrings, and if so, show them by name. First +we have to extract the count of named parentheses from the pattern. */ + +(void)pcre_fullinfo( + re, /* the compiled pattern */ + NULL, /* no extra data - we didn't study the pattern */ + PCRE_INFO_NAMECOUNT, /* number of named substrings */ + &namecount); /* where to put the answer */ + +if (namecount <= 0) printf("No named substrings\n"); else + { + unsigned char *tabptr; + printf("Named substrings\n"); + + /* Before we can access the substrings, we must extract the table for + translating names to numbers, and the size of each entry in the table. */ + + (void)pcre_fullinfo( + re, /* the compiled pattern */ + NULL, /* no extra data - we didn't study the pattern */ + PCRE_INFO_NAMETABLE, /* address of the table */ + &name_table); /* where to put the answer */ + + (void)pcre_fullinfo( + re, /* the compiled pattern */ + NULL, /* no extra data - we didn't study the pattern */ + PCRE_INFO_NAMEENTRYSIZE, /* size of each entry in the table */ + &name_entry_size); /* where to put the answer */ + + /* Now we can scan the table and, for each entry, print the number, the name, + and the substring itself. */ + + tabptr = name_table; + for (i = 0; i < namecount; i++) + { + int n = (tabptr[0] << 8) | tabptr[1]; + printf("(%d) %*s: %.*s\n", n, name_entry_size - 3, tabptr + 2, + ovector[2*n+1] - ovector[2*n], subject + ovector[2*n]); + tabptr += name_entry_size; + } + } + + +/************************************************************************* +* If the "-g" option was given on the command line, we want to continue * +* to search for additional matches in the subject string, in a similar * +* way to the /g option in Perl. This turns out to be trickier than you * +* might think because of the possibility of matching an empty string. * +* What happens is as follows: * +* * +* If the previous match was NOT for an empty string, we can just start * +* the next match at the end of the previous one. * +* * +* If the previous match WAS for an empty string, we can't do that, as it * +* would lead to an infinite loop. Instead, a special call of pcre_exec() * +* is made with the PCRE_NOTEMPTY and PCRE_ANCHORED flags set. The first * +* of these tells PCRE that an empty string is not a valid match; other * +* possibilities must be tried. The second flag restricts PCRE to one * +* match attempt at the initial string position. If this match succeeds, * +* an alternative to the empty string match has been found, and we can * +* proceed round the loop. * +*************************************************************************/ + +if (!find_all) + { + free(re); /* Release the memory used for the compiled pattern */ + return 0; /* Finish unless -g was given */ + } + +/* Loop for second and subsequent matches */ + +for (;;) + { + int options = 0; /* Normally no options */ + int start_offset = ovector[1]; /* Start at end of previous match */ + + /* If the previous match was for an empty string, we are finished if we are + at the end of the subject. Otherwise, arrange to run another match at the + same point to see if a non-empty match can be found. */ + + if (ovector[0] == ovector[1]) + { + if (ovector[0] == subject_length) break; + options = PCRE_NOTEMPTY | PCRE_ANCHORED; + } + + /* Run the next matching operation */ + + rc = pcre_exec( + re, /* the compiled pattern */ + NULL, /* no extra data - we didn't study the pattern */ + subject, /* the subject string */ + subject_length, /* the length of the subject */ + start_offset, /* starting offset in the subject */ + options, /* options */ + ovector, /* output vector for substring information */ + OVECCOUNT); /* number of elements in the output vector */ + + /* This time, a result of NOMATCH isn't an error. If the value in "options" + is zero, it just means we have found all possible matches, so the loop ends. + Otherwise, it means we have failed to find a non-empty-string match at a + point where there was a previous empty-string match. In this case, we do what + Perl does: advance the matching position by one, and continue. We do this by + setting the "end of previous match" offset, because that is picked up at the + top of the loop as the point at which to start again. */ + + if (rc == PCRE_ERROR_NOMATCH) + { + if (options == 0) break; + ovector[1] = start_offset + 1; + continue; /* Go round the loop again */ + } + + /* Other matching errors are not recoverable. */ + + if (rc < 0) + { + printf("Matching error %d\n", rc); + free(re); /* Release memory used for the compiled pattern */ + return 1; + } + + /* Match succeded */ + + printf("\nMatch succeeded again at offset %d\n", ovector[0]); + + /* The match succeeded, but the output vector wasn't big enough. */ + + if (rc == 0) + { + rc = OVECCOUNT/3; + printf("ovector only has room for %d captured substrings\n", rc - 1); + } + + /* As before, show substrings stored in the output vector by number, and then + also any named substrings. */ + + for (i = 0; i < rc; i++) + { + char *substring_start = subject + ovector[2*i]; + int substring_length = ovector[2*i+1] - ovector[2*i]; + printf("%2d: %.*s\n", i, substring_length, substring_start); + } + + if (namecount <= 0) printf("No named substrings\n"); else + { + unsigned char *tabptr = name_table; + printf("Named substrings\n"); + for (i = 0; i < namecount; i++) + { + int n = (tabptr[0] << 8) | tabptr[1]; + printf("(%d) %*s: %.*s\n", n, name_entry_size - 3, tabptr + 2, + ovector[2*n+1] - ovector[2*n], subject + ovector[2*n]); + tabptr += name_entry_size; + } + } + } /* End of loop to find second and subsequent matches */ + +printf("\n"); +free(re); /* Release memory used for the compiled pattern */ +return 0; +} + +/* End of pcredemo.c */ diff --git a/ext/pcre/pcrelib/pcregrep.c b/ext/pcre/pcrelib/pcregrep.c index 7a06993d1950..f6e5180557e5 100644 --- a/ext/pcre/pcrelib/pcregrep.c +++ b/ext/pcre/pcrelib/pcregrep.c @@ -4,13 +4,49 @@ /* This is a grep program that uses the PCRE regular expression library to do its pattern matching. On a Unix or Win32 system it can recurse into -directories. */ +directories. + + Copyright (c) 1997-2005 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ #include #include #include #include #include + +#include +#include +#include + #include "config.h" #include "pcre.h" @@ -19,51 +55,89 @@ directories. */ typedef int BOOL; -#define VERSION "3.0 14-Jan-2003" +#define VERSION "4.0 07-Jun-2005" #define MAX_PATTERN_COUNT 100 +#if BUFSIZ > 8192 +#define MBUFTHIRD BUFSIZ +#else +#define MBUFTHIRD 8192 +#endif + + /************************************************* * Global variables * *************************************************/ static char *pattern_filename = NULL; +static char *stdin_name = (char *)"(standard input)"; static int pattern_count = 0; static pcre **pattern_list; static pcre_extra **hints_list; +static char *include_pattern = NULL; +static char *exclude_pattern = NULL; + +static pcre *include_compiled = NULL; +static pcre *exclude_compiled = NULL; + +static int after_context = 0; +static int before_context = 0; +static int both_context = 0; + static BOOL count_only = FALSE; static BOOL filenames = TRUE; static BOOL filenames_only = FALSE; +static BOOL filenames_nomatch_only = FALSE; +static BOOL hyphenpending = FALSE; static BOOL invert = FALSE; +static BOOL multiline = FALSE; static BOOL number = FALSE; +static BOOL quiet = FALSE; static BOOL recurse = FALSE; static BOOL silent = FALSE; static BOOL whole_lines = FALSE; +static BOOL word_match = FALSE; /* Structure for options and list of them */ +enum { OP_NODATA, OP_STRING, OP_NUMBER }; + typedef struct option_item { + int type; int one_char; + void *dataptr; const char *long_name; const char *help_text; } option_item; static option_item optionlist[] = { - { -1, "help", "display this help and exit" }, - { 'c', "count", "print only a count of matching lines per FILE" }, - { 'h', "no-filename", "suppress the prefixing filename on output" }, - { 'i', "ignore-case", "ignore case distinctions" }, - { 'l', "files-with-matches", "print only FILE names containing matches" }, - { 'n', "line-number", "print line number with output lines" }, - { 'r', "recursive", "recursively scan sub-directories" }, - { 's', "no-messages", "suppress error messages" }, - { 'u', "utf-8", "use UTF-8 mode" }, - { 'V', "version", "print version information and exit" }, - { 'v', "invert-match", "select non-matching lines" }, - { 'x', "line-regex", "force PATTERN to match only whole lines" }, - { 'x', "line-regexp", "force PATTERN to match only whole lines" }, - { 0, NULL, NULL } + { OP_NODATA, -1, NULL, "", " terminate options" }, + { OP_NODATA, -1, NULL, "help", "display this help and exit" }, + { OP_NUMBER, 'A', &after_context, "after-context=number", "set number of following context lines" }, + { OP_NUMBER, 'B', &before_context, "before-context=number", "set number of prior context lines" }, + { OP_NUMBER, 'C', &both_context, "context=number", "set number of context lines, before & after" }, + { OP_NODATA, 'c', NULL, "count", "print only a count of matching lines per FILE" }, + { OP_STRING, 'f', &pattern_filename, "file=path", "read patterns from file" }, + { OP_NODATA, 'h', NULL, "no-filename", "suppress the prefixing filename on output" }, + { OP_NODATA, 'i', NULL, "ignore-case", "ignore case distinctions" }, + { OP_NODATA, 'l', NULL, "files-with-matches", "print only FILE names containing matches" }, + { OP_NODATA, 'L', NULL, "files-without-match","print only FILE names not containing matches" }, + { OP_STRING, -1, &stdin_name, "label=name", "set name for standard input" }, + { OP_NODATA, 'M', NULL, "multiline", "run in multiline mode" }, + { OP_NODATA, 'n', NULL, "line-number", "print line number with output lines" }, + { OP_NODATA, 'q', NULL, "quiet", "suppress output, just set return code" }, + { OP_NODATA, 'r', NULL, "recursive", "recursively scan sub-directories" }, + { OP_STRING, -1, &exclude_pattern, "exclude=pattern","exclude matching files when recursing" }, + { OP_STRING, -1, &include_pattern, "include=pattern","include matching files when recursing" }, + { OP_NODATA, 's', NULL, "no-messages", "suppress error messages" }, + { OP_NODATA, 'u', NULL, "utf-8", "use UTF-8 mode" }, + { OP_NODATA, 'V', NULL, "version", "print version information and exit" }, + { OP_NODATA, 'v', NULL, "invert-match", "select non-matching lines" }, + { OP_NODATA, 'w', NULL, "word-regex(p)", "force PATTERN to match only as a word" }, + { OP_NODATA, 'x', NULL, "line-regex(p)", "force PATTERN to match only whole lines" }, + { OP_NODATA, 0, NULL, NULL, NULL } }; @@ -123,7 +197,8 @@ closedir(dir); /************* Directory scanning in Win32 ***********/ /* I (Philip Hazel) have no means of testing this code. It was contributed by -Lionel Fourquaux. */ +Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES +when it did not exist. */ #elif HAVE_WIN32API @@ -134,6 +209,10 @@ Lionel Fourquaux. */ #ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN #endif +#ifndef INVALID_FILE_ATTRIBUTES +#define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF +#endif + #include typedef struct directory_type @@ -253,59 +332,290 @@ return sys_errlist[n]; /************************************************* -* Grep an individual file * +* Print the previous "after" lines * *************************************************/ +/* This is called if we are about to lose said lines because of buffer filling, +and at the end of the file. + +Arguments: + lastmatchnumber the number of the last matching line, plus one + lastmatchrestart where we restarted after the last match + endptr end of available data + printname filename for printing + +Returns: nothing +*/ + +static void do_after_lines(int lastmatchnumber, char *lastmatchrestart, + char *endptr, char *printname) +{ +if (after_context > 0 && lastmatchnumber > 0) + { + int count = 0; + while (lastmatchrestart < endptr && count++ < after_context) + { + char *pp = lastmatchrestart; + if (printname != NULL) fprintf(stdout, "%s-", printname); + if (number) fprintf(stdout, "%d-", lastmatchnumber++); + while (*pp != '\n') pp++; + fprintf(stdout, "%.*s", pp - lastmatchrestart + 1, lastmatchrestart); + lastmatchrestart = pp + 1; + } + hyphenpending = TRUE; + } +} + + + +/************************************************* +* Grep an individual file * +*************************************************/ + +/* This is called from grep_or_recurse() below. It uses a buffer that is three +times the value of MBUFTHIRD. The matching point is never allowed to stray into +the top third of the buffer, thus keeping more of the file available for +context printing or for multiline scanning. For large files, the pointer will +be in the middle third most of the time, so the bottom third is available for +"before" context printing. + +Arguments: + in the fopened FILE stream + printname the file name if it is to be printed for each match + or NULL if the file name is not to be printed + it cannot be NULL if filenames[_nomatch]_only is set + +Returns: 0 if there was at least one match + 1 otherwise (no matches) +*/ + static int -pcregrep(FILE *in, char *name) +pcregrep(FILE *in, char *printname) { int rc = 1; -int linenumber = 0; +int linenumber = 1; +int lastmatchnumber = 0; int count = 0; int offsets[99]; -char buffer[BUFSIZ]; +char *lastmatchrestart = NULL; +char buffer[3*MBUFTHIRD]; +char *ptr = buffer; +char *endptr; +size_t bufflength; +BOOL endhyphenpending = FALSE; + +/* Do the first read into the start of the buffer and set up the pointer to +end of what we have. */ -while (fgets(buffer, sizeof(buffer), in) != NULL) +bufflength = fread(buffer, 1, 3*MBUFTHIRD, in); +endptr = buffer + bufflength; + +/* Loop while the current pointer is not at the end of the file. For large +files, endptr will be at the end of the buffer when we are in the middle of the +file, but ptr will never get there, because as soon as it gets over 2/3 of the +way, the buffer is shifted left and re-filled. */ + +while (ptr < endptr) { - BOOL match = FALSE; int i; - int length = (int)strlen(buffer); - if (length > 0 && buffer[length-1] == '\n') buffer[--length] = 0; - linenumber++; + BOOL match = FALSE; + char *t = ptr; + size_t length, linelength; + + /* At this point, ptr is at the start of a line. We need to find the length + of the subject string to pass to pcre_exec(). In multiline mode, it is the + length remainder of the data in the buffer. Otherwise, it is the length of + the next line. After matching, we always advance by the length of the next + line. In multiline mode the PCRE_FIRSTLINE option is used for compiling, so + that any match is constrained to be in the first line. */ + + linelength = 0; + while (t < endptr && *t++ != '\n') linelength++; + length = multiline? endptr - ptr : linelength; + + /* Run through all the patterns until one matches. Note that we don't include + the final newline in the subject string. */ for (i = 0; !match && i < pattern_count; i++) { - match = pcre_exec(pattern_list[i], hints_list[i], buffer, length, 0, 0, + match = pcre_exec(pattern_list[i], hints_list[i], ptr, length, 0, 0, offsets, 99) >= 0; - if (match && whole_lines && offsets[1] != length) match = FALSE; } + /* If it's a match or a not-match (as required), print what's wanted. */ + if (match != invert) { + BOOL hyphenprinted = FALSE; + + if (filenames_nomatch_only) return 1; + if (count_only) count++; else if (filenames_only) { - fprintf(stdout, "%s\n", (name == NULL)? "" : name); + fprintf(stdout, "%s\n", printname); return 0; } - else if (silent) return 0; + else if (quiet) return 0; else { - if (name != NULL) fprintf(stdout, "%s:", name); + /* See if there is a requirement to print some "after" lines from a + previous match. We never print any overlaps. */ + + if (after_context > 0 && lastmatchnumber > 0) + { + int linecount = 0; + char *p = lastmatchrestart; + + while (p < ptr && linecount < after_context) + { + while (*p != '\n') p++; + p++; + linecount++; + } + + /* It is important to advance lastmatchrestart during this printing so + that it interacts correctly with any "before" printing below. */ + + while (lastmatchrestart < p) + { + char *pp = lastmatchrestart; + if (printname != NULL) fprintf(stdout, "%s-", printname); + if (number) fprintf(stdout, "%d-", lastmatchnumber++); + while (*pp != '\n') pp++; + fprintf(stdout, "%.*s", pp - lastmatchrestart + 1, lastmatchrestart); + lastmatchrestart = pp + 1; + } + if (lastmatchrestart != ptr) hyphenpending = TRUE; + } + + /* If there were non-contiguous lines printed above, insert hyphens. */ + + if (hyphenpending) + { + fprintf(stdout, "--\n"); + hyphenpending = FALSE; + hyphenprinted = TRUE; + } + + /* See if there is a requirement to print some "before" lines for this + match. Again, don't print overlaps. */ + + if (before_context > 0) + { + int linecount = 0; + char *p = ptr; + + while (p > buffer && (lastmatchnumber == 0 || p > lastmatchrestart) && + linecount++ < before_context) + { + p--; + while (p > buffer && p[-1] != '\n') p--; + } + + if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted) + fprintf(stdout, "--\n"); + + while (p < ptr) + { + char *pp = p; + if (printname != NULL) fprintf(stdout, "%s-", printname); + if (number) fprintf(stdout, "%d-", linenumber - linecount--); + while (*pp != '\n') pp++; + fprintf(stdout, "%.*s", pp - p + 1, p); + p = pp + 1; + } + } + + /* Now print the matching line(s); ensure we set hyphenpending at the end + of the file. */ + + endhyphenpending = TRUE; + if (printname != NULL) fprintf(stdout, "%s:", printname); if (number) fprintf(stdout, "%d:", linenumber); - fprintf(stdout, "%s\n", buffer); + + /* In multiline mode, we want to print to the end of the line in which + the end of the matched string is found, so we adjust linelength and the + line number appropriately. Because the PCRE_FIRSTLINE option is set, the + start of the match will always be before the first \n character. */ + + if (multiline) + { + char *endmatch = ptr + offsets[1]; + t = ptr; + while (t < endmatch) { if (*t++ == '\n') linenumber++; } + while (endmatch < endptr && *endmatch != '\n') endmatch++; + linelength = endmatch - ptr; + } + + fprintf(stdout, "%.*s\n", linelength, ptr); } - rc = 0; + rc = 0; /* Had some success */ + + /* Remember where the last match happened for after_context. We remember + where we are about to restart, and that line's number. */ + + lastmatchrestart = ptr + linelength + 1; + lastmatchnumber = linenumber + 1; } + + /* Advance to after the newline and increment the line number. */ + + ptr += linelength + 1; + linenumber++; + + /* If we haven't yet reached the end of the file (the buffer is full), and + the current point is in the top 1/3 of the buffer, slide the buffer down by + 1/3 and refill it. Before we do this, if some unprinted "after" lines are + about to be lost, print them. */ + + if (bufflength >= sizeof(buffer) && ptr > buffer + 2*MBUFTHIRD) + { + if (after_context > 0 && + lastmatchnumber > 0 && + lastmatchrestart < buffer + MBUFTHIRD) + { + do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname); + lastmatchnumber = 0; + } + + /* Now do the shuffle */ + + memmove(buffer, buffer + MBUFTHIRD, 2*MBUFTHIRD); + ptr -= MBUFTHIRD; + bufflength = 2*MBUFTHIRD + fread(buffer + 2*MBUFTHIRD, 1, MBUFTHIRD, in); + endptr = buffer + bufflength; + + /* Adjust any last match point */ + + if (lastmatchnumber > 0) lastmatchrestart -= MBUFTHIRD; + } + } /* Loop through the whole file */ + +/* End of file; print final "after" lines if wanted; do_after_lines sets +hyphenpending if it prints something. */ + +do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname); +hyphenpending |= endhyphenpending; + +/* Print the file name if we are looking for those without matches and there +were none. If we found a match, we won't have got this far. */ + +if (filenames_nomatch_only) + { + fprintf(stdout, "%s\n", printname); + return 0; } +/* Print the match count if wanted */ + if (count_only) { - if (name != NULL) fprintf(stdout, "%s:", name); + if (printname != NULL) fprintf(stdout, "%s:", printname); fprintf(stdout, "%d\n", count); } @@ -314,41 +624,81 @@ return rc; - /************************************************* * Grep a file or recurse into a directory * *************************************************/ +/* Given a path name, if it's a directory, scan all the files if we are +recursing; if it's a file, grep it. + +Arguments: + pathname the path to investigate + dir_recurse TRUE if recursing is wanted (-r) + show_filenames TRUE if file names are wanted for multiple files, except + for the only file at top level when not filenames_only + only_one_at_top TRUE if the path is the only one at toplevel + +Returns: 0 if there was at least one match + 1 if there were no matches + 2 there was some kind of error + +However, file opening failures are suppressed if "silent" is set. +*/ + static int -grep_or_recurse(char *filename, BOOL dir_recurse, BOOL show_filenames, +grep_or_recurse(char *pathname, BOOL dir_recurse, BOOL show_filenames, BOOL only_one_at_top) { int rc = 1; int sep; FILE *in; +char *printname; -/* If the file is a directory and we are recursing, scan each file within it. -The scanning code is localized so it can be made system-specific. */ +/* If the file name is "-" we scan stdin */ -if ((sep = isdirectory(filename)) != 0 && dir_recurse) +if (strcmp(pathname, "-") == 0) + { + return pcregrep(stdin, + (filenames_only || filenames_nomatch_only || + (show_filenames && !only_one_at_top))? + stdin_name : NULL); + } + +/* If the file is a directory and we are recursing, scan each file within it, +subject to any include or exclude patterns that were set. The scanning code is +localized so it can be made system-specific. */ + +if ((sep = isdirectory(pathname)) != 0 && dir_recurse) { char buffer[1024]; char *nextfile; - directory_type *dir = opendirectory(filename); + directory_type *dir = opendirectory(pathname); if (dir == NULL) { - fprintf(stderr, "pcregrep: Failed to open directory %s: %s\n", filename, - strerror(errno)); + if (!silent) + fprintf(stderr, "pcregrep: Failed to open directory %s: %s\n", pathname, + strerror(errno)); return 2; } while ((nextfile = readdirectory(dir)) != NULL) { - int frc; - sprintf(buffer, "%.512s%c%.128s", filename, sep, nextfile); + int frc, blen; + sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile); + blen = strlen(buffer); + + if (exclude_compiled != NULL && + pcre_exec(exclude_compiled, NULL, buffer, blen, 0, 0, NULL, 0) >= 0) + continue; + + if (include_compiled != NULL && + pcre_exec(include_compiled, NULL, buffer, blen, 0, 0, NULL, 0) < 0) + continue; + frc = grep_or_recurse(buffer, dir_recurse, TRUE, FALSE); - if (frc == 0 && rc == 1) rc = 0; + if (frc > 1) rc = frc; + else if (frc == 0 && rc == 1) rc = 0; } closedirectory(dir); @@ -360,15 +710,20 @@ the first and only argument at top level, we don't show the file name (unless we are only showing the file name). Otherwise, control is via the show_filenames variable. */ -in = fopen(filename, "r"); +in = fopen(pathname, "r"); if (in == NULL) { - fprintf(stderr, "pcregrep: Failed to open %s: %s\n", filename, strerror(errno)); + if (!silent) + fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname, + strerror(errno)); return 2; } -rc = pcregrep(in, (filenames_only || (show_filenames && !only_one_at_top))? - filename : NULL); +printname = (filenames_only || filenames_nomatch_only || + (show_filenames && !only_one_at_top))? pathname : NULL; + +rc = pcregrep(in, printname); + fclose(in); return rc; } @@ -383,7 +738,7 @@ return rc; static int usage(int rc) { -fprintf(stderr, "Usage: pcregrep [-Vcfhilnrsvx] [long-options] [pattern] [file1 file2 ...]\n"); +fprintf(stderr, "Usage: pcregrep [-LMVcfhilnqrsvwx] [long-options] [pattern] [file1 file2 ...]\n"); fprintf(stderr, "Type `pcregrep --help' for more information.\n"); return rc; } @@ -403,6 +758,7 @@ option_item *op; printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n"); printf("Search for PATTERN in each FILE or standard input.\n"); printf("PATTERN must be present if -f is not used.\n"); +printf("\"-\" can be used as a file name to mean STDIN.\n"); printf("Example: pcregrep -i 'hello.*world' menu.h main.c\n\n"); printf("Options:\n"); @@ -418,12 +774,11 @@ for (op = optionlist; op->one_char != 0; op++) printf("%.*s%s\n", n, " ", op->help_text); } -printf("\n -f or --file=\n"); -printf(" Read patterns from instead of using a command line option.\n"); -printf(" Trailing white space is removed; blanks lines are ignored.\n"); -printf(" There is a maximum of %d patterns.\n", MAX_PATTERN_COUNT); +printf("\nWhen reading patterns from a file instead of using a command line option,\n"); +printf("trailing white space is removed and blank lines are ignored.\n"); +printf("There is a maximum of %d patterns.\n", MAX_PATTERN_COUNT); -printf("\nWith no FILE, read standard input. If fewer than two FILEs given, assume -h.\n"); +printf("\nWith no FILEs, read standard input. If fewer than two FILEs given, assume -h.\n"); printf("Exit status is 0 if any matches, 1 if no matches, and 2 if trouble.\n"); } @@ -431,7 +786,7 @@ printf("Exit status is 0 if any matches, 1 if no matches, and 2 if trouble.\n"); /************************************************* -* Handle an option * +* Handle a single-letter, no data option * *************************************************/ static int @@ -443,13 +798,17 @@ switch(letter) case 'c': count_only = TRUE; break; case 'h': filenames = FALSE; break; case 'i': options |= PCRE_CASELESS; break; - case 'l': filenames_only = TRUE; + case 'l': filenames_only = TRUE; break; + case 'L': filenames_nomatch_only = TRUE; break; + case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break; case 'n': number = TRUE; break; + case 'q': quiet = TRUE; break; case 'r': recurse = TRUE; break; case 's': silent = TRUE; break; case 'u': options |= PCRE_UTF8; break; case 'v': invert = TRUE; break; - case 'x': whole_lines = TRUE; options |= PCRE_ANCHORED; break; + case 'w': word_match = TRUE; break; + case 'x': whole_lines = TRUE; break; case 'V': fprintf(stderr, "pcregrep version %s using ", VERSION); @@ -472,6 +831,8 @@ return options; * Main program * *************************************************/ +/* Returns 0 if something matched, 1 if nothing matched, 2 after an error. */ + int main(int argc, char **argv) { @@ -486,32 +847,83 @@ BOOL only_one_at_top; for (i = 1; i < argc; i++) { + option_item *op = NULL; + char *option_data = (char *)""; /* default to keep compiler happy */ + BOOL longop; + BOOL longopwasequals = FALSE; + if (argv[i][0] != '-') break; - /* Missing options */ + /* If we hit an argument that is just "-", it may be a reference to STDIN, + but only if we have previously had -f to define the patterns. */ - if (argv[i][1] == 0) exit(usage(2)); + if (argv[i][1] == 0) + { + if (pattern_filename != NULL) break; + else exit(usage(2)); + } - /* Long name options */ + /* Handle a long name option, or -- to terminate the options */ if (argv[i][1] == '-') { - option_item *op; + char *arg = argv[i] + 2; + char *argequals = strchr(arg, '='); - if (strncmp(argv[i]+2, "file=", 5) == 0) + if (*arg == 0) /* -- terminates options */ { - pattern_filename = argv[i] + 7; - continue; + i++; + break; /* out of the options-handling loop */ } + longop = TRUE; + + /* Some long options have data that follows after =, for example file=name. + Some options have variations in the long name spelling: specifically, we + allow "regexp" because GNU grep allows it, though I personally go along + with Jeff Friedl in preferring "regex" without the "p". These options are + entered in the table as "regex(p)". No option is in both these categories, + fortunately. */ + for (op = optionlist; op->one_char != 0; op++) { - if (strcmp(argv[i]+2, op->long_name) == 0) + char *opbra = strchr(op->long_name, '('); + char *equals = strchr(op->long_name, '='); + if (opbra == NULL) /* Not a (p) case */ { - options = handle_option(op->one_char, options); - break; + if (equals == NULL) /* Not thing=data case */ + { + if (strcmp(arg, op->long_name) == 0) break; + } + else /* Special case xxx=data */ + { + int oplen = equals - op->long_name; + int arglen = (argequals == NULL)? strlen(arg) : argequals - arg; + if (oplen == arglen && strncmp(arg, op->long_name, oplen) == 0) + { + option_data = arg + arglen; + if (*option_data == '=') + { + option_data++; + longopwasequals = TRUE; + } + break; + } + } + } + else /* Special case xxxx(p) */ + { + char buff1[24]; + char buff2[24]; + int baselen = opbra - op->long_name; + sprintf(buff1, "%.*s", baselen, op->long_name); + sprintf(buff2, "%s%.*s", buff1, strlen(op->long_name) - baselen - 2, + opbra + 1); + if (strcmp(arg, buff1) == 0 || strcmp(arg, buff2) == 0) + break; } } + if (op->one_char == 0) { fprintf(stderr, "pcregrep: Unknown option %s\n", argv[i]); @@ -519,30 +931,74 @@ for (i = 1; i < argc; i++) } } - /* One-char options */ + /* One-char options; many that have no data may be in a single argument; we + continue till we hit the last one or one that needs data. */ else { char *s = argv[i] + 1; + longop = FALSE; while (*s != 0) { - if (*s == 'f') + for (op = optionlist; op->one_char != 0; op++) + { if (*s == op->one_char) break; } + if (op->one_char == 0) { - pattern_filename = s + 1; - if (pattern_filename[0] == 0) - { - if (i >= argc - 1) - { - fprintf(stderr, "pcregrep: File name missing after -f\n"); - exit(usage(2)); - } - pattern_filename = argv[++i]; - } + fprintf(stderr, "pcregrep: Unknown option letter '%c' in \"%s\"\n", + *s, argv[i]); + exit(usage(2)); + } + if (op->type != OP_NODATA || s[1] == 0) + { + option_data = s+1; break; } - else options = handle_option(*s++, options); + options = handle_option(*s++, options); } } + + /* At this point we should have op pointing to a matched option */ + + if (op->type == OP_NODATA) + options = handle_option(op->one_char, options); + else + { + if (*option_data == 0) + { + if (i >= argc - 1 || longopwasequals) + { + fprintf(stderr, "pcregrep: Data missing after %s\n", argv[i]); + exit(usage(2)); + } + option_data = argv[++i]; + } + + if (op->type == OP_STRING) *((char **)op->dataptr) = option_data; else + { + char *endptr; + int n = strtoul(option_data, &endptr, 10); + if (*endptr != 0) + { + if (longop) + fprintf(stderr, "pcregrep: Malformed number \"%s\" after --%s\n", + option_data, op->long_name); + else + fprintf(stderr, "pcregrep: Malformed number \"%s\" after -%c\n", + option_data, op->one_char); + exit(usage(2)); + } + *((int *)op->dataptr) = n; + } + } + } + +/* Options have been decoded. If -C was used, its value is used as a default +for -A and -B. */ + +if (both_context > 0) + { + if (after_context == 0) after_context = both_context; + if (before_context == 0) before_context = both_context; } pattern_list = (pcre **)malloc(MAX_PATTERN_COUNT * sizeof(pcre *)); @@ -559,53 +1015,91 @@ if (pattern_list == NULL || hints_list == NULL) if (pattern_filename != NULL) { FILE *f = fopen(pattern_filename, "r"); - char buffer[BUFSIZ]; + char buffer[MBUFTHIRD + 16]; + char *rdstart; + int adjust = 0; + if (f == NULL) { fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pattern_filename, strerror(errno)); return 2; } - while (fgets(buffer, sizeof(buffer), f) != NULL) + + if (whole_lines) + { + strcpy(buffer, "^(?:"); + adjust = 4; + } + else if (word_match) + { + strcpy(buffer, "\\b"); + adjust = 2; + } + + rdstart = buffer + adjust; + while (fgets(rdstart, MBUFTHIRD, f) != NULL) { - char *s = buffer + (int)strlen(buffer); + char *s = rdstart + (int)strlen(rdstart); if (pattern_count >= MAX_PATTERN_COUNT) { fprintf(stderr, "pcregrep: Too many patterns in file (max %d)\n", MAX_PATTERN_COUNT); return 2; } - while (s > buffer && isspace((unsigned char)(s[-1]))) s--; - if (s == buffer) continue; - *s = 0; + while (s > rdstart && isspace((unsigned char)(s[-1]))) s--; + if (s == rdstart) continue; + if (whole_lines) strcpy(s, ")$"); + else if (word_match)strcpy(s, "\\b"); + else *s = 0; pattern_list[pattern_count] = pcre_compile(buffer, options, &error, &errptr, NULL); if (pattern_list[pattern_count++] == NULL) { fprintf(stderr, "pcregrep: Error in regex number %d at offset %d: %s\n", - pattern_count, errptr, error); + pattern_count, errptr - adjust, error); return 2; } } fclose(f); } -/* If no file name, a single regex must be given inline */ +/* If no file name, a single regex must be given inline. */ else { + char buffer[MBUFTHIRD + 16]; + char *pat; + int adjust = 0; + if (i >= argc) return usage(2); - pattern_list[0] = pcre_compile(argv[i++], options, &error, &errptr, NULL); + + if (whole_lines) + { + sprintf(buffer, "^(?:%.*s)$", MBUFTHIRD, argv[i++]); + pat = buffer; + adjust = 4; + } + else if (word_match) + { + sprintf(buffer, "\\b%.*s\\b", MBUFTHIRD, argv[i++]); + pat = buffer; + adjust = 2; + } + else pat = argv[i++]; + + pattern_list[0] = pcre_compile(pat, options, &error, &errptr, NULL); + if (pattern_list[0] == NULL) { - fprintf(stderr, "pcregrep: Error in regex at offset %d: %s\n", errptr, - error); + fprintf(stderr, "pcregrep: Error in regex at offset %d: %s\n", + errptr - adjust, error); return 2; } pattern_count++; } -/* Study the regular expressions, as we will be running them may times */ +/* Study the regular expressions, as we will be running them many times */ for (j = 0; j < pattern_count; j++) { @@ -619,24 +1113,50 @@ for (j = 0; j < pattern_count; j++) } } +/* If there are include or exclude patterns, compile them. */ + +if (exclude_pattern != NULL) + { + exclude_compiled = pcre_compile(exclude_pattern, 0, &error, &errptr, NULL); + if (exclude_compiled == NULL) + { + fprintf(stderr, "pcregrep: Error in 'exclude' regex at offset %d: %s\n", + errptr, error); + return 2; + } + } + +if (include_pattern != NULL) + { + include_compiled = pcre_compile(include_pattern, 0, &error, &errptr, NULL); + if (include_compiled == NULL) + { + fprintf(stderr, "pcregrep: Error in 'include' regex at offset %d: %s\n", + errptr, error); + return 2; + } + } + /* If there are no further arguments, do the business on stdin and exit */ -if (i >= argc) return pcregrep(stdin, NULL); +if (i >= argc) return pcregrep(stdin, + (filenames_only || filenames_nomatch_only)? stdin_name : NULL); /* Otherwise, work through the remaining arguments as files or directories. Pass in the fact that there is only one argument at top level - this suppresses -the file name if the argument is not a directory. */ +the file name if the argument is not a directory and filenames_only is not set. +*/ only_one_at_top = (i == argc - 1); -if (filenames_only) filenames = TRUE; for (; i < argc; i++) { int frc = grep_or_recurse(argv[i], recurse, filenames, only_one_at_top); - if (frc == 0 && rc == 1) rc = 0; + if (frc > 1) rc = frc; + else if (frc == 0 && rc == 1) rc = 0; } return rc; } -/* End */ +/* End of pcregrep */ diff --git a/ext/pcre/pcrelib/pcreposix.c b/ext/pcre/pcrelib/pcreposix.c index b2551bb3ee65..06fd58bcbf55 100644 --- a/ext/pcre/pcrelib/pcreposix.c +++ b/ext/pcre/pcrelib/pcreposix.c @@ -2,99 +2,103 @@ * Perl-Compatible Regular Expressions * *************************************************/ -/* -This is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. See -the file Tech.Notes for some information on the internals. - -This module is a wrapper that provides a POSIX API to the underlying PCRE -functions. - -Written by: Philip Hazel +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. - Copyright (c) 1997-2004 University of Cambridge + Written by Philip Hazel + Copyright (c) 1997-2005 University of Cambridge ----------------------------------------------------------------------------- -Permission is granted to anyone to use this software for any purpose on any -computer system, and to redistribute it freely, subject to the following -restrictions: - -1. This software is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ -2. The origin of this software must not be misrepresented, either by - explicit claim or by omission. -3. Altered versions must be plainly marked as such, and must not be - misrepresented as being the original software. +/* This module is a wrapper that provides a POSIX API to the underlying PCRE +functions. */ -4. If PCRE is embedded in any software that is released under the GNU - General Purpose Licence (GPL), then the terms of that licence shall - supersede any condition above with which it is incompatible. ------------------------------------------------------------------------------ -*/ -#include "internal.h" +#include "pcre_internal.h" #include "pcreposix.h" #include "stdlib.h" -/* Corresponding tables of PCRE error messages and POSIX error codes. */ - -static const char *const estring[] = { - ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9, ERR10, - ERR11, ERR12, ERR13, ERR14, ERR15, ERR16, ERR17, ERR18, ERR19, ERR20, - ERR21, ERR22, ERR23, ERR24, ERR25, ERR26, ERR27, ERR29, ERR29, ERR30, - ERR31, ERR32, ERR33, ERR34, ERR35, ERR36, ERR37, ERR38, ERR39, ERR40, - ERR41, ERR42, ERR43, ERR44 }; +/* Table to translate PCRE compile time error codes into POSIX error codes. */ static const int eint[] = { - REG_EESCAPE, /* "\\ at end of pattern" */ - REG_EESCAPE, /* "\\c at end of pattern" */ - REG_EESCAPE, /* "unrecognized character follows \\" */ - REG_BADBR, /* "numbers out of order in {} quantifier" */ - REG_BADBR, /* "number too big in {} quantifier" */ - REG_EBRACK, /* "missing terminating ] for character class" */ - REG_ECTYPE, /* "invalid escape sequence in character class" */ - REG_ERANGE, /* "range out of order in character class" */ - REG_BADRPT, /* "nothing to repeat" */ - REG_BADRPT, /* "operand of unlimited repeat could match the empty string" */ - REG_ASSERT, /* "internal error: unexpected repeat" */ - REG_BADPAT, /* "unrecognized character after (?" */ - REG_BADPAT, /* "POSIX named classes are supported only within a class" */ - REG_EPAREN, /* "missing )" */ - REG_ESUBREG, /* "reference to non-existent subpattern" */ - REG_INVARG, /* "erroffset passed as NULL" */ - REG_INVARG, /* "unknown option bit(s) set" */ - REG_EPAREN, /* "missing ) after comment" */ - REG_ESIZE, /* "parentheses nested too deeply" */ - REG_ESIZE, /* "regular expression too large" */ - REG_ESPACE, /* "failed to get memory" */ - REG_EPAREN, /* "unmatched brackets" */ - REG_ASSERT, /* "internal error: code overflow" */ - REG_BADPAT, /* "unrecognized character after (?<" */ - REG_BADPAT, /* "lookbehind assertion is not fixed length" */ - REG_BADPAT, /* "malformed number after (?(" */ - REG_BADPAT, /* "conditional group containe more than two branches" */ - REG_BADPAT, /* "assertion expected after (?(" */ - REG_BADPAT, /* "(?R or (?digits must be followed by )" */ - REG_ECTYPE, /* "unknown POSIX class name" */ - REG_BADPAT, /* "POSIX collating elements are not supported" */ - REG_INVARG, /* "this version of PCRE is not compiled with PCRE_UTF8 support" */ - REG_BADPAT, /* "spare error" */ - REG_BADPAT, /* "character value in \x{...} sequence is too large" */ - REG_BADPAT, /* "invalid condition (?(0)" */ - REG_BADPAT, /* "\\C not allowed in lookbehind assertion" */ - REG_EESCAPE, /* "PCRE does not support \\L, \\l, \\N, \\P, \\p, \\U, \\u, or \\X" */ - REG_BADPAT, /* "number after (?C is > 255" */ - REG_BADPAT, /* "closing ) for (?C expected" */ - REG_BADPAT, /* "recursive call could loop indefinitely" */ - REG_BADPAT, /* "unrecognized character after (?P" */ - REG_BADPAT, /* "syntax error after (?P" */ - REG_BADPAT, /* "two named groups have the same name" */ - REG_BADPAT /* "invalid UTF-8 string" */ + 0, /* no error */ + REG_EESCAPE, /* \ at end of pattern */ + REG_EESCAPE, /* \c at end of pattern */ + REG_EESCAPE, /* unrecognized character follows \ */ + REG_BADBR, /* numbers out of order in {} quantifier */ + REG_BADBR, /* number too big in {} quantifier */ + REG_EBRACK, /* missing terminating ] for character class */ + REG_ECTYPE, /* invalid escape sequence in character class */ + REG_ERANGE, /* range out of order in character class */ + REG_BADRPT, /* nothing to repeat */ + REG_BADRPT, /* operand of unlimited repeat could match the empty string */ + REG_ASSERT, /* internal error: unexpected repeat */ + REG_BADPAT, /* unrecognized character after (? */ + REG_BADPAT, /* POSIX named classes are supported only within a class */ + REG_EPAREN, /* missing ) */ + REG_ESUBREG, /* reference to non-existent subpattern */ + REG_INVARG, /* erroffset passed as NULL */ + REG_INVARG, /* unknown option bit(s) set */ + REG_EPAREN, /* missing ) after comment */ + REG_ESIZE, /* parentheses nested too deeply */ + REG_ESIZE, /* regular expression too large */ + REG_ESPACE, /* failed to get memory */ + REG_EPAREN, /* unmatched brackets */ + REG_ASSERT, /* internal error: code overflow */ + REG_BADPAT, /* unrecognized character after (?< */ + REG_BADPAT, /* lookbehind assertion is not fixed length */ + REG_BADPAT, /* malformed number after (?( */ + REG_BADPAT, /* conditional group containe more than two branches */ + REG_BADPAT, /* assertion expected after (?( */ + REG_BADPAT, /* (?R or (?digits must be followed by ) */ + REG_ECTYPE, /* unknown POSIX class name */ + REG_BADPAT, /* POSIX collating elements are not supported */ + REG_INVARG, /* this version of PCRE is not compiled with PCRE_UTF8 support */ + REG_BADPAT, /* spare error */ + REG_BADPAT, /* character value in \x{...} sequence is too large */ + REG_BADPAT, /* invalid condition (?(0) */ + REG_BADPAT, /* \C not allowed in lookbehind assertion */ + REG_EESCAPE, /* PCRE does not support \L, \l, \N, \U, or \u */ + REG_BADPAT, /* number after (?C is > 255 */ + REG_BADPAT, /* closing ) for (?C expected */ + REG_BADPAT, /* recursive call could loop indefinitely */ + REG_BADPAT, /* unrecognized character after (?P */ + REG_BADPAT, /* syntax error after (?P */ + REG_BADPAT, /* two named groups have the same name */ + REG_BADPAT, /* invalid UTF-8 string */ + REG_BADPAT, /* support for \P, \p, and \X has not been compiled */ + REG_BADPAT, /* malformed \P or \p sequence */ + REG_BADPAT /* unknown property name after \P or \p */ }; /* Table of texts corresponding to POSIX error codes */ @@ -123,24 +127,6 @@ static const char *const pstring[] = { -/************************************************* -* Translate PCRE text code to int * -*************************************************/ - -/* PCRE compile-time errors are given as strings defined as macros. We can just -look them up in a table to turn them into POSIX-style error codes. */ - -static int -pcre_posix_error_code(const char *s) -{ -size_t i; -for (i = 0; i < sizeof(estring)/sizeof(char *); i++) - if (strcmp(s, estring[i]) == 0) return eint[i]; -return REG_ASSERT; -} - - - /************************************************* * Translate error code to string * *************************************************/ @@ -208,15 +194,18 @@ regcomp(regex_t *preg, const char *pattern, int cflags) { const char *errorptr; int erroffset; +int errorcode; int options = 0; if ((cflags & REG_ICASE) != 0) options |= PCRE_CASELESS; if ((cflags & REG_NEWLINE) != 0) options |= PCRE_MULTILINE; +if ((cflags & REG_DOTALL) != 0) options |= PCRE_DOTALL; -preg->re_pcre = pcre_compile(pattern, options, &errorptr, &erroffset, NULL); +preg->re_pcre = pcre_compile2(pattern, options, &errorcode, &errorptr, + &erroffset, NULL); preg->re_erroffset = erroffset; -if (preg->re_pcre == NULL) return pcre_posix_error_code(errorptr); +if (preg->re_pcre == NULL) return eint[errorcode]; preg->re_nsub = pcre_info((const pcre *)preg->re_pcre, NULL, NULL); return 0; diff --git a/ext/pcre/pcrelib/pcreposix.h b/ext/pcre/pcrelib/pcreposix.h index 2b97bf44f504..4f1b1abd4515 100644 --- a/ext/pcre/pcrelib/pcreposix.h +++ b/ext/pcre/pcrelib/pcreposix.h @@ -2,14 +2,43 @@ * Perl-Compatible Regular Expressions * *************************************************/ -/* Copyright (c) 1997-2003 University of Cambridge */ - #ifndef _PCREPOSIX_H #define _PCREPOSIX_H /* This is the header for the POSIX wrapper interface to the PCRE Perl- Compatible Regular Expression library. It defines the things POSIX says should -be there. I hope. */ +be there. I hope. + + Copyright (c) 1997-2005 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ /* Have to include stdlib.h in order to ensure that size_t is defined. */ @@ -28,6 +57,10 @@ extern "C" { #define REG_NOTBOL 0x04 #define REG_NOTEOL 0x08 +/* Additional options, not defined by POSIX, but somebody wanted them. */ + +#define REG_DOTALL 0x10 + /* These are not used by PCRE, but by defining them we make it easier to slot PCRE into existing programs that make POSIX calls. */ diff --git a/ext/pcre/pcrelib/pcretest.c b/ext/pcre/pcrelib/pcretest.c index bcc661b68496..9b6347086388 100644 --- a/ext/pcre/pcrelib/pcretest.c +++ b/ext/pcre/pcrelib/pcretest.c @@ -4,7 +4,37 @@ /* This program was hacked up as a tester for PCRE. I really should have written it more tidily in the first place. Will I ever learn? It has grown and -been extended and consequently is now rather untidy in places. */ +been extended and consequently is now rather, er, *very* untidy in places. + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + #include #include @@ -12,12 +42,17 @@ been extended and consequently is now rather untidy in places. */ #include #include #include - -/* We need the internal info for displaying the results of pcre_study(). Also -for getting the opcodes for showing compiled code. */ +#include #define PCRE_SPY /* For Win32 build, import data, not export */ -#include "internal.h" + +/* We need the internal info for displaying the results of pcre_study() and +other internal data; pcretest also uses some of the fixed tables, and generally +has "inside information" compared to a program that strictly follows the PCRE +API. */ + +#include "pcre_internal.h" + /* It is possible to compile this test program without including support for testing the POSIX interface, though this is not available via the standard @@ -27,6 +62,12 @@ Makefile. */ #include "pcreposix.h" #endif +/* It is also possible, for the benefit of the version imported into Exim, to +build pcretest without support for UTF8 (define NOUTF8), without the interface +to the DFA matcher (NODFA), and without the doublecheck of the old "info" +function (define NOINFOCHECK). */ + + #ifndef CLOCKS_PER_SEC #ifdef CLK_TCK #define CLOCKS_PER_SEC CLK_TCK @@ -35,9 +76,10 @@ Makefile. */ #endif #endif -#define LOOPREPEAT 50000 +#define LOOPREPEAT 500000 #define BUFFER_SIZE 30000 +#define PBUFFER_SIZE BUFFER_SIZE #define DBUFFER_SIZE BUFFER_SIZE @@ -52,30 +94,7 @@ static int show_malloc; static int use_utf8; static size_t gotten_store; - -static const int utf8_table1[] = { - 0x0000007f, 0x000007ff, 0x0000ffff, 0x001fffff, 0x03ffffff, 0x7fffffff}; - -static const int utf8_table2[] = { - 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}; - -static const int utf8_table3[] = { - 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01}; - - - -/************************************************* -* Print compiled regex * -*************************************************/ - -/* The code for doing this is held in a separate file that is also included in -pcre.c when it is compiled with the debug switch. It defines a function called -print_internals(), which uses a table of opcode lengths defined by the macro -OP_LENGTHS, whose name must be OP_lengths. */ - -static uschar OP_lengths[] = { OP_LENGTHS }; - -#include "printint.c" +static uschar *pbuffer = NULL; @@ -106,42 +125,6 @@ return(result); -/************************************************* -* Convert character value to UTF-8 * -*************************************************/ - -/* This function takes an integer value in the range 0 - 0x7fffffff -and encodes it as a UTF-8 character in 0 to 6 bytes. - -Arguments: - cvalue the character value - buffer pointer to buffer for result - at least 6 bytes long - -Returns: number of characters placed in the buffer - -1 if input character is negative - 0 if input character is positive but too big (only when - int is longer than 32 bits) -*/ - -static int -ord2utf8(int cvalue, unsigned char *buffer) -{ -register int i, j; -for (i = 0; i < sizeof(utf8_table1)/sizeof(int); i++) - if (cvalue <= utf8_table1[i]) break; -if (i >= sizeof(utf8_table1)/sizeof(int)) return 0; -if (cvalue < 0) return -1; - -buffer += i; -for (j = i; j > 0; j--) - { - *buffer-- = 0x80 | (cvalue & 0x3f); - cvalue >>= 6; - } -*buffer = utf8_table2[i] | cvalue; -return i + 1; -} - /************************************************* * Convert UTF-8 string to value * @@ -158,6 +141,8 @@ Returns: > 0 => the number of bytes consumed -6 to 0 => malformed UTF-8 character at offset = (-return) */ +#if !defined NOUTF8 + static int utf82ord(unsigned char *buffer, int *vptr) { @@ -177,7 +162,7 @@ if (i == 0 || i == 6) return 0; /* invalid UTF-8 */ /* i now has a value in the range 1-5 */ s = 6*i; -d = (c & utf8_table3[i]) << s; +d = (c & _pcre_utf8_table3[i]) << s; for (j = 0; j < i; j++) { @@ -189,8 +174,8 @@ for (j = 0; j < i; j++) /* Check that encoding was the correct unique one */ -for (j = 0; j < sizeof(utf8_table1)/sizeof(int); j++) - if (d <= utf8_table1[j]) break; +for (j = 0; j < _pcre_utf8_table1_size; j++) + if (d <= _pcre_utf8_table1[j]) break; if (j != i) return -(i+1); /* Valid value */ @@ -199,6 +184,8 @@ if (j != i) return -(i+1); return i+1; } +#endif + /************************************************* @@ -216,6 +203,7 @@ int yield = 0; while (length-- > 0) { +#if !defined NOUTF8 if (use_utf8) { int rc = utf82ord(p, &c); @@ -238,6 +226,7 @@ while (length-- > 0) continue; } } +#endif /* Not UTF-8, or malformed UTF-8 */ @@ -269,7 +258,7 @@ data is not zero. */ static int callout(pcre_callout_block *cb) { FILE *f = (first_callout | callout_extra)? outfile : NULL; -int i, pre_start, post_start; +int i, pre_start, post_start, subject_length; if (callout_extra) { @@ -300,16 +289,26 @@ pre_start = pchars((unsigned char *)cb->subject, cb->start_match, f); post_start = pchars((unsigned char *)(cb->subject + cb->start_match), cb->current_position - cb->start_match, f); +subject_length = pchars((unsigned char *)cb->subject, cb->subject_length, NULL); + (void)pchars((unsigned char *)(cb->subject + cb->current_position), cb->subject_length - cb->current_position, f); if (f != NULL) fprintf(f, "\n"); /* Always print appropriate indicators, with callout number if not already -shown */ +shown. For automatic callouts, show the pattern offset. */ -if (callout_extra) fprintf(outfile, " "); - else fprintf(outfile, "%3d ", cb->callout_number); +if (cb->callout_number == 255) + { + fprintf(outfile, "%+3d ", cb->pattern_position); + if (cb->pattern_position > 99) fprintf(outfile, "\n "); + } +else + { + if (callout_extra) fprintf(outfile, " "); + else fprintf(outfile, "%3d ", cb->callout_number); + } for (i = 0; i < pre_start; i++) fprintf(outfile, " "); fprintf(outfile, "^"); @@ -320,6 +319,12 @@ if (post_start > 0) fprintf(outfile, "^"); } +for (i = 0; i < subject_length - pre_start - post_start + 4; i++) + fprintf(outfile, " "); + +fprintf(outfile, "%.*s", (cb->next_item_length == 0)? 1 : cb->next_item_length, + pbuffer + cb->pattern_position); + fprintf(outfile, "\n"); first_callout = 0; @@ -350,7 +355,7 @@ static void *new_malloc(size_t size) void *block = malloc(size); gotten_store = size; if (show_malloc) - fprintf(outfile, "malloc %3d %p\n", size, block); + fprintf(outfile, "malloc %3d %p\n", (int)size, block); return block; } @@ -368,7 +373,7 @@ static void *stack_malloc(size_t size) { void *block = malloc(size); if (show_malloc) - fprintf(outfile, "stack_malloc %3d %p\n", size, block); + fprintf(outfile, "stack_malloc %3d %p\n", (int)size, block); return block; } @@ -395,6 +400,23 @@ if ((rc = pcre_fullinfo(re, study, option, ptr)) < 0) +/************************************************* +* Byte flipping function * +*************************************************/ + +static long int +byteflip(long int value, int n) +{ +if (n == 2) return ((value & 0x00ff) << 8) | ((value & 0xff00) >> 8); +return ((value & 0x000000ff) << 24) | + ((value & 0x0000ff00) << 8) | + ((value & 0x00ff0000) >> 8) | + ((value & 0xff000000) >> 24); +} + + + + /************************************************* * Main Program * *************************************************/ @@ -414,12 +436,14 @@ int showinfo = 0; int showstore = 0; int size_offsets = 45; int size_offsets_max; -int *offsets; +int *offsets = NULL; #if !defined NOPOSIX int posix = 0; #endif int debug = 0; int done = 0; +int all_use_dfa = 0; +int yield = 0; unsigned char *buffer; unsigned char *dbuffer; @@ -429,8 +453,15 @@ when I am debugging. */ buffer = (unsigned char *)malloc(BUFFER_SIZE); dbuffer = (unsigned char *)malloc(DBUFFER_SIZE); +pbuffer = (unsigned char *)malloc(PBUFFER_SIZE); -/* Static so that new_malloc can use it. */ +/* The outfile variable is static so that new_malloc can use it. The _setmode() +stuff is some magic that I don't understand, but which apparently does good +things in Windows. It's related to line terminations. */ + +#if defined(_WIN32) || defined(WIN32) +_setmode( _fileno( stdout ), 0x8000 ); +#endif /* defined(_WIN32) || defined(WIN32) */ outfile = stdout; @@ -445,6 +476,9 @@ while (argc > 1 && argv[op][0] == '-') else if (strcmp(argv[op], "-t") == 0) timeit = 1; else if (strcmp(argv[op], "-i") == 0) showinfo = 1; else if (strcmp(argv[op], "-d") == 0) showinfo = debug = 1; +#if !defined NODFA + else if (strcmp(argv[op], "-dfa") == 0) all_use_dfa = 1; +#endif else if (strcmp(argv[op], "-o") == 0 && argc > 2 && ((size_offsets = get_value((unsigned char *)argv[op+1], &endptr)), *endptr == 0)) @@ -462,6 +496,8 @@ while (argc > 1 && argv[op][0] == '-') printf("Compiled with\n"); (void)pcre_config(PCRE_CONFIG_UTF8, &rc); printf(" %sUTF-8 support\n", rc? "" : "No "); + (void)pcre_config(PCRE_CONFIG_UNICODE_PROPERTIES, &rc); + printf(" %sUnicode properties support\n", rc? "" : "No "); (void)pcre_config(PCRE_CONFIG_NEWLINE, &rc); printf(" Newline character is %s\n", (rc == '\r')? "CR" : "LF"); (void)pcre_config(PCRE_CONFIG_LINK_SIZE, &rc); @@ -479,15 +515,20 @@ while (argc > 1 && argv[op][0] == '-') printf("** Unknown or malformed option %s\n", argv[op]); printf("Usage: pcretest [-d] [-i] [-o ] [-p] [-s] [-t] [ []]\n"); printf(" -C show PCRE compile-time options and exit\n"); - printf(" -d debug: show compiled code; implies -i\n" - " -i show information about compiled pattern\n" + printf(" -d debug: show compiled code; implies -i\n"); +#if !defined NODFA + printf(" -dfa force DFA matching for all subjects\n"); +#endif + printf(" -i show information about compiled pattern\n" + " -m output memory used information\n" " -o set size of offsets vector to \n"); #if !defined NOPOSIX printf(" -p use POSIX interface\n"); #endif - printf(" -s output store information\n" + printf(" -s output store (memory) used information\n" " -t time compilation and execution\n"); - return 1; + yield = 1; + goto EXIT; } op++; argc--; @@ -501,28 +542,31 @@ if (offsets == NULL) { printf("** Failed to get %d bytes of memory for offsets vector\n", size_offsets_max * sizeof(int)); - return 1; + yield = 1; + goto EXIT; } /* Sort out the input and output files */ if (argc > 1) { - infile = fopen(argv[op], "r"); + infile = fopen(argv[op], "rb"); if (infile == NULL) { printf("** Failed to open %s\n", argv[op]); - return 1; + yield = 1; + goto EXIT; } } if (argc > 2) { - outfile = fopen(argv[op+1], "w"); + outfile = fopen(argv[op+1], "wb"); if (outfile == NULL) { printf("** Failed to open %s\n", argv[op+1]); - return 1; + yield = 1; + goto EXIT; } } @@ -551,13 +595,17 @@ while (!done) const char *error; unsigned char *p, *pp, *ppp; + unsigned char *to_file = NULL; const unsigned char *tables = NULL; + unsigned long int true_size, true_study_size = 0; + size_t size, regex_gotten_store; int do_study = 0; int do_debug = debug; int do_G = 0; int do_g = 0; int do_showinfo = showinfo; int do_showrest = 0; + int do_flip = 0; int erroroffset, len, delimiter; use_utf8 = 0; @@ -571,8 +619,93 @@ while (!done) while (isspace(*p)) p++; if (*p == 0) continue; - /* Get the delimiter and seek the end of the pattern; if is isn't - complete, read more. */ + /* See if the pattern is to be loaded pre-compiled from a file. */ + + if (*p == '<' && strchr((char *)(p+1), '<') == NULL) + { + unsigned long int magic; + uschar sbuf[8]; + FILE *f; + + p++; + pp = p + (int)strlen((char *)p); + while (isspace(pp[-1])) pp--; + *pp = 0; + + f = fopen((char *)p, "rb"); + if (f == NULL) + { + fprintf(outfile, "Failed to open %s: %s\n", p, strerror(errno)); + continue; + } + + if (fread(sbuf, 1, 8, f) != 8) goto FAIL_READ; + + true_size = + (sbuf[0] << 24) | (sbuf[1] << 16) | (sbuf[2] << 8) | sbuf[3]; + true_study_size = + (sbuf[4] << 24) | (sbuf[5] << 16) | (sbuf[6] << 8) | sbuf[7]; + + re = (real_pcre *)new_malloc(true_size); + regex_gotten_store = gotten_store; + + if (fread(re, 1, true_size, f) != true_size) goto FAIL_READ; + + magic = ((real_pcre *)re)->magic_number; + if (magic != MAGIC_NUMBER) + { + if (byteflip(magic, sizeof(magic)) == MAGIC_NUMBER) + { + do_flip = 1; + } + else + { + fprintf(outfile, "Data in %s is not a compiled PCRE regex\n", p); + fclose(f); + continue; + } + } + + fprintf(outfile, "Compiled regex%s loaded from %s\n", + do_flip? " (byte-inverted)" : "", p); + + /* Need to know if UTF-8 for printing data strings */ + + new_info(re, NULL, PCRE_INFO_OPTIONS, &options); + use_utf8 = (options & PCRE_UTF8) != 0; + + /* Now see if there is any following study data */ + + if (true_study_size != 0) + { + pcre_study_data *psd; + + extra = (pcre_extra *)new_malloc(sizeof(pcre_extra) + true_study_size); + extra->flags = PCRE_EXTRA_STUDY_DATA; + + psd = (pcre_study_data *)(((char *)extra) + sizeof(pcre_extra)); + extra->study_data = psd; + + if (fread(psd, 1, true_study_size, f) != true_study_size) + { + FAIL_READ: + fprintf(outfile, "Failed to read data from %s\n", p); + if (extra != NULL) new_free(extra); + if (re != NULL) new_free(re); + fclose(f); + continue; + } + fprintf(outfile, "Study data loaded from %s\n", p); + do_study = 1; /* To get the data output if requested */ + } + else fprintf(outfile, "No study data\n"); + + fclose(f); + goto SHOW_INFO; + } + + /* In-line pattern (the usual case). Get the delimiter and seek the end of + the pattern; if is isn't complete, read more. */ delimiter = *p++; @@ -617,9 +750,11 @@ while (!done) if (pp[1] == '\\') *pp++ = '\\'; - /* Terminate the pattern at the delimiter */ + /* Terminate the pattern at the delimiter, and save a copy of the pattern + for callouts. */ *pp++ = 0; + strcpy((char *)pbuffer, (char *)p); /* Look for options after final delimiter */ @@ -631,6 +766,7 @@ while (!done) { switch (*pp++) { + case 'f': options |= PCRE_FIRSTLINE; break; case 'g': do_g = 1; break; case 'i': options |= PCRE_CASELESS; break; case 'm': options |= PCRE_MULTILINE; break; @@ -639,8 +775,10 @@ while (!done) case '+': do_showrest = 1; break; case 'A': options |= PCRE_ANCHORED; break; + case 'C': options |= PCRE_AUTO_CALLOUT; break; case 'D': do_debug = do_showinfo = 1; break; case 'E': options |= PCRE_DOLLAR_ENDONLY; break; + case 'F': do_flip = 1; break; case 'G': do_G = 1; break; case 'I': do_showinfo = 1; break; case 'M': log_store = 1; break; @@ -658,7 +796,8 @@ while (!done) case 'L': ppp = pp; - while (*ppp != '\n' && *ppp != ' ') ppp++; + /* The '\r' test here is so that it works on Windows */ + while (*ppp != '\n' && *ppp != '\r' && *ppp != ' ') ppp++; *ppp = 0; if (setlocale(LC_CTYPE, (const char *)pp) == NULL) { @@ -669,7 +808,18 @@ while (!done) pp = ppp; break; - case '\n': case ' ': break; + case '>': + to_file = pp; + while (*pp != 0) pp++; + while (isspace(pp[-1])) pp--; + *pp = 0; + break; + + case '\r': /* So that it works in Windows */ + case '\n': + case ' ': + break; + default: fprintf(outfile, "** Unknown option '%c'\n", pp[-1]); goto SKIP_DATA; @@ -685,8 +835,10 @@ while (!done) { int rc; int cflags = 0; + if ((options & PCRE_CASELESS) != 0) cflags |= REG_ICASE; if ((options & PCRE_MULTILINE) != 0) cflags |= REG_NEWLINE; + if ((options & PCRE_DOTALL) != 0) cflags |= REG_DOTALL; rc = regcomp(&preg, (char *)p, cflags); /* Compilation failed; go back for another re, skipping to blank line @@ -759,19 +911,84 @@ while (!done) sizeof(real_pcre) - ((real_pcre *)re)->name_count * ((real_pcre *)re)->name_entry_size)); + /* Extract the size for possible writing before possibly flipping it, + and remember the store that was got. */ + + true_size = ((real_pcre *)re)->size; + regex_gotten_store = gotten_store; + + /* If /S was present, study the regexp to generate additional info to + help with the matching. */ + + if (do_study) + { + if (timeit) + { + register int i; + clock_t time_taken; + clock_t start_time = clock(); + for (i = 0; i < LOOPREPEAT; i++) + extra = pcre_study(re, study_options, &error); + time_taken = clock() - start_time; + if (extra != NULL) free(extra); + fprintf(outfile, " Study time %.3f milliseconds\n", + (((double)time_taken * 1000.0) / (double)LOOPREPEAT) / + (double)CLOCKS_PER_SEC); + } + extra = pcre_study(re, study_options, &error); + if (error != NULL) + fprintf(outfile, "Failed to study: %s\n", error); + else if (extra != NULL) + true_study_size = ((pcre_study_data *)(extra->study_data))->size; + } + + /* If the 'F' option was present, we flip the bytes of all the integer + fields in the regex data block and the study block. This is to make it + possible to test PCRE's handling of byte-flipped patterns, e.g. those + compiled on a different architecture. */ + + if (do_flip) + { + real_pcre *rre = (real_pcre *)re; + rre->magic_number = byteflip(rre->magic_number, sizeof(rre->magic_number)); + rre->size = byteflip(rre->size, sizeof(rre->size)); + rre->options = byteflip(rre->options, sizeof(rre->options)); + rre->top_bracket = byteflip(rre->top_bracket, sizeof(rre->top_bracket)); + rre->top_backref = byteflip(rre->top_backref, sizeof(rre->top_backref)); + rre->first_byte = byteflip(rre->first_byte, sizeof(rre->first_byte)); + rre->req_byte = byteflip(rre->req_byte, sizeof(rre->req_byte)); + rre->name_table_offset = byteflip(rre->name_table_offset, + sizeof(rre->name_table_offset)); + rre->name_entry_size = byteflip(rre->name_entry_size, + sizeof(rre->name_entry_size)); + rre->name_count = byteflip(rre->name_count, sizeof(rre->name_count)); + + if (extra != NULL) + { + pcre_study_data *rsd = (pcre_study_data *)(extra->study_data); + rsd->size = byteflip(rsd->size, sizeof(rsd->size)); + rsd->options = byteflip(rsd->options, sizeof(rsd->options)); + } + } + + /* Extract information from the compiled data if required */ + + SHOW_INFO: + if (do_showinfo) { - unsigned long int get_options; + unsigned long int get_options, all_options; +#if !defined NOINFOCHECK int old_first_char, old_options, old_count; +#endif int count, backrefmax, first_char, need_char; int nameentrysize, namecount; const uschar *nametable; - size_t size; if (do_debug) { fprintf(outfile, "------------------------------------------------------------------\n"); - print_internals(re, outfile); + _pcre_printint(re, outfile); } new_info(re, NULL, PCRE_INFO_OPTIONS, &get_options); @@ -784,6 +1001,7 @@ while (!done) new_info(re, NULL, PCRE_INFO_NAMECOUNT, &namecount); new_info(re, NULL, PCRE_INFO_NAMETABLE, (void *)&nametable); +#if !defined NOINFOCHECK old_count = pcre_info(re, &old_options, &old_first_char); if (count < 0) fprintf(outfile, "Error %d from pcre_info()\n", count); @@ -801,10 +1019,11 @@ while (!done) "Options disagreement: pcre_fullinfo=%ld pcre_info=%d\n", get_options, old_options); } +#endif - if (size != gotten_store) fprintf(outfile, + if (size != regex_gotten_store) fprintf(outfile, "Size disagreement: pcre_fullinfo=%d call to malloc for %d\n", - size, gotten_store); + (int)size, (int)regex_gotten_store); fprintf(outfile, "Capturing subpattern count = %d\n", count); if (backrefmax > 0) @@ -822,12 +1041,25 @@ while (!done) } } + /* The NOPARTIAL bit is a private bit in the options, so we have + to fish it out via out back door */ + + all_options = ((real_pcre *)re)->options; + if (do_flip) + { + all_options = byteflip(all_options, sizeof(all_options)); + } + + if ((all_options & PCRE_NOPARTIAL) != 0) + fprintf(outfile, "Partial matching not supported\n"); + if (get_options == 0) fprintf(outfile, "No options\n"); - else fprintf(outfile, "Options:%s%s%s%s%s%s%s%s%s%s\n", + else fprintf(outfile, "Options:%s%s%s%s%s%s%s%s%s%s%s\n", ((get_options & PCRE_ANCHORED) != 0)? " anchored" : "", ((get_options & PCRE_CASELESS) != 0)? " caseless" : "", ((get_options & PCRE_EXTENDED) != 0)? " extended" : "", ((get_options & PCRE_MULTILINE) != 0)? " multiline" : "", + ((get_options & PCRE_FIRSTLINE) != 0)? " firstline" : "", ((get_options & PCRE_DOTALL) != 0)? " dotall" : "", ((get_options & PCRE_DOLLAR_ENDONLY) != 0)? " dollar_endonly" : "", ((get_options & PCRE_EXTRA) != 0)? " extra" : "", @@ -871,77 +1103,107 @@ while (!done) else fprintf(outfile, "Need char = %d%s\n", ch, caseless); } - } - - /* If /S was present, study the regexp to generate additional info to - help with the matching. */ - - if (do_study) - { - if (timeit) - { - register int i; - clock_t time_taken; - clock_t start_time = clock(); - for (i = 0; i < LOOPREPEAT; i++) - extra = pcre_study(re, study_options, &error); - time_taken = clock() - start_time; - if (extra != NULL) free(extra); - fprintf(outfile, " Study time %.3f milliseconds\n", - (((double)time_taken * 1000.0) / (double)LOOPREPEAT) / - (double)CLOCKS_PER_SEC); - } - - extra = pcre_study(re, study_options, &error); - if (error != NULL) - fprintf(outfile, "Failed to study: %s\n", error); - else if (extra == NULL) - fprintf(outfile, "Study returned NULL\n"); /* Don't output study size; at present it is in any case a fixed value, but it varies, depending on the computer architecture, and - so messes up the test suite. */ + so messes up the test suite. (And with the /F option, it might be + flipped.) */ - else if (do_showinfo) + if (do_study) { - size_t size; - uschar *start_bits = NULL; - new_info(re, extra, PCRE_INFO_STUDYSIZE, &size); - new_info(re, extra, PCRE_INFO_FIRSTTABLE, &start_bits); - /* fprintf(outfile, "Study size = %d\n", size); */ - if (start_bits == NULL) - fprintf(outfile, "No starting character set\n"); + if (extra == NULL) + fprintf(outfile, "Study returned NULL\n"); else { - int i; - int c = 24; - fprintf(outfile, "Starting character set: "); - for (i = 0; i < 256; i++) + uschar *start_bits = NULL; + new_info(re, extra, PCRE_INFO_FIRSTTABLE, &start_bits); + + if (start_bits == NULL) + fprintf(outfile, "No starting byte set\n"); + else { - if ((start_bits[i/8] & (1<<(i%8))) != 0) + int i; + int c = 24; + fprintf(outfile, "Starting byte set: "); + for (i = 0; i < 256; i++) { - if (c > 75) - { - fprintf(outfile, "\n "); - c = 2; - } - if (isprint(i) && i != ' ') + if ((start_bits[i/8] & (1<<(i&7))) != 0) { - fprintf(outfile, "%c ", i); - c += 2; - } - else - { - fprintf(outfile, "\\x%02x ", i); - c += 5; + if (c > 75) + { + fprintf(outfile, "\n "); + c = 2; + } + if (isprint(i) && i != ' ') + { + fprintf(outfile, "%c ", i); + c += 2; + } + else + { + fprintf(outfile, "\\x%02x ", i); + c += 5; + } } } + fprintf(outfile, "\n"); } - fprintf(outfile, "\n"); } } } - } + + /* If the '>' option was present, we write out the regex to a file, and + that is all. The first 8 bytes of the file are the regex length and then + the study length, in big-endian order. */ + + if (to_file != NULL) + { + FILE *f = fopen((char *)to_file, "wb"); + if (f == NULL) + { + fprintf(outfile, "Unable to open %s: %s\n", to_file, strerror(errno)); + } + else + { + uschar sbuf[8]; + sbuf[0] = (true_size >> 24) & 255; + sbuf[1] = (true_size >> 16) & 255; + sbuf[2] = (true_size >> 8) & 255; + sbuf[3] = (true_size) & 255; + + sbuf[4] = (true_study_size >> 24) & 255; + sbuf[5] = (true_study_size >> 16) & 255; + sbuf[6] = (true_study_size >> 8) & 255; + sbuf[7] = (true_study_size) & 255; + + if (fwrite(sbuf, 1, 8, f) < 8 || + fwrite(re, 1, true_size, f) < true_size) + { + fprintf(outfile, "Write error on %s: %s\n", to_file, strerror(errno)); + } + else + { + fprintf(outfile, "Compiled regex written to %s\n", to_file); + if (extra != NULL) + { + if (fwrite(extra->study_data, 1, true_study_size, f) < + true_study_size) + { + fprintf(outfile, "Write error on %s: %s\n", to_file, + strerror(errno)); + } + else fprintf(outfile, "Study data written to %s\n", to_file); + } + } + fclose(f); + } + + new_free(re); + if (extra != NULL) new_free(extra); + if (tables != NULL) new_free((void *)tables); + continue; /* With next regex */ + } + } /* End of non-POSIX compile */ /* Read data lines and test them */ @@ -961,6 +1223,7 @@ while (!done) int gmatched = 0; int start_offset = 0; int g_notempty = 0; + int use_dfa = 0; options = 0; @@ -1016,6 +1279,7 @@ while (!done) /* Handle \x{..} specially - new Perl thing for utf8 */ +#if !defined NOUTF8 if (*p == '{') { unsigned char *pt = p; @@ -1026,7 +1290,7 @@ while (!done) { unsigned char buff8[8]; int ii, utn; - utn = ord2utf8(c, buff8); + utn = _pcre_ord2utf8(c, buff8); for (ii = 0; ii < utn - 1; ii++) *q++ = buff8[ii]; c = buff8[ii]; /* Last byte */ p = pt + 1; @@ -1034,6 +1298,7 @@ while (!done) } /* Not correct form; fall through */ } +#endif /* Ordinary \x */ @@ -1045,10 +1310,14 @@ while (!done) } break; - case 0: /* Allows for an empty line */ + case 0: /* \ followed by EOF allows for an empty line */ p--; continue; + case '>': + while(isdigit(*p)) start_offset = start_offset * 10 + *p++ - '0'; + continue; + case 'A': /* Option setting */ options |= PCRE_ANCHORED; continue; @@ -1110,6 +1379,21 @@ while (!done) } continue; +#if !defined NODFA + case 'D': +#if !defined NOPOSIX + if (posix || do_posix) + printf("** Can't use dfa matching in POSIX mode: \\D ignored\n"); + else +#endif + use_dfa = 1; + continue; + + case 'F': + options |= PCRE_DFA_SHORTEST; + continue; +#endif + case 'G': if (isdigit(*p)) { @@ -1152,13 +1436,24 @@ while (!done) { printf("** Failed to get %d bytes of memory for offsets vector\n", size_offsets_max * sizeof(int)); - return 1; + yield = 1; + goto EXIT; } } use_size_offsets = n; if (n == 0) use_offsets = NULL; /* Ensures it can't write to it */ continue; + case 'P': + options |= PCRE_PARTIAL; + continue; + +#if !defined NODFA + case 'R': + options |= PCRE_DFA_RESTART; + continue; +#endif + case 'S': show_malloc = 1; continue; @@ -1176,6 +1471,12 @@ while (!done) *q = 0; len = q - dbuffer; + if ((all_use_dfa || use_dfa) && find_match_limit) + { + printf("**Match limit not relevant for DFA matching: ignored\n"); + find_match_limit = 0; + } + /* Handle matching via the POSIX interface, which does not support timing or playing with the match limit or callout data. */ @@ -1233,9 +1534,23 @@ while (!done) register int i; clock_t time_taken; clock_t start_time = clock(); + +#if !defined NODFA + if (all_use_dfa || use_dfa) + { + int workspace[1000]; + for (i = 0; i < LOOPREPEAT; i++) + count = pcre_dfa_exec(re, NULL, (char *)bptr, len, start_offset, + options | g_notempty, use_offsets, use_size_offsets, workspace, + sizeof(workspace)/sizeof(int)); + } + else +#endif + for (i = 0; i < LOOPREPEAT; i++) count = pcre_exec(re, extra, (char *)bptr, len, start_offset, options | g_notempty, use_offsets, use_size_offsets); + time_taken = clock() - start_time; fprintf(outfile, "Execute time %.3f milliseconds\n", (((double)time_taken * 1000.0) / (double)LOOPREPEAT) / @@ -1269,7 +1584,8 @@ while (!done) min = mid; mid = (mid == max - 1)? max : (max > 0)? (min + max)/2 : mid*2; } - else if (count >= 0 || count == PCRE_ERROR_NOMATCH) + else if (count >= 0 || count == PCRE_ERROR_NOMATCH || + count == PCRE_ERROR_PARTIAL) { if (mid == min + 1) { @@ -1305,13 +1621,30 @@ while (!done) /* The normal case is just to do the match once, with the default value of match_limit. */ - else count = pcre_exec(re, extra, (char *)bptr, len, - start_offset, options | g_notempty, use_offsets, use_size_offsets); +#if !defined NODFA + else if (all_use_dfa || use_dfa) + { + int workspace[1000]; + count = pcre_dfa_exec(re, NULL, (char *)bptr, len, start_offset, + options | g_notempty, use_offsets, use_size_offsets, workspace, + sizeof(workspace)/sizeof(int)); + if (count == 0) + { + fprintf(outfile, "Matched, but too many subsidiary matches\n"); + count = use_size_offsets/2; + } + } +#endif - if (count == 0) + else { - fprintf(outfile, "Matched, but too many substrings\n"); - count = use_size_offsets/3; + count = pcre_exec(re, extra, (char *)bptr, len, + start_offset, options | g_notempty, use_offsets, use_size_offsets); + if (count == 0) + { + fprintf(outfile, "Matched, but too many substrings\n"); + count = use_size_offsets/3; + } } /* Matched */ @@ -1393,6 +1726,20 @@ while (!done) } } + /* There was a partial match */ + + else if (count == PCRE_ERROR_PARTIAL) + { + fprintf(outfile, "Partial match"); +#if !defined NODFA + if ((all_use_dfa || use_dfa) && use_size_offsets > 2) + fprintf(outfile, ": %.*s", use_offsets[1] - use_offsets[0], + bptr + use_offsets[0]); +#endif + fprintf(outfile, "\n"); + break; /* Out of the /g loop */ + } + /* Failed to match. If this is a /g or /G loop and we previously set g_notempty after a null match, this is not necessarily the end. We want to advance the start offset, and continue. In the case of UTF-8 @@ -1467,17 +1814,28 @@ while (!done) if (posix || do_posix) regfree(&preg); #endif - if (re != NULL) free(re); - if (extra != NULL) free(extra); + if (re != NULL) new_free(re); + if (extra != NULL) new_free(extra); if (tables != NULL) { - free((void *)tables); + new_free((void *)tables); setlocale(LC_CTYPE, "C"); } } if (infile == stdin) fprintf(outfile, "\n"); -return 0; + +EXIT: + +if (infile != NULL && infile != stdin) fclose(infile); +if (outfile != NULL && outfile != stdout) fclose(outfile); + +free(buffer); +free(dbuffer); +free(pbuffer); +free(offsets); + +return yield; } -/* End */ +/* End of pcretest.c */ diff --git a/ext/pcre/pcrelib/testdata/grepinput b/ext/pcre/pcrelib/testdata/grepinput new file mode 100644 index 000000000000..2a89c2e09dd5 --- /dev/null +++ b/ext/pcre/pcrelib/testdata/grepinput @@ -0,0 +1,588 @@ +This is a file of miscellaneous text that is used as test data for checking +that the pcregrep command is working correctly. The file must be more than 24K +long so that it needs more than a single read() call to process it. New +features should be added at the end, because some of the tests involve the +output of line numbers, and we don't want these to change. + +PATTERN at the start of a line. +In the middle of a line, PATTERN appears. + +This pattern is in lower case. + +Here follows a whole lot of stuff that makes the file over 24K long. + +------------------------------------------------------------------------------- +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the +lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox +jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick +brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. +------------------------------------------------------------------------------- + +Check up on PATTERN near the end. + +This is the last line of this file. diff --git a/ext/pcre/pcrelib/testdata/grepinputx b/ext/pcre/pcrelib/testdata/grepinputx new file mode 100644 index 000000000000..aebba027703a --- /dev/null +++ b/ext/pcre/pcrelib/testdata/grepinputx @@ -0,0 +1,42 @@ +This is a second file of input for the pcregrep tests. + +Here is the pattern again. + +Pattern +That time it was on a line by itself. + +To pat or not to pat, that is the question. + +complete pair +of lines + +That was a complete pair +of lines all by themselves. + +complete pair +of lines + +And there they were again, to check line numbers. + +one +two +three +four +five +six +seven +eight +nine +ten +eleven +twelve +thirteen +fourteen +fifteen +sixteen +seventeen +eighteen +nineteen +twenty + +This is the last line of this file. diff --git a/ext/pcre/pcrelib/testdata/greplist b/ext/pcre/pcrelib/testdata/greplist new file mode 100644 index 000000000000..bb2705e390ab --- /dev/null +++ b/ext/pcre/pcrelib/testdata/greplist @@ -0,0 +1,4 @@ +This is a file of patterns for testing the -f option. Don't include any blank +lines because they will match everything! +pattern +line by itself diff --git a/ext/pcre/pcrelib/testdata/grepoutput b/ext/pcre/pcrelib/testdata/grepoutput new file mode 100644 index 000000000000..27ab7e4a5ff6 --- /dev/null +++ b/ext/pcre/pcrelib/testdata/grepoutput @@ -0,0 +1,336 @@ +pcregrep version 4.0 07-Jun-2005 using PCRE version 6.2 01-Aug-2005 +---------------------------- Test 1 ------------------------------ +PATTERN at the start of a line. +In the middle of a line, PATTERN appears. +Check up on PATTERN near the end. +---------------------------- Test 2 ------------------------------ +PATTERN at the start of a line. +---------------------------- Test 3 ------------------------------ +7:PATTERN at the start of a line. +8:In the middle of a line, PATTERN appears. +10:This pattern is in lower case. +586:Check up on PATTERN near the end. +---------------------------- Test 4 ------------------------------ +4 +---------------------------- Test 5 ------------------------------ +./testdata/grepinput:7:PATTERN at the start of a line. +./testdata/grepinput:8:In the middle of a line, PATTERN appears. +./testdata/grepinput:10:This pattern is in lower case. +./testdata/grepinput:586:Check up on PATTERN near the end. +-- +./testdata/grepinputx:3:Here is the pattern again. +./testdata/grepinputx:5:Pattern +---------------------------- Test 6 ------------------------------ +7:PATTERN at the start of a line. +8:In the middle of a line, PATTERN appears. +10:This pattern is in lower case. +586:Check up on PATTERN near the end. +-- +3:Here is the pattern again. +5:Pattern +---------------------------- Test 7 ------------------------------ +./testdata/grepinput +./testdata/grepinputx +---------------------------- Test 8 ------------------------------ +./testdata/grepinput +---------------------------- Test 9 ------------------------------ +RC=0 +---------------------------- Test 10 ----------------------------- +RC=1 +---------------------------- Test 11 ----------------------------- +1:This is a second file of input for the pcregrep tests. +2: +4: +5:Pattern +6:That time it was on a line by itself. +7: +8:To pat or not to pat, that is the question. +9: +10:complete pair +11:of lines +12: +13:That was a complete pair +14:of lines all by themselves. +15: +16:complete pair +17:of lines +18: +19:And there they were again, to check line numbers. +20: +21:one +22:two +23:three +24:four +25:five +26:six +27:seven +28:eight +29:nine +30:ten +31:eleven +32:twelve +33:thirteen +34:fourteen +35:fifteen +36:sixteen +37:seventeen +38:eighteen +39:nineteen +40:twenty +41: +42:This is the last line of this file. +---------------------------- Test 12 ----------------------------- +Pattern +---------------------------- Test 13 ----------------------------- +Here is the pattern again. +That time it was on a line by itself. +---------------------------- Test 14 ----------------------------- +./testdata/grepinputx:To pat or not to pat, that is the question. +---------------------------- Test 15 ----------------------------- +pcregrep: Error in regex at offset 4: nothing to repeat +---------------------------- Test 16 ----------------------------- +pcregrep: Failed to open ./testdata/nonexistfile: No such file or directory +---------------------------- Test 17 ----------------------------- +features should be added at the end, because some of the tests involve the +output of line numbers, and we don't want these to change. +---------------------------- Test 18 ----------------------------- +4:features should be added at the end, because some of the tests involve the +output of line numbers, and we don't want these to change. +583:brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. +------------------------------------------------------------------------------- +---------------------------- Test 19 ----------------------------- +Pattern +---------------------------- Test 20 ----------------------------- +10:complete pair +of lines +16:complete pair +of lines +---------------------------- Test 21 ----------------------------- +24:four +25-five +26-six +27-seven +-- +34:fourteen +35-fifteen +36-sixteen +37-seventeen +---------------------------- Test 22 ----------------------------- +20-one +21-two +22-three +24:four +-- +30-eleven +31-twelve +32-thirteen +34:fourteen +---------------------------- Test 23 ----------------------------- +one +two +three +four +five +six +seven +-- +eleven +twelve +thirteen +fourteen +fifteen +sixteen +seventeen +---------------------------- Test 24 ----------------------------- +four +five +six +seven +eight +nine +ten +eleven +twelve +thirteen +fourteen +fifteen +sixteen +seventeen +eighteen +nineteen +twenty + +This is the last line of this file. +---------------------------- Test 25 ----------------------------- +14- +15-complete pair +16-of lines +17- +18-And there they were again, to check line numbers. +19- +20-one +21-two +22-three +24:four +25-five +26-six +27-seven +28-eight +29-nine +30-ten +31-eleven +32-twelve +33-thirteen +34:fourteen +---------------------------- Test 26 ----------------------------- + +complete pair +of lines + +And there they were again, to check line numbers. + +one +two +three +four +five +six +seven +eight +nine +ten +eleven +twelve +thirteen +fourteen +fifteen +sixteen +seventeen +eighteen +nineteen +twenty + +This is the last line of this file. +---------------------------- Test 27 ----------------------------- +four +five +six +seven +eight +nine +ten +eleven +twelve +thirteen +fourteen +fifteen +sixteen +seventeen +eighteen +nineteen +twenty + +This is the last line of this file. +---------------------------- Test 28 ----------------------------- +13-of lines all by themselves. +14- +15-complete pair +16-of lines +17- +18-And there they were again, to check line numbers. +19- +20-one +21-two +22-three +24:four +25-five +26-six +27-seven +28-eight +29-nine +30-ten +31-eleven +32-twelve +33-thirteen +34:fourteen +---------------------------- Test 29 ----------------------------- +of lines all by themselves. + +complete pair +of lines + +And there they were again, to check line numbers. + +one +two +three +four +five +six +seven +eight +nine +ten +eleven +twelve +thirteen +fourteen +fifteen +sixteen +seventeen +eighteen +nineteen +twenty + +This is the last line of this file. +---------------------------- Test 30 ----------------------------- +./testdata/grepinput-3-features should be added at the end, because some of the tests involve the +./testdata/grepinput-4-output of line numbers, and we don't want these to change. +./testdata/grepinput-5- +./testdata/grepinput:7:PATTERN at the start of a line. +./testdata/grepinput:8:In the middle of a line, PATTERN appears. +./testdata/grepinput-9- +./testdata/grepinput:10:This pattern is in lower case. +-- +./testdata/grepinput-582-brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. +./testdata/grepinput-583-------------------------------------------------------------------------------- +./testdata/grepinput-584- +./testdata/grepinput:586:Check up on PATTERN near the end. +-- +./testdata/grepinputx-1-This is a second file of input for the pcregrep tests. +./testdata/grepinputx-2- +./testdata/grepinputx:3:Here is the pattern again. +./testdata/grepinputx-4- +./testdata/grepinputx:5:Pattern +---------------------------- Test 31 ----------------------------- +./testdata/grepinput:7:PATTERN at the start of a line. +./testdata/grepinput:8:In the middle of a line, PATTERN appears. +./testdata/grepinput-9- +./testdata/grepinput:10:This pattern is in lower case. +./testdata/grepinput-11- +./testdata/grepinput-12-Here follows a whole lot of stuff that makes the file over 24K long. +./testdata/grepinput-13- +-- +./testdata/grepinput:586:Check up on PATTERN near the end. +./testdata/grepinput-587- +./testdata/grepinput-588-This is the last line of this file. +-- +./testdata/grepinputx:3:Here is the pattern again. +./testdata/grepinputx-4- +./testdata/grepinputx:5:Pattern +./testdata/grepinputx-6-That time it was on a line by itself. +./testdata/grepinputx-7- +./testdata/grepinputx-8-To pat or not to pat, that is the question. +---------------------------- Test 32 ----------------------------- +./testdata/grepinputx +---------------------------- Test 33 ----------------------------- +pcregrep: Failed to open ./testdata/grepnonexist: No such file or directory +RC=2 +---------------------------- Test 34 ----------------------------- +RC=2 +---------------------------- Test 35 ----------------------------- +./testdata/grepinputx +RC=0 +---------------------------- Test 36 ----------------------------- +./testdata/grepinputx +RC=0 diff --git a/ext/pcre/pcrelib/testdata/testinput1 b/ext/pcre/pcrelib/testdata/testinput1 index c64257685be8..88ff5bf8e7dd 100644 --- a/ext/pcre/pcrelib/testdata/testinput1 +++ b/ext/pcre/pcrelib/testdata/testinput1 @@ -1358,7 +1358,7 @@ /^[W-c]+$/ WXY_^abc - ***Failers + *** Failers wxy /^[W-c]+$/i @@ -3560,7 +3560,7 @@ the.quick.brown.fox a100.b200.300c 12-ab.1245 - ***Failers + *** Failers \ .a -a @@ -3805,4 +3805,46 @@ :1 1: +/[z\Qa-d]\E]/ + z + a + - + d + ] + *** Failers + b + +/[\z\C]/ + z + C + +/\M/ + M + +/(a+)*b/ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +/(?i)reg(?:ul(?:[aä]|ae)r|ex)/ + REGular + regulaer + Regex + regulär + +/Åæåä[à-ÿÀ-ß]+/ + Åæåäà + Åæåäÿ + ÅæåäÀ + Åæåäß + +/(?<=Z)X./ + \x84XAZXB + +/ab cd (?x) de fg/ + ab cd defg + +/ab cd(?x) de fg/ + ab cddefg + ** Failers + abcddefg + / End of testinput1 / diff --git a/ext/pcre/pcrelib/testdata/testinput2 b/ext/pcre/pcrelib/testdata/testinput2 index 2dd498a713be..befb65a4412f 100644 --- a/ext/pcre/pcrelib/testdata/testinput2 +++ b/ext/pcre/pcrelib/testdata/testinput2 @@ -38,7 +38,7 @@ /[abcd/ -/[\B]/ +/(?X)[\B]/ /[z-a]/ @@ -266,6 +266,18 @@ /(?!alphabet)[ab]/S /(?<=foo\n)^bar/m + foo\nbarbar + ***Failers + rhubarb + barbell + abc\nbarton + +/^(?<=foo\n)bar/m + foo\nbarbar + ***Failers + rhubarb + barbell + abc\nbarton /(?>^abc)/m abc @@ -654,10 +666,16 @@ /^[[:alnum:]]/D +/^[[:^alnum:]]/D + /^[[:alpha:]]/D + +/^[[:^alpha:]]/D /^[[:ascii:]]/D +/^[[:^ascii:]]/D + /^[[:blank:]]/D /^[[:cntrl:]]/D @@ -817,7 +835,7 @@ /\Q\Eabc/D /x*+\w/D - ****Failers + *** Failers xxxxx /x?+/D @@ -890,20 +908,10 @@ /\N{name}/ -/\pP/ - -/\PP/ - -/\p{prop}/ - -/\P{prop}/ - /\u/ /\U/ -/\X/ - /[/ /[a-/ @@ -1061,6 +1069,12 @@ /(?<=(abc)(?C))xyz/ abcxyz\C+ +/a(b+)(c*)(?C1)/ + abbbbbccc\C*1 + +/a(b+?)(c*?)(?C1)/ + abbbbbccc\C*1 + /(?C)abc/ /(?C)^abc/ @@ -1159,4 +1173,281 @@ /(?Pa)...(?P=a)bbb(?P>a)d/D +/^\W*(?:(?P(?P.)\W*(?P>one)\W*(?P=two)|)|(?P(?P.)\W*(?P>three)\W*(?P=four)|\W*.\W*))\W*$/i + 1221 + Satan, oscillate my metallic sonatas! + A man, a plan, a canal: Panama! + Able was I ere I saw Elba. + *** Failers + The quick brown fox + +/((?(R)a|b))\1(?1)?/ + bb + bbaa + +/(.*)a/sI + +/(.*)a\1/sI + +/(.*)a(b)\2/sI + +/((.*)a|(.*)b)z/sI + +/((.*)a|(.*)b)z\1/sI + +/((.*)a|(.*)b)z\2/sI + +/((.*)a|(.*)b)z\3/sI + +/((.*)a|^(.*)b)z\3/sI + +/(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)a/sI + +/(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)a\31/sI + +/(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)a\32/sI + +/(a)(bc)/ND + abc + +/(?Pa)(bc)/ND + abc + +/(a)(?Pbc)/ND + +/(a+)*zz/ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaazzbbbbbb\M + aaaaaaaaaaaaaz\M + +/(aaa(?C1)bbb|ab)/ + aaabbb + aaabbb\C*0 + aaabbb\C*1 + aaabbb\C*-1 + +/ab(?Pcd)ef(?Pgh)/ + abcdefgh + abcdefgh\C1\Gtwo + abcdefgh\Cone\Ctwo + abcdefgh\Cthree + +/(?P)(?P)/D + +/(?P)(?P)/D + +/(?Pzz)(?Paa)/ + zzaa\CZ + zzaa\CA + +/(?Peks)(?Peccs)/ + +/(?Pabc(?Pdef)(?Pxyz))/ + +"\[((?P\d+)(,(?P>elem))*)\]" + [10,20,30,5,5,4,4,2,43,23,4234] + *** Failers + [] + +"\[((?P\d+)(,(?P>elem))*)?\]" + [10,20,30,5,5,4,4,2,43,23,4234] + [] + +/(a(b(?2)c))?/D + +/(a(b(?2)c))*/D + +/(a(b(?2)c)){0,2}/D + +/[ab]{1}+/D + +/((w\/|-|with)*(free|immediate)*.*?shipping\s*[!.-]*)/i + Baby Bjorn Active Carrier - With free SHIPPING!! + +/((w\/|-|with)*(free|immediate)*.*?shipping\s*[!.-]*)/iS + Baby Bjorn Active Carrier - With free SHIPPING!! + +/a*.*b/SD + +/(a|b)*.?c/SD + +/abc(?C255)de(?C)f/D + +/abcde/CD + abcde + abcdfe + +/a*b/CD + ab + aaaab + aaaacb + +/a+b/CD + ab + aaaab + aaaacb + +/(abc|def)x/CD + abcx + defx + abcdefzx + +/(ab|cd){3,4}/C + ababab + abcdabcd + abcdcdcdcdcd + +/([ab]{,4}c|xy)/CD + Note: that { does NOT introduce a quantifier + +/([ab]{1,4}c|xy){4,5}?123/CD + aacaacaacaacaac123 + +/\b.*/I + ab cd\>1 + +/\b.*/Is + ab cd\>1 + +/(?!.bcd).*/I + Xbcd12345 + +/abcde/ + ab\P + abc\P + abcd\P + abcde\P + the quick brown abc\P + ** Failers\P + the quick brown abxyz fox\P + +"^(0?[1-9]|[12][0-9]|3[01])/(0?[1-9]|1[012])/(20)?\d\d$" + 13/05/04\P + 13/5/2004\P + 02/05/09\P + 1\P + 1/2\P + 1/2/0\P + 1/2/04\P + 0\P + 02/\P + 02/0\P + 02/1\P + ** Failers\P + \P + 123\P + 33/4/04\P + 3/13/04\P + 0/1/2003\P + 0/\P + 02/0/\P + 02/13\P + +/0{0,2}ABC/I + +/\d{3,}ABC/I + +/\d*ABC/I + +/[abc]+DE/I + +/[abc]?123/ + 123\P + a\P + b\P + c\P + c12\P + c123\P + +/^(?:\d){3,5}X/ + 1\P + 123\P + 123X + 1234\P + 1234X + 12345\P + 12345X + *** Failers + 1X + 123456\P + +/abc/>testsavedregex +testsavedregex +testsavedregex +testsavedregex +(.)*~smg + \n\n\nPartner der LCO\nde\nPartner der LINEAS Consulting\nGmbH\nLINEAS Consulting GmbH Hamburg\nPartnerfirmen\n30 days\nindex,follow\n\nja\n3\nPartner\n\n\nLCO\nLINEAS Consulting\n15.10.2003\n\n\n\n\nDie Partnerfirmen der LINEAS Consulting\nGmbH\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n + +/^a/IF + +/line\nbreak/ + this is a line\nbreak + line one\nthis is a line\nbreak in the second line + +/line\nbreak/f + this is a line\nbreak + ** Failers + line one\nthis is a line\nbreak in the second line + +/line\nbreak/mf + this is a line\nbreak + ** Failers + line one\nthis is a line\nbreak in the second line + +/ab.cd/P + ab-cd + ab=cd + ** Failers + ab\ncd + +/ab.cd/Ps + ab-cd + ab=cd + ab\ncd + +/(?i)(?-i)AbCd/ + AbCd + ** Failers + abcd + +/a{11111111111111111111}/ + +/(){64294967295}/ + +/(){2,4294967295}/ + +"(?i:a)(?i:b)(?i:c)(?i:d)(?i:e)(?i:f)(?i:g)(?i:h)(?i:i)(?i:j)(k)(?i:l)A\1B" + abcdefghijklAkB + +"(?Pa)(?Pb)(?Pc)(?Pd)(?Pe)(?Pf)(?Pg)(?Ph)(?Pi)(?Pj)(?Pk)(?Pl)A\11B" + abcdefghijklAkB + +"(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)A\11B" + abcdefghijklAkB + +"(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +"(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + / End of testinput2 / diff --git a/ext/pcre/pcrelib/testdata/testinput3 b/ext/pcre/pcrelib/testdata/testinput3 index 391aa620696f..c2abdbfdb55c 100644 --- a/ext/pcre/pcrelib/testdata/testinput3 +++ b/ext/pcre/pcrelib/testdata/testinput3 @@ -2,7 +2,7 @@ *** Failers École -/^[\w]+/Lfr +/^[\w]+/Lfr_FR École /^[\w]+/ @@ -12,7 +12,7 @@ /^[\W]+/ École -/^[\W]+/Lfr +/^[\W]+/Lfr_FR *** Failers École @@ -21,7 +21,7 @@ *** Failers a -/[\b]/Lfr +/[\b]/Lfr_FR \b *** Failers a @@ -30,13 +30,13 @@ *** Failers École -/^\w+/Lfr +/^\w+/Lfr_FR École /(.+)\b(.+)/ École -/(.+)\b(.+)/Lfr +/(.+)\b(.+)/Lfr_FR *** Failers École @@ -45,19 +45,19 @@ *** Failers école -/École/iLfr +/École/iLfr_FR École école /\w/IS -/\w/ISLfr +/\w/ISLfr_FR -/^[\xc8-\xc9]/iLfr +/^[\xc8-\xc9]/iLfr_FR École école -/^[\xc8-\xc9]/Lfr +/^[\xc8-\xc9]/Lfr_FR École *** Failers école diff --git a/ext/pcre/pcrelib/testdata/testinput4 b/ext/pcre/pcrelib/testdata/testinput4 index 51d6b976328f..c16e9d9983bb 100644 --- a/ext/pcre/pcrelib/testdata/testinput4 +++ b/ext/pcre/pcrelib/testdata/testinput4 @@ -152,4 +152,362 @@ X\x{1234}YZ X\x{1234}\x{512} +/[^a]+/8g + bcd + \x{100}aY\x{256}Z + +/^[^a]{2}/8 + \x{100}bc + +/^[^a]{2,}/8 + \x{100}bcAa + +/^[^a]{2,}?/8 + \x{100}bca + +/[^a]+/8ig + bcd + \x{100}aY\x{256}Z + +/^[^a]{2}/8i + \x{100}bc + +/^[^a]{2,}/8i + \x{100}bcAa + +/^[^a]{2,}?/8i + \x{100}bca + +/\x{100}{0,0}/8 + abcd + +/\x{100}?/8 + abcd + \x{100}\x{100} + +/\x{100}{0,3}/8 + \x{100}\x{100} + \x{100}\x{100}\x{100}\x{100} + +/\x{100}*/8 + abce + \x{100}\x{100}\x{100}\x{100} + +/\x{100}{1,1}/8 + abcd\x{100}\x{100}\x{100}\x{100} + +/\x{100}{1,3}/8 + abcd\x{100}\x{100}\x{100}\x{100} + +/\x{100}+/8 + abcd\x{100}\x{100}\x{100}\x{100} + +/\x{100}{3}/8 + abcd\x{100}\x{100}\x{100}XX + +/\x{100}{3,5}/8 + abcd\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}XX + +/\x{100}{3,}/8 + abcd\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}XX + +/(?<=a\x{100}{2}b)X/8+ + Xyyya\x{100}\x{100}bXzzz + +/\D*/8 + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +/\D*/8 + \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} + +/\D/8 + 1X2 + 1\x{100}2 + +/>\S/8 + > >X Y + > >\x{100} Y + +/\d/8 + \x{100}3 + +/\s/8 + \x{100} X + +/\D+/8 + 12abcd34 + *** Failers + 1234 + +/\D{2,3}/8 + 12abcd34 + 12ab34 + *** Failers + 1234 + 12a34 + +/\D{2,3}?/8 + 12abcd34 + 12ab34 + *** Failers + 1234 + 12a34 + +/\d+/8 + 12abcd34 + *** Failers + +/\d{2,3}/8 + 12abcd34 + 1234abcd + *** Failers + 1.4 + +/\d{2,3}?/8 + 12abcd34 + 1234abcd + *** Failers + 1.4 + +/\S+/8 + 12abcd34 + *** Failers + \ \ + +/\S{2,3}/8 + 12abcd34 + 1234abcd + *** Failers + \ \ + +/\S{2,3}?/8 + 12abcd34 + 1234abcd + *** Failers + \ \ + +/>\s+ <34 + *** Failers + +/>\s{2,3} \s{2,3}? \xff< + +/[\xff]/8 + >\x{ff}< + +/[^\xFF]/ + XYZ + +/[^\xff]/8 + XYZ + \x{123} + +/^[ac]*b/8 + xb + +/^[ac\x{100}]*b/8 + xb + +/^[^x]*b/8i + xb + +/^[^x]*b/8 + xb + +/^\d*b/8 + xb + +/(|a)/g8 + catac + a\x{256}a + +/^\x{85}$/8i + \x{85} + / End of testinput4 / diff --git a/ext/pcre/pcrelib/testdata/testinput5 b/ext/pcre/pcrelib/testdata/testinput5 index 81fe233e6ba1..fe6ee3e65652 100644 --- a/ext/pcre/pcrelib/testdata/testinput5 +++ b/ext/pcre/pcrelib/testdata/testinput5 @@ -87,5 +87,177 @@ /X(\C)(.*)/8 X\x{1234} X\nabc + +/^[ab]/8D + bar + *** Failers + c + \x{ff} + \x{100} + +/^[^ab]/8D + c + \x{ff} + \x{100} + *** Failers + aaa + +/[^ab\xC0-\xF0]/8SD + \x{f1} + \x{bf} + \x{100} + \x{1000} + *** Failers + \x{c0} + \x{f0} + +/Ä€{3,4}/8SD + \x{100}\x{100}\x{100}\x{100\x{100} + +/(\x{100}+|x)/8SD + +/(\x{100}*a|x)/8SD + +/(\x{100}{0,2}a|x)/8SD + +/(\x{100}{1,2}a|x)/8SD + +/\x{100}*(\d+|"(?1)")/8 + 1234 + "1234" + \x{100}1234 + "\x{100}1234" + \x{100}\x{100}12ab + \x{100}\x{100}"12" + *** Failers + \x{100}\x{100}abcd + +/\x{100}/8D + +/\x{100}*/8D + +/a\x{100}*/8D + +/ab\x{100}*/8D + +/a\x{100}\x{101}*/8D + +/a\x{100}\x{101}+/8D + +/\x{100}*A/8D + A + +/\x{100}*\d(?R)/8D + +/[^\x{c4}]/D + +/[^\x{c4}]/8D + +/[\x{100}]/8DM + \x{100} + Z\x{100} + \x{100}Z + *** Failers + +/[Z\x{100}]/8DM + Z\x{100} + \x{100} + \x{100}Z + *** Failers + +/[\x{200}-\x{100}]/8 + +/[Ä€-Ä„]/8 + \x{100} + \x{104} + *** Failers + \x{105} + \x{ff} + +/[z-\x{100}]/8D + +/[z\Qa-d]Ä€\E]/8D + \x{100} + Ä€ + +/[\xFF]/D + >\xff< + +/[\xff]/D8 + >\x{ff}< + +/[^\xFF]/D + +/[^\xff]/8D + +/[Ä-Ü]/8 + Ö # Matches without Study + \x{d6} + +/[Ä-Ü]/8S + Ö <-- Same with Study + \x{d6} + +/[\x{c4}-\x{dc}]/8 + Ö # Matches without Study + \x{d6} + +/[\x{c4}-\x{dc}]/8S + Ö <-- Same with Study + \x{d6} + +/[Ã]/8 + +/Ã/8 + +/ÃÃÃxxx/8 + +/ÃÃÃxxx/8?D + +/abc/8 + Ã] + à + ÃÃà + ÃÃÃ\? + +/anything/8 + \xc0\x80 + \xc1\x8f + \xe0\x9f\x80 + \xf0\x8f\x80\x80 + \xf8\x87\x80\x80\x80 + \xfc\x83\x80\x80\x80\x80 + \xfe\x80\x80\x80\x80\x80 + \xff\x80\x80\x80\x80\x80 + \xc3\x8f + \xe0\xaf\x80 + \xe1\x80\x80 + \xf0\x9f\x80\x80 + \xf1\x8f\x80\x80 + \xf8\x88\x80\x80\x80 + \xf9\x87\x80\x80\x80 + \xfc\x84\x80\x80\x80\x80 + \xfd\x83\x80\x80\x80\x80 + +/\x{100}abc(xyz(?1))/8D + +/[^\x{100}]abc(xyz(?1))/8D + +/[ab\x{100}]abc(xyz(?1))/8D + +/(\x{100}(b(?2)c))?/D8 + +/(\x{100}(b(?2)c)){0,2}/D8 + +/(\x{100}(b(?1)c))?/D8 + +/(\x{100}(b(?1)c)){0,2}/D8 + +/\W/8 + A.B + A\x{100}B + +/\w/8 + \x{100}X / End of testinput5 / diff --git a/ext/pcre/pcrelib/testdata/testinput6 b/ext/pcre/pcrelib/testdata/testinput6 index 00748513c65c..01a39477ac45 100644 --- a/ext/pcre/pcrelib/testdata/testinput6 +++ b/ext/pcre/pcrelib/testdata/testinput6 @@ -1,78 +1,517 @@ -/\x{100}/8DM +/^\pC\pL\pM\pN\pP\pS\pZ3 + *** Failers + xyzabc + xyzabc\>2 + +/x\dy\Dz/ + x9yzz + x0y+z + *** Failers + xyz + xxy0z + +/x\sy\Sz/ + x yzz + x y+z + *** Failers + xyz + xxyyz + +/x\wy\Wz/ + xxy+z + *** Failers + xxy0z + x+y+z + +/x.y/ + x+y + x-y + *** Failers + x\ny + +/x.y/s + x+y + x-y + x\ny + +/(a.b(?s)c.d|x.y)p.q/ + a+bc+dp+q + a+bc\ndp+q + x\nyp+q + *** Failers + a\nbc\ndp+q + a+bc\ndp\nq + x\nyp\nq + +/a\d\z/ + ba0 + *** Failers + ba0\n + ba0\ncd + +/a\d\z/m + ba0 + *** Failers + ba0\n + ba0\ncd + +/a\d\Z/ + ba0 + ba0\n + *** Failers + ba0\ncd + +/a\d\Z/m + ba0 + ba0\n + *** Failers + ba0\ncd + +/a\d$/ + ba0 + ba0\n + *** Failers + ba0\ncd + +/a\d$/m + ba0 + ba0\n + ba0\ncd + *** Failers + +/abc/i + abc + aBc + ABC + +/[^a]/ + abcd + +/ab?\w/ + abz + abbz + azz + +/x{0,3}yz/ + ayzq + axyzq + axxyz + axxxyzq + axxxxyzq + *** Failers + ax + axx + +/x{3}yz/ + axxxyzq + axxxxyzq + *** Failers + ax + axx + ayzq + axyzq + axxyz + +/x{2,3}yz/ + axxyz + axxxyzq + axxxxyzq + *** Failers + ax + axx + ayzq + axyzq + +/[^a]+/ + bac + bcdefax + *** Failers + aaaaa + +/[^a]*/ + bac + bcdefax + *** Failers + aaaaa + +/[^a]{3,5}/ + xyz + awxyza + abcdefa + abcdefghijk + *** Failers + axya + axa + aaaaa + +/\d*/ + 1234b567 + xyz + +/\D*/ + a1234b567 + xyz + +/\d+/ + ab1234c56 + *** Failers + xyz + +/\D+/ + ab123c56 + *** Failers + 789 + +/\d?A/ + 045ABC + ABC + *** Failers + XYZ + +/\D?A/ + ABC + BAC + 9ABC + *** Failers + +/a+/ + aaaa + +/^.*xyz/ + xyz + ggggggggxyz + +/^.+xyz/ + abcdxyz + axyz + *** Failers + xyz + +/^.?xyz/ + xyz + cxyz + +/^\d{2,3}X/ + 12X + 123X + *** Failers + X + 1X + 1234X + +/^[abcd]\d/ + a45 + b93 + c99z + d04 + *** Failers + e45 + abcd + abcd1234 + 1234 + +/^[abcd]*\d/ + a45 + b93 + c99z + d04 + abcd1234 + 1234 + *** Failers + e45 + abcd + +/^[abcd]+\d/ + a45 + b93 + c99z + d04 + abcd1234 + *** Failers + 1234 + e45 + abcd + +/^a+X/ + aX + aaX + +/^[abcd]?\d/ + a45 + b93 + c99z + d04 + 1234 + *** Failers + abcd1234 + e45 + +/^[abcd]{2,3}\d/ + ab45 + bcd93 + *** Failers + 1234 + a36 + abcd1234 + ee45 + +/^(abc)*\d/ + abc45 + abcabcabc45 + 42xyz + *** Failers + +/^(abc)+\d/ + abc45 + abcabcabc45 + *** Failers + 42xyz + +/^(abc)?\d/ + abc45 + 42xyz + *** Failers + abcabcabc45 + +/^(abc){2,3}\d/ + abcabc45 + abcabcabc45 + *** Failers + abcabcabcabc45 + abc45 + 42xyz + +/1(abc|xyz)2(?1)3/ + 1abc2abc3456 + 1abc2xyz3456 + +/^(a*\w|ab)=(a*\w|ab)/ + ab=ab + +/^(a*\w|ab)=(?1)/ + ab=ab + +/^([^()]|\((?1)*\))*$/ + abc + a(b)c + a(b(c))d + *** Failers) + a(b(c)d + +/^>abc>([^()]|\((?1)*\))*abc>123abc>1(2)3abc>(1(2)3)a*)\d/ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9876 + *** Failers + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +/< (?: (?(R) \d++ | [^<>]*+) | (?R)) * >/x + <> + + hij> + hij> + def> + + *** Failers + 3 + *** Failers + defabcxyz + +/^abcdef/ + ab\P + abcde\P + abcdef\P + *** Failers + abx\P + +/^a{2,4}\d+z/ + a\P + aa\P + aa2\P + aaa\P + aaa23\P + aaaa12345\P + aa0z\P + aaaa4444444444444z\P + *** Failers + az\P + aaaaa\P + a56\P + +/^abcdef/ + abc\P + def\R + +/(?<=foo)bar/ + xyzfo\P + foob\R\P\>2 + foobar...\R\P\>4 + xyzfo\P + foobar\R\>2 + *** Failers + xyzfo\P + obar\R + +/(ab*(cd|ef))+X/ + adfadadaklhlkalkajhlkjahdfasdfasdfladsfjkj\P\Z + lkjhlkjhlkjhlkjhabbbbbbcdaefabbbbbbbefa\P\B\Z + cdabbbbbbbb\P\R\B\Z + efabbbbbbbbbbbbbbbb\P\R\B\Z + bbbbbbbbbbbbcdXyasdfadf\P\R\B\Z + +/(a|b)/SF>testsavedregex +>>aaabxyzpqrrrabbxyyyypqAzz + >aaaabxyzpqrrrabbxyyyypqAzz + >>>>abcxyzpqrrrabbxyyyypqAzz + *** Failers + abxyzpqrrabbxyyyypqAzz + abxyzpqrrrrabbxyyyypqAzz + abxyzpqrrrabxyyyypqAzz + aaaabcxyzzzzpqrrrabbbxyyyyyypqAzz + aaaabcxyzzzzpqrrrabbbxyyypqAzz + aaabcxyzpqrrrabbxyyyypqqqqqqqAzz + +/^(abc){1,2}zz/ + abczz + abcabczz + *** Failers + zz + abcabcabczz + >>abczz + +/^(b+?|a){1,2}?c/ + bc + bbc + bbbc + bac + bbac + aac + abbbbbbbbbbbc + bbbbbbbbbbbac + *** Failers + aaac + abbbbbbbbbbbac + +/^(b+|a){1,2}c/ + bc + bbc + bbbc + bac + bbac + aac + abbbbbbbbbbbc + bbbbbbbbbbbac + *** Failers + aaac + abbbbbbbbbbbac + +/^(b+|a){1,2}?bc/ + bbc + +/^(b*|ba){1,2}?bc/ + babc + bbabc + bababc + *** Failers + bababbc + babababc + +/^(ba|b*){1,2}?bc/ + babc + bbabc + bababc + *** Failers + bababbc + babababc + +/^\ca\cA\c[\c{\c:/ + \x01\x01\e;z + +/^[ab\]cde]/ + athing + bthing + ]thing + cthing + dthing + ething + *** Failers + fthing + [thing + \\thing + +/^[]cde]/ + ]thing + cthing + dthing + ething + *** Failers + athing + fthing + +/^[^ab\]cde]/ + fthing + [thing + \\thing + *** Failers + athing + bthing + ]thing + cthing + dthing + ething + +/^[^]cde]/ + athing + fthing + *** Failers + ]thing + cthing + dthing + ething + +/^\�/ + � + +/^ÿ/ + ÿ + +/^[0-9]+$/ + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 100 + *** Failers + abc + +/^.*nter/ + enter + inter + uponter + +/^xxx[0-9]+$/ + xxx0 + xxx1234 + *** Failers + xxx + +/^.+[0-9][0-9][0-9]$/ + x123 + xx123 + 123456 + *** Failers + 123 + x1234 + +/^.+?[0-9][0-9][0-9]$/ + x123 + xx123 + 123456 + *** Failers + 123 + x1234 + +/^([^!]+)!(.+)=apquxz\.ixr\.zzz\.ac\.uk$/ + abc!pqr=apquxz.ixr.zzz.ac.uk + *** Failers + !pqr=apquxz.ixr.zzz.ac.uk + abc!=apquxz.ixr.zzz.ac.uk + abc!pqr=apquxz:ixr.zzz.ac.uk + abc!pqr=apquxz.ixr.zzz.ac.ukk + +/:/ + Well, we need a colon: somewhere + *** Fail if we don't + +/([\da-f:]+)$/i + 0abc + abc + fed + E + :: + 5f03:12C0::932e + fed def + Any old stuff + *** Failers + 0zzz + gzzz + fed\x20 + Any old rubbish + +/^.*\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/ + .1.2.3 + A.12.123.0 + *** Failers + .1.2.3333 + 1.2.3 + 1234.2.3 + +/^(\d+)\s+IN\s+SOA\s+(\S+)\s+(\S+)\s*\(\s*$/ + 1 IN SOA non-sp1 non-sp2( + 1 IN SOA non-sp1 non-sp2 ( + *** Failers + 1IN SOA non-sp1 non-sp2( + +/^[a-zA-Z\d][a-zA-Z\d\-]*(\.[a-zA-Z\d][a-zA-z\d\-]*)*\.$/ + a. + Z. + 2. + ab-c.pq-r. + sxk.zzz.ac.uk. + x-.y-. + *** Failers + -abc.peq. + +/^\*\.[a-z]([a-z\-\d]*[a-z\d]+)?(\.[a-z]([a-z\-\d]*[a-z\d]+)?)*$/ + *.a + *.b0-a + *.c3-b.c + *.c-a.b-c + *** Failers + *.0 + *.a- + *.a-b.c- + *.c-a.0-c + +/^(?=ab(de))(abd)(e)/ + abde + +/^(?!(ab)de|x)(abd)(f)/ + abdf + +/^(?=(ab(cd)))(ab)/ + abcd + +/^[\da-f](\.[\da-f])*$/i + a.b.c.d + A.B.C.D + a.b.c.1.2.3.C + +/^\".*\"\s*(;.*)?$/ + \"1234\" + \"abcd\" ; + \"\" ; rhubarb + *** Failers + \"1234\" : things + +/^$/ + \ + *** Failers + +/ ^ a (?# begins with a) b\sc (?# then b c) $ (?# then end)/x + ab c + *** Failers + abc + ab cde + +/(?x) ^ a (?# begins with a) b\sc (?# then b c) $ (?# then end)/ + ab c + *** Failers + abc + ab cde + +/^ a\ b[c ]d $/x + a bcd + a b d + *** Failers + abcd + ab d + +/^(a(b(c)))(d(e(f)))(h(i(j)))(k(l(m)))$/ + abcdefhijklm + +/^(?:a(b(c)))(?:d(e(f)))(?:h(i(j)))(?:k(l(m)))$/ + abcdefhijklm + +/^[\w][\W][\s][\S][\d][\D][\b][\n][\c]][\022]/ + a+ Z0+\x08\n\x1d\x12 + +/^[.^$|()*+?{,}]+/ + .^\$(*+)|{?,?} + +/^a*\w/ + z + az + aaaz + a + aa + aaaa + a+ + aa+ + +/^a*?\w/ + z + az + aaaz + a + aa + aaaa + a+ + aa+ + +/^a+\w/ + az + aaaz + aa + aaaa + aa+ + +/^a+?\w/ + az + aaaz + aa + aaaa + aa+ + +/^\d{8}\w{2,}/ + 1234567890 + 12345678ab + 12345678__ + *** Failers + 1234567 + +/^[aeiou\d]{4,5}$/ + uoie + 1234 + 12345 + aaaaa + *** Failers + 123456 + +/^[aeiou\d]{4,5}?/ + uoie + 1234 + 12345 + aaaaa + 123456 + +/^From +([^ ]+) +[a-zA-Z][a-zA-Z][a-zA-Z] +[a-zA-Z][a-zA-Z][a-zA-Z] +[0-9]?[0-9] +[0-9][0-9]:[0-9][0-9]/ + From abcd Mon Sep 01 12:33:02 1997 + +/^From\s+\S+\s+([a-zA-Z]{3}\s+){2}\d{1,2}\s+\d\d:\d\d/ + From abcd Mon Sep 01 12:33:02 1997 + From abcd Mon Sep 1 12:33:02 1997 + *** Failers + From abcd Sep 01 12:33:02 1997 + +/^12.34/s + 12\n34 + 12\r34 + +/\w+(?=\t)/ + the quick brown\t fox + +/foo(?!bar)(.*)/ + foobar is foolish see? + +/(?:(?!foo)...|^.{0,2})bar(.*)/ + foobar crowbar etc + barrel + 2barrel + A barrel + +/^(\D*)(?=\d)(?!123)/ + abc456 + *** Failers + abc123 + +/^1234(?# test newlines + inside)/ + 1234 + +/^1234 #comment in extended re + /x + 1234 + +/#rhubarb + abcd/x + abcd + +/^abcd#rhubarb/x + abcd + +/(?!^)abc/ + the abc + *** Failers + abc + +/(?=^)abc/ + abc + *** Failers + the abc + +/^[ab]{1,3}(ab*|b)/ + aabbbbb + +/^[ab]{1,3}?(ab*|b)/ + aabbbbb + +/^[ab]{1,3}?(ab*?|b)/ + aabbbbb + +/^[ab]{1,3}(ab*?|b)/ + aabbbbb + +/ (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* # optional leading comment +(?: (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +" (?: # opening quote... +[^\\\x80-\xff\n\015"] # Anything except backslash and quote +| # or +\\ [^\x80-\xff] # Escaped something (something != CR) +)* " # closing quote +) # initial word +(?: (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* \. (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +" (?: # opening quote... +[^\\\x80-\xff\n\015"] # Anything except backslash and quote +| # or +\\ [^\x80-\xff] # Escaped something (something != CR) +)* " # closing quote +) )* # further okay, if led by a period +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* @ (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| \[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) # initial subdomain +(?: # +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* \. # if led by a period... +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| \[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) # ...further okay +)* +# address +| # or +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +" (?: # opening quote... +[^\\\x80-\xff\n\015"] # Anything except backslash and quote +| # or +\\ [^\x80-\xff] # Escaped something (something != CR) +)* " # closing quote +) # one word, optionally followed by.... +(?: +[^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] | # atom and space parts, or... +\( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) | # comments, or... + +" (?: # opening quote... +[^\\\x80-\xff\n\015"] # Anything except backslash and quote +| # or +\\ [^\x80-\xff] # Escaped something (something != CR) +)* " # closing quote +# quoted strings +)* +< (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* # leading < +(?: @ (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| \[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) # initial subdomain +(?: # +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* \. # if led by a period... +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| \[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) # ...further okay +)* + +(?: (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* , (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* @ (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| \[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) # initial subdomain +(?: # +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* \. # if led by a period... +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| \[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) # ...further okay +)* +)* # further okay, if led by comma +: # closing colon +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* )? # optional route +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +" (?: # opening quote... +[^\\\x80-\xff\n\015"] # Anything except backslash and quote +| # or +\\ [^\x80-\xff] # Escaped something (something != CR) +)* " # closing quote +) # initial word +(?: (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* \. (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +" (?: # opening quote... +[^\\\x80-\xff\n\015"] # Anything except backslash and quote +| # or +\\ [^\x80-\xff] # Escaped something (something != CR) +)* " # closing quote +) )* # further okay, if led by a period +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* @ (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| \[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) # initial subdomain +(?: # +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* \. # if led by a period... +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| \[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) # ...further okay +)* +# address spec +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* > # trailing > +# name and address +) (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* # optional trailing comment +/x + Alan Other + + user\@dom.ain + \"A. Other\" (a comment) + A. Other (a comment) + \"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\"\@x400-re.lay + A missing angle @,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +" # " +[^\\\x80-\xff\n\015"] * # normal +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* +" # " +# Quoted string +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +\. +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +" # " +[^\\\x80-\xff\n\015"] * # normal +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* +" # " +# Quoted string +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +\[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\. +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +\[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address +| # or +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +" # " +[^\\\x80-\xff\n\015"] * # normal +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* +" # " +# Quoted string +) +# leading word +[^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] * # "normal" atoms and or spaces +(?: +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +| +" # " +[^\\\x80-\xff\n\015"] * # normal +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* +" # " +) # "special" comment or quoted string +[^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] * # more "normal" +)* +< +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# < +(?: +@ +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +\[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\. +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +\[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +(?: , +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +@ +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +\[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\. +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +\[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +)* # additional domains +: +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)? # optional route +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +" # " +[^\\\x80-\xff\n\015"] * # normal +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* +" # " +# Quoted string +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +\. +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +" # " +[^\\\x80-\xff\n\015"] * # normal +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* +" # " +# Quoted string +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +\[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\. +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +\[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address spec +> # > +# name and address +) +/x + Alan Other + + user\@dom.ain + \"A. Other\" (a comment) + A. Other (a comment) + \"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\"\@x400-re.lay + A missing angle ]{0,})>]{0,})>([\d]{0,}\.)(.*)((
([\w\W\s\d][^<>]{0,})|[\s]{0,}))<\/a><\/TD>]{0,})>([\w\W\s\d][^<>]{0,})<\/TD>]{0,})>([\w\W\s\d][^<>]{0,})<\/TD><\/TR>/is + 43.
Word Processor
(N-1286)
Lega lstaff.comCA - Statewide + +/a[^a]b/ + acb + a\nb + +/a.b/ + acb + *** Failers + a\nb + +/a[^a]b/s + acb + a\nb + +/a.b/s + acb + a\nb + +/^(b+?|a){1,2}?c/ + bac + bbac + bbbac + bbbbac + bbbbbac + +/^(b+|a){1,2}?c/ + bac + bbac + bbbac + bbbbac + bbbbbac + +/(?!\A)x/m + x\nb\n + a\bx\n + +/\x0{ab}/ + \0{ab} + +/(A|B)*?CD/ + CD + +/(A|B)*CD/ + CD + +/(?.*/)foo" + /this/is/a/very/long/line/in/deed/with/very/many/slashes/in/it/you/see/ + +"(?>.*/)foo" + /this/is/a/very/long/line/in/deed/with/very/many/slashes/in/and/foo + +/(?>(\.\d\d[1-9]?))\d+/ + 1.230003938 + 1.875000282 + *** Failers + 1.235 + +/^((?>\w+)|(?>\s+))*$/ + now is the time for all good men to come to the aid of the party + *** Failers + this is not a line with only words and spaces! + +/(\d+)(\w)/ + 12345a + 12345+ + +/((?>\d+))(\w)/ + 12345a + *** Failers + 12345+ + +/(?>a+)b/ + aaab + +/((?>a+)b)/ + aaab + +/(?>(a+))b/ + aaab + +/(?>b)+/ + aaabbbccc + +/(?>a+|b+|c+)*c/ + aaabbbbccccd + +/(a+|b+|c+)*c/ + aaabbbbccccd + +/((?>[^()]+)|\([^()]*\))+/ + ((abc(ade)ufh()()x + +/\(((?>[^()]+)|\([^()]+\))+\)/ + (abc) + (abc(def)xyz) + *** Failers + ((()aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +/a(?-i)b/i + ab + Ab + *** Failers + aB + AB + +/(a (?x)b c)d e/ + a bcd e + *** Failers + a b cd e + abcd e + a bcde + +/(a b(?x)c d (?-x)e f)/ + a bcde f + *** Failers + abcdef + +/(a(?i)b)c/ + abc + aBc + *** Failers + abC + aBC + Abc + ABc + ABC + AbC + +/a(?i:b)c/ + abc + aBc + *** Failers + ABC + abC + aBC + +/a(?i:b)*c/ + aBc + aBBc + *** Failers + aBC + aBBC + +/a(?=b(?i)c)\w\wd/ + abcd + abCd + *** Failers + aBCd + abcD + +/(?s-i:more.*than).*million/i + more than million + more than MILLION + more \n than Million + *** Failers + MORE THAN MILLION + more \n than \n million + +/(?:(?s-i)more.*than).*million/i + more than million + more than MILLION + more \n than Million + *** Failers + MORE THAN MILLION + more \n than \n million + +/(?>a(?i)b+)+c/ + abc + aBbc + aBBc + *** Failers + Abc + abAb + abbC + +/(?=a(?i)b)\w\wc/ + abc + aBc + *** Failers + Ab + abC + aBC + +/(?<=a(?i)b)(\w\w)c/ + abxxc + aBxxc + *** Failers + Abxxc + ABxxc + abxxC + +/^(?(?=abc)\w{3}:|\d\d)$/ + abc: + 12 + *** Failers + 123 + xyz + +/^(?(?!abc)\d\d|\w{3}:)$/ + abc: + 12 + *** Failers + 123 + xyz + +/(?(?<=foo)bar|cat)/ + foobar + cat + fcat + focat + *** Failers + foocat + +/(?(?a*)*/ + a + aa + aaaa + +/(abc|)+/ + abc + abcabc + abcabcabc + xyz + +/([a]*)*/ + a + aaaaa + +/([ab]*)*/ + a + b + ababab + aaaabcde + bbbb + +/([^a]*)*/ + b + bbbb + aaa + +/([^ab]*)*/ + cccc + abab + +/([a]*?)*/ + a + aaaa + +/([ab]*?)*/ + a + b + abab + baba + +/([^a]*?)*/ + b + bbbb + aaa + +/([^ab]*?)*/ + c + cccc + baba + +/(?>a*)*/ + a + aaabcde + +/((?>a*))*/ + aaaaa + aabbaa + +/((?>a*?))*/ + aaaaa + aabbaa + +/(?(?=[^a-z]+[a-z]) \d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} ) /x + 12-sep-98 + 12-09-98 + *** Failers + sep-12-98 + +/(?i:saturday|sunday)/ + saturday + sunday + Saturday + Sunday + SATURDAY + SUNDAY + SunDay + +/(a(?i)bc|BB)x/ + abcx + aBCx + bbx + BBx + *** Failers + abcX + aBCX + bbX + BBX + +/^([ab](?i)[cd]|[ef])/ + ac + aC + bD + elephant + Europe + frog + France + *** Failers + Africa + +/^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)/ + ab + aBd + xy + xY + zebra + Zambesi + *** Failers + aCD + XY + +/(?<=foo\n)^bar/m + foo\nbar + *** Failers + bar + baz\nbar + +/(?<=(?]&/ + <&OUT + +/(?:(f)(o)(o)|(b)(a)(r))*/ + foobar + +/(?<=a)b/ + ab + *** Failers + cb + b + +/(?a+)ab/ + +/(?>a+)b/ + aaab + +/([[:]+)/ + a:[b]: + +/([[=]+)/ + a=[b]= + +/([[.]+)/ + a.[b]. + +/((?>a+)b)/ + aaab + +/(?>(a+))b/ + aaab + +/((?>[^()]+)|\([^()]*\))+/ + ((abc(ade)ufh()()x + +/a\Z/ + *** Failers + aaab + a\nb\n + +/b\Z/ + a\nb\n + +/b\z/ + +/b\Z/ + a\nb + +/b\z/ + a\nb + *** Failers + +/(?>.*)(?<=(abcd|wxyz))/ + alphabetabcd + endingwxyz + *** Failers + a rather long string that doesn't end with one of them + +/word (?>(?:(?!otherword)[a-zA-Z0-9]+ ){0,30})otherword/ + word cat dog elephant mussel cow horse canary baboon snake shark otherword + word cat dog elephant mussel cow horse canary baboon snake shark + +/word (?>[a-zA-Z0-9]+ ){0,30}otherword/ + word cat dog elephant mussel cow horse canary baboon snake shark the quick brown fox and the lazy dog and several other words getting close to thirty by now I hope + +/(?<=\d{3}(?!999))foo/ + 999foo + 123999foo + *** Failers + 123abcfoo + +/(?<=(?!...999)\d{3})foo/ + 999foo + 123999foo + *** Failers + 123abcfoo + +/(?<=\d{3}(?!999)...)foo/ + 123abcfoo + 123456foo + *** Failers + 123999foo + +/(?<=\d{3}...)(?Z)+|A)*/ + ZABCDEFG + +/((?>)+|A)*/ + ZABCDEFG + +/a*/g + abbab + +/^[a-\d]/ + abcde + -things + 0digit + *** Failers + bcdef + +/^[\d-a]/ + abcde + -things + 0digit + *** Failers + bcdef + +/[[:space:]]+/ + > \x09\x0a\x0c\x0d\x0b< + +/[[:blank:]]+/ + > \x09\x0a\x0c\x0d\x0b< + +/[\s]+/ + > \x09\x0a\x0c\x0d\x0b< + +/\s+/ + > \x09\x0a\x0c\x0d\x0b< + +/a b/x + ab + +/(?!\A)x/m + a\nxb\n + +/(?!^)x/m + a\nxb\n + +/abc\Qabc\Eabc/ + abcabcabc + +/abc\Q(*+|\Eabc/ + abc(*+|abc + +/ abc\Q abc\Eabc/x + abc abcabc + *** Failers + abcabcabc + +/abc#comment + \Q#not comment + literal\E/x + abc#not comment\n literal + +/abc#comment + \Q#not comment + literal/x + abc#not comment\n literal + +/abc#comment + \Q#not comment + literal\E #more comment + /x + abc#not comment\n literal + +/abc#comment + \Q#not comment + literal\E #more comment/x + abc#not comment\n literal + +/\Qabc\$xyz\E/ + abc\\\$xyz + +/\Qabc\E\$\Qxyz\E/ + abc\$xyz + +/\Gabc/ + abc + *** Failers + xyzabc + +/\Gabc./g + abc1abc2xyzabc3 + +/abc./g + abc1abc2xyzabc3 + +/a(?x: b c )d/ + XabcdY + *** Failers + Xa b c d Y + +/((?x)x y z | a b c)/ + XabcY + AxyzB + +/(?i)AB(?-i)C/ + XabCY + *** Failers + XabcY + +/((?i)AB(?-i)C|D)E/ + abCE + DE + *** Failers + abcE + abCe + dE + De + +/[z\Qa-d]\E]/ + z + a + - + d + ] + *** Failers + b + +/[\z\C]/ + z + C + +/\M/ + M + +/(a+)*b/ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +/(?i)reg(?:ul(?:[aä]|ae)r|ex)/ + REGular + regulaer + Regex + regulär + +/Åæåä[à-ÿÀ-ß]+/ + Åæåäà + Åæåäÿ + ÅæåäÀ + Åæåäß + +/(?<=Z)X./ + \x84XAZXB + +/^(?(2)a|(1)(2))+$/ + 123a + +/(?<=a|bbbb)c/ + ac + bbbbc + +/abc/>testsavedregex +testsavedregex +testsavedregex +testsavedregex +\S/8 + > >X Y + > >\x{100} Y + +/\d/8 + \x{100}3 + +/\s/8 + \x{100} X + +/\D+/8 + 12abcd34 + *** Failers + 1234 + +/\D{2,3}/8 + 12abcd34 + 12ab34 + *** Failers + 1234 + 12a34 + +/\D{2,3}?/8 + 12abcd34 + 12ab34 + *** Failers + 1234 + 12a34 + +/\d+/8 + 12abcd34 + *** Failers + +/\d{2,3}/8 + 12abcd34 + 1234abcd + *** Failers + 1.4 + +/\d{2,3}?/8 + 12abcd34 + 1234abcd + *** Failers + 1.4 + +/\S+/8 + 12abcd34 + *** Failers + \ \ + +/\S{2,3}/8 + 12abcd34 + 1234abcd + *** Failers + \ \ + +/\S{2,3}?/8 + 12abcd34 + 1234abcd + *** Failers + \ \ + +/>\s+ <34 + *** Failers + +/>\s{2,3} \s{2,3}? \xff< + +/[\xff]/8 + >\x{ff}< + +/[^\xFF]/ + XYZ + +/[^\xff]/8 + XYZ + \x{123} + +/^[ac]*b/8 + xb + +/^[ac\x{100}]*b/8 + xb + +/^[^x]*b/8i + xb + +/^[^x]*b/8 + xb + +/^\d*b/8 + xb + +/(|a)/g8 + catac + a\x{256}a + +/^\x{85}$/8i + \x{85} + +/ End of testinput 8 / diff --git a/ext/pcre/pcrelib/testdata/testinput9 b/ext/pcre/pcrelib/testdata/testinput9 new file mode 100644 index 000000000000..f18dd12c4a67 --- /dev/null +++ b/ext/pcre/pcrelib/testdata/testinput9 @@ -0,0 +1,599 @@ +/\pL\P{Nd}/8 + AB + *** Failers + A0 + 00 + +/\X./8 + AB + A\x{300}BC + A\x{300}\x{301}\x{302}BC + *** Failers + \x{300} + +/\X\X/8 + ABC + A\x{300}B\x{300}\x{301}C + A\x{300}\x{301}\x{302}BC + *** Failers + \x{300} + +/^\pL+/8 + abcd + a + *** Failers + +/^\PL+/8 + 1234 + = + *** Failers + abcd + +/^\X+/8 + abcdA\x{300}\x{301}\x{302} + A\x{300}\x{301}\x{302} + A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302} + a + *** Failers + \x{300}\x{301}\x{302} + +/\X?abc/8 + abc + A\x{300}abc + A\x{300}\x{301}\x{302}A\x{300}A\x{300}A\x{300}abcxyz + \x{300}abc + *** Failers + +/^\X?abc/8 + abc + A\x{300}abc + *** Failers + A\x{300}\x{301}\x{302}A\x{300}A\x{300}A\x{300}abcxyz + \x{300}abc + +/\X*abc/8 + abc + A\x{300}abc + A\x{300}\x{301}\x{302}A\x{300}A\x{300}A\x{300}abcxyz + \x{300}abc + *** Failers + +/^\X*abc/8 + abc + A\x{300}abc + A\x{300}\x{301}\x{302}A\x{300}A\x{300}A\x{300}abcxyz + *** Failers + \x{300}abc + +/^\pL?=./8 + A=b + =c + *** Failers + 1=2 + AAAA=b + +/^\pL*=./8 + AAAA=b + =c + *** Failers + 1=2 + +/^\X{2,3}X/8 + A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}X + A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}X + *** Failers + X + A\x{300}\x{301}\x{302}X + A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}X + +/^\pC\pL\pM\pN\pP\pS\pZ ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y [ \ ] ^ _ ` a b c d @@ -185,7 +191,7 @@ Capturing subpattern count = 1 No options No first char No need char -Starting character set: \x09 \x0a \x0c \x0d \x20 a b +Starting byte set: \x09 \x0a \x0c \x0d \x20 a b /(ab\2)/ Failed: reference to non-existent subpattern at offset 6 @@ -297,7 +303,7 @@ Need char = 'x' Capturing subpattern count = 0 Options: anchored No first char -Need char = 'x' +No need char the quick brown fox 0: the quick brown fox *** Failers @@ -320,6 +326,7 @@ No need char /.*((abc)$|(def))/ Capturing subpattern count = 3 +Partial matching not supported No options First char at start or follows \n No need char @@ -396,6 +403,7 @@ Failed: missing terminating ] for character class at offset 4 /[^aeiou ]{3,}/ Capturing subpattern count = 0 +Partial matching not supported No options No first char No need char @@ -404,6 +412,7 @@ No need char /<.*>/ Capturing subpattern count = 0 +Partial matching not supported No options First char = '<' Need char = '>' @@ -412,6 +421,7 @@ Need char = '>' /<.*?>/ Capturing subpattern count = 0 +Partial matching not supported No options First char = '<' Need char = '>' @@ -420,6 +430,7 @@ Need char = '>' /<.*>/U Capturing subpattern count = 0 +Partial matching not supported Options: ungreedy First char = '<' Need char = '>' @@ -428,6 +439,7 @@ Need char = '>' /(?U)<.*>/ Capturing subpattern count = 0 +Partial matching not supported Options: ungreedy First char = '<' Need char = '>' @@ -436,6 +448,7 @@ Need char = '>' /<.*?>/U Capturing subpattern count = 0 +Partial matching not supported Options: ungreedy First char = '<' Need char = '>' @@ -444,6 +457,7 @@ Need char = '>' /={3,}/U Capturing subpattern count = 0 +Partial matching not supported Options: ungreedy First char = '=' Need char = '=' @@ -452,6 +466,7 @@ Need char = '=' /(?U)={3,}?/ Capturing subpattern count = 0 +Partial matching not supported Options: ungreedy First char = '=' Need char = '=' @@ -499,7 +514,7 @@ No need char Capturing subpattern count = 0 Options: anchored caseless No first char -Need char = '4' +No need char /(^b|(?i)^d)/ Capturing subpattern count = 1 @@ -510,6 +525,7 @@ No need char /(?s).*/ Capturing subpattern count = 0 +Partial matching not supported Options: anchored dotall No first char No need char @@ -519,21 +535,21 @@ Capturing subpattern count = 0 No options No first char No need char -Starting character set: a b c d +Starting byte set: a b c d /(?i)[abcd]/S Capturing subpattern count = 0 Options: caseless No first char No need char -Starting character set: A B C D a b c d +Starting byte set: A B C D a b c d /(?m)[xy]|(b|c)/S Capturing subpattern count = 1 Options: multiline No first char No need char -Starting character set: b c x y +Starting byte set: b c x y /(^a|^b)/m Capturing subpattern count = 1 @@ -568,6 +584,7 @@ Failed: unrecognized character after (?< at offset 5 /((?s)blah)\s+\1/ Capturing subpattern count = 1 Max back reference = 1 +Partial matching not supported No options First char = 'b' Need char = 'h' @@ -575,6 +592,7 @@ Need char = 'h' /((?i)blah)\s+\1/ Capturing subpattern count = 1 Max back reference = 1 +Partial matching not supported No options Case state changes First char = 'b' (caseless) @@ -582,14 +600,14 @@ Need char = 'h' (caseless) /((?i)b)/DS ------------------------------------------------------------------ - 0 16 Bra 0 - 3 8 Bra 1 + 0 15 Bra 0 + 3 7 Bra 1 6 01 Opt - 8 1 b - 11 8 Ket - 14 00 Opt - 16 16 Ket - 19 End + 8 NC b + 10 7 Ket + 13 00 Opt + 15 15 Ket + 18 End ------------------------------------------------------------------ Capturing subpattern count = 1 No options @@ -600,11 +618,12 @@ Study returned NULL /(a*b|(?i:c*(?-i)d))/S Capturing subpattern count = 1 +Partial matching not supported No options Case state changes No first char No need char -Starting character set: C a b c d +Starting byte set: C a b c d /a$/ Capturing subpattern count = 0 @@ -642,7 +661,7 @@ No match Capturing subpattern count = 0 Options: anchored multiline No first char -Need char = 'c' +No need char /^abc/m Capturing subpattern count = 0 @@ -652,9 +671,10 @@ Need char = 'c' /^((a+)(?U)([ab]+)(?-U)([bc]+)(\w*))/ Capturing subpattern count = 5 +Partial matching not supported Options: anchored No first char -Need char = 'a' +No need char aaaaabbbbbcccccdef 0: aaaaabbbbbcccccdef 1: aaaaabbbbbcccccdef @@ -668,27 +688,53 @@ Capturing subpattern count = 0 No options No first char No need char -Starting character set: a b +Starting byte set: a b /(?^abc)/m Capturing subpattern count = 0 @@ -744,6 +790,7 @@ No need char /(?>.*)(?<=(abcd)|(xyz))/ Capturing subpattern count = 2 +Partial matching not supported No options First char at start or follows \n No need char @@ -825,7 +872,7 @@ Capturing subpattern count = 1 Max back reference = 1 Options: anchored No first char -Need char = 'a' +No need char aaaaaa 0: aaaaaa 1: aa @@ -966,6 +1013,7 @@ copy substring 5 failed -7 /(.{20})/ Capturing subpattern count = 1 +Partial matching not supported No options No first char No need char @@ -983,6 +1031,7 @@ copy substring 1 failed -6 /(.{15})/ Capturing subpattern count = 1 +Partial matching not supported No options No first char No need char @@ -997,6 +1046,7 @@ No need char /(.{16})/ Capturing subpattern count = 1 +Partial matching not supported No options No first char No need char @@ -1015,7 +1065,7 @@ copy substring 1 failed -6 Capturing subpattern count = 3 Options: anchored No first char -Need char = 'f' +No need char adef\G1\G2\G3\G4\L 0: adef 1: a @@ -1053,7 +1103,7 @@ get substring 4 failed -7 Capturing subpattern count = 0 Options: anchored No first char -Need char = 'f' +No need char abc\00def\L\C0 0: abc\x00def 0C abc (7) @@ -1062,109 +1112,116 @@ Need char = 'f' /word ((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+ )?)?)?)?)?)?)?)?)?otherword/M -Memory allocation (code space): 428 +Memory allocation (code space): 432 Capturing subpattern count = 8 +Partial matching not supported No options First char = 'w' Need char = 'd' /.*X/D ------------------------------------------------------------------ - 0 8 Bra 0 + 0 7 Bra 0 3 Any* - 5 1 X - 8 8 Ket - 11 End + 5 X + 7 7 Ket + 10 End ------------------------------------------------------------------ Capturing subpattern count = 0 +Partial matching not supported No options First char at start or follows \n Need char = 'X' /.*X/Ds ------------------------------------------------------------------ - 0 8 Bra 0 + 0 7 Bra 0 3 Any* - 5 1 X - 8 8 Ket - 11 End + 5 X + 7 7 Ket + 10 End ------------------------------------------------------------------ Capturing subpattern count = 0 +Partial matching not supported Options: anchored dotall No first char Need char = 'X' /(.*X|^B)/D ------------------------------------------------------------------ - 0 21 Bra 0 - 3 8 Bra 1 + 0 19 Bra 0 + 3 7 Bra 1 6 Any* - 8 1 X - 11 7 Alt - 14 ^ - 15 1 B - 18 15 Ket - 21 21 Ket - 24 End + 8 X + 10 6 Alt + 13 ^ + 14 B + 16 13 Ket + 19 19 Ket + 22 End ------------------------------------------------------------------ Capturing subpattern count = 1 +Partial matching not supported No options First char at start or follows \n No need char /(.*X|^B)/Ds ------------------------------------------------------------------ - 0 21 Bra 0 - 3 8 Bra 1 + 0 19 Bra 0 + 3 7 Bra 1 6 Any* - 8 1 X - 11 7 Alt - 14 ^ - 15 1 B - 18 15 Ket - 21 21 Ket - 24 End + 8 X + 10 6 Alt + 13 ^ + 14 B + 16 13 Ket + 19 19 Ket + 22 End ------------------------------------------------------------------ Capturing subpattern count = 1 +Partial matching not supported Options: anchored dotall No first char No need char /(?s)(.*X|^B)/D ------------------------------------------------------------------ - 0 21 Bra 0 - 3 8 Bra 1 + 0 19 Bra 0 + 3 7 Bra 1 6 Any* - 8 1 X - 11 7 Alt - 14 ^ - 15 1 B - 18 15 Ket - 21 21 Ket - 24 End + 8 X + 10 6 Alt + 13 ^ + 14 B + 16 13 Ket + 19 19 Ket + 22 End ------------------------------------------------------------------ Capturing subpattern count = 1 +Partial matching not supported Options: anchored dotall No first char No need char /(?s:.*X|^B)/D ------------------------------------------------------------------ - 0 27 Bra 0 - 3 10 Bra 0 + 0 25 Bra 0 + 3 9 Bra 0 6 04 Opt 8 Any* - 10 1 X - 13 9 Alt - 16 04 Opt - 18 ^ - 19 1 B - 22 19 Ket - 25 00 Opt - 27 27 Ket - 30 End + 10 X + 12 8 Alt + 15 04 Opt + 17 ^ + 18 B + 20 17 Ket + 23 00 Opt + 25 25 Ket + 28 End ------------------------------------------------------------------ Capturing subpattern count = 0 +Partial matching not supported No options First char at start or follows \n No need char @@ -1242,13 +1299,14 @@ Need char = 's' Capturing subpattern count = 0 Options: anchored No first char -Need char = 's' +No need char ississippi 0: iss 0+ issippi /.*iss/g+ Capturing subpattern count = 0 +Partial matching not supported No options First char at start or follows \n Need char = 's' @@ -1292,7 +1350,7 @@ Need char = 'i' Capturing subpattern count = 0 Options: anchored No first char -Need char = 's' +No need char Mississippi 0: Mis 0+ sissippi @@ -1301,7 +1359,7 @@ Need char = 's' Capturing subpattern count = 0 Options: anchored No first char -Need char = 10 +No need char ab\nab\ncd 0: ab\x0a 0+ ab\x0acd @@ -1349,36 +1407,42 @@ Need char = 'c' /a*/ Capturing subpattern count = 0 +Partial matching not supported No options No first char No need char /a+/ Capturing subpattern count = 0 +Partial matching not supported No options First char = 'a' No need char /(baa|a+)/ Capturing subpattern count = 1 +Partial matching not supported No options No first char Need char = 'a' /a{0,3}/ Capturing subpattern count = 0 +Partial matching not supported No options No first char No need char /baa{3,}/ Capturing subpattern count = 0 +Partial matching not supported No options First char = 'b' Need char = 'a' /"([^\\"]+|\\.)*"/ Capturing subpattern count = 1 +Partial matching not supported No options First char = '"' Need char = '"' @@ -1433,60 +1497,70 @@ Need char = 'b' /abc*/ Capturing subpattern count = 0 +Partial matching not supported No options First char = 'a' Need char = 'b' /ab.c*/ Capturing subpattern count = 0 +Partial matching not supported No options First char = 'a' Need char = 'b' /a.c*/ Capturing subpattern count = 0 +Partial matching not supported No options First char = 'a' No need char /.c*/ Capturing subpattern count = 0 +Partial matching not supported No options No first char No need char /ac*/ Capturing subpattern count = 0 +Partial matching not supported No options First char = 'a' No need char /(a.c*|b.c*)/ Capturing subpattern count = 1 +Partial matching not supported No options No first char No need char /a.c*|aba/ Capturing subpattern count = 0 +Partial matching not supported No options First char = 'a' No need char /.+a/ Capturing subpattern count = 0 +Partial matching not supported No options No first char Need char = 'a' /(?=abcda)a.*/ Capturing subpattern count = 0 +Partial matching not supported No options First char = 'a' Need char = 'a' /(?=a)a.*/ Capturing subpattern count = 0 +Partial matching not supported No options First char = 'a' No need char @@ -1499,12 +1573,14 @@ No need char /a\d*/ Capturing subpattern count = 0 +Partial matching not supported No options First char = 'a' No need char /ab\d*/ Capturing subpattern count = 0 +Partial matching not supported No options First char = 'a' Need char = 'b' @@ -1523,6 +1599,7 @@ Need char = 'd' /ab\d+/ Capturing subpattern count = 0 +Partial matching not supported No options First char = 'a' Need char = 'b' @@ -1640,6 +1717,7 @@ Study returned NULL \) # Closing ) /x Capturing subpattern count = 0 +Partial matching not supported Options: extended First char = '(' Need char = ')' @@ -1668,6 +1746,7 @@ No match /\( ( (?>[^()]+) | (?R) )* \) /xg Capturing subpattern count = 1 +Partial matching not supported Options: extended First char = '(' Need char = ')' @@ -1682,6 +1761,7 @@ Need char = ')' /\( (?: (?>[^()]+) | (?R) ) \) /x Capturing subpattern count = 0 +Partial matching not supported Options: extended First char = '(' Need char = ')' @@ -1700,6 +1780,7 @@ No match /\( (?: (?>[^()]+) | (?R) )? \) /x Capturing subpattern count = 0 +Partial matching not supported Options: extended First char = '(' Need char = ')' @@ -1710,6 +1791,7 @@ Need char = ')' /\( ( (?>[^()]+) | (?R) )* \) /x Capturing subpattern count = 1 +Partial matching not supported Options: extended First char = '(' Need char = ')' @@ -1719,6 +1801,7 @@ Need char = ')' /\( ( ( (?>[^()]+) | (?R) )* ) \) /x Capturing subpattern count = 2 +Partial matching not supported Options: extended First char = '(' Need char = ')' @@ -1729,6 +1812,7 @@ Need char = ')' /\( (123)? ( ( (?>[^()]+) | (?R) )* ) \) /x Capturing subpattern count = 3 +Partial matching not supported Options: extended First char = '(' Need char = ')' @@ -1745,6 +1829,7 @@ Need char = ')' /\( ( (123)? ( (?>[^()]+) | (?R) )* ) \) /x Capturing subpattern count = 3 +Partial matching not supported Options: extended First char = '(' Need char = ')' @@ -1761,6 +1846,7 @@ Need char = ')' /\( (((((((((( ( (?>[^()]+) | (?R) )* )))))))))) \) /x Capturing subpattern count = 11 +Partial matching not supported Options: extended First char = '(' Need char = ')' @@ -1780,6 +1866,7 @@ Need char = ')' /\( ( ( (?>[^()<>]+) | ((?>[^()]+)) | (?R) )* ) \) /x Capturing subpattern count = 3 +Partial matching not supported Options: extended First char = '(' Need char = ')' @@ -1791,6 +1878,7 @@ Need char = ')' /\( ( ( (?>[^()]+) | ((?R)) )* ) \) /x Capturing subpattern count = 3 +Partial matching not supported Options: extended First char = '(' Need char = ')' @@ -1818,6 +1906,19 @@ Options: anchored No first char No need char +/^[[:^alnum:]]/D +------------------------------------------------------------------ + 0 37 Bra 0 + 3 ^ + 4 [\x00-/:-@[-`{-\xff] + 37 37 Ket + 40 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Options: anchored +No first char +No need char + /^[[:alpha:]]/D ------------------------------------------------------------------ 0 37 Bra 0 @@ -1830,6 +1931,19 @@ Capturing subpattern count = 0 Options: anchored No first char No need char + +/^[[:^alpha:]]/D +------------------------------------------------------------------ + 0 37 Bra 0 + 3 ^ + 4 [\x00-@[-`{-\xff] + 37 37 Ket + 40 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Options: anchored +No first char +No need char /^[[:ascii:]]/D ------------------------------------------------------------------ @@ -1844,6 +1958,19 @@ Options: anchored No first char No need char +/^[[:^ascii:]]/D +------------------------------------------------------------------ + 0 37 Bra 0 + 3 ^ + 4 [\x80-\xff] + 37 37 Ket + 40 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Options: anchored +No first char +No need char + /^[[:blank:]]/D ------------------------------------------------------------------ 0 37 Bra 0 @@ -2004,7 +2131,7 @@ No need char ------------------------------------------------------------------ 0 37 Bra 0 3 ^ - 4 [\x00-/1-2:-\xff] + 4 [\x00-/12:-\xff] 37 37 Ket 40 End ------------------------------------------------------------------ @@ -2029,7 +2156,7 @@ No need char /[01[:alpha:]%]/D ------------------------------------------------------------------ 0 36 Bra 0 - 3 [%0-1A-Za-z] + 3 [%01A-Za-z] 36 36 Ket 39 End ------------------------------------------------------------------ @@ -2102,6 +2229,7 @@ Need char = 'd' /(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\w+)\s+(\270)/ Capturing subpattern count = 271 Max back reference = 270 +Partial matching not supported No options No first char No need char @@ -2408,7 +2536,7 @@ Need char = 's' Capturing subpattern count = 2 Options: anchored No first char -Need char = 'a' +No need char aba 0: aba 1: a @@ -2418,7 +2546,7 @@ Need char = 'a' Capturing subpattern count = 2 Options: anchored No first char -Need char = 'a' +No need char aabbaa 0: aabbaa 1: aa @@ -2428,7 +2556,7 @@ Need char = 'a' Capturing subpattern count = 2 Options: anchored No first char -Need char = 'a' +No need char aabbaa 0: aabbaa 1: aa @@ -2438,7 +2566,7 @@ Need char = 'a' Capturing subpattern count = 2 Options: anchored No first char -Need char = 'a' +No need char aabbaa 0: aabbaa 1: aa @@ -2448,7 +2576,7 @@ Need char = 'a' Capturing subpattern count = 1 Options: anchored No first char -Need char = 'a' +No need char aabbaa 0: aabbaa 1: bb @@ -2457,7 +2585,7 @@ Need char = 'a' Capturing subpattern count = 3 Options: anchored No first char -Need char = 'a' +No need char aabbaa 0: aabbaa 1: aa @@ -2468,7 +2596,7 @@ Need char = 'a' Capturing subpattern count = 2 Options: anchored No first char -Need char = 'a' +No need char aabbaa 0: aabbaa 1: bb @@ -2478,7 +2606,7 @@ Need char = 'a' Capturing subpattern count = 1 Options: anchored No first char -Need char = 'a' +No need char aabbaa 0: aabbaa 1: bb @@ -2487,7 +2615,7 @@ Need char = 'a' Capturing subpattern count = 1 Options: anchored No first char -Need char = 'a' +No need char aabbbaa 0: aabbbaa 1: bbb @@ -2496,7 +2624,7 @@ Need char = 'a' Capturing subpattern count = 1 Options: anchored No first char -Need char = 'a' +No need char aabbbaa 0: aabbbaa 1: bbb @@ -2505,7 +2633,7 @@ Need char = 'a' Capturing subpattern count = 1 Options: anchored No first char -Need char = 'a' +No need char aabbaa 0: aabbaa 1: b @@ -2514,7 +2642,7 @@ Need char = 'a' Capturing subpattern count = 1 Options: anchored No first char -Need char = 'a' +No need char aabbbaa 0: aabbbaa 1: bb @@ -2523,7 +2651,7 @@ Need char = 'a' Capturing subpattern count = 3 Options: anchored No first char -Need char = 'a' +No need char aabbbaa 0: aabbbaa 1: aa @@ -2534,7 +2662,7 @@ Need char = 'a' Capturing subpattern count = 3 Options: anchored No first char -Need char = 'a' +No need char aabbbbaa 0: aabbbbaa 1: aa @@ -2560,12 +2688,12 @@ No first char No need char /a#/xMD -Memory allocation (code space): 13 +Memory allocation (code space): 9 ------------------------------------------------------------------ - 0 6 Bra 0 - 3 1 a - 6 6 Ket - 9 End + 0 5 Bra 0 + 3 a + 5 5 Ket + 8 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: extended @@ -2575,7 +2703,7 @@ No need char /[\s]/D ------------------------------------------------------------------ 0 36 Bra 0 - 3 [\x09-\x0a\x0c-\x0d ] + 3 [\x09\x0a\x0c\x0d ] 36 36 Ket 39 End ------------------------------------------------------------------ @@ -2598,12 +2726,12 @@ No need char /a(?i)b/D ------------------------------------------------------------------ - 0 11 Bra 0 - 3 1 a - 6 01 Opt - 8 1 b - 11 11 Ket - 14 End + 0 9 Bra 0 + 3 a + 5 01 Opt + 7 NC b + 9 9 Ket + 12 End ------------------------------------------------------------------ Capturing subpattern count = 0 No options @@ -2621,15 +2749,15 @@ No match /(a(?i)b)/D ------------------------------------------------------------------ - 0 19 Bra 0 - 3 11 Bra 1 - 6 1 a - 9 01 Opt - 11 1 b - 14 11 Ket - 17 00 Opt - 19 19 Ket - 22 End + 0 17 Bra 0 + 3 9 Bra 1 + 6 a + 8 01 Opt + 10 NC b + 12 9 Ket + 15 00 Opt + 17 17 Ket + 20 End ------------------------------------------------------------------ Capturing subpattern count = 1 No options @@ -2649,10 +2777,10 @@ No match / (?i)abc/xD ------------------------------------------------------------------ - 0 8 Bra 0 - 3 3 abc - 8 8 Ket - 11 End + 0 9 Bra 0 + 3 NC abc + 9 9 Ket + 12 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: caseless extended @@ -2662,10 +2790,10 @@ Need char = 'c' (caseless) /#this is a comment (?i)abc/xD ------------------------------------------------------------------ - 0 8 Bra 0 - 3 3 abc - 8 8 Ket - 11 End + 0 9 Bra 0 + 3 NC abc + 9 9 Ket + 12 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: caseless extended @@ -2674,11 +2802,10 @@ Need char = 'c' (caseless) /123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890/D ------------------------------------------------------------------ - 0 307 Bra 0 - 3 250 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 -255 50 12345678901234567890123456789012345678901234567890 -307 307 Ket -310 End + 0 603 Bra 0 + 3 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 +603 603 Ket +606 End ------------------------------------------------------------------ Capturing subpattern count = 0 No options @@ -2687,11 +2814,10 @@ Need char = '0' /\Q123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890/D ------------------------------------------------------------------ - 0 307 Bra 0 - 3 250 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 -255 50 12345678901234567890123456789012345678901234567890 -307 307 Ket -310 End + 0 603 Bra 0 + 3 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 +603 603 Ket +606 End ------------------------------------------------------------------ Capturing subpattern count = 0 No options @@ -2713,10 +2839,10 @@ No need char /\Q\Ex/D ------------------------------------------------------------------ - 0 6 Bra 0 - 3 1 x - 6 6 Ket - 9 End + 0 5 Bra 0 + 3 x + 5 5 Ket + 8 End ------------------------------------------------------------------ Capturing subpattern count = 0 No options @@ -2725,10 +2851,10 @@ No need char / \Q\E/D ------------------------------------------------------------------ - 0 6 Bra 0 - 3 1 - 6 6 Ket - 9 End + 0 5 Bra 0 + 3 + 5 5 Ket + 8 End ------------------------------------------------------------------ Capturing subpattern count = 0 No options @@ -2737,10 +2863,10 @@ No need char /a\Q\E/D ------------------------------------------------------------------ - 0 6 Bra 0 - 3 1 a - 6 6 Ket - 9 End + 0 5 Bra 0 + 3 a + 5 5 Ket + 8 End ------------------------------------------------------------------ Capturing subpattern count = 0 No options @@ -2755,11 +2881,10 @@ No need char /a\Q\Eb/D ------------------------------------------------------------------ - 0 9 Bra 0 - 3 1 a - 6 1 b - 9 9 Ket - 12 End + 0 7 Bra 0 + 3 ab + 7 7 Ket + 10 End ------------------------------------------------------------------ Capturing subpattern count = 0 No options @@ -2770,10 +2895,10 @@ Need char = 'b' /\Q\Eabc/D ------------------------------------------------------------------ - 0 8 Bra 0 - 3 3 abc - 8 8 Ket - 11 End + 0 9 Bra 0 + 3 abc + 9 9 Ket + 12 End ------------------------------------------------------------------ Capturing subpattern count = 0 No options @@ -2791,10 +2916,11 @@ Need char = 'c' 15 End ------------------------------------------------------------------ Capturing subpattern count = 0 +Partial matching not supported No options No first char No need char - ****Failers + *** Failers 0: F xxxxx No match @@ -2823,36 +2949,38 @@ No need char 14 End ------------------------------------------------------------------ Capturing subpattern count = 0 +Partial matching not supported No options First char = 'x' No need char /x{1,3}+/D ------------------------------------------------------------------ - 0 16 Bra 0 - 3 10 Once - 6 1 x - 9 x{,2} - 13 10 Ket - 16 16 Ket - 19 End + 0 15 Bra 0 + 3 9 Once + 6 x + 8 x{,2} + 12 9 Ket + 15 15 Ket + 18 End ------------------------------------------------------------------ Capturing subpattern count = 0 +Partial matching not supported No options First char = 'x' No need char /(x)*+/D ------------------------------------------------------------------ - 0 19 Bra 0 - 3 13 Once + 0 18 Bra 0 + 3 12 Once 6 Brazero - 7 6 Bra 1 - 10 1 x - 13 6 KetRmax - 16 13 Ket - 19 19 Ket - 22 End + 7 5 Bra 1 + 10 x + 12 5 KetRmax + 15 12 Ket + 18 18 Ket + 21 End ------------------------------------------------------------------ Capturing subpattern count = 1 No options @@ -2861,6 +2989,7 @@ No need char /^(\w++|\s++)*$/ Capturing subpattern count = 1 +Partial matching not supported Options: anchored No first char No need char @@ -2874,6 +3003,7 @@ No match /(\d++)(\w)/ Capturing subpattern count = 2 +Partial matching not supported No options No first char No need char @@ -2888,6 +3018,7 @@ No match /a++b/ Capturing subpattern count = 0 +Partial matching not supported No options First char = 'a' Need char = 'b' @@ -2896,6 +3027,7 @@ Need char = 'b' /(a++b)/ Capturing subpattern count = 1 +Partial matching not supported No options First char = 'a' Need char = 'b' @@ -2905,6 +3037,7 @@ Need char = 'b' /(a++)b/ Capturing subpattern count = 1 +Partial matching not supported No options First char = 'a' Need char = 'b' @@ -2914,6 +3047,7 @@ Need char = 'b' /([^()]++|\([^()]*\))+/ Capturing subpattern count = 1 +Partial matching not supported No options No first char No need char @@ -2923,6 +3057,7 @@ No need char /\(([^()]++|\([^()]+\))+\)/ Capturing subpattern count = 1 +Partial matching not supported No options First char = '(' Need char = ')' @@ -2939,24 +3074,24 @@ No match /(abc){1,3}+/D ------------------------------------------------------------------ - 0 50 Bra 0 - 3 44 Once - 6 8 Bra 1 - 9 3 abc - 14 8 Ket - 17 Brazero - 18 26 Bra 0 - 21 8 Bra 1 - 24 3 abc - 29 8 Ket - 32 Brazero - 33 8 Bra 1 - 36 3 abc - 41 8 Ket - 44 26 Ket - 47 44 Ket - 50 50 Ket - 53 End + 0 53 Bra 0 + 3 47 Once + 6 9 Bra 1 + 9 abc + 15 9 Ket + 18 Brazero + 19 28 Bra 0 + 22 9 Bra 1 + 25 abc + 31 9 Ket + 34 Brazero + 35 9 Bra 1 + 38 abc + 44 9 Ket + 47 28 Ket + 50 47 Ket + 53 53 Ket + 56 End ------------------------------------------------------------------ Capturing subpattern count = 1 No options @@ -2977,16 +3112,17 @@ Failed: nothing to repeat at offset 7 /x(?U)a++b/D ------------------------------------------------------------------ - 0 17 Bra 0 - 3 1 x - 6 5 Once - 9 a+ - 11 5 Ket - 14 1 b - 17 17 Ket - 20 End + 0 15 Bra 0 + 3 x + 5 5 Once + 8 a+ + 10 5 Ket + 13 b + 15 15 Ket + 18 End ------------------------------------------------------------------ Capturing subpattern count = 0 +Partial matching not supported No options First char = 'x' Need char = 'b' @@ -2995,16 +3131,17 @@ Need char = 'b' /(?U)xa++b/D ------------------------------------------------------------------ - 0 17 Bra 0 - 3 1 x - 6 5 Once - 9 a+ - 11 5 Ket - 14 1 b - 17 17 Ket - 20 End + 0 15 Bra 0 + 3 x + 5 5 Once + 8 a+ + 10 5 Ket + 13 b + 15 15 Ket + 18 End ------------------------------------------------------------------ Capturing subpattern count = 0 +Partial matching not supported Options: ungreedy First char = 'x' Need char = 'b' @@ -3020,10 +3157,10 @@ Need char = 'b' 10 a+ 12 5 Ket 15 37 Bra 3 - 18 [a-b]+? + 18 [ab]+? 52 37 Ket 55 37 Bra 4 - 58 [b-c]+ + 58 [bc]+ 92 37 Ket 95 5 Bra 5 98 \w* @@ -3033,38 +3170,41 @@ Need char = 'b' 109 End ------------------------------------------------------------------ Capturing subpattern count = 5 +Partial matching not supported Options: anchored No first char -Need char = 'a' +No need char /^x(?U)a+b/D ------------------------------------------------------------------ - 0 12 Bra 0 + 0 10 Bra 0 3 ^ - 4 1 x - 7 a+? - 9 1 b - 12 12 Ket - 15 End + 4 x + 6 a+? + 8 b + 10 10 Ket + 13 End ------------------------------------------------------------------ Capturing subpattern count = 0 +Partial matching not supported Options: anchored No first char Need char = 'b' /^x(?U)(a+)b/D ------------------------------------------------------------------ - 0 18 Bra 0 + 0 16 Bra 0 3 ^ - 4 1 x - 7 5 Bra 1 - 10 a+? - 12 5 Ket - 15 1 b - 18 18 Ket - 21 End + 4 x + 6 5 Bra 1 + 9 a+? + 11 5 Ket + 14 b + 16 16 Ket + 19 End ------------------------------------------------------------------ Capturing subpattern count = 1 +Partial matching not supported Options: anchored No first char Need char = 'b' @@ -3079,34 +3219,19 @@ Failed: POSIX collating elements are not supported at offset 0 Failed: POSIX named classes are supported only within a class at offset 0 /\l/ -Failed: PCRE does not support \L, \l, \N, \P, \p, \U, \u, or \X at offset 1 +Failed: PCRE does not support \L, \l, \N, \U, or \u at offset 1 /\L/ -Failed: PCRE does not support \L, \l, \N, \P, \p, \U, \u, or \X at offset 1 +Failed: PCRE does not support \L, \l, \N, \U, or \u at offset 1 /\N{name}/ -Failed: PCRE does not support \L, \l, \N, \P, \p, \U, \u, or \X at offset 1 - -/\pP/ -Failed: PCRE does not support \L, \l, \N, \P, \p, \U, \u, or \X at offset 1 - -/\PP/ -Failed: PCRE does not support \L, \l, \N, \P, \p, \U, \u, or \X at offset 1 - -/\p{prop}/ -Failed: PCRE does not support \L, \l, \N, \P, \p, \U, \u, or \X at offset 1 - -/\P{prop}/ -Failed: PCRE does not support \L, \l, \N, \P, \p, \U, \u, or \X at offset 1 +Failed: PCRE does not support \L, \l, \N, \U, or \u at offset 1 /\u/ -Failed: PCRE does not support \L, \l, \N, \P, \p, \U, \u, or \X at offset 1 +Failed: PCRE does not support \L, \l, \N, \U, or \u at offset 1 /\U/ -Failed: PCRE does not support \L, \l, \N, \P, \p, \U, \u, or \X at offset 1 - -/\X/ -Failed: PCRE does not support \L, \l, \N, \P, \p, \U, \u, or \X at offset 1 +Failed: PCRE does not support \L, \l, \N, \U, or \u at offset 1 /[/ Failed: missing terminating ] for character class at offset 1 @@ -3121,7 +3246,7 @@ Failed: missing terminating ] for character class at offset 10 Memory allocation (code space): 40 ------------------------------------------------------------------ 0 36 Bra 0 - 3 [\x09-\x0a\x0c-\x0d ] + 3 [\x09\x0a\x0c\x0d ] 36 36 Ket 39 End ------------------------------------------------------------------ @@ -3158,6 +3283,7 @@ No need char /< (?: (?(R) \d++ | [^<>]*+) | (?R)) * >/x Capturing subpattern count = 0 +Partial matching not supported Options: extended First char = '<' Need char = '>' @@ -3179,14 +3305,13 @@ No match No match |8J\$WE\<\.rX\+ix\[d1b\!H\#\?vV0vrK\:ZH1\=2M\>iV\;\?aPhFB\<\*vW\@QW\@sO9\}cfZA\-i\'w\%hKd6gt1UJP\,15_\#QY\$M\^Mss_U\/\]\&LK9\[5vQub\^w\[KDD\qmj\;2\}YWFdYx\.Ap\]hjCPTP\(n28k\+3\;o\&WXqs\/gOXdr\$\:r\'do0\;b4c\(f_Gr\=\"\\4\)\[01T7ajQJvL\$W\~mL_sS\/4h\:x\*\[ZN\=KLs\&L5zX\/\/\>it\,o\:aU\(\;Z\>pW\&T7oP\'2K\^E\:x9\'c\[\%z\-\,64JQ5AeH_G\#KijUKghQw\^\\vea3a\?kka_G\$8\#\`\*kynsxzBLru\'\]k_\[7FrVx\}\^\=\$blx\>s\-N\%j\;D\*aZDnsw\:YKZ\%Q\.Kne9\#hP\?\+b3\(SOvL\,\^\;\&u5\@\?5C5Bhb\=m\-vEh_L15Jl\]U\)0RP6\{q\%L\^_z5E\'Dw6X\b|DM -Memory allocation (code space): 421 +Memory allocation (code space): 826 ------------------------------------------------------------------ - 0 417 Bra 0 - 3 250 8J$WE<.rX+ix[d1b!H#?vV0vrK:ZH1=2M>iV;?aPhFB<*vW@QW@sO9}cfZA-i'w%hKd6gt1UJP,15_#QY$M^Mss_U/]&LK9[5vQub^w[KDDqmj;2}YWFdYx.Ap]hjCPTP(n28k+3;o&WXqs/gOXdr$:r'do0;b4c(f_Gr="\4)[01T7ajQJvL$W~mL_sS/4h:x*[ZN=KLs&L5zX//>it,o:aU(;Z>pW&T7oP'2K^E: -255 159 x9'c[%z-,64JQ5AeH_G#KijUKghQw^\vea3a?kka_G$8#`*kynsxzBLru']k_[7FrVx}^=$blx>s-N%j;D*aZDnsw:YKZ%Q.Kne9#hP?+b3(SOvL,^;&u5@?5C5Bhb=m-vEh_L15Jl]U)0RP6{q%L^_z5E'Dw6X -416 \b -417 417 Ket -420 End + 0 822 Bra 0 + 3 8J$WE<.rX+ix[d1b!H#?vV0vrK:ZH1=2M>iV;?aPhFB<*vW@QW@sO9}cfZA-i'w%hKd6gt1UJP,15_#QY$M^Mss_U/]&LK9[5vQub^w[KDDqmj;2}YWFdYx.Ap]hjCPTP(n28k+3;o&WXqs/gOXdr$:r'do0;b4c(f_Gr="\4)[01T7ajQJvL$W~mL_sS/4h:x*[ZN=KLs&L5zX//>it,o:aU(;Z>pW&T7oP'2K^E:x9'c[%z-,64JQ5AeH_G#KijUKghQw^\vea3a?kka_G$8#`*kynsxzBLru']k_[7FrVx}^=$blx>s-N%j;D*aZDnsw:YKZ%Q.Kne9#hP?+b3(SOvL,^;&u5@?5C5Bhb=m-vEh_L15Jl]U)0RP6{q%L^_z5E'Dw6X +821 \b +822 822 Ket +825 End ------------------------------------------------------------------ Capturing subpattern count = 0 No options @@ -3194,14 +3319,13 @@ First char = '8' Need char = 'X' |\$\<\.X\+ix\[d1b\!H\#\?vV0vrK\:ZH1\=2M\>iV\;\?aPhFB\<\*vW\@QW\@sO9\}cfZA\-i\'w\%hKd6gt1UJP\,15_\#QY\$M\^Mss_U\/\]\&LK9\[5vQub\^w\[KDD\qmj\;2\}YWFdYx\.Ap\]hjCPTP\(n28k\+3\;o\&WXqs\/gOXdr\$\:r\'do0\;b4c\(f_Gr\=\"\\4\)\[01T7ajQJvL\$W\~mL_sS\/4h\:x\*\[ZN\=KLs\&L5zX\/\/\>it\,o\:aU\(\;Z\>pW\&T7oP\'2K\^E\:x9\'c\[\%z\-\,64JQ5AeH_G\#KijUKghQw\^\\vea3a\?kka_G\$8\#\`\*kynsxzBLru\'\]k_\[7FrVx\}\^\=\$blx\>s\-N\%j\;D\*aZDnsw\:YKZ\%Q\.Kne9\#hP\?\+b3\(SOvL\,\^\;\&u5\@\?5C5Bhb\=m\-vEh_L15Jl\]U\)0RP6\{q\%L\^_z5E\'Dw6X\b|DM -Memory allocation (code space): 416 +Memory allocation (code space): 816 ------------------------------------------------------------------ - 0 412 Bra 0 - 3 250 $<.X+ix[d1b!H#?vV0vrK:ZH1=2M>iV;?aPhFB<*vW@QW@sO9}cfZA-i'w%hKd6gt1UJP,15_#QY$M^Mss_U/]&LK9[5vQub^w[KDDqmj;2}YWFdYx.Ap]hjCPTP(n28k+3;o&WXqs/gOXdr$:r'do0;b4c(f_Gr="\4)[01T7ajQJvL$W~mL_sS/4h:x*[ZN=KLs&L5zX//>it,o:aU(;Z>pW&T7oP'2K^E:x9'c[ -255 154 %z-,64JQ5AeH_G#KijUKghQw^\vea3a?kka_G$8#`*kynsxzBLru']k_[7FrVx}^=$blx>s-N%j;D*aZDnsw:YKZ%Q.Kne9#hP?+b3(SOvL,^;&u5@?5C5Bhb=m-vEh_L15Jl]U)0RP6{q%L^_z5E'Dw6X -411 \b -412 412 Ket -415 End + 0 812 Bra 0 + 3 $<.X+ix[d1b!H#?vV0vrK:ZH1=2M>iV;?aPhFB<*vW@QW@sO9}cfZA-i'w%hKd6gt1UJP,15_#QY$M^Mss_U/]&LK9[5vQub^w[KDDqmj;2}YWFdYx.Ap]hjCPTP(n28k+3;o&WXqs/gOXdr$:r'do0;b4c(f_Gr="\4)[01T7ajQJvL$W~mL_sS/4h:x*[ZN=KLs&L5zX//>it,o:aU(;Z>pW&T7oP'2K^E:x9'c[%z-,64JQ5AeH_G#KijUKghQw^\vea3a?kka_G$8#`*kynsxzBLru']k_[7FrVx}^=$blx>s-N%j;D*aZDnsw:YKZ%Q.Kne9#hP?+b3(SOvL,^;&u5@?5C5Bhb=m-vEh_L15Jl]U)0RP6{q%L^_z5E'Dw6X +811 \b +812 812 Ket +815 End ------------------------------------------------------------------ Capturing subpattern count = 0 No options @@ -3211,12 +3335,14 @@ Need char = 'X' /(.*)\d+\1/I Capturing subpattern count = 1 Max back reference = 1 +Partial matching not supported No options No first char No need char /(.*)\d+/I Capturing subpattern count = 1 +Partial matching not supported No options First char at start or follows \n No need char @@ -3224,12 +3350,14 @@ No need char /(.*)\d+\1/Is Capturing subpattern count = 1 Max back reference = 1 +Partial matching not supported Options: dotall No first char No need char /(.*)\d+/Is Capturing subpattern count = 1 +Partial matching not supported Options: anchored dotall No first char No need char @@ -3237,13 +3365,15 @@ No need char /(.*(xyz))\d+\2/I Capturing subpattern count = 2 Max back reference = 2 +Partial matching not supported No options -No first char +First char at start or follows \n Need char = 'z' /((.*))\d+\1/I Capturing subpattern count = 2 Max back reference = 1 +Partial matching not supported No options No first char No need char @@ -3260,6 +3390,7 @@ Need char = 'b' /(?=a).*/I Capturing subpattern count = 0 +Partial matching not supported No options First char = 'a' No need char @@ -3366,7 +3497,7 @@ Capturing subpattern count = 0 No options No first char No need char -Starting character set: a b +Starting byte set: a b /[^a]/I Capturing subpattern count = 0 @@ -3385,7 +3516,7 @@ Capturing subpattern count = 0 No options No first char Need char = '6' -Starting character set: 0 1 2 3 4 5 6 7 8 9 +Starting byte set: 0 1 2 3 4 5 6 7 8 9 /a^b/I Capturing subpattern count = 0 @@ -3418,7 +3549,7 @@ Capturing subpattern count = 0 Options: caseless No first char No need char -Starting character set: A B a b +Starting byte set: A B a b /[ab](?i)cd/IS Capturing subpattern count = 0 @@ -3426,7 +3557,7 @@ No options Case state changes No first char Need char = 'd' (caseless) -Starting character set: a b +Starting byte set: a b /abc(?C)def/ Capturing subpattern count = 0 @@ -3435,11 +3566,11 @@ First char = 'a' Need char = 'f' abcdef --->abcdef - 0 ^ ^ + 0 ^ ^ d 0: abcdef 1234abcdef --->1234abcdef - 0 ^ ^ + 0 ^ ^ d 0: abcdef *** Failers No match @@ -3447,7 +3578,7 @@ No match No match abcxyzf --->abcxyzf - 0 ^ ^ + 0 ^ ^ d No match /abc(?C)de(?C1)f/ @@ -3457,8 +3588,8 @@ First char = 'a' Need char = 'f' 123abcdef --->123abcdef - 0 ^ ^ - 1 ^ ^ + 0 ^ ^ d + 1 ^ ^ f 0: abcdef /(?C1)\dabc(?C2)def/ @@ -3468,22 +3599,22 @@ No first char Need char = 'f' 1234abcdef --->1234abcdef - 1 ^ - 1 ^ - 1 ^ - 1 ^ - 2 ^ ^ + 1 ^ \d + 1 ^ \d + 1 ^ \d + 1 ^ \d + 2 ^ ^ d 0: 4abcdef *** Failers No match abcdef --->abcdef - 1 ^ - 1 ^ - 1 ^ - 1 ^ - 1 ^ - 1 ^ + 1 ^ \d + 1 ^ \d + 1 ^ \d + 1 ^ \d + 1 ^ \d + 1 ^ \d No match /(?C255)ab/ @@ -3510,7 +3641,7 @@ Need char = 'f' No match \x83\x0\x61bcdef --->\x83\x00abcdef - 0 ^ ^ + 0 ^ ^ d 0: abcdef /(abc)(?C)de(?C1)f/ @@ -3520,8 +3651,8 @@ First char = 'a' Need char = 'f' 123abcdef --->123abcdef - 0 ^ ^ - 1 ^ ^ + 0 ^ ^ d + 1 ^ ^ f 0: abcdef 1: abc 123abcdef\C+ @@ -3529,12 +3660,12 @@ Callout 0: last capture = 1 0: 1: abc --->123abcdef - ^ ^ + ^ ^ d Callout 1: last capture = 1 0: 1: abc --->123abcdef - ^ ^ + ^ ^ f 0: abcdef 1: abc 123abcdef\C- @@ -3544,8 +3675,8 @@ Callout 1: last capture = 1 No match 123abcdef\C!1 --->123abcdef - 0 ^ ^ - 1 ^ ^ + 0 ^ ^ d + 1 ^ ^ f No match /(?C0)(abc(?C1))*/ @@ -3555,34 +3686,35 @@ No first char No need char abcabcabc --->abcabcabc - 0 ^ - 1 ^ ^ - 1 ^ ^ - 1 ^ ^ + 0 ^ (abc(?C1))* + 1 ^ ^ ) + 1 ^ ^ ) + 1 ^ ^ ) 0: abcabcabc 1: abc abcabc\C!1!3 --->abcabc - 0 ^ - 1 ^ ^ - 1 ^ ^ + 0 ^ (abc(?C1))* + 1 ^ ^ ) + 1 ^ ^ ) 0: abcabc 1: abc *** Failers --->*** Failers - 0 ^ + 0 ^ (abc(?C1))* 0: abcabcabc\C!1!3 --->abcabcabc - 0 ^ - 1 ^ ^ - 1 ^ ^ - 1 ^ ^ + 0 ^ (abc(?C1))* + 1 ^ ^ ) + 1 ^ ^ ) + 1 ^ ^ ) 0: abcabc 1: abc /(\d{3}(?C))*/ Capturing subpattern count = 1 +Partial matching not supported No options No first char No need char @@ -3590,36 +3722,36 @@ No need char Callout 0: last capture = -1 0: --->123 - ^ ^ + ^ ^ ) 0: 123 1: 123 123456\C+ Callout 0: last capture = -1 0: --->123456 - ^ ^ + ^ ^ ) Callout 0: last capture = 1 0: 1: 123 --->123456 - ^ ^ + ^ ^ ) 0: 123456 1: 456 123456789\C+ Callout 0: last capture = -1 0: --->123456789 - ^ ^ + ^ ^ ) Callout 0: last capture = 1 0: 1: 123 --->123456789 - ^ ^ + ^ ^ ) Callout 0: last capture = 1 0: 1: 456 --->123456789 - ^ ^ + ^ ^ ) 0: 123456789 1: 789 @@ -3634,11 +3766,11 @@ Callout 0: last capture = 2 1: 2: xyz --->xyzabc - ^ ^ + ^ ^ p Callout 1: last capture = -1 0: --->xyzabc - ^ + ^ x 0: xyzabc 1: xyzabc @@ -3654,12 +3786,12 @@ Callout 0: last capture = 3 2: 3: xyz --->Xxyzabc - ^ ^ + ^ ^ p Callout 1: last capture = 1 0: 1: X --->Xxyzabc - ^^ + ^^ x 0: Xxyzabc 1: X 2: xyzabc @@ -3674,7 +3806,7 @@ Callout 0: last capture = 1 0: 1: abc --->abcdef - ^ + ^ a 0: abcdef 1: abc @@ -3688,11 +3820,11 @@ Callout 1: last capture = 1 0: 1: abc --->abcxyz - ^ ^ + ^ ^ d Callout 2: last capture = -1 0: --->abcxyz - ^ + ^ a 0: abcxyz /(?<=(abc)(?C))xyz/ @@ -3705,10 +3837,62 @@ Callout 0: last capture = 1 0: 1: abc --->abcxyz - ^ + ^ ) 0: xyz 1: abc +/a(b+)(c*)(?C1)/ +Capturing subpattern count = 2 +Partial matching not supported +No options +First char = 'a' +Need char = 'b' + abbbbbccc\C*1 +--->abbbbbccc + 1 ^ ^ +Callout data = 1 + 1 ^ ^ +Callout data = 1 + 1 ^ ^ +Callout data = 1 + 1 ^ ^ +Callout data = 1 + 1 ^ ^ +Callout data = 1 + 1 ^ ^ +Callout data = 1 + 1 ^ ^ +Callout data = 1 + 1 ^ ^ +Callout data = 1 +No match + +/a(b+?)(c*?)(?C1)/ +Capturing subpattern count = 2 +Partial matching not supported +No options +First char = 'a' +Need char = 'b' + abbbbbccc\C*1 +--->abbbbbccc + 1 ^ ^ +Callout data = 1 + 1 ^ ^ +Callout data = 1 + 1 ^ ^ +Callout data = 1 + 1 ^ ^ +Callout data = 1 + 1 ^ ^ +Callout data = 1 + 1 ^ ^ +Callout data = 1 + 1 ^ ^ +Callout data = 1 + 1 ^ ^ +Callout data = 1 +No match + /(?C)abc/ Capturing subpattern count = 0 No options @@ -3719,14 +3903,14 @@ Need char = 'c' Capturing subpattern count = 0 Options: anchored No first char -Need char = 'c' +No need char /(?C)a|b/S Capturing subpattern count = 0 No options No first char No need char -Starting character set: a b +Starting byte set: a b /(?R)/ Failed: recursive call could loop indefinitely at offset 3 @@ -3811,14 +3995,14 @@ Need char = '<' /(a(?1)b)/D ------------------------------------------------------------------ - 0 18 Bra 0 - 3 12 Bra 1 - 6 1 a - 9 3 Recurse - 12 1 b - 15 12 Ket - 18 18 Ket - 21 End + 0 16 Bra 0 + 3 10 Bra 1 + 6 a + 8 3 Recurse + 11 b + 13 10 Ket + 16 16 Ket + 19 End ------------------------------------------------------------------ Capturing subpattern count = 1 No options @@ -3827,16 +4011,16 @@ Need char = 'b' /(a(?1)+b)/D ------------------------------------------------------------------ - 0 24 Bra 0 - 3 18 Bra 1 - 6 1 a - 9 6 Bra 0 - 12 3 Recurse - 15 6 KetRmax - 18 1 b - 21 18 Ket - 24 24 Ket - 27 End + 0 22 Bra 0 + 3 16 Bra 1 + 6 a + 8 6 Bra 0 + 11 3 Recurse + 14 6 KetRmax + 17 b + 19 16 Ket + 22 22 Ket + 25 End ------------------------------------------------------------------ Capturing subpattern count = 1 No options @@ -3846,6 +4030,7 @@ Need char = 'b' /^\W*(?:((.)\W*(?1)\W*\2|)|((.)\W*(?3)\W*\4|\W*.\W*))\W*$/i Capturing subpattern count = 4 Max back reference = 4 +Partial matching not supported Options: anchored caseless No first char No need char @@ -3878,6 +4063,7 @@ No match /^(\d+|\((?1)([+*-])(?1)\)|-(?1))$/ Capturing subpattern count = 2 +Partial matching not supported Options: anchored No first char No need char @@ -3900,7 +4086,7 @@ No match Capturing subpattern count = 2 Options: anchored No first char -Need char = 'z' +No need char xyz 0: xyz 1: xyz @@ -3918,6 +4104,7 @@ No match /((< (?: (?(R) \d++ | [^<>]*+) | (?2)) * >))/x Capturing subpattern count = 2 +Partial matching not supported Options: extended First char = '<' Need char = '>' @@ -3960,7 +4147,7 @@ Failed: reference to non-existent subpattern at offset 4 Capturing subpattern count = 1 Options: anchored No first char -Need char = 'f' +No need char abcdefabc 0: abcdefabc 1: abc @@ -3969,7 +4156,7 @@ Need char = 'f' Capturing subpattern count = 1 Options: anchored No first char -Need char = '=' +No need char a=a 0: a=a 1: a @@ -3984,7 +4171,7 @@ Need char = '=' Capturing subpattern count = 2 Options: anchored No first char -Need char = '=' +No need char a=a 0: a=a 1: a @@ -4000,19 +4187,19 @@ Need char = '=' /a(?Pb|c)d(?Pe)/D ------------------------------------------------------------------ - 0 33 Bra 0 - 3 1 a - 6 6 Bra 1 - 9 1 b - 12 6 Alt - 15 1 c - 18 12 Ket - 21 1 d - 24 6 Bra 2 - 27 1 e - 30 6 Ket - 33 33 Ket - 36 End + 0 28 Bra 0 + 3 a + 5 5 Bra 1 + 8 b + 10 5 Alt + 13 c + 15 10 Ket + 18 d + 20 5 Bra 2 + 23 e + 25 5 Ket + 28 28 Ket + 31 End ------------------------------------------------------------------ Capturing subpattern count = 2 Named capturing subpatterns: @@ -4032,21 +4219,21 @@ Need char = 'e' /(?:a(?Pc(?Pd)))(?Pa)/D ------------------------------------------------------------------ - 0 39 Bra 0 - 3 24 Bra 0 - 6 1 a - 9 15 Bra 1 - 12 1 c - 15 6 Bra 2 - 18 1 d - 21 6 Ket - 24 15 Ket - 27 24 Ket - 30 6 Bra 3 - 33 1 a - 36 6 Ket - 39 39 Ket - 42 End + 0 35 Bra 0 + 3 21 Bra 0 + 6 a + 8 13 Bra 1 + 11 c + 13 5 Bra 2 + 16 d + 18 5 Ket + 21 13 Ket + 24 21 Ket + 27 5 Bra 3 + 30 a + 32 5 Ket + 35 35 Ket + 38 End ------------------------------------------------------------------ Capturing subpattern count = 3 Named capturing subpatterns: @@ -4059,30 +4246,1701 @@ Need char = 'a' /(?Pa)...(?P=a)bbb(?P>a)d/D ------------------------------------------------------------------ - 0 29 Bra 0 - 3 6 Bra 1 - 6 1 a - 9 6 Ket + 0 28 Bra 0 + 3 5 Bra 1 + 6 a + 8 5 Ket + 11 Any 12 Any 13 Any - 14 Any - 15 \1 - 18 3 bbb + 14 \1 + 17 bbb 23 3 Recurse - 26 1 d - 29 29 Ket - 32 End + 26 d + 28 28 Ket + 31 End ------------------------------------------------------------------ Capturing subpattern count = 1 +Max back reference = 1 Named capturing subpatterns: a 1 No options First char = 'a' Need char = 'd' -/ End of testinput2 / -Capturing subpattern count = 0 -No options -First char = ' ' -Need char = ' ' - +/^\W*(?:(?P(?P.)\W*(?P>one)\W*(?P=two)|)|(?P(?P.)\W*(?P>three)\W*(?P=four)|\W*.\W*))\W*$/i +Capturing subpattern count = 4 +Max back reference = 4 +Named capturing subpatterns: + four 4 + one 1 + three 3 + two 2 +Partial matching not supported +Options: anchored caseless +No first char +No need char + 1221 + 0: 1221 + 1: 1221 + 2: 1 + Satan, oscillate my metallic sonatas! + 0: Satan, oscillate my metallic sonatas! + 1: + 2: + 3: Satan, oscillate my metallic sonatas + 4: S + A man, a plan, a canal: Panama! + 0: A man, a plan, a canal: Panama! + 1: + 2: + 3: A man, a plan, a canal: Panama + 4: A + Able was I ere I saw Elba. + 0: Able was I ere I saw Elba. + 1: + 2: + 3: Able was I ere I saw Elba + 4: A + *** Failers +No match + The quick brown fox +No match + +/((?(R)a|b))\1(?1)?/ +Capturing subpattern count = 1 +Max back reference = 1 +No options +No first char +No need char + bb + 0: bb + 1: b + bbaa + 0: bba + 1: b + +/(.*)a/sI +Capturing subpattern count = 1 +Partial matching not supported +Options: anchored dotall +No first char +Need char = 'a' + +/(.*)a\1/sI +Capturing subpattern count = 1 +Max back reference = 1 +Partial matching not supported +Options: dotall +No first char +Need char = 'a' + +/(.*)a(b)\2/sI +Capturing subpattern count = 2 +Max back reference = 2 +Partial matching not supported +Options: anchored dotall +No first char +Need char = 'b' + +/((.*)a|(.*)b)z/sI +Capturing subpattern count = 3 +Partial matching not supported +Options: anchored dotall +No first char +Need char = 'z' + +/((.*)a|(.*)b)z\1/sI +Capturing subpattern count = 3 +Max back reference = 1 +Partial matching not supported +Options: dotall +No first char +Need char = 'z' + +/((.*)a|(.*)b)z\2/sI +Capturing subpattern count = 3 +Max back reference = 2 +Partial matching not supported +Options: dotall +No first char +Need char = 'z' + +/((.*)a|(.*)b)z\3/sI +Capturing subpattern count = 3 +Max back reference = 3 +Partial matching not supported +Options: dotall +No first char +Need char = 'z' + +/((.*)a|^(.*)b)z\3/sI +Capturing subpattern count = 3 +Max back reference = 3 +Partial matching not supported +Options: anchored dotall +No first char +Need char = 'z' + +/(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)a/sI +Capturing subpattern count = 31 +Partial matching not supported +Options: anchored dotall +No first char +No need char + +/(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)a\31/sI +Capturing subpattern count = 31 +Max back reference = 31 +Partial matching not supported +Options: dotall +No first char +No need char + +/(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)a\32/sI +Capturing subpattern count = 32 +Max back reference = 32 +Partial matching not supported +Options: dotall +No first char +No need char + +/(a)(bc)/ND +------------------------------------------------------------------ + 0 21 Bra 0 + 3 5 Bra 0 + 6 a + 8 5 Ket + 11 7 Bra 0 + 14 bc + 18 7 Ket + 21 21 Ket + 24 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Options: +First char = 'a' +Need char = 'c' + abc + 0: abc + +/(?Pa)(bc)/ND +------------------------------------------------------------------ + 0 21 Bra 0 + 3 5 Bra 1 + 6 a + 8 5 Ket + 11 7 Bra 0 + 14 bc + 18 7 Ket + 21 21 Ket + 24 End +------------------------------------------------------------------ +Capturing subpattern count = 1 +Named capturing subpatterns: + one 1 +Options: +First char = 'a' +Need char = 'c' + abc + 0: abc + 1: a + +/(a)(?Pbc)/ND +------------------------------------------------------------------ + 0 21 Bra 0 + 3 5 Bra 0 + 6 a + 8 5 Ket + 11 7 Bra 1 + 14 bc + 18 7 Ket + 21 21 Ket + 24 End +------------------------------------------------------------------ +Capturing subpattern count = 1 +Named capturing subpatterns: + named 1 +Options: +First char = 'a' +Need char = 'c' + +/(a+)*zz/ +Capturing subpattern count = 1 +Partial matching not supported +No options +No first char +Need char = 'z' + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaazzbbbbbb\M +Minimum match limit = 8 + 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaazz + 1: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaz\M +Minimum match limit = 32768 +No match + +/(aaa(?C1)bbb|ab)/ +Capturing subpattern count = 1 +No options +First char = 'a' +Need char = 'b' + aaabbb +--->aaabbb + 1 ^ ^ b + 0: aaabbb + 1: aaabbb + aaabbb\C*0 +--->aaabbb + 1 ^ ^ b + 0: aaabbb + 1: aaabbb + aaabbb\C*1 +--->aaabbb + 1 ^ ^ b +Callout data = 1 + 0: ab + 1: ab + aaabbb\C*-1 +--->aaabbb + 1 ^ ^ b +Callout data = -1 +No match + +/ab(?Pcd)ef(?Pgh)/ +Capturing subpattern count = 2 +Named capturing subpatterns: + one 1 + two 2 +No options +First char = 'a' +Need char = 'h' + abcdefgh + 0: abcdefgh + 1: cd + 2: gh + abcdefgh\C1\Gtwo + 0: abcdefgh + 1: cd + 2: gh + 1C cd (2) + 2G gh (2) + abcdefgh\Cone\Ctwo + 0: abcdefgh + 1: cd + 2: gh + 1C cd (2) + 2C gh (2) + abcdefgh\Cthree +no parentheses with name "three" + 0: abcdefgh + 1: cd + 2: gh + +/(?P)(?P)/D +------------------------------------------------------------------ + 0 15 Bra 0 + 3 3 Bra 1 + 6 3 Ket + 9 3 Bra 2 + 12 3 Ket + 15 15 Ket + 18 End +------------------------------------------------------------------ +Capturing subpattern count = 2 +Named capturing subpatterns: + Tes 1 + Test 2 +No options +No first char +No need char + +/(?P)(?P)/D +------------------------------------------------------------------ + 0 15 Bra 0 + 3 3 Bra 1 + 6 3 Ket + 9 3 Bra 2 + 12 3 Ket + 15 15 Ket + 18 End +------------------------------------------------------------------ +Capturing subpattern count = 2 +Named capturing subpatterns: + Tes 2 + Test 1 +No options +No first char +No need char + +/(?Pzz)(?Paa)/ +Capturing subpattern count = 2 +Named capturing subpatterns: + A 2 + Z 1 +No options +First char = 'z' +Need char = 'a' + zzaa\CZ + 0: zzaa + 1: zz + 2: aa + 1C zz (2) + zzaa\CA + 0: zzaa + 1: zz + 2: aa + 2C aa (2) + +/(?Peks)(?Peccs)/ +Failed: two named groups have the same name at offset 16 + +/(?Pabc(?Pdef)(?Pxyz))/ +Failed: two named groups have the same name at offset 31 + +"\[((?P\d+)(,(?P>elem))*)\]" +Capturing subpattern count = 3 +Named capturing subpatterns: + elem 2 +Partial matching not supported +No options +First char = '[' +Need char = ']' + [10,20,30,5,5,4,4,2,43,23,4234] + 0: [10,20,30,5,5,4,4,2,43,23,4234] + 1: 10,20,30,5,5,4,4,2,43,23,4234 + 2: 10 + 3: ,4234 + *** Failers +No match + [] +No match + +"\[((?P\d+)(,(?P>elem))*)?\]" +Capturing subpattern count = 3 +Named capturing subpatterns: + elem 2 +Partial matching not supported +No options +First char = '[' +Need char = ']' + [10,20,30,5,5,4,4,2,43,23,4234] + 0: [10,20,30,5,5,4,4,2,43,23,4234] + 1: 10,20,30,5,5,4,4,2,43,23,4234 + 2: 10 + 3: ,4234 + [] + 0: [] + +/(a(b(?2)c))?/D +------------------------------------------------------------------ + 0 25 Bra 0 + 3 Brazero + 4 18 Bra 1 + 7 a + 9 10 Bra 2 + 12 b + 14 9 Recurse + 17 c + 19 10 Ket + 22 18 Ket + 25 25 Ket + 28 End +------------------------------------------------------------------ +Capturing subpattern count = 2 +No options +No first char +No need char + +/(a(b(?2)c))*/D +------------------------------------------------------------------ + 0 25 Bra 0 + 3 Brazero + 4 18 Bra 1 + 7 a + 9 10 Bra 2 + 12 b + 14 9 Recurse + 17 c + 19 10 Ket + 22 18 KetRmax + 25 25 Ket + 28 End +------------------------------------------------------------------ +Capturing subpattern count = 2 +No options +No first char +No need char + +/(a(b(?2)c)){0,2}/D +------------------------------------------------------------------ + 0 53 Bra 0 + 3 Brazero + 4 46 Bra 0 + 7 18 Bra 1 + 10 a + 12 10 Bra 2 + 15 b + 17 12 Recurse + 20 c + 22 10 Ket + 25 18 Ket + 28 Brazero + 29 18 Bra 1 + 32 a + 34 10 Bra 2 + 37 b + 39 12 Recurse + 42 c + 44 10 Ket + 47 18 Ket + 50 46 Ket + 53 53 Ket + 56 End +------------------------------------------------------------------ +Capturing subpattern count = 2 +No options +No first char +No need char + +/[ab]{1}+/D +------------------------------------------------------------------ + 0 47 Bra 0 + 3 41 Once + 6 [ab]{1,1} + 44 41 Ket + 47 47 Ket + 50 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +No options +No first char +No need char + +/((w\/|-|with)*(free|immediate)*.*?shipping\s*[!.-]*)/i +Capturing subpattern count = 3 +Partial matching not supported +Options: caseless +No first char +Need char = 'g' (caseless) + Baby Bjorn Active Carrier - With free SHIPPING!! + 0: Baby Bjorn Active Carrier - With free SHIPPING!! + 1: Baby Bjorn Active Carrier - With free SHIPPING!! + +/((w\/|-|with)*(free|immediate)*.*?shipping\s*[!.-]*)/iS +Capturing subpattern count = 3 +Partial matching not supported +Options: caseless +No first char +Need char = 'g' (caseless) +Study returned NULL + Baby Bjorn Active Carrier - With free SHIPPING!! + 0: Baby Bjorn Active Carrier - With free SHIPPING!! + 1: Baby Bjorn Active Carrier - With free SHIPPING!! + +/a*.*b/SD +------------------------------------------------------------------ + 0 9 Bra 0 + 3 a* + 5 Any* + 7 b + 9 9 Ket + 12 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Partial matching not supported +No options +No first char +Need char = 'b' +Study returned NULL + +/(a|b)*.?c/SD +------------------------------------------------------------------ + 0 21 Bra 0 + 3 Brazero + 4 5 Bra 1 + 7 a + 9 5 Alt + 12 b + 14 10 KetRmax + 17 Any? + 19 c + 21 21 Ket + 24 End +------------------------------------------------------------------ +Capturing subpattern count = 1 +No options +No first char +Need char = 'c' +Study returned NULL + +/abc(?C255)de(?C)f/D +------------------------------------------------------------------ + 0 27 Bra 0 + 3 abc + 9 Callout 255 10 1 + 15 de + 19 Callout 0 16 1 + 25 f + 27 27 Ket + 30 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +No options +First char = 'a' +Need char = 'f' + +/abcde/CD +------------------------------------------------------------------ + 0 49 Bra 0 + 3 Callout 255 0 1 + 9 a + 11 Callout 255 1 1 + 17 b + 19 Callout 255 2 1 + 25 c + 27 Callout 255 3 1 + 33 d + 35 Callout 255 4 1 + 41 e + 43 Callout 255 5 0 + 49 49 Ket + 52 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Options: +First char = 'a' +Need char = 'e' + abcde +--->abcde + +0 ^ a + +1 ^^ b + +2 ^ ^ c + +3 ^ ^ d + +4 ^ ^ e + +5 ^ ^ + 0: abcde + abcdfe +--->abcdfe + +0 ^ a + +1 ^^ b + +2 ^ ^ c + +3 ^ ^ d + +4 ^ ^ e +No match + +/a*b/CD +------------------------------------------------------------------ + 0 25 Bra 0 + 3 Callout 255 0 2 + 9 a* + 11 Callout 255 2 1 + 17 b + 19 Callout 255 3 0 + 25 25 Ket + 28 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Partial matching not supported +Options: +No first char +Need char = 'b' + ab +--->ab + +0 ^ a* + +2 ^^ b + +3 ^ ^ + 0: ab + aaaab +--->aaaab + +0 ^ a* + +2 ^ ^ b + +3 ^ ^ + 0: aaaab + aaaacb +--->aaaacb + +0 ^ a* + +2 ^ ^ b + +2 ^ ^ b + +2 ^ ^ b + +2 ^^ b + +2 ^ b + +0 ^ a* + +2 ^ ^ b + +2 ^ ^ b + +2 ^^ b + +2 ^ b + +0 ^ a* + +2 ^ ^ b + +2 ^^ b + +2 ^ b + +0 ^ a* + +2 ^^ b + +2 ^ b + +0 ^ a* + +2 ^ b + +0 ^ a* + +2 ^ b + +3 ^^ + 0: b + +/a+b/CD +------------------------------------------------------------------ + 0 25 Bra 0 + 3 Callout 255 0 2 + 9 a+ + 11 Callout 255 2 1 + 17 b + 19 Callout 255 3 0 + 25 25 Ket + 28 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Partial matching not supported +Options: +First char = 'a' +Need char = 'b' + ab +--->ab + +0 ^ a+ + +2 ^^ b + +3 ^ ^ + 0: ab + aaaab +--->aaaab + +0 ^ a+ + +2 ^ ^ b + +3 ^ ^ + 0: aaaab + aaaacb +--->aaaacb + +0 ^ a+ + +2 ^ ^ b + +2 ^ ^ b + +2 ^ ^ b + +2 ^^ b + +0 ^ a+ + +2 ^ ^ b + +2 ^ ^ b + +2 ^^ b + +0 ^ a+ + +2 ^ ^ b + +2 ^^ b + +0 ^ a+ + +2 ^^ b +No match + +/(abc|def)x/CD +------------------------------------------------------------------ + 0 92 Bra 0 + 3 Callout 255 0 9 + 9 33 Bra 1 + 12 Callout 255 1 1 + 18 a + 20 Callout 255 2 1 + 26 b + 28 Callout 255 3 1 + 34 c + 36 Callout 255 4 0 + 42 33 Alt + 45 Callout 255 5 1 + 51 d + 53 Callout 255 6 1 + 59 e + 61 Callout 255 7 1 + 67 f + 69 Callout 255 8 0 + 75 66 Ket + 78 Callout 255 9 1 + 84 x + 86 Callout 255 10 0 + 92 92 Ket + 95 End +------------------------------------------------------------------ +Capturing subpattern count = 1 +Options: +No first char +Need char = 'x' + abcx +--->abcx + +0 ^ (abc|def) + +1 ^ a + +2 ^^ b + +3 ^ ^ c + +4 ^ ^ | + +9 ^ ^ x ++10 ^ ^ + 0: abcx + 1: abc + defx +--->defx + +0 ^ (abc|def) + +1 ^ a + +5 ^ d + +6 ^^ e + +7 ^ ^ f + +8 ^ ^ ) + +9 ^ ^ x ++10 ^ ^ + 0: defx + 1: def + abcdefzx +--->abcdefzx + +0 ^ (abc|def) + +1 ^ a + +2 ^^ b + +3 ^ ^ c + +4 ^ ^ | + +9 ^ ^ x + +5 ^ d + +0 ^ (abc|def) + +1 ^ a + +5 ^ d + +0 ^ (abc|def) + +1 ^ a + +5 ^ d + +0 ^ (abc|def) + +1 ^ a + +5 ^ d + +6 ^^ e + +7 ^ ^ f + +8 ^ ^ ) + +9 ^ ^ x + +0 ^ (abc|def) + +1 ^ a + +5 ^ d + +0 ^ (abc|def) + +1 ^ a + +5 ^ d + +0 ^ (abc|def) + +1 ^ a + +5 ^ d + +0 ^ (abc|def) + +1 ^ a + +5 ^ d +No match + +/(ab|cd){3,4}/C +Capturing subpattern count = 1 +Options: +No first char +No need char + ababab +--->ababab + +0 ^ (ab|cd){3,4} + +1 ^ a + +2 ^^ b + +3 ^ ^ | + +1 ^ ^ a + +2 ^ ^ b + +3 ^ ^ | + +1 ^ ^ a + +2 ^ ^ b + +3 ^ ^ | + +1 ^ ^ a + +4 ^ ^ c ++12 ^ ^ + 0: ababab + 1: ab + abcdabcd +--->abcdabcd + +0 ^ (ab|cd){3,4} + +1 ^ a + +2 ^^ b + +3 ^ ^ | + +1 ^ ^ a + +4 ^ ^ c + +5 ^ ^ d + +6 ^ ^ ) + +1 ^ ^ a + +2 ^ ^ b + +3 ^ ^ | + +1 ^ ^ a + +4 ^ ^ c + +5 ^ ^ d + +6 ^ ^ ) ++12 ^ ^ + 0: abcdabcd + 1: cd + abcdcdcdcdcd +--->abcdcdcdcdcd + +0 ^ (ab|cd){3,4} + +1 ^ a + +2 ^^ b + +3 ^ ^ | + +1 ^ ^ a + +4 ^ ^ c + +5 ^ ^ d + +6 ^ ^ ) + +1 ^ ^ a + +4 ^ ^ c + +5 ^ ^ d + +6 ^ ^ ) + +1 ^ ^ a + +4 ^ ^ c + +5 ^ ^ d + +6 ^ ^ ) ++12 ^ ^ + 0: abcdcdcd + 1: cd + +/([ab]{,4}c|xy)/CD +------------------------------------------------------------------ + 0 131 Bra 0 + 3 Callout 255 0 14 + 9 88 Bra 1 + 12 Callout 255 1 4 + 18 [ab] + 51 Callout 255 5 1 + 57 { + 59 Callout 255 6 1 + 65 , + 67 Callout 255 7 1 + 73 4 + 75 Callout 255 8 1 + 81 } + 83 Callout 255 9 1 + 89 c + 91 Callout 255 10 0 + 97 25 Alt +100 Callout 255 11 1 +106 x +108 Callout 255 12 1 +114 y +116 Callout 255 13 0 +122 113 Ket +125 Callout 255 14 0 +131 131 Ket +134 End +------------------------------------------------------------------ +Capturing subpattern count = 1 +Options: +No first char +No need char + Note: that { does NOT introduce a quantifier +--->Note: that { does NOT introduce a quantifier + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] + +5 ^^ { ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] + +5 ^^ { ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] + +5 ^^ { ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x + +0 ^ ([ab]{,4}c|xy) + +1 ^ [ab] ++11 ^ x +No match + +/([ab]{1,4}c|xy){4,5}?123/CD +------------------------------------------------------------------ + 0 485 Bra 0 + 3 Callout 255 0 21 + 9 61 Bra 1 + 12 Callout 255 1 9 + 18 [ab]{1,4} + 56 Callout 255 10 1 + 62 c + 64 Callout 255 11 0 + 70 25 Alt + 73 Callout 255 12 1 + 79 x + 81 Callout 255 13 1 + 87 y + 89 Callout 255 14 0 + 95 86 Ket + 98 61 Bra 1 +101 Callout 255 1 9 +107 [ab]{1,4} +145 Callout 255 10 1 +151 c +153 Callout 255 11 0 +159 25 Alt +162 Callout 255 12 1 +168 x +170 Callout 255 13 1 +176 y +178 Callout 255 14 0 +184 86 Ket +187 61 Bra 1 +190 Callout 255 1 9 +196 [ab]{1,4} +234 Callout 255 10 1 +240 c +242 Callout 255 11 0 +248 25 Alt +251 Callout 255 12 1 +257 x +259 Callout 255 13 1 +265 y +267 Callout 255 14 0 +273 86 Ket +276 61 Bra 1 +279 Callout 255 1 9 +285 [ab]{1,4} +323 Callout 255 10 1 +329 c +331 Callout 255 11 0 +337 25 Alt +340 Callout 255 12 1 +346 x +348 Callout 255 13 1 +354 y +356 Callout 255 14 0 +362 86 Ket +365 Braminzero +366 61 Bra 1 +369 Callout 255 1 9 +375 [ab]{1,4} +413 Callout 255 10 1 +419 c +421 Callout 255 11 0 +427 25 Alt +430 Callout 255 12 1 +436 x +438 Callout 255 13 1 +444 y +446 Callout 255 14 0 +452 86 Ket +455 Callout 255 21 1 +461 1 +463 Callout 255 22 1 +469 2 +471 Callout 255 23 1 +477 3 +479 Callout 255 24 0 +485 485 Ket +488 End +------------------------------------------------------------------ +Capturing subpattern count = 1 +Partial matching not supported +Options: +No first char +Need char = '3' + aacaacaacaacaac123 +--->aacaacaacaacaac123 + +0 ^ ([ab]{1,4}c|xy){4,5}? + +1 ^ [ab]{1,4} ++10 ^ ^ c ++11 ^ ^ | + +1 ^ ^ [ab]{1,4} ++10 ^ ^ c ++11 ^ ^ | + +1 ^ ^ [ab]{1,4} ++10 ^ ^ c ++11 ^ ^ | + +1 ^ ^ [ab]{1,4} ++10 ^ ^ c ++11 ^ ^ | ++21 ^ ^ 1 + +1 ^ ^ [ab]{1,4} ++10 ^ ^ c ++11 ^ ^ | ++21 ^ ^ 1 ++22 ^ ^ 2 ++23 ^ ^ 3 ++24 ^ ^ + 0: aacaacaacaacaac123 + 1: aac + +/\b.*/I +Capturing subpattern count = 0 +Partial matching not supported +No options +No first char +No need char + ab cd\>1 + 0: cd + +/\b.*/Is +Capturing subpattern count = 0 +Partial matching not supported +Options: dotall +No first char +No need char + ab cd\>1 + 0: cd + +/(?!.bcd).*/I +Capturing subpattern count = 0 +Partial matching not supported +No options +No first char +No need char + Xbcd12345 + 0: bcd12345 + +/abcde/ +Capturing subpattern count = 0 +No options +First char = 'a' +Need char = 'e' + ab\P +Partial match + abc\P +Partial match + abcd\P +Partial match + abcde\P + 0: abcde + the quick brown abc\P +Partial match + ** Failers\P +No match + the quick brown abxyz fox\P +No match + +"^(0?[1-9]|[12][0-9]|3[01])/(0?[1-9]|1[012])/(20)?\d\d$" +Capturing subpattern count = 3 +Options: anchored +No first char +Need char = '/' + 13/05/04\P + 0: 13/05/04 + 1: 13 + 2: 05 + 13/5/2004\P + 0: 13/5/2004 + 1: 13 + 2: 5 + 3: 20 + 02/05/09\P + 0: 02/05/09 + 1: 02 + 2: 05 + 1\P +Partial match + 1/2\P +Partial match + 1/2/0\P +Partial match + 1/2/04\P + 0: 1/2/04 + 1: 1 + 2: 2 + 0\P +Partial match + 02/\P +Partial match + 02/0\P +Partial match + 02/1\P +Partial match + ** Failers\P +No match + \P +No match + 123\P +No match + 33/4/04\P +No match + 3/13/04\P +No match + 0/1/2003\P +No match + 0/\P +No match + 02/0/\P +No match + 02/13\P +No match + +/0{0,2}ABC/I +Capturing subpattern count = 0 +Partial matching not supported +No options +No first char +Need char = 'C' + +/\d{3,}ABC/I +Capturing subpattern count = 0 +Partial matching not supported +No options +No first char +Need char = 'C' + +/\d*ABC/I +Capturing subpattern count = 0 +Partial matching not supported +No options +No first char +Need char = 'C' + +/[abc]+DE/I +Capturing subpattern count = 0 +Partial matching not supported +No options +No first char +Need char = 'E' + +/[abc]?123/ +Capturing subpattern count = 0 +No options +No first char +Need char = '3' + 123\P + 0: 123 + a\P +Partial match + b\P +Partial match + c\P +Partial match + c12\P +Partial match + c123\P + 0: c123 + +/^(?:\d){3,5}X/ +Capturing subpattern count = 0 +Options: anchored +No first char +Need char = 'X' + 1\P +Partial match + 123\P +Partial match + 123X + 0: 123X + 1234\P +Partial match + 1234X + 0: 1234X + 12345\P +Partial match + 12345X + 0: 12345X + *** Failers +No match + 1X +No match + 123456\P +No match + +/abc/>testsavedregex +Capturing subpattern count = 0 +No options +First char = 'a' +Need char = 'c' +Compiled regex written to testsavedregex +testsavedregex +Capturing subpattern count = 0 +No options +First char = 'a' +Need char = 'c' +Compiled regex written to testsavedregex +testsavedregex +Capturing subpattern count = 1 +No options +No first char +No need char +Starting byte set: a b +Compiled regex written to testsavedregex +Study data written to testsavedregex +testsavedregex +Capturing subpattern count = 1 +No options +No first char +No need char +Starting byte set: a b +Compiled regex written to testsavedregex +Study data written to testsavedregex +(.)*~smg +Capturing subpattern count = 3 +Max back reference = 1 +Partial matching not supported +Options: multiline dotall +First char = '<' +Need char = '>' + \n\n\nPartner der LCO\nde\nPartner der LINEAS Consulting\nGmbH\nLINEAS Consulting GmbH Hamburg\nPartnerfirmen\n30 days\nindex,follow\n\nja\n3\nPartner\n\n\nLCO\nLINEAS Consulting\n15.10.2003\n\n\n\n\nDie Partnerfirmen der LINEAS Consulting\nGmbH\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n + 0: \x0a\x0aPartner der LCO\x0ade\x0aPartner der LINEAS Consulting\x0aGmbH\x0aLINEAS Consulting GmbH Hamburg\x0aPartnerfirmen\x0a30 days\x0aindex,follow\x0a\x0aja\x0a3\x0aPartner\x0a\x0a\x0aLCO\x0aLINEAS Consulting\x0a15.10.2003\x0a\x0a\x0a\x0a\x0aDie Partnerfirmen der LINEAS Consulting\x0aGmbH\x0a\x0a\x0a \x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a + 1: seite + 2: \x0a + 3: seite + +/^a/IF +Capturing subpattern count = 0 +Options: anchored +No first char +No need char + +/line\nbreak/ +Capturing subpattern count = 0 +No options +First char = 'l' +Need char = 'k' + this is a line\nbreak + 0: line\x0abreak + line one\nthis is a line\nbreak in the second line + 0: line\x0abreak + +/line\nbreak/f +Capturing subpattern count = 0 +Options: firstline +First char = 'l' +Need char = 'k' + this is a line\nbreak + 0: line\x0abreak + ** Failers +No match + line one\nthis is a line\nbreak in the second line +No match + +/line\nbreak/mf +Capturing subpattern count = 0 +Options: multiline firstline +First char = 'l' +Need char = 'k' + this is a line\nbreak + 0: line\x0abreak + ** Failers +No match + line one\nthis is a line\nbreak in the second line +No match + +/ab.cd/P + ab-cd + 0: ab-cd + ab=cd + 0: ab=cd + ** Failers +No match: POSIX code 17: match failed + ab\ncd +No match: POSIX code 17: match failed + +/ab.cd/Ps + ab-cd + 0: ab-cd + ab=cd + 0: ab=cd + ab\ncd + 0: ab\x0acd + +/(?i)(?-i)AbCd/ +Capturing subpattern count = 0 +No options +First char = 'A' +Need char = 'd' + AbCd + 0: AbCd + ** Failers +No match + abcd +No match + +/a{11111111111111111111}/ +Failed: number too big in {} quantifier at offset 22 + +/(){64294967295}/ +Failed: number too big in {} quantifier at offset 14 + +/(){2,4294967295}/ +Failed: number too big in {} quantifier at offset 15 + +"(?i:a)(?i:b)(?i:c)(?i:d)(?i:e)(?i:f)(?i:g)(?i:h)(?i:i)(?i:j)(k)(?i:l)A\1B" +Capturing subpattern count = 1 +Max back reference = 1 +No options +Case state changes +First char = 'a' (caseless) +Need char = 'B' + abcdefghijklAkB + 0: abcdefghijklAkB + 1: k + +"(?Pa)(?Pb)(?Pc)(?Pd)(?Pe)(?Pf)(?Pg)(?Ph)(?Pi)(?Pj)(?Pk)(?Pl)A\11B" +Capturing subpattern count = 12 +Max back reference = 11 +Named capturing subpatterns: + n0 1 + n1 2 + n10 11 + n11 12 + n2 3 + n3 4 + n4 5 + n5 6 + n6 7 + n7 8 + n8 9 + n9 10 +No options +First char = 'a' +Need char = 'B' + abcdefghijklAkB + 0: abcdefghijklAkB + 1: a + 2: b + 3: c + 4: d + 5: e + 6: f + 7: g + 8: h + 9: i +10: j +11: k +12: l + +"(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)A\11B" +Capturing subpattern count = 12 +Max back reference = 11 +No options +First char = 'a' +Need char = 'B' + abcdefghijklAkB + 0: abcdefghijklAkB + 1: a + 2: b + 3: c + 4: d + 5: e + 6: f + 7: g + 8: h + 9: i +10: j +11: k +12: l + +"(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)" +Capturing subpattern count = 101 +Named capturing subpatterns: + name0 1 + name1 2 + name10 11 + name100 101 + name11 12 + name12 13 + name13 14 + name14 15 + name15 16 + name16 17 + name17 18 + name18 19 + name19 20 + name2 3 + name20 21 + name21 22 + name22 23 + name23 24 + name24 25 + name25 26 + name26 27 + name27 28 + name28 29 + name29 30 + name3 4 + name30 31 + name31 32 + name32 33 + name33 34 + name34 35 + name35 36 + name36 37 + name37 38 + name38 39 + name39 40 + name4 5 + name40 41 + name41 42 + name42 43 + name43 44 + name44 45 + name45 46 + name46 47 + name47 48 + name48 49 + name49 50 + name5 6 + name50 51 + name51 52 + name52 53 + name53 54 + name54 55 + name55 56 + name56 57 + name57 58 + name58 59 + name59 60 + name6 7 + name60 61 + name61 62 + name62 63 + name63 64 + name64 65 + name65 66 + name66 67 + name67 68 + name68 69 + name69 70 + name7 8 + name70 71 + name71 72 + name72 73 + name73 74 + name74 75 + name75 76 + name76 77 + name77 78 + name78 79 + name79 80 + name8 9 + name80 81 + name81 82 + name82 83 + name83 84 + name84 85 + name85 86 + name86 87 + name87 88 + name88 89 + name89 90 + name9 10 + name90 91 + name91 92 + name92 93 + name93 94 + name94 95 + name95 96 + name96 97 + name97 98 + name98 99 + name99 100 +No options +First char = 'a' +Need char = 'a' + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +Matched, but too many substrings + 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 1: a + 2: a + 3: a + 4: a + 5: a + 6: a + 7: a + 8: a + 9: a +10: a +11: a +12: a +13: a +14: a + +"(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)" +Capturing subpattern count = 101 +No options +First char = 'a' +Need char = 'a' + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +Matched, but too many substrings + 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 1: a + 2: a + 3: a + 4: a + 5: a + 6: a + 7: a + 8: a + 9: a +10: a +11: a +12: a +13: a +14: a + +/ End of testinput2 / +Capturing subpattern count = 0 +No options +First char = ' ' +Need char = ' ' diff --git a/ext/pcre/pcrelib/testdata/testoutput3 b/ext/pcre/pcrelib/testdata/testoutput3 index 8cc3e8dc6461..16ebc7125a37 100644 --- a/ext/pcre/pcrelib/testdata/testoutput3 +++ b/ext/pcre/pcrelib/testdata/testoutput3 @@ -1,4 +1,4 @@ -PCRE version 3.92 11-Sep-2002 +PCRE version 6.2 01-Aug-2005 /^[\w]+/ *** Failers @@ -6,7 +6,7 @@ No match École No match -/^[\w]+/Lfr +/^[\w]+/Lfr_FR École 0: École @@ -20,7 +20,7 @@ No match École 0: \xc9 -/^[\W]+/Lfr +/^[\W]+/Lfr_FR *** Failers 0: *** École @@ -34,7 +34,7 @@ No match a No match -/[\b]/Lfr +/[\b]/Lfr_FR \b 0: \x08 *** Failers @@ -48,7 +48,7 @@ No match École No match -/^\w+/Lfr +/^\w+/Lfr_FR École 0: École @@ -58,7 +58,7 @@ No match 1: \xc9 2: cole -/(.+)\b(.+)/Lfr +/(.+)\b(.+)/Lfr_FR *** Failers 0: *** Failers 1: *** @@ -74,7 +74,7 @@ No match école No match -/École/iLfr +/École/iLfr_FR École 0: École école @@ -85,26 +85,26 @@ Capturing subpattern count = 0 No options No first char No need char -Starting character set: 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P +Starting byte set: 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ a b c d e f g h i j k l m n o p q r s t u v w x y z -/\w/ISLfr +/\w/ISLfr_FR Capturing subpattern count = 0 No options No first char No need char -Starting character set: 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P +Starting byte set: 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ a b c d e f g h i j k l m n o p q r s t u v w x y z - À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å - æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö ø ù ú û ü ý þ ÿ + µ À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö Ø Ù Ú Û Ü Ý Þ ß à á â ã ä + å æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö ø ù ú û ü ý þ ÿ -/^[\xc8-\xc9]/iLfr +/^[\xc8-\xc9]/iLfr_FR École 0: É école 0: é -/^[\xc8-\xc9]/Lfr +/^[\xc8-\xc9]/Lfr_FR École 0: É *** Failers @@ -113,4 +113,3 @@ No match No match / End of testinput3 / - diff --git a/ext/pcre/pcrelib/testdata/testoutput4 b/ext/pcre/pcrelib/testdata/testoutput4 index 3018c9baa7f1..234fd1ae145e 100644 --- a/ext/pcre/pcrelib/testdata/testoutput4 +++ b/ext/pcre/pcrelib/testdata/testoutput4 @@ -1,4 +1,4 @@ -PCRE version 3.92 11-Sep-2002 +PCRE version 6.2 01-Aug-2005 /-- Do not use the \x{} construct except with patterns that have the --/ /-- /8 option set, because PCRE doesn't recognize them as UTF-8 unless --/ @@ -300,5 +300,604 @@ No match X\x{1234}\x{512} 0: X\x{1234} -/ End of testinput4 / +/[^a]+/8g + bcd + 0: bcd + \x{100}aY\x{256}Z + 0: \x{100} + 0: Y\x{256}Z + +/^[^a]{2}/8 + \x{100}bc + 0: \x{100}b + +/^[^a]{2,}/8 + \x{100}bcAa + 0: \x{100}bcA + +/^[^a]{2,}?/8 + \x{100}bca + 0: \x{100}b + +/[^a]+/8ig + bcd + 0: bcd + \x{100}aY\x{256}Z + 0: \x{100} + 0: Y\x{256}Z + +/^[^a]{2}/8i + \x{100}bc + 0: \x{100}b + +/^[^a]{2,}/8i + \x{100}bcAa + 0: \x{100}bc + +/^[^a]{2,}?/8i + \x{100}bca + 0: \x{100}b + +/\x{100}{0,0}/8 + abcd + 0: + +/\x{100}?/8 + abcd + 0: + \x{100}\x{100} + 0: \x{100} + +/\x{100}{0,3}/8 + \x{100}\x{100} + 0: \x{100}\x{100} + \x{100}\x{100}\x{100}\x{100} + 0: \x{100}\x{100}\x{100} + +/\x{100}*/8 + abce + 0: + \x{100}\x{100}\x{100}\x{100} + 0: \x{100}\x{100}\x{100}\x{100} + +/\x{100}{1,1}/8 + abcd\x{100}\x{100}\x{100}\x{100} + 0: \x{100} + +/\x{100}{1,3}/8 + abcd\x{100}\x{100}\x{100}\x{100} + 0: \x{100}\x{100}\x{100} + +/\x{100}+/8 + abcd\x{100}\x{100}\x{100}\x{100} + 0: \x{100}\x{100}\x{100}\x{100} + +/\x{100}{3}/8 + abcd\x{100}\x{100}\x{100}XX + 0: \x{100}\x{100}\x{100} + +/\x{100}{3,5}/8 + abcd\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}XX + 0: \x{100}\x{100}\x{100}\x{100}\x{100} + +/\x{100}{3,}/8 + abcd\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}XX + 0: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} + +/(?<=a\x{100}{2}b)X/8+ + Xyyya\x{100}\x{100}bXzzz + 0: X + 0+ zzz + +/\D*/8 + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +/\D*/8 + \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} + 0: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} + +/\D/8 + 1X2 + 0: X + 1\x{100}2 + 0: \x{100} + +/>\S/8 + > >X Y + 0: >X + > >\x{100} Y + 0: >\x{100} + +/\d/8 + \x{100}3 + 0: 3 + +/\s/8 + \x{100} X + 0: + +/\D+/8 + 12abcd34 + 0: abcd + *** Failers + 0: *** Failers + 1234 +No match + +/\D{2,3}/8 + 12abcd34 + 0: abc + 12ab34 + 0: ab + *** Failers + 0: *** + 1234 +No match + 12a34 +No match + +/\D{2,3}?/8 + 12abcd34 + 0: ab + 12ab34 + 0: ab + *** Failers + 0: ** + 1234 +No match + 12a34 +No match + +/\d+/8 + 12abcd34 + 0: 12 + *** Failers +No match + +/\d{2,3}/8 + 12abcd34 + 0: 12 + 1234abcd + 0: 123 + *** Failers +No match + 1.4 +No match + +/\d{2,3}?/8 + 12abcd34 + 0: 12 + 1234abcd + 0: 12 + *** Failers +No match + 1.4 +No match + +/\S+/8 + 12abcd34 + 0: 12abcd34 + *** Failers + 0: *** + \ \ +No match + +/\S{2,3}/8 + 12abcd34 + 0: 12a + 1234abcd + 0: 123 + *** Failers + 0: *** + \ \ +No match +/\S{2,3}?/8 + 12abcd34 + 0: 12 + 1234abcd + 0: 12 + *** Failers + 0: ** + \ \ +No match + +/>\s+ <34 + 0: > < + 0+ 34 + *** Failers +No match + +/>\s{2,3} < + 0+ cd + ab> < + 0+ ce + *** Failers +No match + ab> \s{2,3}? < + 0+ cd + ab> < + 0+ ce + *** Failers +No match + ab> \xff< + 0: \xff + +/[\xff]/8 + >\x{ff}< + 0: \x{ff} + +/[^\xFF]/ + XYZ + 0: X + +/[^\xff]/8 + XYZ + 0: X + \x{123} + 0: \x{123} + +/^[ac]*b/8 + xb +No match + +/^[ac\x{100}]*b/8 + xb +No match + +/^[^x]*b/8i + xb +No match + +/^[^x]*b/8 + xb +No match + +/^\d*b/8 + xb +No match + +/(|a)/g8 + catac + 0: + 1: + 0: + 1: + 0: a + 1: a + 0: + 1: + 0: + 1: + 0: a + 1: a + 0: + 1: + 0: + 1: + a\x{256}a + 0: + 1: + 0: a + 1: a + 0: + 1: + 0: + 1: + 0: a + 1: a + 0: + 1: + +/^\x{85}$/8i + \x{85} + 0: \x{85} + +/ End of testinput4 / diff --git a/ext/pcre/pcrelib/testdata/testoutput5 b/ext/pcre/pcrelib/testdata/testoutput5 index 01daca505ee1..6e0d41802050 100644 --- a/ext/pcre/pcrelib/testdata/testoutput5 +++ b/ext/pcre/pcrelib/testdata/testoutput5 @@ -1,12 +1,12 @@ -PCRE version 3.92 11-Sep-2002 +PCRE version 6.2 01-Aug-2005 /\x{100}/8DM -Memory allocation (code space): 11 +Memory allocation (code space): 10 ------------------------------------------------------------------ - 0 7 Bra 0 - 3 2 \xc4\x80 - 7 7 Ket - 10 End + 0 6 Bra 0 + 3 \x{100} + 6 6 Ket + 9 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf8 @@ -14,12 +14,12 @@ First char = 196 Need char = 128 /\x{1000}/8DM -Memory allocation (code space): 12 +Memory allocation (code space): 11 ------------------------------------------------------------------ - 0 8 Bra 0 - 3 3 \xe1\x80\x80 - 8 8 Ket - 11 End + 0 7 Bra 0 + 3 \x{1000} + 7 7 Ket + 10 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf8 @@ -27,12 +27,12 @@ First char = 225 Need char = 128 /\x{10000}/8DM -Memory allocation (code space): 13 +Memory allocation (code space): 12 ------------------------------------------------------------------ - 0 9 Bra 0 - 3 4 \xf0\x90\x80\x80 - 9 9 Ket - 12 End + 0 8 Bra 0 + 3 \x{10000} + 8 8 Ket + 11 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf8 @@ -40,12 +40,12 @@ First char = 240 Need char = 128 /\x{100000}/8DM -Memory allocation (code space): 13 +Memory allocation (code space): 12 ------------------------------------------------------------------ - 0 9 Bra 0 - 3 4 \xf4\x80\x80\x80 - 9 9 Ket - 12 End + 0 8 Bra 0 + 3 \x{100000} + 8 8 Ket + 11 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf8 @@ -53,12 +53,12 @@ First char = 244 Need char = 128 /\x{1000000}/8DM -Memory allocation (code space): 14 +Memory allocation (code space): 13 ------------------------------------------------------------------ - 0 10 Bra 0 - 3 5 \xf9\x80\x80\x80\x80 - 10 10 Ket - 13 End + 0 9 Bra 0 + 3 \x{1000000} + 9 9 Ket + 12 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf8 @@ -66,12 +66,12 @@ First char = 249 Need char = 128 /\x{4000000}/8DM -Memory allocation (code space): 15 +Memory allocation (code space): 14 ------------------------------------------------------------------ - 0 11 Bra 0 - 3 6 \xfc\x84\x80\x80\x80\x80 - 11 11 Ket - 14 End + 0 10 Bra 0 + 3 \x{4000000} + 10 10 Ket + 13 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf8 @@ -79,12 +79,12 @@ First char = 252 Need char = 128 /\x{7fffFFFF}/8DM -Memory allocation (code space): 15 +Memory allocation (code space): 14 ------------------------------------------------------------------ - 0 11 Bra 0 - 3 6 \xfd\xbf\xbf\xbf\xbf\xbf - 11 11 Ket - 14 End + 0 10 Bra 0 + 3 \x{7fffffff} + 10 10 Ket + 13 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf8 @@ -92,20 +92,30 @@ First char = 253 Need char = 191 /[\x{ff}]/8DM -Memory allocation (code space): 40 +Memory allocation (code space): 10 ------------------------------------------------------------------ 0 6 Bra 0 - 3 1 \xff + 3 \x{ff} 6 6 Ket 9 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf8 -First char = 255 -No need char +First char = 195 +Need char = 191 /[\x{100}]/8DM -Failed: characters with values > 255 are not yet supported in classes at offset 7 +Memory allocation (code space): 47 +------------------------------------------------------------------ + 0 11 Bra 0 + 3 [\x{100}] + 11 11 Ket + 14 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Options: utf8 +No first char +No need char /\x{ffffffff}/8 Failed: character value in \x{...} sequence is too large at offset 11 @@ -119,10 +129,10 @@ Failed: character value in \x{...} sequence is too large at offset 12 /\x80/8D ------------------------------------------------------------------ - 0 7 Bra 0 - 3 2 \xc2\x80 - 7 7 Ket - 10 End + 0 6 Bra 0 + 3 \x{80} + 6 6 Ket + 9 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf8 @@ -131,10 +141,10 @@ Need char = 128 /\xff/8D ------------------------------------------------------------------ - 0 7 Bra 0 - 3 2 \xc3\xbf - 7 7 Ket - 10 End + 0 6 Bra 0 + 3 \x{ff} + 6 6 Ket + 9 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf8 @@ -143,10 +153,10 @@ Need char = 191 /\x{0041}\x{2262}\x{0391}\x{002e}/D8 ------------------------------------------------------------------ - 0 12 Bra 0 - 3 7 A\xe2\x89\xa2\xce\x91. - 12 12 Ket - 15 End + 0 14 Bra 0 + 3 A\x{2262}\x{391}. + 14 14 Ket + 17 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf8 @@ -157,10 +167,10 @@ Need char = '.' /\x{D55c}\x{ad6d}\x{C5B4}/D8 ------------------------------------------------------------------ - 0 14 Bra 0 - 3 9 \xed\x95\x9c\xea\xb5\xad\xec\x96\xb4 - 14 14 Ket - 17 End + 0 15 Bra 0 + 3 \x{d55c}\x{ad6d}\x{c5b4} + 15 15 Ket + 18 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf8 @@ -171,10 +181,10 @@ Need char = 180 /\x{65e5}\x{672c}\x{8a9e}/D8 ------------------------------------------------------------------ - 0 14 Bra 0 - 3 9 \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e - 14 14 Ket - 17 End + 0 15 Bra 0 + 3 \x{65e5}\x{672c}\x{8a9e} + 15 15 Ket + 18 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf8 @@ -185,10 +195,10 @@ Need char = 158 /\x{80}/D8 ------------------------------------------------------------------ - 0 7 Bra 0 - 3 2 \xc2\x80 - 7 7 Ket - 10 End + 0 6 Bra 0 + 3 \x{80} + 6 6 Ket + 9 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf8 @@ -197,10 +207,10 @@ Need char = 128 /\x{084}/D8 ------------------------------------------------------------------ - 0 7 Bra 0 - 3 2 \xc2\x84 - 7 7 Ket - 10 End + 0 6 Bra 0 + 3 \x{84} + 6 6 Ket + 9 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf8 @@ -209,10 +219,10 @@ Need char = 132 /\x{104}/D8 ------------------------------------------------------------------ - 0 7 Bra 0 - 3 2 \xc4\x84 - 7 7 Ket - 10 End + 0 6 Bra 0 + 3 \x{104} + 6 6 Ket + 9 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf8 @@ -221,10 +231,10 @@ Need char = 132 /\x{861}/D8 ------------------------------------------------------------------ - 0 8 Bra 0 - 3 3 \xe0\xa1\xa1 - 8 8 Ket - 11 End + 0 7 Bra 0 + 3 \x{861} + 7 7 Ket + 10 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf8 @@ -233,10 +243,10 @@ Need char = 161 /\x{212ab}/D8 ------------------------------------------------------------------ - 0 9 Bra 0 - 3 4 \xf0\xa1\x8a\xab - 9 9 Ket - 12 End + 0 8 Bra 0 + 3 \x{212ab} + 8 8 Ket + 11 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf8 @@ -245,14 +255,15 @@ Need char = 171 /.{3,5}X/D8 ------------------------------------------------------------------ - 0 14 Bra 0 + 0 13 Bra 0 3 Any{3} 7 Any{0,2} - 11 1 X - 14 14 Ket - 17 End + 11 X + 13 13 Ket + 16 End ------------------------------------------------------------------ Capturing subpattern count = 0 +Partial matching not supported Options: utf8 No first char Need char = 'X' @@ -269,6 +280,7 @@ Need char = 'X' 14 End ------------------------------------------------------------------ Capturing subpattern count = 0 +Partial matching not supported Options: utf8 No first char No need char @@ -334,6 +346,730 @@ No match 0: X\x{0a}abc 1: \x{0a} 2: abc + +/^[ab]/8D +------------------------------------------------------------------ + 0 37 Bra 0 + 3 ^ + 4 [ab] + 37 37 Ket + 40 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Options: anchored utf8 +No first char +No need char + bar + 0: b + *** Failers +No match + c +No match + \x{ff} +No match + \x{100} +No match -/ End of testinput5 / +/^[^ab]/8D +------------------------------------------------------------------ + 0 37 Bra 0 + 3 ^ + 4 [\x00-`c-\xff] (neg) + 37 37 Ket + 40 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Options: anchored utf8 +No first char +No need char + c + 0: c + \x{ff} + 0: \x{ff} + \x{100} + 0: \x{100} + *** Failers + 0: * + aaa +No match + +/[^ab\xC0-\xF0]/8SD +------------------------------------------------------------------ + 0 36 Bra 0 + 3 [\x00-`c-\xbf\xf1-\xff] (neg) + 36 36 Ket + 39 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Options: utf8 +No first char +No need char +Starting byte set: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a + \x0b \x0c \x0d \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 + \x1a \x1b \x1c \x1d \x1e \x1f \x20 ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 + 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y + Z [ \ ] ^ _ ` c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ \x7f + \xc2 \xc3 \xc4 \xc5 \xc6 \xc7 \xc8 \xc9 \xca \xcb \xcc \xcd \xce \xcf \xd0 + \xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7 \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf + \xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee + \xef \xf0 \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd + \xfe \xff + \x{f1} + 0: \x{f1} + \x{bf} + 0: \x{bf} + \x{100} + 0: \x{100} + \x{1000} + 0: \x{1000} + *** Failers + 0: * + \x{c0} +No match + \x{f0} +No match + +/Ä€{3,4}/8SD +------------------------------------------------------------------ + 0 13 Bra 0 + 3 \x{100}{3} + 8 \x{100}{,1} + 13 13 Ket + 16 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Partial matching not supported +Options: utf8 +First char = 196 +Need char = 128 +Study returned NULL + \x{100}\x{100}\x{100}\x{100\x{100} + 0: \x{100}\x{100}\x{100} + +/(\x{100}+|x)/8SD +------------------------------------------------------------------ + 0 17 Bra 0 + 3 6 Bra 1 + 6 \x{100}+ + 9 5 Alt + 12 x + 14 11 Ket + 17 17 Ket + 20 End +------------------------------------------------------------------ +Capturing subpattern count = 1 +Partial matching not supported +Options: utf8 +No first char +No need char +Starting byte set: x \xc4 + +/(\x{100}*a|x)/8SD +------------------------------------------------------------------ + 0 19 Bra 0 + 3 8 Bra 1 + 6 \x{100}* + 9 a + 11 5 Alt + 14 x + 16 13 Ket + 19 19 Ket + 22 End +------------------------------------------------------------------ +Capturing subpattern count = 1 +Partial matching not supported +Options: utf8 +No first char +No need char +Starting byte set: a x \xc4 + +/(\x{100}{0,2}a|x)/8SD +------------------------------------------------------------------ + 0 21 Bra 0 + 3 10 Bra 1 + 6 \x{100}{,2} + 11 a + 13 5 Alt + 16 x + 18 15 Ket + 21 21 Ket + 24 End +------------------------------------------------------------------ +Capturing subpattern count = 1 +Partial matching not supported +Options: utf8 +No first char +No need char +Starting byte set: a x \xc4 + +/(\x{100}{1,2}a|x)/8SD +------------------------------------------------------------------ + 0 24 Bra 0 + 3 13 Bra 1 + 6 \x{100} + 9 \x{100}{,1} + 14 a + 16 5 Alt + 19 x + 21 18 Ket + 24 24 Ket + 27 End +------------------------------------------------------------------ +Capturing subpattern count = 1 +Partial matching not supported +Options: utf8 +No first char +No need char +Starting byte set: x \xc4 + +/\x{100}*(\d+|"(?1)")/8 + 1234 + 0: 1234 + 1: 1234 + "1234" + 0: "1234" + 1: "1234" + \x{100}1234 + 0: \x{100}1234 + 1: 1234 + "\x{100}1234" + 0: \x{100}1234 + 1: 1234 + \x{100}\x{100}12ab + 0: \x{100}\x{100}12 + 1: 12 + \x{100}\x{100}"12" + 0: \x{100}\x{100}"12" + 1: "12" + *** Failers +No match + \x{100}\x{100}abcd +No match + +/\x{100}/8D +------------------------------------------------------------------ + 0 6 Bra 0 + 3 \x{100} + 6 6 Ket + 9 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Options: utf8 +First char = 196 +Need char = 128 + +/\x{100}*/8D +------------------------------------------------------------------ + 0 6 Bra 0 + 3 \x{100}* + 6 6 Ket + 9 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Partial matching not supported +Options: utf8 +No first char +No need char +/a\x{100}*/8D +------------------------------------------------------------------ + 0 8 Bra 0 + 3 a + 5 \x{100}* + 8 8 Ket + 11 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Partial matching not supported +Options: utf8 +First char = 'a' +No need char + +/ab\x{100}*/8D +------------------------------------------------------------------ + 0 10 Bra 0 + 3 ab + 7 \x{100}* + 10 10 Ket + 13 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Partial matching not supported +Options: utf8 +First char = 'a' +Need char = 'b' + +/a\x{100}\x{101}*/8D +------------------------------------------------------------------ + 0 11 Bra 0 + 3 a\x{100} + 8 \x{101}* + 11 11 Ket + 14 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Partial matching not supported +Options: utf8 +First char = 'a' +Need char = 128 + +/a\x{100}\x{101}+/8D +------------------------------------------------------------------ + 0 11 Bra 0 + 3 a\x{100} + 8 \x{101}+ + 11 11 Ket + 14 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Partial matching not supported +Options: utf8 +First char = 'a' +Need char = 129 + +/\x{100}*A/8D +------------------------------------------------------------------ + 0 8 Bra 0 + 3 \x{100}* + 6 A + 8 8 Ket + 11 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Partial matching not supported +Options: utf8 +No first char +Need char = 'A' + A + 0: A + +/\x{100}*\d(?R)/8D +------------------------------------------------------------------ + 0 10 Bra 0 + 3 \x{100}* + 6 \d + 7 0 Recurse + 10 10 Ket + 13 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Partial matching not supported +Options: utf8 +No first char +No need char + +/[^\x{c4}]/D +------------------------------------------------------------------ + 0 36 Bra 0 + 3 [\x01-35-bd-z|~-\xff] (neg) + 36 36 Ket + 39 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +No options +No first char +No need char + +/[^\x{c4}]/8D +------------------------------------------------------------------ + 0 36 Bra 0 + 3 [\x00-\xc3\xc5-\xff] (neg) + 36 36 Ket + 39 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Options: utf8 +No first char +No need char + +/[\x{100}]/8DM +Memory allocation (code space): 47 +------------------------------------------------------------------ + 0 11 Bra 0 + 3 [\x{100}] + 11 11 Ket + 14 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Options: utf8 +No first char +No need char + \x{100} + 0: \x{100} + Z\x{100} + 0: \x{100} + \x{100}Z + 0: \x{100} + *** Failers +No match + +/[Z\x{100}]/8DM +Memory allocation (code space): 47 +------------------------------------------------------------------ + 0 43 Bra 0 + 3 [Z\x{100}] + 43 43 Ket + 46 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Options: utf8 +No first char +No need char + Z\x{100} + 0: Z + \x{100} + 0: \x{100} + \x{100}Z + 0: \x{100} + *** Failers +No match + +/[\x{200}-\x{100}]/8 +Failed: range out of order in character class at offset 15 + +/[Ä€-Ä„]/8 + \x{100} + 0: \x{100} + \x{104} + 0: \x{104} + *** Failers +No match + \x{105} +No match + \x{ff} +No match + +/[z-\x{100}]/8D +------------------------------------------------------------------ + 0 12 Bra 0 + 3 [z-\x{100}] + 12 12 Ket + 15 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Options: utf8 +No first char +No need char + +/[z\Qa-d]Ä€\E]/8D +------------------------------------------------------------------ + 0 43 Bra 0 + 3 [\-\]adz\x{100}] + 43 43 Ket + 46 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Options: utf8 +No first char +No need char + \x{100} + 0: \x{100} + Ä€ + 0: \x{100} + +/[\xFF]/D +------------------------------------------------------------------ + 0 5 Bra 0 + 3 \xff + 5 5 Ket + 8 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +No options +First char = 255 +No need char + >\xff< + 0: \xff + +/[\xff]/D8 +------------------------------------------------------------------ + 0 6 Bra 0 + 3 \x{ff} + 6 6 Ket + 9 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Options: utf8 +First char = 195 +Need char = 191 + >\x{ff}< + 0: \x{ff} + +/[^\xFF]/D +------------------------------------------------------------------ + 0 5 Bra 0 + 3 [^\xff] + 5 5 Ket + 8 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +No options +No first char +No need char + +/[^\xff]/8D +------------------------------------------------------------------ + 0 36 Bra 0 + 3 [\x00-\xfe] (neg) + 36 36 Ket + 39 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Options: utf8 +No first char +No need char + +/[Ä-Ü]/8 + Ö # Matches without Study + 0: \x{d6} + \x{d6} + 0: \x{d6} + +/[Ä-Ü]/8S + Ö <-- Same with Study + 0: \x{d6} + \x{d6} + 0: \x{d6} + +/[\x{c4}-\x{dc}]/8 + Ö # Matches without Study + 0: \x{d6} + \x{d6} + 0: \x{d6} + +/[\x{c4}-\x{dc}]/8S + Ö <-- Same with Study + 0: \x{d6} + \x{d6} + 0: \x{d6} + +/[Ã]/8 +Failed: invalid UTF-8 string at offset 2 + +/Ã/8 +Failed: invalid UTF-8 string at offset 0 + +/ÃÃÃxxx/8 +Failed: invalid UTF-8 string at offset 1 + +/ÃÃÃxxx/8?D +------------------------------------------------------------------ + 0 15 Bra 0 + 3 \X{c0}\X{c0}\X{c0}xxx + 15 15 Ket + 18 End +------------------------------------------------------------------ +Capturing subpattern count = 0 +Options: utf8 no_utf8_check +First char = 195 +Need char = 'x' + +/abc/8 + Ã] +Error -10 + à +Error -10 + ÃÃà +Error -10 + ÃÃÃ\? +No match + +/anything/8 + \xc0\x80 +Error -10 + \xc1\x8f +Error -10 + \xe0\x9f\x80 +Error -10 + \xf0\x8f\x80\x80 +Error -10 + \xf8\x87\x80\x80\x80 +Error -10 + \xfc\x83\x80\x80\x80\x80 +Error -10 + \xfe\x80\x80\x80\x80\x80 +Error -10 + \xff\x80\x80\x80\x80\x80 +Error -10 + \xc3\x8f +No match + \xe0\xaf\x80 +No match + \xe1\x80\x80 +No match + \xf0\x9f\x80\x80 +No match + \xf1\x8f\x80\x80 +No match + \xf8\x88\x80\x80\x80 +No match + \xf9\x87\x80\x80\x80 +No match + \xfc\x84\x80\x80\x80\x80 +No match + \xfd\x83\x80\x80\x80\x80 +No match + +/\x{100}abc(xyz(?1))/8D +------------------------------------------------------------------ + 0 27 Bra 0 + 3 \x{100}abc + 12 12 Bra 1 + 15 xyz + 21 12 Recurse + 24 12 Ket + 27 27 Ket + 30 End +------------------------------------------------------------------ +Capturing subpattern count = 1 +Options: utf8 +First char = 196 +Need char = 'z' + +/[^\x{100}]abc(xyz(?1))/8D +------------------------------------------------------------------ + 0 32 Bra 0 + 3 [^\x{100}] + 11 abc + 17 12 Bra 1 + 20 xyz + 26 17 Recurse + 29 12 Ket + 32 32 Ket + 35 End +------------------------------------------------------------------ +Capturing subpattern count = 1 +Options: utf8 +No first char +Need char = 'z' + +/[ab\x{100}]abc(xyz(?1))/8D +------------------------------------------------------------------ + 0 64 Bra 0 + 3 [ab\x{100}] + 43 abc + 49 12 Bra 1 + 52 xyz + 58 49 Recurse + 61 12 Ket + 64 64 Ket + 67 End +------------------------------------------------------------------ +Capturing subpattern count = 1 +Options: utf8 +No first char +Need char = 'z' + +/(\x{100}(b(?2)c))?/D8 +------------------------------------------------------------------ + 0 26 Bra 0 + 3 Brazero + 4 19 Bra 1 + 7 \x{100} + 10 10 Bra 2 + 13 b + 15 10 Recurse + 18 c + 20 10 Ket + 23 19 Ket + 26 26 Ket + 29 End +------------------------------------------------------------------ +Capturing subpattern count = 2 +Options: utf8 +No first char +No need char + +/(\x{100}(b(?2)c)){0,2}/D8 +------------------------------------------------------------------ + 0 55 Bra 0 + 3 Brazero + 4 48 Bra 0 + 7 19 Bra 1 + 10 \x{100} + 13 10 Bra 2 + 16 b + 18 13 Recurse + 21 c + 23 10 Ket + 26 19 Ket + 29 Brazero + 30 19 Bra 1 + 33 \x{100} + 36 10 Bra 2 + 39 b + 41 13 Recurse + 44 c + 46 10 Ket + 49 19 Ket + 52 48 Ket + 55 55 Ket + 58 End +------------------------------------------------------------------ +Capturing subpattern count = 2 +Options: utf8 +No first char +No need char + +/(\x{100}(b(?1)c))?/D8 +------------------------------------------------------------------ + 0 26 Bra 0 + 3 Brazero + 4 19 Bra 1 + 7 \x{100} + 10 10 Bra 2 + 13 b + 15 4 Recurse + 18 c + 20 10 Ket + 23 19 Ket + 26 26 Ket + 29 End +------------------------------------------------------------------ +Capturing subpattern count = 2 +Options: utf8 +No first char +No need char + +/(\x{100}(b(?1)c)){0,2}/D8 +------------------------------------------------------------------ + 0 55 Bra 0 + 3 Brazero + 4 48 Bra 0 + 7 19 Bra 1 + 10 \x{100} + 13 10 Bra 2 + 16 b + 18 7 Recurse + 21 c + 23 10 Ket + 26 19 Ket + 29 Brazero + 30 19 Bra 1 + 33 \x{100} + 36 10 Bra 2 + 39 b + 41 7 Recurse + 44 c + 46 10 Ket + 49 19 Ket + 52 48 Ket + 55 55 Ket + 58 End +------------------------------------------------------------------ +Capturing subpattern count = 2 +Options: utf8 +No first char +No need char + +/\W/8 + A.B + 0: . + A\x{100}B + 0: \x{100} + +/\w/8 + \x{100}X + 0: X + +/ End of testinput5 / diff --git a/ext/pcre/pcrelib/testdata/testoutput6 b/ext/pcre/pcrelib/testdata/testoutput6 index fcf084670fa3..9f9421e51937 100644 --- a/ext/pcre/pcrelib/testdata/testoutput6 +++ b/ext/pcre/pcrelib/testdata/testoutput6 @@ -1,319 +1,1013 @@ -PCRE version 3.9 02-Jan-2002 +PCRE version 6.2 01-Aug-2005 -/\x{100}/8DM -Memory allocation (code space): 11 ------------------------------------------------------------------- - 0 7 Bra 0 - 3 2 \xc4\x80 - 7 7 Ket - 10 End ------------------------------------------------------------------- -Capturing subpattern count = 0 -Options: utf8 -First char = 196 -Need char = 128 +/^\pC\pL\pM\pN\pP\pS\pZ 255 are not yet supported in classes at offset 7 +/[\P{Nd}]+/8 + abcd + 0: abcd + ** Failers + 0: ** Failers + 1234 +No match -/\x{ffffffff}/8 -Failed: character value in \x{...} sequence is too large at offset 11 +/\D+/8 + 11111111111111111111111111111111111111111111111111111111111111111111111 +No match + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +/\P{Nd}+/8 + 11111111111111111111111111111111111111111111111111111111111111111111111 +No match + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -/\x{100000000}/8 -Failed: character value in \x{...} sequence is too large at offset 12 +/[\D]+/8 + 11111111111111111111111111111111111111111111111111111111111111111111111 +No match + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -/^\x{100}a\x{1234}/8 - \x{100}a\x{1234}bcd - 0: \x{100}a\x{1234} +/[\P{Nd}]+/8 + 11111111111111111111111111111111111111111111111111111111111111111111111 +No match + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -/\x80/8D ------------------------------------------------------------------- - 0 7 Bra 0 - 3 2 \xc2\x80 - 7 7 Ket - 10 End ------------------------------------------------------------------- -Capturing subpattern count = 0 -Options: utf8 -First char = 194 -Need char = 128 +/[\D\P{Nd}]+/8 + 11111111111111111111111111111111111111111111111111111111111111111111111 +No match + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -/\xff/8D ------------------------------------------------------------------- - 0 7 Bra 0 - 3 2 \xc3\xbf - 7 7 Ket - 10 End ------------------------------------------------------------------- -Capturing subpattern count = 0 -Options: utf8 -First char = 195 -Need char = 191 +/\pL/8 + a + 0: a + A + 0: A -/\x{0041}\x{2262}\x{0391}\x{002e}/D8 ------------------------------------------------------------------- - 0 12 Bra 0 - 3 7 A\xe2\x89\xa2\xce\x91. - 12 12 Ket - 15 End ------------------------------------------------------------------- -Capturing subpattern count = 0 -Options: utf8 -First char = 'A' -Need char = '.' - \x{0041}\x{2262}\x{0391}\x{002e} - 0: A\x{2262}\x{391}. +/\pL/8i + a + 0: a + A + 0: A -/\x{D55c}\x{ad6d}\x{C5B4}/D8 ------------------------------------------------------------------- - 0 14 Bra 0 - 3 9 \xed\x95\x9c\xea\xb5\xad\xec\x96\xb4 - 14 14 Ket - 17 End ------------------------------------------------------------------- -Capturing subpattern count = 0 -Options: utf8 -First char = 237 -Need char = 180 - \x{D55c}\x{ad6d}\x{C5B4} - 0: \x{d55c}\x{ad6d}\x{c5b4} +/\p{Lu}/8 + A + 0: A + aZ + 0: Z + ** Failers + 0: F + abc +No match -/\x{65e5}\x{672c}\x{8a9e}/D8 ------------------------------------------------------------------- - 0 14 Bra 0 - 3 9 \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e - 14 14 Ket - 17 End ------------------------------------------------------------------- -Capturing subpattern count = 0 -Options: utf8 -First char = 230 -Need char = 158 - \x{65e5}\x{672c}\x{8a9e} - 0: \x{65e5}\x{672c}\x{8a9e} +/\p{Lu}/8i + A + 0: A + aZ + 0: Z + ** Failers + 0: F + abc +No match -/\x{80}/D8 +/\p{Ll}/8 + a + 0: a + Az + 0: z + ** Failers + 0: a + ABC +No match + +/\p{Ll}/8i + a + 0: a + Az + 0: z + ** Failers + 0: a + ABC +No match + +/^\x{c0}$/8i + \x{c0} + 0: \x{c0} + \x{e0} + 0: \x{e0} + +/^\x{e0}$/8i + \x{c0} + 0: \x{c0} + \x{e0} + 0: \x{e0} + +/A\x{391}\x{10427}\x{ff3a}\x{1fb0}/8 + A\x{391}\x{10427}\x{ff3a}\x{1fb0} + 0: A\x{391}\x{10427}\x{ff3a}\x{1fb0} + ** Failers +No match + a\x{391}\x{10427}\x{ff3a}\x{1fb0} +No match + A\x{3b1}\x{10427}\x{ff3a}\x{1fb0} +No match + A\x{391}\x{1044F}\x{ff3a}\x{1fb0} +No match + A\x{391}\x{10427}\x{ff5a}\x{1fb0} +No match + A\x{391}\x{10427}\x{ff3a}\x{1fb8} +No match + +/A\x{391}\x{10427}\x{ff3a}\x{1fb0}/8i + A\x{391}\x{10427}\x{ff3a}\x{1fb0} + 0: A\x{391}\x{10427}\x{ff3a}\x{1fb0} + a\x{391}\x{10427}\x{ff3a}\x{1fb0} + 0: a\x{391}\x{10427}\x{ff3a}\x{1fb0} + A\x{3b1}\x{10427}\x{ff3a}\x{1fb0} + 0: A\x{3b1}\x{10427}\x{ff3a}\x{1fb0} + A\x{391}\x{1044F}\x{ff3a}\x{1fb0} + 0: A\x{391}\x{1044f}\x{ff3a}\x{1fb0} + A\x{391}\x{10427}\x{ff5a}\x{1fb0} + 0: A\x{391}\x{10427}\x{ff5a}\x{1fb0} + A\x{391}\x{10427}\x{ff3a}\x{1fb8} + 0: A\x{391}\x{10427}\x{ff3a}\x{1fb8} + +/A\x{391}\x{10427}\x{ff3a}\x{1fb0}/8iD ------------------------------------------------------------------ - 0 7 Bra 0 - 3 2 \xc2\x80 - 7 7 Ket - 10 End + 0 21 Bra 0 + 3 NC A\x{391}\x{10427}\x{ff3a}\x{1fb0} + 21 21 Ket + 24 End ------------------------------------------------------------------ Capturing subpattern count = 0 -Options: utf8 -First char = 194 -Need char = 128 +Options: caseless utf8 +First char = 'A' (caseless) +No need char -/\x{084}/D8 +/A\x{391}\x{10427}\x{ff3a}\x{1fb0}/8D ------------------------------------------------------------------ - 0 7 Bra 0 - 3 2 \xc2\x84 - 7 7 Ket - 10 End + 0 21 Bra 0 + 3 A\x{391}\x{10427}\x{ff3a}\x{1fb0} + 21 21 Ket + 24 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf8 -First char = 194 -Need char = 132 +First char = 'A' +Need char = 176 -/\x{104}/D8 +/AB\x{1fb0}/8D ------------------------------------------------------------------ - 0 7 Bra 0 - 3 2 \xc4\x84 - 7 7 Ket - 10 End + 0 11 Bra 0 + 3 AB\x{1fb0} + 11 11 Ket + 14 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf8 -First char = 196 -Need char = 132 +First char = 'A' +Need char = 176 -/\x{861}/D8 +/AB\x{1fb0}/8Di ------------------------------------------------------------------ - 0 8 Bra 0 - 3 3 \xe0\xa1\xa1 - 8 8 Ket - 11 End + 0 11 Bra 0 + 3 NC AB\x{1fb0} + 11 11 Ket + 14 End ------------------------------------------------------------------ Capturing subpattern count = 0 -Options: utf8 -First char = 224 -Need char = 161 +Options: caseless utf8 +First char = 'A' (caseless) +Need char = 'B' (caseless) + +/\x{391}+/8i + \x{391}\x{3b1}\x{3b1}\x{3b1}\x{391} + 0: \x{391}\x{3b1}\x{3b1}\x{3b1}\x{391} + +/\x{391}{3,5}(.)/8i + \x{391}\x{3b1}\x{3b1}\x{3b1}\x{391}X + 0: \x{391}\x{3b1}\x{3b1}\x{3b1}\x{391}X + 1: X + +/\x{391}{3,5}?(.)/8i + \x{391}\x{3b1}\x{3b1}\x{3b1}\x{391}X + 0: \x{391}\x{3b1}\x{3b1}\x{3b1} + 1: \x{3b1} -/\x{212ab}/D8 +/[\x{391}\x{ff3a}]/8i + \x{391} + 0: \x{391} + \x{ff3a} + 0: \x{ff3a} + \x{3b1} + 0: \x{3b1} + \x{ff5a} + 0: \x{ff5a} + +/[\x{c0}\x{391}]/8i + \x{c0} + 0: \x{c0} + \x{e0} + 0: \x{e0} + +/[\x{105}-\x{109}]/8iD ------------------------------------------------------------------ - 0 9 Bra 0 - 3 4 \xf0\xa1\x8a\xab - 9 9 Ket - 12 End + 0 13 Bra 0 + 3 [\x{104}-\x{109}] + 13 13 Ket + 16 End ------------------------------------------------------------------ Capturing subpattern count = 0 -Options: utf8 -First char = 240 -Need char = 171 - -/.{3,5}X/D8 +Options: caseless utf8 +No first char +No need char + \x{104} + 0: \x{104} + \x{105} + 0: \x{105} + \x{109} + 0: \x{109} + ** Failers +No match + \x{100} +No match + \x{10a} +No match + +/[z-\x{100}]/8iD ------------------------------------------------------------------ - 0 14 Bra 0 - 3 Any{3} - 7 Any{0,2} - 11 1 X - 14 14 Ket - 17 End + 0 20 Bra 0 + 3 [Z\x{39c}\x{178}z-\x{101}] + 20 20 Ket + 23 End ------------------------------------------------------------------ Capturing subpattern count = 0 -Options: utf8 +Options: caseless utf8 No first char -Need char = 'X' - \x{212ab}\x{212ab}\x{212ab}\x{861}X - 0: \x{212ab}\x{212ab}\x{212ab}\x{861}X - +No need char + Z + 0: Z + z + 0: z + \x{39c} + 0: \x{39c} + \x{178} + 0: \x{178} + | + 0: | + \x{80} + 0: \x{80} + \x{ff} + 0: \x{ff} + \x{100} + 0: \x{100} + \x{101} + 0: \x{101} + ** Failers +No match + \x{102} +No match + Y +No match + y +No match -/.{3,5}?/D8 +/[z-\x{100}]/8Di ------------------------------------------------------------------ - 0 11 Bra 0 - 3 Any{3} - 7 Any{0,2}? - 11 11 Ket - 14 End + 0 20 Bra 0 + 3 [Z\x{39c}\x{178}z-\x{101}] + 20 20 Ket + 23 End ------------------------------------------------------------------ Capturing subpattern count = 0 -Options: utf8 +Options: caseless utf8 No first char No need char - \x{212ab}\x{212ab}\x{212ab}\x{861} - 0: \x{212ab}\x{212ab}\x{212ab} -/-- These tests are here rather than in testinput5 because Perl 5.6 has --/ -/-- some problems with UTF-8 support, in the area of \x{..} where the --/ +/^\X/8 + A + 0: A + A\x{300}BC + 0: A\x{300} + A\x{300}\x{301}\x{302}BC + 0: A\x{300}\x{301}\x{302} + *** Failers + 0: * + \x{300} +No match + +/^[\X]/8 + X123 + 0: X + *** Failers No match -/-- value is < 255. It grumbles about invalid UTF-8 strings. --/ + AXYZ No match -/^[a\x{c0}]b/8 - \x{c0}b - 0: \x{c0}b - -/^([a\x{c0}]*?)aa/8 - a\x{c0}aaaa/ - 0: a\x{c0}aa - 1: a\x{c0} - -/^([a\x{c0}]*?)aa/8 - a\x{c0}aaaa/ - 0: a\x{c0}aa - 1: a\x{c0} - a\x{c0}a\x{c0}aaa/ - 0: a\x{c0}a\x{c0}aa - 1: a\x{c0}a\x{c0} - -/^([a\x{c0}]*)aa/8 - a\x{c0}aaaa/ - 0: a\x{c0}aaaa - 1: a\x{c0}aa - a\x{c0}a\x{c0}aaa/ - 0: a\x{c0}a\x{c0}aaa - 1: a\x{c0}a\x{c0}a - -/^([a\x{c0}]*)a\x{c0}/8 - a\x{c0}aaaa/ - 0: a\x{c0} +/^(\X*)C/8 + A\x{300}\x{301}\x{302}BCA\x{300}\x{301} + 0: A\x{300}\x{301}\x{302}BC + 1: A\x{300}\x{301}\x{302}B + A\x{300}\x{301}\x{302}BCA\x{300}\x{301}C + 0: A\x{300}\x{301}\x{302}BCA\x{300}\x{301}C + 1: A\x{300}\x{301}\x{302}BCA\x{300}\x{301} + +/^(\X*?)C/8 + A\x{300}\x{301}\x{302}BCA\x{300}\x{301} + 0: A\x{300}\x{301}\x{302}BC + 1: A\x{300}\x{301}\x{302}B + A\x{300}\x{301}\x{302}BCA\x{300}\x{301}C + 0: A\x{300}\x{301}\x{302}BC + 1: A\x{300}\x{301}\x{302}B + +/^(\X*)(.)/8 + A\x{300}\x{301}\x{302}BCA\x{300}\x{301} + 0: A\x{300}\x{301}\x{302}BCA + 1: A\x{300}\x{301}\x{302}BC + 2: A + A\x{300}\x{301}\x{302}BCA\x{300}\x{301}C + 0: A\x{300}\x{301}\x{302}BCA\x{300}\x{301}C + 1: A\x{300}\x{301}\x{302}BCA\x{300}\x{301} + 2: C + +/^(\X*?)(.)/8 + A\x{300}\x{301}\x{302}BCA\x{300}\x{301} + 0: A + 1: + 2: A + A\x{300}\x{301}\x{302}BCA\x{300}\x{301}C + 0: A 1: - a\x{c0}a\x{c0}aaa/ - 0: a\x{c0}a\x{c0} - 1: a\x{c0} + 2: A -/ End of testinput6 / +/^\X(.)/8 + *** Failers + 0: ** + 1: * + A\x{300}\x{301}\x{302} +No match +/^\X{2,3}(.)/8 + A\x{300}\x{301}B\x{300}X + 0: A\x{300}\x{301}B\x{300}X + 1: X + A\x{300}\x{301}B\x{300}C\x{300}\x{301} + 0: A\x{300}\x{301}B\x{300}C + 1: C + A\x{300}\x{301}B\x{300}C\x{300}\x{301}X + 0: A\x{300}\x{301}B\x{300}C\x{300}\x{301}X + 1: X + A\x{300}\x{301}B\x{300}C\x{300}\x{301}DA\x{300}X + 0: A\x{300}\x{301}B\x{300}C\x{300}\x{301}D + 1: D + +/^\X{2,3}?(.)/8 + A\x{300}\x{301}B\x{300}X + 0: A\x{300}\x{301}B\x{300}X + 1: X + A\x{300}\x{301}B\x{300}C\x{300}\x{301} + 0: A\x{300}\x{301}B\x{300}C + 1: C + A\x{300}\x{301}B\x{300}C\x{300}\x{301}X + 0: A\x{300}\x{301}B\x{300}C + 1: C + A\x{300}\x{301}B\x{300}C\x{300}\x{301}DA\x{300}X + 0: A\x{300}\x{301}B\x{300}C + 1: C + +/ End of testinput6 / diff --git a/ext/pcre/pcrelib/testdata/testoutput7 b/ext/pcre/pcrelib/testdata/testoutput7 new file mode 100644 index 000000000000..85dd0a634400 --- /dev/null +++ b/ext/pcre/pcrelib/testdata/testoutput7 @@ -0,0 +1,6517 @@ +PCRE version 6.2 01-Aug-2005 + +/abc/ + abc + 0: abc + +/ab*c/ + abc + 0: abc + abbbbc + 0: abbbbc + ac + 0: ac + +/ab+c/ + abc + 0: abc + abbbbbbc + 0: abbbbbbc + *** Failers +No match + ac +No match + ab +No match + +/a*/ + a + 0: a + 1: + aaaaaaaaaaaaaaaaa + 0: aaaaaaaaaaaaaaaaa + 1: aaaaaaaaaaaaaaaa + 2: aaaaaaaaaaaaaaa + 3: aaaaaaaaaaaaaa + 4: aaaaaaaaaaaaa + 5: aaaaaaaaaaaa + 6: aaaaaaaaaaa + 7: aaaaaaaaaa + 8: aaaaaaaaa + 9: aaaaaaaa +10: aaaaaaa +11: aaaaaa +12: aaaaa +13: aaaa +14: aaa +15: aa +16: a +17: + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +Matched, but too many subsidiary matches + 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 1: aaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 2: aaaaaaaaaaaaaaaaaaaaaaaaaaaa + 3: aaaaaaaaaaaaaaaaaaaaaaaaaaa + 4: aaaaaaaaaaaaaaaaaaaaaaaaaa + 5: aaaaaaaaaaaaaaaaaaaaaaaaa + 6: aaaaaaaaaaaaaaaaaaaaaaaa + 7: aaaaaaaaaaaaaaaaaaaaaaa + 8: aaaaaaaaaaaaaaaaaaaaaa + 9: aaaaaaaaaaaaaaaaaaaaa +10: aaaaaaaaaaaaaaaaaaaa +11: aaaaaaaaaaaaaaaaaaa +12: aaaaaaaaaaaaaaaaaa +13: aaaaaaaaaaaaaaaaa +14: aaaaaaaaaaaaaaaa +15: aaaaaaaaaaaaaaa +16: aaaaaaaaaaaaaa +17: aaaaaaaaaaaaa +18: aaaaaaaaaaaa +19: aaaaaaaaaaa +20: aaaaaaaaaa +21: aaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\F + 0: + +/(a|abcd|african)/ + a + 0: a + abcd + 0: abcd + 1: a + african + 0: african + 1: a + +/^abc/ + abcdef + 0: abc + *** Failers +No match + xyzabc +No match + xyz\nabc +No match + +/^abc/m + abcdef + 0: abc + xyz\nabc + 0: abc + *** Failers +No match + xyzabc +No match + +/\Aabc/ + abcdef + 0: abc + *** Failers +No match + xyzabc +No match + xyz\nabc +No match + +/\Aabc/m + abcdef + 0: abc + *** Failers +No match + xyzabc +No match + xyz\nabc +No match + +/\Gabc/ + abcdef + 0: abc + xyzabc\>3 + 0: abc + *** Failers +No match + xyzabc +No match + xyzabc\>2 +No match + +/x\dy\Dz/ + x9yzz + 0: x9yzz + x0y+z + 0: x0y+z + *** Failers +No match + xyz +No match + xxy0z +No match + +/x\sy\Sz/ + x yzz + 0: x yzz + x y+z + 0: x y+z + *** Failers +No match + xyz +No match + xxyyz +No match + +/x\wy\Wz/ + xxy+z + 0: xxy+z + *** Failers +No match + xxy0z +No match + x+y+z +No match + +/x.y/ + x+y + 0: x+y + x-y + 0: x-y + *** Failers +No match + x\ny +No match + +/x.y/s + x+y + 0: x+y + x-y + 0: x-y + x\ny + 0: x\x0ay + +/(a.b(?s)c.d|x.y)p.q/ + a+bc+dp+q + 0: a+bc+dp+q + a+bc\ndp+q + 0: a+bc\x0adp+q + x\nyp+q + 0: x\x0ayp+q + *** Failers +No match + a\nbc\ndp+q +No match + a+bc\ndp\nq +No match + x\nyp\nq +No match + +/a\d\z/ + ba0 + 0: a0 + *** Failers +No match + ba0\n +No match + ba0\ncd +No match + +/a\d\z/m + ba0 + 0: a0 + *** Failers +No match + ba0\n +No match + ba0\ncd +No match + +/a\d\Z/ + ba0 + 0: a0 + ba0\n + 0: a0 + *** Failers +No match + ba0\ncd +No match + +/a\d\Z/m + ba0 + 0: a0 + ba0\n + 0: a0 + *** Failers +No match + ba0\ncd +No match + +/a\d$/ + ba0 + 0: a0 + ba0\n + 0: a0 + *** Failers +No match + ba0\ncd +No match + +/a\d$/m + ba0 + 0: a0 + ba0\n + 0: a0 + ba0\ncd + 0: a0 + *** Failers +No match + +/abc/i + abc + 0: abc + aBc + 0: aBc + ABC + 0: ABC + +/[^a]/ + abcd + 0: b + +/ab?\w/ + abz + 0: abz + 1: ab + abbz + 0: abb + 1: ab + azz + 0: az + +/x{0,3}yz/ + ayzq + 0: yz + axyzq + 0: xyz + axxyz + 0: xxyz + axxxyzq + 0: xxxyz + axxxxyzq + 0: xxxyz + *** Failers +No match + ax +No match + axx +No match + +/x{3}yz/ + axxxyzq + 0: xxxyz + axxxxyzq + 0: xxxyz + *** Failers +No match + ax +No match + axx +No match + ayzq +No match + axyzq +No match + axxyz +No match + +/x{2,3}yz/ + axxyz + 0: xxyz + axxxyzq + 0: xxxyz + axxxxyzq + 0: xxxyz + *** Failers +No match + ax +No match + axx +No match + ayzq +No match + axyzq +No match + +/[^a]+/ + bac + 0: b + bcdefax + 0: bcdef + 1: bcde + 2: bcd + 3: bc + 4: b + *** Failers + 0: *** F + 1: *** + 2: *** + 3: ** + 4: * + aaaaa +No match + +/[^a]*/ + bac + 0: b + 1: + bcdefax + 0: bcdef + 1: bcde + 2: bcd + 3: bc + 4: b + 5: + *** Failers + 0: *** F + 1: *** + 2: *** + 3: ** + 4: * + 5: + aaaaa + 0: + +/[^a]{3,5}/ + xyz + 0: xyz + awxyza + 0: wxyz + 1: wxy + abcdefa + 0: bcdef + 1: bcde + 2: bcd + abcdefghijk + 0: bcdef + 1: bcde + 2: bcd + *** Failers + 0: *** F + 1: *** + 2: *** + axya +No match + axa +No match + aaaaa +No match + +/\d*/ + 1234b567 + 0: 1234 + 1: 123 + 2: 12 + 3: 1 + 4: + xyz + 0: + +/\D*/ + a1234b567 + 0: a + 1: + xyz + 0: xyz + 1: xy + 2: x + 3: + +/\d+/ + ab1234c56 + 0: 1234 + 1: 123 + 2: 12 + 3: 1 + *** Failers +No match + xyz +No match + +/\D+/ + ab123c56 + 0: ab + 1: a + *** Failers + 0: *** Failers + 1: *** Failer + 2: *** Faile + 3: *** Fail + 4: *** Fai + 5: *** Fa + 6: *** F + 7: *** + 8: *** + 9: ** +10: * + 789 +No match + +/\d?A/ + 045ABC + 0: 5A + ABC + 0: A + *** Failers +No match + XYZ +No match + +/\D?A/ + ABC + 0: A + BAC + 0: BA + 9ABC + 0: A + *** Failers +No match + +/a+/ + aaaa + 0: aaaa + 1: aaa + 2: aa + 3: a + +/^.*xyz/ + xyz + 0: xyz + ggggggggxyz + 0: ggggggggxyz + +/^.+xyz/ + abcdxyz + 0: abcdxyz + axyz + 0: axyz + *** Failers +No match + xyz +No match + +/^.?xyz/ + xyz + 0: xyz + cxyz + 0: cxyz + +/^\d{2,3}X/ + 12X + 0: 12X + 123X + 0: 123X + *** Failers +No match + X +No match + 1X +No match + 1234X +No match + +/^[abcd]\d/ + a45 + 0: a4 + b93 + 0: b9 + c99z + 0: c9 + d04 + 0: d0 + *** Failers +No match + e45 +No match + abcd +No match + abcd1234 +No match + 1234 +No match + +/^[abcd]*\d/ + a45 + 0: a4 + b93 + 0: b9 + c99z + 0: c9 + d04 + 0: d0 + abcd1234 + 0: abcd1 + 1234 + 0: 1 + *** Failers +No match + e45 +No match + abcd +No match + +/^[abcd]+\d/ + a45 + 0: a4 + b93 + 0: b9 + c99z + 0: c9 + d04 + 0: d0 + abcd1234 + 0: abcd1 + *** Failers +No match + 1234 +No match + e45 +No match + abcd +No match + +/^a+X/ + aX + 0: aX + aaX + 0: aaX + +/^[abcd]?\d/ + a45 + 0: a4 + b93 + 0: b9 + c99z + 0: c9 + d04 + 0: d0 + 1234 + 0: 1 + *** Failers +No match + abcd1234 +No match + e45 +No match + +/^[abcd]{2,3}\d/ + ab45 + 0: ab4 + bcd93 + 0: bcd9 + *** Failers +No match + 1234 +No match + a36 +No match + abcd1234 +No match + ee45 +No match + +/^(abc)*\d/ + abc45 + 0: abc4 + abcabcabc45 + 0: abcabcabc4 + 42xyz + 0: 4 + *** Failers +No match + +/^(abc)+\d/ + abc45 + 0: abc4 + abcabcabc45 + 0: abcabcabc4 + *** Failers +No match + 42xyz +No match + +/^(abc)?\d/ + abc45 + 0: abc4 + 42xyz + 0: 4 + *** Failers +No match + abcabcabc45 +No match + +/^(abc){2,3}\d/ + abcabc45 + 0: abcabc4 + abcabcabc45 + 0: abcabcabc4 + *** Failers +No match + abcabcabcabc45 +No match + abc45 +No match + 42xyz +No match + +/1(abc|xyz)2(?1)3/ + 1abc2abc3456 + 0: 1abc2abc3 + 1abc2xyz3456 + 0: 1abc2xyz3 + +/^(a*\w|ab)=(a*\w|ab)/ + ab=ab + 0: ab=ab + 1: ab=a + +/^(a*\w|ab)=(?1)/ + ab=ab + 0: ab=ab + 1: ab=a + +/^([^()]|\((?1)*\))*$/ + abc + 0: abc + a(b)c + 0: a(b)c + a(b(c))d + 0: a(b(c))d + *** Failers) +No match + a(b(c)d +No match + +/^>abc>([^()]|\((?1)*\))*abc>123abc>123abc>1(2)3abc>1(2)3abc>(1(2)3)abc>(1(2)3)a*)\d/ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9876 + 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9 + *** Failers +No match + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +No match + +/< (?: (?(R) \d++ | [^<>]*+) | (?R)) * >/x + <> + 0: <> + + 0: + hij> + 0: hij> + hij> + 0: + def> + 0: def> + + 0: <> + *** Failers +No match + abcxyz + 1 ^ ^ x + 0: abcxyz + 123abcxyz999 +--->123abcxyz999 + 1 ^ ^ x + 0: abcxyz + +/(ab|cd){3,4}/C + ababab +--->ababab + +0 ^ (ab|cd){3,4} + +1 ^ a + +4 ^ c + +2 ^^ b + +3 ^ ^ | + +1 ^ ^ a + +4 ^ ^ c + +2 ^ ^ b + +3 ^ ^ | + +1 ^ ^ a + +4 ^ ^ c + +2 ^ ^ b + +3 ^ ^ | ++12 ^ ^ + +1 ^ ^ a + +4 ^ ^ c + 0: ababab + abcdabcd +--->abcdabcd + +0 ^ (ab|cd){3,4} + +1 ^ a + +4 ^ c + +2 ^^ b + +3 ^ ^ | + +1 ^ ^ a + +4 ^ ^ c + +5 ^ ^ d + +6 ^ ^ ) + +1 ^ ^ a + +4 ^ ^ c + +2 ^ ^ b + +3 ^ ^ | ++12 ^ ^ + +1 ^ ^ a + +4 ^ ^ c + +5 ^ ^ d + +6 ^ ^ ) ++12 ^ ^ + 0: abcdabcd + 1: abcdab + abcdcdcdcdcd +--->abcdcdcdcdcd + +0 ^ (ab|cd){3,4} + +1 ^ a + +4 ^ c + +2 ^^ b + +3 ^ ^ | + +1 ^ ^ a + +4 ^ ^ c + +5 ^ ^ d + +6 ^ ^ ) + +1 ^ ^ a + +4 ^ ^ c + +5 ^ ^ d + +6 ^ ^ ) ++12 ^ ^ + +1 ^ ^ a + +4 ^ ^ c + +5 ^ ^ d + +6 ^ ^ ) ++12 ^ ^ + 0: abcdcdcd + 1: abcdcd + +/^abc/ + abcdef + 0: abc + *** Failers +No match + abcdef\B +No match + +/^(a*|xyz)/ + bcd + 0: + aaabcd + 0: aaa + 1: aa + 2: a + 3: + xyz + 0: xyz + 1: + xyz\N + 0: xyz + *** Failers + 0: + bcd\N +No match + +/xyz$/ + xyz + 0: xyz + xyz\n + 0: xyz + *** Failers +No match + xyz\Z +No match + xyz\n\Z +No match + +/xyz$/m + xyz + 0: xyz + xyz\n + 0: xyz + abcxyz\npqr + 0: xyz + abcxyz\npqr\Z + 0: xyz + xyz\n\Z + 0: xyz + *** Failers +No match + xyz\Z +No match + +/\Gabc/ + abcdef + 0: abc + defabcxyz\>3 + 0: abc + *** Failers +No match + defabcxyz +No match + +/^abcdef/ + ab\P +Partial match: ab + abcde\P +Partial match: abcde + abcdef\P + 0: abcdef + *** Failers +No match + abx\P +No match + +/^a{2,4}\d+z/ + a\P +Partial match: a + aa\P +Partial match: aa + aa2\P +Partial match: aa2 + aaa\P +Partial match: aaa + aaa23\P +Partial match: aaa23 + aaaa12345\P +Partial match: aaaa12345 + aa0z\P + 0: aa0z + aaaa4444444444444z\P + 0: aaaa4444444444444z + *** Failers +No match + az\P +No match + aaaaa\P +No match + a56\P +No match + +/^abcdef/ + abc\P +Partial match: abc + def\R + 0: def + +/(?<=foo)bar/ + xyzfo\P +No match + foob\R\P\>2 +Partial match: b + foobar...\R\P\>4 + 0: ar + xyzfo\P +No match + foobar\R\>2 + 0: bar + *** Failers +No match + xyzfo\P +No match + obar\R +No match + +/(ab*(cd|ef))+X/ + adfadadaklhlkalkajhlkjahdfasdfasdfladsfjkj\P\Z +No match + lkjhlkjhlkjhlkjhabbbbbbcdaefabbbbbbbefa\P\B\Z +Partial match: abbbbbbcdaefabbbbbbbefa + cdabbbbbbbb\P\R\B\Z +Partial match: cdabbbbbbbb + efabbbbbbbbbbbbbbbb\P\R\B\Z +Partial match: efabbbbbbbbbbbbbbbb + bbbbbbbbbbbbcdXyasdfadf\P\R\B\Z + 0: bbbbbbbbbbbbcdX + +/(a|b)/SF>testsavedregex +Compiled regex written to testsavedregex +Study data written to testsavedregex +>>aaabxyzpqrrrabbxyyyypqAzz + 0: aaabxyzpqrrrabbxyyyypqAzz + >aaaabxyzpqrrrabbxyyyypqAzz + 0: aaaabxyzpqrrrabbxyyyypqAzz + >>>>abcxyzpqrrrabbxyyyypqAzz + 0: abcxyzpqrrrabbxyyyypqAzz + *** Failers +No match + abxyzpqrrabbxyyyypqAzz +No match + abxyzpqrrrrabbxyyyypqAzz +No match + abxyzpqrrrabxyyyypqAzz +No match + aaaabcxyzzzzpqrrrabbbxyyyyyypqAzz +No match + aaaabcxyzzzzpqrrrabbbxyyypqAzz +No match + aaabcxyzpqrrrabbxyyyypqqqqqqqAzz +No match + +/^(abc){1,2}zz/ + abczz + 0: abczz + abcabczz + 0: abcabczz + *** Failers +No match + zz +No match + abcabcabczz +No match + >>abczz +No match + +/^(b+?|a){1,2}?c/ + bc + 0: bc + bbc + 0: bbc + bbbc + 0: bbbc + bac + 0: bac + bbac + 0: bbac + aac + 0: aac + abbbbbbbbbbbc + 0: abbbbbbbbbbbc + bbbbbbbbbbbac + 0: bbbbbbbbbbbac + *** Failers +No match + aaac +No match + abbbbbbbbbbbac +No match + +/^(b+|a){1,2}c/ + bc + 0: bc + bbc + 0: bbc + bbbc + 0: bbbc + bac + 0: bac + bbac + 0: bbac + aac + 0: aac + abbbbbbbbbbbc + 0: abbbbbbbbbbbc + bbbbbbbbbbbac + 0: bbbbbbbbbbbac + *** Failers +No match + aaac +No match + abbbbbbbbbbbac +No match + +/^(b+|a){1,2}?bc/ + bbc + 0: bbc + +/^(b*|ba){1,2}?bc/ + babc + 0: babc + bbabc + 0: bbabc + bababc + 0: bababc + *** Failers +No match + bababbc +No match + babababc +No match + +/^(ba|b*){1,2}?bc/ + babc + 0: babc + bbabc + 0: bbabc + bababc + 0: bababc + *** Failers +No match + bababbc +No match + babababc +No match + +/^\ca\cA\c[\c{\c:/ + \x01\x01\e;z + 0: \x01\x01\x1b;z + +/^[ab\]cde]/ + athing + 0: a + bthing + 0: b + ]thing + 0: ] + cthing + 0: c + dthing + 0: d + ething + 0: e + *** Failers +No match + fthing +No match + [thing +No match + \\thing +No match + +/^[]cde]/ + ]thing + 0: ] + cthing + 0: c + dthing + 0: d + ething + 0: e + *** Failers +No match + athing +No match + fthing +No match + +/^[^ab\]cde]/ + fthing + 0: f + [thing + 0: [ + \\thing + 0: \ + *** Failers + 0: * + athing +No match + bthing +No match + ]thing +No match + cthing +No match + dthing +No match + ething +No match + +/^[^]cde]/ + athing + 0: a + fthing + 0: f + *** Failers + 0: * + ]thing +No match + cthing +No match + dthing +No match + ething +No match + +/^\�/ + � + 0: \x81 + +/^ÿ/ + ÿ + 0: \xff + +/^[0-9]+$/ + 0 + 0: 0 + 1 + 0: 1 + 2 + 0: 2 + 3 + 0: 3 + 4 + 0: 4 + 5 + 0: 5 + 6 + 0: 6 + 7 + 0: 7 + 8 + 0: 8 + 9 + 0: 9 + 10 + 0: 10 + 100 + 0: 100 + *** Failers +No match + abc +No match + +/^.*nter/ + enter + 0: enter + inter + 0: inter + uponter + 0: uponter + +/^xxx[0-9]+$/ + xxx0 + 0: xxx0 + xxx1234 + 0: xxx1234 + *** Failers +No match + xxx +No match + +/^.+[0-9][0-9][0-9]$/ + x123 + 0: x123 + xx123 + 0: xx123 + 123456 + 0: 123456 + *** Failers +No match + 123 +No match + x1234 + 0: x1234 + +/^.+?[0-9][0-9][0-9]$/ + x123 + 0: x123 + xx123 + 0: xx123 + 123456 + 0: 123456 + *** Failers +No match + 123 +No match + x1234 + 0: x1234 + +/^([^!]+)!(.+)=apquxz\.ixr\.zzz\.ac\.uk$/ + abc!pqr=apquxz.ixr.zzz.ac.uk + 0: abc!pqr=apquxz.ixr.zzz.ac.uk + *** Failers +No match + !pqr=apquxz.ixr.zzz.ac.uk +No match + abc!=apquxz.ixr.zzz.ac.uk +No match + abc!pqr=apquxz:ixr.zzz.ac.uk +No match + abc!pqr=apquxz.ixr.zzz.ac.ukk +No match + +/:/ + Well, we need a colon: somewhere + 0: : + *** Fail if we don't +No match + +/([\da-f:]+)$/i + 0abc + 0: 0abc + abc + 0: abc + fed + 0: fed + E + 0: E + :: + 0: :: + 5f03:12C0::932e + 0: 5f03:12C0::932e + fed def + 0: def + Any old stuff + 0: ff + *** Failers +No match + 0zzz +No match + gzzz +No match + fed\x20 +No match + Any old rubbish +No match + +/^.*\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/ + .1.2.3 + 0: .1.2.3 + A.12.123.0 + 0: A.12.123.0 + *** Failers +No match + .1.2.3333 +No match + 1.2.3 +No match + 1234.2.3 +No match + +/^(\d+)\s+IN\s+SOA\s+(\S+)\s+(\S+)\s*\(\s*$/ + 1 IN SOA non-sp1 non-sp2( + 0: 1 IN SOA non-sp1 non-sp2( + 1 IN SOA non-sp1 non-sp2 ( + 0: 1 IN SOA non-sp1 non-sp2 ( + *** Failers +No match + 1IN SOA non-sp1 non-sp2( +No match + +/^[a-zA-Z\d][a-zA-Z\d\-]*(\.[a-zA-Z\d][a-zA-z\d\-]*)*\.$/ + a. + 0: a. + Z. + 0: Z. + 2. + 0: 2. + ab-c.pq-r. + 0: ab-c.pq-r. + sxk.zzz.ac.uk. + 0: sxk.zzz.ac.uk. + x-.y-. + 0: x-.y-. + *** Failers +No match + -abc.peq. +No match + +/^\*\.[a-z]([a-z\-\d]*[a-z\d]+)?(\.[a-z]([a-z\-\d]*[a-z\d]+)?)*$/ + *.a + 0: *.a + *.b0-a + 0: *.b0-a + *.c3-b.c + 0: *.c3-b.c + *.c-a.b-c + 0: *.c-a.b-c + *** Failers +No match + *.0 +No match + *.a- +No match + *.a-b.c- +No match + *.c-a.0-c +No match + +/^(?=ab(de))(abd)(e)/ + abde + 0: abde + +/^(?!(ab)de|x)(abd)(f)/ + abdf + 0: abdf + +/^(?=(ab(cd)))(ab)/ + abcd + 0: ab + +/^[\da-f](\.[\da-f])*$/i + a.b.c.d + 0: a.b.c.d + A.B.C.D + 0: A.B.C.D + a.b.c.1.2.3.C + 0: a.b.c.1.2.3.C + +/^\".*\"\s*(;.*)?$/ + \"1234\" + 0: "1234" + \"abcd\" ; + 0: "abcd" ; + \"\" ; rhubarb + 0: "" ; rhubarb + *** Failers +No match + \"1234\" : things +No match + +/^$/ + \ + 0: + *** Failers +No match + +/ ^ a (?# begins with a) b\sc (?# then b c) $ (?# then end)/x + ab c + 0: ab c + *** Failers +No match + abc +No match + ab cde +No match + +/(?x) ^ a (?# begins with a) b\sc (?# then b c) $ (?# then end)/ + ab c + 0: ab c + *** Failers +No match + abc +No match + ab cde +No match + +/^ a\ b[c ]d $/x + a bcd + 0: a bcd + a b d + 0: a b d + *** Failers +No match + abcd +No match + ab d +No match + +/^(a(b(c)))(d(e(f)))(h(i(j)))(k(l(m)))$/ + abcdefhijklm + 0: abcdefhijklm + +/^(?:a(b(c)))(?:d(e(f)))(?:h(i(j)))(?:k(l(m)))$/ + abcdefhijklm + 0: abcdefhijklm + +/^[\w][\W][\s][\S][\d][\D][\b][\n][\c]][\022]/ + a+ Z0+\x08\n\x1d\x12 + 0: a+ Z0+\x08\x0a\x1d\x12 + +/^[.^$|()*+?{,}]+/ + .^\$(*+)|{?,?} + 0: .^$(*+)|{?,?} + 1: .^$(*+)|{?,? + 2: .^$(*+)|{?, + 3: .^$(*+)|{? + 4: .^$(*+)|{ + 5: .^$(*+)| + 6: .^$(*+) + 7: .^$(*+ + 8: .^$(* + 9: .^$( +10: .^$ +11: .^ +12: . + +/^a*\w/ + z + 0: z + az + 0: az + 1: a + aaaz + 0: aaaz + 1: aaa + 2: aa + 3: a + a + 0: a + aa + 0: aa + 1: a + aaaa + 0: aaaa + 1: aaa + 2: aa + 3: a + a+ + 0: a + aa+ + 0: aa + 1: a + +/^a*?\w/ + z + 0: z + az + 0: az + 1: a + aaaz + 0: aaaz + 1: aaa + 2: aa + 3: a + a + 0: a + aa + 0: aa + 1: a + aaaa + 0: aaaa + 1: aaa + 2: aa + 3: a + a+ + 0: a + aa+ + 0: aa + 1: a + +/^a+\w/ + az + 0: az + aaaz + 0: aaaz + 1: aaa + 2: aa + aa + 0: aa + aaaa + 0: aaaa + 1: aaa + 2: aa + aa+ + 0: aa + +/^a+?\w/ + az + 0: az + aaaz + 0: aaaz + 1: aaa + 2: aa + aa + 0: aa + aaaa + 0: aaaa + 1: aaa + 2: aa + aa+ + 0: aa + +/^\d{8}\w{2,}/ + 1234567890 + 0: 1234567890 + 12345678ab + 0: 12345678ab + 12345678__ + 0: 12345678__ + *** Failers +No match + 1234567 +No match + +/^[aeiou\d]{4,5}$/ + uoie + 0: uoie + 1234 + 0: 1234 + 12345 + 0: 12345 + aaaaa + 0: aaaaa + *** Failers +No match + 123456 +No match + +/^[aeiou\d]{4,5}?/ + uoie + 0: uoie + 1234 + 0: 1234 + 12345 + 0: 12345 + 1: 1234 + aaaaa + 0: aaaaa + 1: aaaa + 123456 + 0: 12345 + 1: 1234 + +/^From +([^ ]+) +[a-zA-Z][a-zA-Z][a-zA-Z] +[a-zA-Z][a-zA-Z][a-zA-Z] +[0-9]?[0-9] +[0-9][0-9]:[0-9][0-9]/ + From abcd Mon Sep 01 12:33:02 1997 + 0: From abcd Mon Sep 01 12:33 + +/^From\s+\S+\s+([a-zA-Z]{3}\s+){2}\d{1,2}\s+\d\d:\d\d/ + From abcd Mon Sep 01 12:33:02 1997 + 0: From abcd Mon Sep 01 12:33 + From abcd Mon Sep 1 12:33:02 1997 + 0: From abcd Mon Sep 1 12:33 + *** Failers +No match + From abcd Sep 01 12:33:02 1997 +No match + +/^12.34/s + 12\n34 + 0: 12\x0a34 + 12\r34 + 0: 12\x0d34 + +/\w+(?=\t)/ + the quick brown\t fox + 0: brown + +/foo(?!bar)(.*)/ + foobar is foolish see? + 0: foolish see? + 1: foolish see + 2: foolish se + 3: foolish s + 4: foolish + 5: foolish + 6: foolis + 7: fooli + 8: fool + 9: foo + +/(?:(?!foo)...|^.{0,2})bar(.*)/ + foobar crowbar etc + 0: rowbar etc + 1: rowbar et + 2: rowbar e + 3: rowbar + 4: rowbar + barrel + 0: barrel + 1: barre + 2: barr + 3: bar + 2barrel + 0: 2barrel + 1: 2barre + 2: 2barr + 3: 2bar + A barrel + 0: A barrel + 1: A barre + 2: A barr + 3: A bar + +/^(\D*)(?=\d)(?!123)/ + abc456 + 0: abc + *** Failers +No match + abc123 +No match + +/^1234(?# test newlines + inside)/ + 1234 + 0: 1234 + +/^1234 #comment in extended re + /x + 1234 + 0: 1234 + +/#rhubarb + abcd/x + abcd + 0: abcd + +/^abcd#rhubarb/x + abcd + 0: abcd + +/(?!^)abc/ + the abc + 0: abc + *** Failers +No match + abc +No match + +/(?=^)abc/ + abc + 0: abc + *** Failers +No match + the abc +No match + +/^[ab]{1,3}(ab*|b)/ + aabbbbb + 0: aabbbbb + 1: aabbbb + 2: aabbb + 3: aabb + 4: aab + 5: aa + +/^[ab]{1,3}?(ab*|b)/ + aabbbbb + 0: aabbbbb + 1: aabbbb + 2: aabbb + 3: aabb + 4: aab + 5: aa + +/^[ab]{1,3}?(ab*?|b)/ + aabbbbb + 0: aabbbbb + 1: aabbbb + 2: aabbb + 3: aabb + 4: aab + 5: aa + +/^[ab]{1,3}(ab*?|b)/ + aabbbbb + 0: aabbbbb + 1: aabbbb + 2: aabbb + 3: aabb + 4: aab + 5: aa + +/ (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* # optional leading comment +(?: (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +" (?: # opening quote... +[^\\\x80-\xff\n\015"] # Anything except backslash and quote +| # or +\\ [^\x80-\xff] # Escaped something (something != CR) +)* " # closing quote +) # initial word +(?: (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* \. (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +" (?: # opening quote... +[^\\\x80-\xff\n\015"] # Anything except backslash and quote +| # or +\\ [^\x80-\xff] # Escaped something (something != CR) +)* " # closing quote +) )* # further okay, if led by a period +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* @ (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| \[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) # initial subdomain +(?: # +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* \. # if led by a period... +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| \[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) # ...further okay +)* +# address +| # or +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +" (?: # opening quote... +[^\\\x80-\xff\n\015"] # Anything except backslash and quote +| # or +\\ [^\x80-\xff] # Escaped something (something != CR) +)* " # closing quote +) # one word, optionally followed by.... +(?: +[^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] | # atom and space parts, or... +\( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) | # comments, or... + +" (?: # opening quote... +[^\\\x80-\xff\n\015"] # Anything except backslash and quote +| # or +\\ [^\x80-\xff] # Escaped something (something != CR) +)* " # closing quote +# quoted strings +)* +< (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* # leading < +(?: @ (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| \[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) # initial subdomain +(?: # +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* \. # if led by a period... +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| \[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) # ...further okay +)* + +(?: (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* , (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* @ (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| \[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) # initial subdomain +(?: # +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* \. # if led by a period... +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| \[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) # ...further okay +)* +)* # further okay, if led by comma +: # closing colon +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* )? # optional route +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +" (?: # opening quote... +[^\\\x80-\xff\n\015"] # Anything except backslash and quote +| # or +\\ [^\x80-\xff] # Escaped something (something != CR) +)* " # closing quote +) # initial word +(?: (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* \. (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +" (?: # opening quote... +[^\\\x80-\xff\n\015"] # Anything except backslash and quote +| # or +\\ [^\x80-\xff] # Escaped something (something != CR) +)* " # closing quote +) )* # further okay, if led by a period +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* @ (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| \[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) # initial subdomain +(?: # +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* \. # if led by a period... +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| \[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) # ...further okay +)* +# address spec +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* > # trailing > +# name and address +) (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* # optional trailing comment +/x + Alan Other + 0: Alan Other + + 0: user@dom.ain + 1: user@dom + user\@dom.ain + 0: user@dom.ain + 1: user@dom + \"A. Other\" (a comment) + 0: "A. Other" (a comment) + 1: "A. Other" + 2: "A. Other" + A. Other (a comment) + 0: Other (a comment) + 1: Other + 2: Other + \"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\"\@x400-re.lay + 0: "/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/"@x400-re.lay + 1: "/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/"@x400-re + A missing angle @,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +" # " +[^\\\x80-\xff\n\015"] * # normal +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* +" # " +# Quoted string +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +\. +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +" # " +[^\\\x80-\xff\n\015"] * # normal +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* +" # " +# Quoted string +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +\[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\. +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +\[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address +| # or +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +" # " +[^\\\x80-\xff\n\015"] * # normal +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* +" # " +# Quoted string +) +# leading word +[^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] * # "normal" atoms and or spaces +(?: +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +| +" # " +[^\\\x80-\xff\n\015"] * # normal +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* +" # " +) # "special" comment or quoted string +[^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] * # more "normal" +)* +< +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# < +(?: +@ +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +\[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\. +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +\[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +(?: , +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +@ +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +\[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\. +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +\[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +)* # additional domains +: +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)? # optional route +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +" # " +[^\\\x80-\xff\n\015"] * # normal +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* +" # " +# Quoted string +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +\. +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +" # " +[^\\\x80-\xff\n\015"] * # normal +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* +" # " +# Quoted string +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +\[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\. +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +\[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address spec +> # > +# name and address +) +/x + Alan Other + 0: Alan Other + + 0: user@dom.ain + 1: user@dom + user\@dom.ain + 0: user@dom.ain + 1: user@dom + \"A. Other\" (a comment) + 0: "A. Other" + A. Other (a comment) + 0: Other + \"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\"\@x400-re.lay + 0: "/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/"@x400-re.lay + 1: "/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/"@x400-re + A missing angle ?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff + +/P[^*]TAIRE[^*]{1,6}?LL/ + xxxxxxxxxxxPSTAIREISLLxxxxxxxxx + 0: PSTAIREISLL + +/P[^*]TAIRE[^*]{1,}?LL/ + xxxxxxxxxxxPSTAIREISLLxxxxxxxxx + 0: PSTAIREISLL + +/(\.\d\d[1-9]?)\d+/ + 1.230003938 + 0: .230003938 + 1: .23000393 + 2: .2300039 + 3: .230003 + 4: .23000 + 5: .2300 + 6: .230 + 1.875000282 + 0: .875000282 + 1: .87500028 + 2: .8750002 + 3: .875000 + 4: .87500 + 5: .8750 + 6: .875 + 1.235 + 0: .235 + +/(\.\d\d((?=0)|\d(?=\d)))/ + 1.230003938 + 0: .230 + 1: .23 + 1.875000282 + 0: .875 + *** Failers +No match + 1.235 +No match + +/a(?)b/ + ab + 0: ab + +/\b(foo)\s+(\w+)/i + Food is on the foo table + 0: foo table + 1: foo tabl + 2: foo tab + 3: foo ta + 4: foo t + +/foo(.*)bar/ + The food is under the bar in the barn. + 0: food is under the bar in the bar + 1: food is under the bar + +/foo(.*?)bar/ + The food is under the bar in the barn. + 0: food is under the bar in the bar + 1: food is under the bar + +/(.*)(\d*)/ + I have 2 numbers: 53147 +Matched, but too many subsidiary matches + 0: I have 2 numbers: 53147 + 1: I have 2 numbers: 5314 + 2: I have 2 numbers: 531 + 3: I have 2 numbers: 53 + 4: I have 2 numbers: 5 + 5: I have 2 numbers: + 6: I have 2 numbers: + 7: I have 2 numbers + 8: I have 2 number + 9: I have 2 numbe +10: I have 2 numb +11: I have 2 num +12: I have 2 nu +13: I have 2 n +14: I have 2 +15: I have 2 +16: I have +17: I have +18: I hav +19: I ha +20: I h +21: I + +/(.*)(\d+)/ + I have 2 numbers: 53147 + 0: I have 2 numbers: 53147 + 1: I have 2 numbers: 5314 + 2: I have 2 numbers: 531 + 3: I have 2 numbers: 53 + 4: I have 2 numbers: 5 + 5: I have 2 + +/(.*?)(\d*)/ + I have 2 numbers: 53147 +Matched, but too many subsidiary matches + 0: I have 2 numbers: 53147 + 1: I have 2 numbers: 5314 + 2: I have 2 numbers: 531 + 3: I have 2 numbers: 53 + 4: I have 2 numbers: 5 + 5: I have 2 numbers: + 6: I have 2 numbers: + 7: I have 2 numbers + 8: I have 2 number + 9: I have 2 numbe +10: I have 2 numb +11: I have 2 num +12: I have 2 nu +13: I have 2 n +14: I have 2 +15: I have 2 +16: I have +17: I have +18: I hav +19: I ha +20: I h +21: I + +/(.*?)(\d+)/ + I have 2 numbers: 53147 + 0: I have 2 numbers: 53147 + 1: I have 2 numbers: 5314 + 2: I have 2 numbers: 531 + 3: I have 2 numbers: 53 + 4: I have 2 numbers: 5 + 5: I have 2 + +/(.*)(\d+)$/ + I have 2 numbers: 53147 + 0: I have 2 numbers: 53147 + +/(.*?)(\d+)$/ + I have 2 numbers: 53147 + 0: I have 2 numbers: 53147 + +/(.*)\b(\d+)$/ + I have 2 numbers: 53147 + 0: I have 2 numbers: 53147 + +/(.*\D)(\d+)$/ + I have 2 numbers: 53147 + 0: I have 2 numbers: 53147 + +/^\D*(?!123)/ + ABC123 + 0: AB + 1: A + 2: + +/^(\D*)(?=\d)(?!123)/ + ABC445 + 0: ABC + *** Failers +No match + ABC123 +No match + +/^[W-]46]/ + W46]789 + 0: W46] + -46]789 + 0: -46] + *** Failers +No match + Wall +No match + Zebra +No match + 42 +No match + [abcd] +No match + ]abcd[ +No match + +/^[W-\]46]/ + W46]789 + 0: W + Wall + 0: W + Zebra + 0: Z + Xylophone + 0: X + 42 + 0: 4 + [abcd] + 0: [ + ]abcd[ + 0: ] + \\backslash + 0: \ + *** Failers +No match + -46]789 +No match + well +No match + +/\d\d\/\d\d\/\d\d\d\d/ + 01/01/2000 + 0: 01/01/2000 + +/word (?:[a-zA-Z0-9]+ ){0,10}otherword/ + word cat dog elephant mussel cow horse canary baboon snake shark otherword + 0: word cat dog elephant mussel cow horse canary baboon snake shark otherword + word cat dog elephant mussel cow horse canary baboon snake shark +No match + +/word (?:[a-zA-Z0-9]+ ){0,300}otherword/ + word cat dog elephant mussel cow horse canary baboon snake shark the quick brown fox and the lazy dog and several other words getting close to thirty by now I hope +No match + +/^(a){0,0}/ + bcd + 0: + abc + 0: + aab + 0: + +/^(a){0,1}/ + bcd + 0: + abc + 0: a + 1: + aab + 0: a + 1: + +/^(a){0,2}/ + bcd + 0: + abc + 0: a + 1: + aab + 0: aa + 1: a + 2: + +/^(a){0,3}/ + bcd + 0: + abc + 0: a + 1: + aab + 0: aa + 1: a + 2: + aaa + 0: aaa + 1: aa + 2: a + 3: + +/^(a){0,}/ + bcd + 0: + abc + 0: a + 1: + aab + 0: aa + 1: a + 2: + aaa + 0: aaa + 1: aa + 2: a + 3: + aaaaaaaa + 0: aaaaaaaa + 1: aaaaaaa + 2: aaaaaa + 3: aaaaa + 4: aaaa + 5: aaa + 6: aa + 7: a + 8: + +/^(a){1,1}/ + bcd +No match + abc + 0: a + aab + 0: a + +/^(a){1,2}/ + bcd +No match + abc + 0: a + aab + 0: aa + 1: a + +/^(a){1,3}/ + bcd +No match + abc + 0: a + aab + 0: aa + 1: a + aaa + 0: aaa + 1: aa + 2: a + +/^(a){1,}/ + bcd +No match + abc + 0: a + aab + 0: aa + 1: a + aaa + 0: aaa + 1: aa + 2: a + aaaaaaaa + 0: aaaaaaaa + 1: aaaaaaa + 2: aaaaaa + 3: aaaaa + 4: aaaa + 5: aaa + 6: aa + 7: a + +/.*\.gif/ + borfle\nbib.gif\nno + 0: bib.gif + +/.{0,}\.gif/ + borfle\nbib.gif\nno + 0: bib.gif + +/.*\.gif/m + borfle\nbib.gif\nno + 0: bib.gif + +/.*\.gif/s + borfle\nbib.gif\nno + 0: borfle\x0abib.gif + +/.*\.gif/ms + borfle\nbib.gif\nno + 0: borfle\x0abib.gif + +/.*$/ + borfle\nbib.gif\nno + 0: no + +/.*$/m + borfle\nbib.gif\nno + 0: borfle + +/.*$/s + borfle\nbib.gif\nno + 0: borfle\x0abib.gif\x0ano + +/.*$/ms + borfle\nbib.gif\nno + 0: borfle\x0abib.gif\x0ano + 1: borfle\x0abib.gif + 2: borfle + +/.*$/ + borfle\nbib.gif\nno\n + 0: no + +/.*$/m + borfle\nbib.gif\nno\n + 0: borfle + +/.*$/s + borfle\nbib.gif\nno\n + 0: borfle\x0abib.gif\x0ano\x0a + 1: borfle\x0abib.gif\x0ano + +/.*$/ms + borfle\nbib.gif\nno\n + 0: borfle\x0abib.gif\x0ano\x0a + 1: borfle\x0abib.gif\x0ano + 2: borfle\x0abib.gif + 3: borfle + +/(.*X|^B)/ + abcde\n1234Xyz + 0: 1234X + BarFoo + 0: B + *** Failers +No match + abcde\nBar +No match + +/(.*X|^B)/m + abcde\n1234Xyz + 0: 1234X + BarFoo + 0: B + abcde\nBar + 0: B + +/(.*X|^B)/s + abcde\n1234Xyz + 0: abcde\x0a1234X + BarFoo + 0: B + *** Failers +No match + abcde\nBar +No match + +/(.*X|^B)/ms + abcde\n1234Xyz + 0: abcde\x0a1234X + BarFoo + 0: B + abcde\nBar + 0: B + +/(?s)(.*X|^B)/ + abcde\n1234Xyz + 0: abcde\x0a1234X + BarFoo + 0: B + *** Failers +No match + abcde\nBar +No match + +/(?s:.*X|^B)/ + abcde\n1234Xyz + 0: abcde\x0a1234X + BarFoo + 0: B + *** Failers +No match + abcde\nBar +No match + +/^.*B/ + **** Failers +No match + abc\nB +No match + +/(?s)^.*B/ + abc\nB + 0: abc\x0aB + +/(?m)^.*B/ + abc\nB + 0: B + +/(?ms)^.*B/ + abc\nB + 0: abc\x0aB + +/(?ms)^B/ + abc\nB + 0: B + +/(?s)B$/ + B\n + 0: B + +/^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/ + 123456654321 + 0: 123456654321 + +/^\d\d\d\d\d\d\d\d\d\d\d\d/ + 123456654321 + 0: 123456654321 + +/^[\d][\d][\d][\d][\d][\d][\d][\d][\d][\d][\d][\d]/ + 123456654321 + 0: 123456654321 + +/^[abc]{12}/ + abcabcabcabc + 0: abcabcabcabc + +/^[a-c]{12}/ + abcabcabcabc + 0: abcabcabcabc + +/^(a|b|c){12}/ + abcabcabcabc + 0: abcabcabcabc + +/^[abcdefghijklmnopqrstuvwxy0123456789]/ + n + 0: n + *** Failers +No match + z +No match + +/abcde{0,0}/ + abcd + 0: abcd + *** Failers +No match + abce +No match + +/ab[cd]{0,0}e/ + abe + 0: abe + *** Failers +No match + abcde +No match + +/ab(c){0,0}d/ + abd + 0: abd + *** Failers +No match + abcd +No match + +/a(b*)/ + a + 0: a + ab + 0: ab + 1: a + abbbb + 0: abbbb + 1: abbb + 2: abb + 3: ab + 4: a + *** Failers + 0: a + bbbbb +No match + +/ab\d{0}e/ + abe + 0: abe + *** Failers +No match + ab1e +No match + +/"([^\\"]+|\\.)*"/ + the \"quick\" brown fox + 0: "quick" + \"the \\\"quick\\\" brown fox\" + 0: "the \"quick\" brown fox" + +/.*?/g+ + abc + 0: abc + 0+ + 1: ab + 2: a + 3: + 0: + 0+ + +/\b/g+ + abc + 0: + 0+ abc + 0: + 0+ + +/\b/+g + abc + 0: + 0+ abc + 0: + 0+ + +//g + abc + 0: + 0: + 0: + 0: + +/]{0,})>]{0,})>([\d]{0,}\.)(.*)((
([\w\W\s\d][^<>]{0,})|[\s]{0,}))<\/a><\/TD>]{0,})>([\w\W\s\d][^<>]{0,})<\/TD>]{0,})>([\w\W\s\d][^<>]{0,})<\/TD><\/TR>/is + 43.
Word Processor
(N-1286)
Lega lstaff.comCA - Statewide + 0: 43.Word Processor
(N-1286)
Lega lstaff.comCA - Statewide + +/a[^a]b/ + acb + 0: acb + a\nb + 0: a\x0ab + +/a.b/ + acb + 0: acb + *** Failers +No match + a\nb +No match + +/a[^a]b/s + acb + 0: acb + a\nb + 0: a\x0ab + +/a.b/s + acb + 0: acb + a\nb + 0: a\x0ab + +/^(b+?|a){1,2}?c/ + bac + 0: bac + bbac + 0: bbac + bbbac + 0: bbbac + bbbbac + 0: bbbbac + bbbbbac + 0: bbbbbac + +/^(b+|a){1,2}?c/ + bac + 0: bac + bbac + 0: bbac + bbbac + 0: bbbac + bbbbac + 0: bbbbac + bbbbbac + 0: bbbbbac + +/(?!\A)x/m + x\nb\n +No match + a\bx\n + 0: x + +/\x0{ab}/ + \0{ab} + 0: \x00{ab} + +/(A|B)*?CD/ + CD + 0: CD + +/(A|B)*CD/ + CD + 0: CD + +/(?.*/)foo" + /this/is/a/very/long/line/in/deed/with/very/many/slashes/in/it/you/see/ +No match + +"(?>.*/)foo" + /this/is/a/very/long/line/in/deed/with/very/many/slashes/in/and/foo + 0: /this/is/a/very/long/line/in/deed/with/very/many/slashes/in/and/foo + +/(?>(\.\d\d[1-9]?))\d+/ + 1.230003938 + 0: .230003938 + 1: .23000393 + 2: .2300039 + 3: .230003 + 4: .23000 + 5: .2300 + 6: .230 + 1.875000282 + 0: .875000282 + 1: .87500028 + 2: .8750002 + 3: .875000 + 4: .87500 + 5: .8750 + *** Failers +No match + 1.235 +No match + +/^((?>\w+)|(?>\s+))*$/ + now is the time for all good men to come to the aid of the party + 0: now is the time for all good men to come to the aid of the party + *** Failers +No match + this is not a line with only words and spaces! +No match + +/(\d+)(\w)/ + 12345a + 0: 12345a + 1: 12345 + 2: 1234 + 3: 123 + 4: 12 + 12345+ + 0: 12345 + 1: 1234 + 2: 123 + 3: 12 + +/((?>\d+))(\w)/ + 12345a + 0: 12345a + *** Failers +No match + 12345+ +No match + +/(?>a+)b/ + aaab + 0: aaab + +/((?>a+)b)/ + aaab + 0: aaab + +/(?>(a+))b/ + aaab + 0: aaab + +/(?>b)+/ + aaabbbccc + 0: bbb + 1: bb + 2: b + +/(?>a+|b+|c+)*c/ + aaabbbbccccd + 0: aaabbbbcccc + 1: aaabbbbc + +/(a+|b+|c+)*c/ + aaabbbbccccd + 0: aaabbbbcccc + 1: aaabbbbccc + 2: aaabbbbcc + 3: aaabbbbc + +/((?>[^()]+)|\([^()]*\))+/ + ((abc(ade)ufh()()x + 0: abc(ade)ufh()()x + 1: abc(ade)ufh()() + 2: abc(ade)ufh() + 3: abc(ade)ufh + 4: abc(ade) + 5: abc + +/\(((?>[^()]+)|\([^()]+\))+\)/ + (abc) + 0: (abc) + (abc(def)xyz) + 0: (abc(def)xyz) + *** Failers +No match + ((()aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +No match + +/a(?-i)b/i + ab + 0: ab + Ab + 0: Ab + *** Failers +No match + aB +No match + AB +No match + +/(a (?x)b c)d e/ + a bcd e + 0: a bcd e + *** Failers +No match + a b cd e +No match + abcd e +No match + a bcde +No match + +/(a b(?x)c d (?-x)e f)/ + a bcde f + 0: a bcde f + *** Failers +No match + abcdef +No match + +/(a(?i)b)c/ + abc + 0: abc + aBc + 0: aBc + *** Failers +No match + abC +No match + aBC +No match + Abc +No match + ABc +No match + ABC +No match + AbC +No match + +/a(?i:b)c/ + abc + 0: abc + aBc + 0: aBc + *** Failers +No match + ABC +No match + abC +No match + aBC +No match + +/a(?i:b)*c/ + aBc + 0: aBc + aBBc + 0: aBBc + *** Failers +No match + aBC +No match + aBBC +No match + +/a(?=b(?i)c)\w\wd/ + abcd + 0: abcd + abCd + 0: abCd + *** Failers +No match + aBCd +No match + abcD +No match + +/(?s-i:more.*than).*million/i + more than million + 0: more than million + more than MILLION + 0: more than MILLION + more \n than Million + 0: more \x0a than Million + *** Failers +No match + MORE THAN MILLION +No match + more \n than \n million +No match + +/(?:(?s-i)more.*than).*million/i + more than million + 0: more than million + more than MILLION + 0: more than MILLION + more \n than Million + 0: more \x0a than Million + *** Failers +No match + MORE THAN MILLION +No match + more \n than \n million +No match + +/(?>a(?i)b+)+c/ + abc + 0: abc + aBbc + 0: aBbc + aBBc + 0: aBBc + *** Failers +No match + Abc +No match + abAb +No match + abbC +No match + +/(?=a(?i)b)\w\wc/ + abc + 0: abc + aBc + 0: aBc + *** Failers +No match + Ab +No match + abC +No match + aBC +No match + +/(?<=a(?i)b)(\w\w)c/ + abxxc + 0: xxc + aBxxc + 0: xxc + *** Failers +No match + Abxxc +No match + ABxxc +No match + abxxC +No match + +/^(?(?=abc)\w{3}:|\d\d)$/ + abc: + 0: abc: + 12 + 0: 12 + *** Failers +No match + 123 +No match + xyz +No match + +/^(?(?!abc)\d\d|\w{3}:)$/ + abc: + 0: abc: + 12 + 0: 12 + *** Failers +No match + 123 +No match + xyz +No match + +/(?(?<=foo)bar|cat)/ + foobar + 0: bar + cat + 0: cat + fcat + 0: cat + focat + 0: cat + *** Failers +No match + foocat +No match + +/(?(?a*)*/ + a + 0: a + 1: + aa + 0: aa + 1: + aaaa + 0: aaaa + 1: + +/(abc|)+/ + abc + 0: abc + 1: + abcabc + 0: abcabc + 1: abc + 2: + abcabcabc + 0: abcabcabc + 1: abcabc + 2: abc + 3: + xyz + 0: + +/([a]*)*/ + a + 0: a + 1: + aaaaa + 0: aaaaa + 1: aaaa + 2: aaa + 3: aa + 4: a + 5: + +/([ab]*)*/ + a + 0: a + 1: + b + 0: b + 1: + ababab + 0: ababab + 1: ababa + 2: abab + 3: aba + 4: ab + 5: a + 6: + aaaabcde + 0: aaaab + 1: aaaa + 2: aaa + 3: aa + 4: a + 5: + bbbb + 0: bbbb + 1: bbb + 2: bb + 3: b + 4: + +/([^a]*)*/ + b + 0: b + 1: + bbbb + 0: bbbb + 1: bbb + 2: bb + 3: b + 4: + aaa + 0: + +/([^ab]*)*/ + cccc + 0: cccc + 1: ccc + 2: cc + 3: c + 4: + abab + 0: + +/([a]*?)*/ + a + 0: a + 1: + aaaa + 0: aaaa + 1: aaa + 2: aa + 3: a + 4: + +/([ab]*?)*/ + a + 0: a + 1: + b + 0: b + 1: + abab + 0: abab + 1: aba + 2: ab + 3: a + 4: + baba + 0: baba + 1: bab + 2: ba + 3: b + 4: + +/([^a]*?)*/ + b + 0: b + 1: + bbbb + 0: bbbb + 1: bbb + 2: bb + 3: b + 4: + aaa + 0: + +/([^ab]*?)*/ + c + 0: c + 1: + cccc + 0: cccc + 1: ccc + 2: cc + 3: c + 4: + baba + 0: + +/(?>a*)*/ + a + 0: a + 1: + aaabcde + 0: aaa + 1: + +/((?>a*))*/ + aaaaa + 0: aaaaa + 1: + aabbaa + 0: aa + 1: + +/((?>a*?))*/ + aaaaa + 0: aaaaa + 1: + aabbaa + 0: aa + 1: + +/(?(?=[^a-z]+[a-z]) \d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} ) /x + 12-sep-98 + 0: 12-sep-98 + 12-09-98 + 0: 12-09-98 + *** Failers +No match + sep-12-98 +No match + +/(?i:saturday|sunday)/ + saturday + 0: saturday + sunday + 0: sunday + Saturday + 0: Saturday + Sunday + 0: Sunday + SATURDAY + 0: SATURDAY + SUNDAY + 0: SUNDAY + SunDay + 0: SunDay + +/(a(?i)bc|BB)x/ + abcx + 0: abcx + aBCx + 0: aBCx + bbx + 0: bbx + BBx + 0: BBx + *** Failers +No match + abcX +No match + aBCX +No match + bbX +No match + BBX +No match + +/^([ab](?i)[cd]|[ef])/ + ac + 0: ac + aC + 0: aC + bD + 0: bD + elephant + 0: e + Europe + 0: E + frog + 0: f + France + 0: F + *** Failers +No match + Africa +No match + +/^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)/ + ab + 0: ab + aBd + 0: aBd + xy + 0: xy + xY + 0: xY + zebra + 0: z + Zambesi + 0: Z + *** Failers +No match + aCD +No match + XY +No match + +/(?<=foo\n)^bar/m + foo\nbar + 0: bar + *** Failers +No match + bar +No match + baz\nbar +No match + +/(?<=(?]&/ + <&OUT + 0: <& + +/(?:(f)(o)(o)|(b)(a)(r))*/ + foobar + 0: foobar + 1: foo + 2: + +/(?<=a)b/ + ab + 0: b + *** Failers +No match + cb +No match + b +No match + +/(?a+)ab/ + +/(?>a+)b/ + aaab + 0: aaab + +/([[:]+)/ + a:[b]: + 0: :[ + 1: : + +/([[=]+)/ + a=[b]= + 0: =[ + 1: = + +/([[.]+)/ + a.[b]. + 0: .[ + 1: . + +/((?>a+)b)/ + aaab + 0: aaab + +/(?>(a+))b/ + aaab + 0: aaab + +/((?>[^()]+)|\([^()]*\))+/ + ((abc(ade)ufh()()x + 0: abc(ade)ufh()()x + 1: abc(ade)ufh()() + 2: abc(ade)ufh() + 3: abc(ade)ufh + 4: abc(ade) + 5: abc + +/a\Z/ + *** Failers +No match + aaab +No match + a\nb\n +No match + +/b\Z/ + a\nb\n + 0: b + +/b\z/ + +/b\Z/ + a\nb + 0: b + +/b\z/ + a\nb + 0: b + *** Failers +No match + +/(?>.*)(?<=(abcd|wxyz))/ + alphabetabcd + 0: alphabetabcd + endingwxyz + 0: endingwxyz + *** Failers +No match + a rather long string that doesn't end with one of them +No match + +/word (?>(?:(?!otherword)[a-zA-Z0-9]+ ){0,30})otherword/ + word cat dog elephant mussel cow horse canary baboon snake shark otherword + 0: word cat dog elephant mussel cow horse canary baboon snake shark otherword + word cat dog elephant mussel cow horse canary baboon snake shark +No match + +/word (?>[a-zA-Z0-9]+ ){0,30}otherword/ + word cat dog elephant mussel cow horse canary baboon snake shark the quick brown fox and the lazy dog and several other words getting close to thirty by now I hope +No match + +/(?<=\d{3}(?!999))foo/ + 999foo + 0: foo + 123999foo + 0: foo + *** Failers +No match + 123abcfoo +No match + +/(?<=(?!...999)\d{3})foo/ + 999foo + 0: foo + 123999foo + 0: foo + *** Failers +No match + 123abcfoo +No match + +/(?<=\d{3}(?!999)...)foo/ + 123abcfoo + 0: foo + 123456foo + 0: foo + *** Failers +No match + 123999foo +No match + +/(?<=\d{3}...)(?Z)+|A)*/ + ZABCDEFG + 0: ZA + 1: Z + 2: + +/((?>)+|A)*/ + ZABCDEFG + 0: + +/a*/g + abbab + 0: a + 1: + 0: + 0: + 0: a + 1: + 0: + 0: + +/^[a-\d]/ + abcde + 0: a + -things + 0: - + 0digit + 0: 0 + *** Failers +No match + bcdef +No match + +/^[\d-a]/ + abcde + 0: a + -things + 0: - + 0digit + 0: 0 + *** Failers +No match + bcdef +No match + +/[[:space:]]+/ + > \x09\x0a\x0c\x0d\x0b< + 0: \x09\x0a\x0c\x0d\x0b + 1: \x09\x0a\x0c\x0d + 2: \x09\x0a\x0c + 3: \x09\x0a + 4: \x09 + 5: + +/[[:blank:]]+/ + > \x09\x0a\x0c\x0d\x0b< + 0: \x09 + 1: + +/[\s]+/ + > \x09\x0a\x0c\x0d\x0b< + 0: \x09\x0a\x0c\x0d + 1: \x09\x0a\x0c + 2: \x09\x0a + 3: \x09 + 4: + +/\s+/ + > \x09\x0a\x0c\x0d\x0b< + 0: \x09\x0a\x0c\x0d + 1: \x09\x0a\x0c + 2: \x09\x0a + 3: \x09 + 4: + +/a b/x + ab +No match + +/(?!\A)x/m + a\nxb\n + 0: x + +/(?!^)x/m + a\nxb\n +No match + +/abc\Qabc\Eabc/ + abcabcabc + 0: abcabcabc + +/abc\Q(*+|\Eabc/ + abc(*+|abc + 0: abc(*+|abc + +/ abc\Q abc\Eabc/x + abc abcabc + 0: abc abcabc + *** Failers +No match + abcabcabc +No match + +/abc#comment + \Q#not comment + literal\E/x + abc#not comment\n literal + 0: abc#not comment\x0a literal + +/abc#comment + \Q#not comment + literal/x + abc#not comment\n literal + 0: abc#not comment\x0a literal + +/abc#comment + \Q#not comment + literal\E #more comment + /x + abc#not comment\n literal + 0: abc#not comment\x0a literal + +/abc#comment + \Q#not comment + literal\E #more comment/x + abc#not comment\n literal + 0: abc#not comment\x0a literal + +/\Qabc\$xyz\E/ + abc\\\$xyz + 0: abc\$xyz + +/\Qabc\E\$\Qxyz\E/ + abc\$xyz + 0: abc$xyz + +/\Gabc/ + abc + 0: abc + *** Failers +No match + xyzabc +No match + +/\Gabc./g + abc1abc2xyzabc3 + 0: abc1 + 0: abc2 + +/abc./g + abc1abc2xyzabc3 + 0: abc1 + 0: abc2 + 0: abc3 + +/a(?x: b c )d/ + XabcdY + 0: abcd + *** Failers +No match + Xa b c d Y +No match + +/((?x)x y z | a b c)/ + XabcY + 0: abc + AxyzB + 0: xyz + +/(?i)AB(?-i)C/ + XabCY + 0: abC + *** Failers +No match + XabcY +No match + +/((?i)AB(?-i)C|D)E/ + abCE + 0: abCE + DE + 0: DE + *** Failers +No match + abcE +No match + abCe +No match + dE +No match + De +No match + +/[z\Qa-d]\E]/ + z + 0: z + a + 0: a + - + 0: - + d + 0: d + ] + 0: ] + *** Failers + 0: a + b +No match + +/[\z\C]/ + z + 0: z + C + 0: C + +/\M/ + M + 0: M + +/(a+)*b/ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +No match + +/(?i)reg(?:ul(?:[aä]|ae)r|ex)/ + REGular + 0: REGular + regulaer + 0: regulaer + Regex + 0: Regex + regulär + 0: regul\xe4r + +/Åæåä[à-ÿÀ-ß]+/ + Åæåäà + 0: \xc5\xe6\xe5\xe4\xe0 + Åæåäÿ + 0: \xc5\xe6\xe5\xe4\xff + ÅæåäÀ + 0: \xc5\xe6\xe5\xe4\xc0 + Åæåäß + 0: \xc5\xe6\xe5\xe4\xdf + +/(?<=Z)X./ + \x84XAZXB + 0: XB + +/^(?(2)a|(1)(2))+$/ + 123a +Error -17 + +/(?<=a|bbbb)c/ + ac + 0: c + bbbbc + 0: c + +/abc/>testsavedregex +Compiled regex written to testsavedregex +testsavedregex +Compiled regex written to testsavedregex +testsavedregex +Compiled regex written to testsavedregex +Study data written to testsavedregex +testsavedregex +Compiled regex written to testsavedregex +Study data written to testsavedregex +\S/8 + > >X Y + 0: >X + > >\x{100} Y + 0: >\x{100} + +/\d/8 + \x{100}3 + 0: 3 + +/\s/8 + \x{100} X + 0: + +/\D+/8 + 12abcd34 + 0: abcd + 1: abc + 2: ab + 3: a + *** Failers + 0: *** Failers + 1: *** Failer + 2: *** Faile + 3: *** Fail + 4: *** Fai + 5: *** Fa + 6: *** F + 7: *** + 8: *** + 9: ** +10: * + 1234 +No match + +/\D{2,3}/8 + 12abcd34 + 0: abc + 1: ab + 12ab34 + 0: ab + *** Failers + 0: *** + 1: ** + 1234 +No match + 12a34 +No match + +/\D{2,3}?/8 + 12abcd34 + 0: abc + 1: ab + 12ab34 + 0: ab + *** Failers + 0: *** + 1: ** + 1234 +No match + 12a34 +No match + +/\d+/8 + 12abcd34 + 0: 12 + 1: 1 + *** Failers +No match + +/\d{2,3}/8 + 12abcd34 + 0: 12 + 1234abcd + 0: 123 + 1: 12 + *** Failers +No match + 1.4 +No match + +/\d{2,3}?/8 + 12abcd34 + 0: 12 + 1234abcd + 0: 123 + 1: 12 + *** Failers +No match + 1.4 +No match + +/\S+/8 + 12abcd34 + 0: 12abcd34 + 1: 12abcd3 + 2: 12abcd + 3: 12abc + 4: 12ab + 5: 12a + 6: 12 + 7: 1 + *** Failers + 0: *** + 1: ** + 2: * + \ \ +No match + +/\S{2,3}/8 + 12abcd34 + 0: 12a + 1: 12 + 1234abcd + 0: 123 + 1: 12 + *** Failers + 0: *** + 1: ** + \ \ +No match + +/\S{2,3}?/8 + 12abcd34 + 0: 12a + 1: 12 + 1234abcd + 0: 123 + 1: 12 + *** Failers + 0: *** + 1: ** + \ \ +No match + +/>\s+ <34 + 0: > < + *** Failers +No match + +/>\s{2,3} < + ab> < + *** Failers +No match + ab> \s{2,3}? < + ab> < + *** Failers +No match + ab> \xff< + 0: \xff + +/[\xff]/8 + >\x{ff}< + 0: \x{ff} + +/[^\xFF]/ + XYZ + 0: X + +/[^\xff]/8 + XYZ + 0: X + \x{123} + 0: \x{123} + +/^[ac]*b/8 + xb +No match + +/^[ac\x{100}]*b/8 + xb +No match + +/^[^x]*b/8i + xb +No match + +/^[^x]*b/8 + xb +No match + +/^\d*b/8 + xb +No match + +/(|a)/g8 + catac + 0: + 0: a + 1: + 0: + 0: a + 1: + 0: + 0: + a\x{256}a + 0: a + 1: + 0: + 0: a + 1: + 0: + +/^\x{85}$/8i + \x{85} + 0: \x{85} + +/ End of testinput 8 / diff --git a/ext/pcre/pcrelib/testdata/testoutput9 b/ext/pcre/pcrelib/testdata/testoutput9 new file mode 100644 index 000000000000..f7b46611d05a --- /dev/null +++ b/ext/pcre/pcrelib/testdata/testoutput9 @@ -0,0 +1,1234 @@ +PCRE version 6.2 01-Aug-2005 + +/\pL\P{Nd}/8 + AB + 0: AB + *** Failers + 0: Fa + A0 +No match + 00 +No match + +/\X./8 + AB + 0: AB + A\x{300}BC + 0: A\x{300}B + A\x{300}\x{301}\x{302}BC + 0: A\x{300}\x{301}\x{302}B + *** Failers + 0: ** + \x{300} +No match + +/\X\X/8 + ABC + 0: AB + A\x{300}B\x{300}\x{301}C + 0: A\x{300}B\x{300}\x{301} + A\x{300}\x{301}\x{302}BC + 0: A\x{300}\x{301}\x{302}B + *** Failers + 0: ** + \x{300} +No match + +/^\pL+/8 + abcd + 0: abcd + 1: abc + 2: ab + 3: a + a + 0: a + *** Failers +No match + +/^\PL+/8 + 1234 + 0: 1234 + 1: 123 + 2: 12 + 3: 1 + = + 0: = + *** Failers + 0: *** + 1: *** + 2: ** + 3: * + abcd +No match + +/^\X+/8 + abcdA\x{300}\x{301}\x{302} + 0: abcdA\x{300}\x{301}\x{302} + 1: abcd + 2: abc + 3: ab + 4: a + A\x{300}\x{301}\x{302} + 0: A\x{300}\x{301}\x{302} + A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302} + 0: A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302} + 1: A\x{300}\x{301}\x{302} + a + 0: a + *** Failers + 0: *** Failers + 1: *** Failer + 2: *** Faile + 3: *** Fail + 4: *** Fai + 5: *** Fa + 6: *** F + 7: *** + 8: *** + 9: ** +10: * + \x{300}\x{301}\x{302} +No match + +/\X?abc/8 + abc + 0: abc + A\x{300}abc + 0: A\x{300}abc + A\x{300}\x{301}\x{302}A\x{300}A\x{300}A\x{300}abcxyz + 0: A\x{300}abc + \x{300}abc + 0: abc + *** Failers +No match + +/^\X?abc/8 + abc + 0: abc + A\x{300}abc + 0: A\x{300}abc + *** Failers +No match + A\x{300}\x{301}\x{302}A\x{300}A\x{300}A\x{300}abcxyz +No match + \x{300}abc +No match + +/\X*abc/8 + abc + 0: abc + A\x{300}abc + 0: A\x{300}abc + A\x{300}\x{301}\x{302}A\x{300}A\x{300}A\x{300}abcxyz + 0: A\x{300}\x{301}\x{302}A\x{300}A\x{300}A\x{300}abc + \x{300}abc + 0: abc + *** Failers +No match + +/^\X*abc/8 + abc + 0: abc + A\x{300}abc + 0: A\x{300}abc + A\x{300}\x{301}\x{302}A\x{300}A\x{300}A\x{300}abcxyz + 0: A\x{300}\x{301}\x{302}A\x{300}A\x{300}A\x{300}abc + *** Failers +No match + \x{300}abc +No match + +/^\pL?=./8 + A=b + 0: A=b + =c + 0: =c + *** Failers +No match + 1=2 +No match + AAAA=b +No match + +/^\pL*=./8 + AAAA=b + 0: AAAA=b + =c + 0: =c + *** Failers +No match + 1=2 +No match + +/^\X{2,3}X/8 + A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}X + 0: A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}X + A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}X + 0: A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}X + *** Failers +No match + X +No match + A\x{300}\x{301}\x{302}X +No match + A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}X +No match + +/^\pC\pL\pM\pN\pP\pS\pZf1 | ((node->f0 & f0_chhmask) << 16); + if (cc == d) break; + if (cc < d) + { + if ((node->f0 & f0_leftexists) == 0) return -1; + node ++; + } + else + { + register int roffset = (node->f2 & f2_rightmask) >> f2_rightshift; + if (roffset == 0) return -1; + node += 1 << (roffset - 1); + } + } + +switch ((*type_ptr = ((node->f0 & f0_typemask) >> f0_typeshift))) + { + case ucp_Cc: + case ucp_Cf: + case ucp_Cn: + case ucp_Co: + case ucp_Cs: + return ucp_C; + break; + + case ucp_Ll: + case ucp_Lu: + case_offset = node->f2 & f2_casemask; + if ((case_offset & 0x0100) != 0) case_offset |= 0xfffff000; + *case_ptr = (case_offset == 0)? 0 : cc + case_offset; + return ucp_L; + + case ucp_Lm: + case ucp_Lo: + case ucp_Lt: + *case_ptr = 0; + return ucp_L; + break; + + case ucp_Mc: + case ucp_Me: + case ucp_Mn: + return ucp_M; + break; + + case ucp_Nd: + case ucp_Nl: + case ucp_No: + return ucp_N; + break; + + case ucp_Pc: + case ucp_Pd: + case ucp_Pe: + case ucp_Pf: + case ucp_Pi: + case ucp_Ps: + case ucp_Po: + return ucp_P; + break; + + case ucp_Sc: + case ucp_Sk: + case ucp_Sm: + case ucp_So: + return ucp_S; + break; + + case ucp_Zl: + case ucp_Zp: + case ucp_Zs: + return ucp_Z; + break; + + default: /* "Should never happen" */ + return -1; + break; + } +} + +/* End of ucp_findchar.c */ diff --git a/ext/pcre/pcrelib/ucpinternal.h b/ext/pcre/pcrelib/ucpinternal.h new file mode 100644 index 000000000000..faefb030c9f6 --- /dev/null +++ b/ext/pcre/pcrelib/ucpinternal.h @@ -0,0 +1,91 @@ +/************************************************* +* libucp - Unicode Property Table handler * +*************************************************/ + +/* Internal header file defining the layout of compact nodes in the tree. */ + +typedef struct cnode { + unsigned short int f0; + unsigned short int f1; + unsigned short int f2; +} cnode; + +/* Things for the f0 field */ + +#define f0_leftexists 0x8000 /* Left child exists */ +#define f0_typemask 0x3f00 /* Type bits */ +#define f0_typeshift 8 /* Type shift */ +#define f0_chhmask 0x00ff /* Character high bits */ + +/* Things for the f2 field */ + +#define f2_rightmask 0xf000 /* Mask for right offset bits */ +#define f2_rightshift 12 /* Shift for right offset */ +#define f2_casemask 0x0fff /* Mask for case offset */ + +/* The tree consists of a vector of structures of type cnode, with the root +node as the first element. The three short ints (16-bits) are used as follows: + +(f0) (1) The 0x8000 bit of f0 is set if a left child exists. The child's node + is the next node in the vector. + (2) The 0x4000 bits of f0 is spare. + (3) The 0x3f00 bits of f0 contain the character type; this is a number + defined by the enumeration in ucp.h (e.g. ucp_Lu). + (4) The bottom 8 bits of f0 contain the most significant byte of the + character's 24-bit codepoint. + +(f1) (1) The f1 field contains the two least significant bytes of the + codepoint. + +(f2) (1) The 0xf000 bits of f2 contain zero if there is no right child of this + node. Otherwise, they contain one plus the exponent of the power of + two of the offset to the right node (e.g. a value of 3 means 8). The + units of the offset are node items. + + (2) The 0x0fff bits of f2 contain the signed offset from this character to + its alternate cased value. They are zero if there is no such + character. + + +----------------------------------------------------------------------------- +||.|.| type (6) | ms char (8) || ls char (16) ||....| case offset (12) || +----------------------------------------------------------------------------- + | | | + | |-> spare | + | exponent of right + |-> left child exists child offset + + +The upper/lower casing information is set only for characters that come in +pairs. There are (at present) four non-one-to-one mappings in the Unicode data. +These are ignored. They are: + + 1FBE Greek Prosgegrammeni (lower, with upper -> capital iota) + 2126 Ohm + 212A Kelvin + 212B Angstrom + +Certainly for the last three, having an alternate case would seem to be a +mistake. I don't know any Greek, so cannot comment on the first one. + + +When searching the tree, proceed as follows: + +(1) Start at the first node. + +(2) Extract the character value from f1 and the bottom 8 bits of f0; + +(3) Compare with the character being sought. If equal, we are done. + +(4) If the test character is smaller, inspect the f0_leftexists flag. If it is + not set, the character is not in the tree. If it is set, move to the next + node, and go to (2). + +(5) If the test character is bigger, extract the f2_rightmask bits from f2, and + shift them right by f2_rightshift. If the result is zero, the character is + not in the tree. Otherwise, calculate the number of nodes to skip by + shifting the value 1 left by this number minus one. Go to (2). +*/ + + +/* End of internal.h */ diff --git a/ext/pcre/pcrelib/ucptable.c b/ext/pcre/pcrelib/ucptable.c new file mode 100644 index 000000000000..7fb3a1234329 --- /dev/null +++ b/ext/pcre/pcrelib/ucptable.c @@ -0,0 +1,15105 @@ +/* This source module is automatically generated from the Unicode +property table. See internal.h for a description of the layout. */ + +static cnode ucp_table[] = { + { 0x9a00, 0x2f1f, 0xe000 }, + { 0x8700, 0x1558, 0xd000 }, + { 0x8700, 0x0a99, 0xc000 }, + { 0x8500, 0x0435, 0xbfe0 }, + { 0x8500, 0x01ff, 0xafff }, + { 0x8500, 0x00ff, 0x9079 }, + { 0x8000, 0x007f, 0x8000 }, + { 0x9500, 0x003f, 0x7000 }, + { 0x8000, 0x001f, 0x6000 }, + { 0x8000, 0x000f, 0x5000 }, + { 0x8000, 0x0007, 0x4000 }, + { 0x8000, 0x0003, 0x3000 }, + { 0x8000, 0x0001, 0x2000 }, + { 0x0000, 0x0000, 0x0000 }, + { 0x0000, 0x0002, 0x0000 }, + { 0x8000, 0x0005, 0x2000 }, + { 0x0000, 0x0004, 0x0000 }, + { 0x0000, 0x0006, 0x0000 }, + { 0x8000, 0x000b, 0x3000 }, + { 0x8000, 0x0009, 0x2000 }, + { 0x0000, 0x0008, 0x0000 }, + { 0x0000, 0x000a, 0x0000 }, + { 0x8000, 0x000d, 0x2000 }, + { 0x0000, 0x000c, 0x0000 }, + { 0x0000, 0x000e, 0x0000 }, + { 0x8000, 0x0017, 0x4000 }, + { 0x8000, 0x0013, 0x3000 }, + { 0x8000, 0x0011, 0x2000 }, + { 0x0000, 0x0010, 0x0000 }, + { 0x0000, 0x0012, 0x0000 }, + { 0x8000, 0x0015, 0x2000 }, + { 0x0000, 0x0014, 0x0000 }, + { 0x0000, 0x0016, 0x0000 }, + { 0x8000, 0x001b, 0x3000 }, + { 0x8000, 0x0019, 0x2000 }, + { 0x0000, 0x0018, 0x0000 }, + { 0x0000, 0x001a, 0x0000 }, + { 0x8000, 0x001d, 0x2000 }, + { 0x0000, 0x001c, 0x0000 }, + { 0x0000, 0x001e, 0x0000 }, + { 0x9500, 0x002f, 0x5000 }, + { 0x9500, 0x0027, 0x4000 }, + { 0x9500, 0x0023, 0x3000 }, + { 0x9500, 0x0021, 0x2000 }, + { 0x1d00, 0x0020, 0x0000 }, + { 0x1500, 0x0022, 0x0000 }, + { 0x9500, 0x0025, 0x2000 }, + { 0x1700, 0x0024, 0x0000 }, + { 0x1500, 0x0026, 0x0000 }, + { 0x9900, 0x002b, 0x3000 }, + { 0x9200, 0x0029, 0x2000 }, + { 0x1600, 0x0028, 0x0000 }, + { 0x1500, 0x002a, 0x0000 }, + { 0x9100, 0x002d, 0x2000 }, + { 0x1500, 0x002c, 0x0000 }, + { 0x1500, 0x002e, 0x0000 }, + { 0x8d00, 0x0037, 0x4000 }, + { 0x8d00, 0x0033, 0x3000 }, + { 0x8d00, 0x0031, 0x2000 }, + { 0x0d00, 0x0030, 0x0000 }, + { 0x0d00, 0x0032, 0x0000 }, + { 0x8d00, 0x0035, 0x2000 }, + { 0x0d00, 0x0034, 0x0000 }, + { 0x0d00, 0x0036, 0x0000 }, + { 0x9500, 0x003b, 0x3000 }, + { 0x8d00, 0x0039, 0x2000 }, + { 0x0d00, 0x0038, 0x0000 }, + { 0x1500, 0x003a, 0x0000 }, + { 0x9900, 0x003d, 0x2000 }, + { 0x1900, 0x003c, 0x0000 }, + { 0x1900, 0x003e, 0x0000 }, + { 0x9000, 0x005f, 0x6000 }, + { 0x8900, 0x004f, 0x5020 }, + { 0x8900, 0x0047, 0x4020 }, + { 0x8900, 0x0043, 0x3020 }, + { 0x8900, 0x0041, 0x2020 }, + { 0x1500, 0x0040, 0x0000 }, + { 0x0900, 0x0042, 0x0020 }, + { 0x8900, 0x0045, 0x2020 }, + { 0x0900, 0x0044, 0x0020 }, + { 0x0900, 0x0046, 0x0020 }, + { 0x8900, 0x004b, 0x3020 }, + { 0x8900, 0x0049, 0x2020 }, + { 0x0900, 0x0048, 0x0020 }, + { 0x0900, 0x004a, 0x0020 }, + { 0x8900, 0x004d, 0x2020 }, + { 0x0900, 0x004c, 0x0020 }, + { 0x0900, 0x004e, 0x0020 }, + { 0x8900, 0x0057, 0x4020 }, + { 0x8900, 0x0053, 0x3020 }, + { 0x8900, 0x0051, 0x2020 }, + { 0x0900, 0x0050, 0x0020 }, + { 0x0900, 0x0052, 0x0020 }, + { 0x8900, 0x0055, 0x2020 }, + { 0x0900, 0x0054, 0x0020 }, + { 0x0900, 0x0056, 0x0020 }, + { 0x9600, 0x005b, 0x3000 }, + { 0x8900, 0x0059, 0x2020 }, + { 0x0900, 0x0058, 0x0020 }, + { 0x0900, 0x005a, 0x0020 }, + { 0x9200, 0x005d, 0x2000 }, + { 0x1500, 0x005c, 0x0000 }, + { 0x1800, 0x005e, 0x0000 }, + { 0x8500, 0x006f, 0x5fe0 }, + { 0x8500, 0x0067, 0x4fe0 }, + { 0x8500, 0x0063, 0x3fe0 }, + { 0x8500, 0x0061, 0x2fe0 }, + { 0x1800, 0x0060, 0x0000 }, + { 0x0500, 0x0062, 0x0fe0 }, + { 0x8500, 0x0065, 0x2fe0 }, + { 0x0500, 0x0064, 0x0fe0 }, + { 0x0500, 0x0066, 0x0fe0 }, + { 0x8500, 0x006b, 0x3fe0 }, + { 0x8500, 0x0069, 0x2fe0 }, + { 0x0500, 0x0068, 0x0fe0 }, + { 0x0500, 0x006a, 0x0fe0 }, + { 0x8500, 0x006d, 0x2fe0 }, + { 0x0500, 0x006c, 0x0fe0 }, + { 0x0500, 0x006e, 0x0fe0 }, + { 0x8500, 0x0077, 0x4fe0 }, + { 0x8500, 0x0073, 0x3fe0 }, + { 0x8500, 0x0071, 0x2fe0 }, + { 0x0500, 0x0070, 0x0fe0 }, + { 0x0500, 0x0072, 0x0fe0 }, + { 0x8500, 0x0075, 0x2fe0 }, + { 0x0500, 0x0074, 0x0fe0 }, + { 0x0500, 0x0076, 0x0fe0 }, + { 0x9600, 0x007b, 0x3000 }, + { 0x8500, 0x0079, 0x2fe0 }, + { 0x0500, 0x0078, 0x0fe0 }, + { 0x0500, 0x007a, 0x0fe0 }, + { 0x9200, 0x007d, 0x2000 }, + { 0x1900, 0x007c, 0x0000 }, + { 0x1900, 0x007e, 0x0000 }, + { 0x9500, 0x00bf, 0x7000 }, + { 0x8000, 0x009f, 0x6000 }, + { 0x8000, 0x008f, 0x5000 }, + { 0x8000, 0x0087, 0x4000 }, + { 0x8000, 0x0083, 0x3000 }, + { 0x8000, 0x0081, 0x2000 }, + { 0x0000, 0x0080, 0x0000 }, + { 0x0000, 0x0082, 0x0000 }, + { 0x8000, 0x0085, 0x2000 }, + { 0x0000, 0x0084, 0x0000 }, + { 0x0000, 0x0086, 0x0000 }, + { 0x8000, 0x008b, 0x3000 }, + { 0x8000, 0x0089, 0x2000 }, + { 0x0000, 0x0088, 0x0000 }, + { 0x0000, 0x008a, 0x0000 }, + { 0x8000, 0x008d, 0x2000 }, + { 0x0000, 0x008c, 0x0000 }, + { 0x0000, 0x008e, 0x0000 }, + { 0x8000, 0x0097, 0x4000 }, + { 0x8000, 0x0093, 0x3000 }, + { 0x8000, 0x0091, 0x2000 }, + { 0x0000, 0x0090, 0x0000 }, + { 0x0000, 0x0092, 0x0000 }, + { 0x8000, 0x0095, 0x2000 }, + { 0x0000, 0x0094, 0x0000 }, + { 0x0000, 0x0096, 0x0000 }, + { 0x8000, 0x009b, 0x3000 }, + { 0x8000, 0x0099, 0x2000 }, + { 0x0000, 0x0098, 0x0000 }, + { 0x0000, 0x009a, 0x0000 }, + { 0x8000, 0x009d, 0x2000 }, + { 0x0000, 0x009c, 0x0000 }, + { 0x0000, 0x009e, 0x0000 }, + { 0x9800, 0x00af, 0x5000 }, + { 0x9a00, 0x00a7, 0x4000 }, + { 0x9700, 0x00a3, 0x3000 }, + { 0x9500, 0x00a1, 0x2000 }, + { 0x1d00, 0x00a0, 0x0000 }, + { 0x1700, 0x00a2, 0x0000 }, + { 0x9700, 0x00a5, 0x2000 }, + { 0x1700, 0x00a4, 0x0000 }, + { 0x1a00, 0x00a6, 0x0000 }, + { 0x9400, 0x00ab, 0x3000 }, + { 0x9a00, 0x00a9, 0x2000 }, + { 0x1800, 0x00a8, 0x0000 }, + { 0x0500, 0x00aa, 0x0000 }, + { 0x8100, 0x00ad, 0x2000 }, + { 0x1900, 0x00ac, 0x0000 }, + { 0x1a00, 0x00ae, 0x0000 }, + { 0x9500, 0x00b7, 0x4000 }, + { 0x8f00, 0x00b3, 0x3000 }, + { 0x9900, 0x00b1, 0x2000 }, + { 0x1a00, 0x00b0, 0x0000 }, + { 0x0f00, 0x00b2, 0x0000 }, + { 0x8500, 0x00b5, 0x22e7 }, + { 0x1800, 0x00b4, 0x0000 }, + { 0x1a00, 0x00b6, 0x0000 }, + { 0x9300, 0x00bb, 0x3000 }, + { 0x8f00, 0x00b9, 0x2000 }, + { 0x1800, 0x00b8, 0x0000 }, + { 0x0500, 0x00ba, 0x0000 }, + { 0x8f00, 0x00bd, 0x2000 }, + { 0x0f00, 0x00bc, 0x0000 }, + { 0x0f00, 0x00be, 0x0000 }, + { 0x8500, 0x00df, 0x6000 }, + { 0x8900, 0x00cf, 0x5020 }, + { 0x8900, 0x00c7, 0x4020 }, + { 0x8900, 0x00c3, 0x3020 }, + { 0x8900, 0x00c1, 0x2020 }, + { 0x0900, 0x00c0, 0x0020 }, + { 0x0900, 0x00c2, 0x0020 }, + { 0x8900, 0x00c5, 0x2020 }, + { 0x0900, 0x00c4, 0x0020 }, + { 0x0900, 0x00c6, 0x0020 }, + { 0x8900, 0x00cb, 0x3020 }, + { 0x8900, 0x00c9, 0x2020 }, + { 0x0900, 0x00c8, 0x0020 }, + { 0x0900, 0x00ca, 0x0020 }, + { 0x8900, 0x00cd, 0x2020 }, + { 0x0900, 0x00cc, 0x0020 }, + { 0x0900, 0x00ce, 0x0020 }, + { 0x9900, 0x00d7, 0x4000 }, + { 0x8900, 0x00d3, 0x3020 }, + { 0x8900, 0x00d1, 0x2020 }, + { 0x0900, 0x00d0, 0x0020 }, + { 0x0900, 0x00d2, 0x0020 }, + { 0x8900, 0x00d5, 0x2020 }, + { 0x0900, 0x00d4, 0x0020 }, + { 0x0900, 0x00d6, 0x0020 }, + { 0x8900, 0x00db, 0x3020 }, + { 0x8900, 0x00d9, 0x2020 }, + { 0x0900, 0x00d8, 0x0020 }, + { 0x0900, 0x00da, 0x0020 }, + { 0x8900, 0x00dd, 0x2020 }, + { 0x0900, 0x00dc, 0x0020 }, + { 0x0900, 0x00de, 0x0020 }, + { 0x8500, 0x00ef, 0x5fe0 }, + { 0x8500, 0x00e7, 0x4fe0 }, + { 0x8500, 0x00e3, 0x3fe0 }, + { 0x8500, 0x00e1, 0x2fe0 }, + { 0x0500, 0x00e0, 0x0fe0 }, + { 0x0500, 0x00e2, 0x0fe0 }, + { 0x8500, 0x00e5, 0x2fe0 }, + { 0x0500, 0x00e4, 0x0fe0 }, + { 0x0500, 0x00e6, 0x0fe0 }, + { 0x8500, 0x00eb, 0x3fe0 }, + { 0x8500, 0x00e9, 0x2fe0 }, + { 0x0500, 0x00e8, 0x0fe0 }, + { 0x0500, 0x00ea, 0x0fe0 }, + { 0x8500, 0x00ed, 0x2fe0 }, + { 0x0500, 0x00ec, 0x0fe0 }, + { 0x0500, 0x00ee, 0x0fe0 }, + { 0x9900, 0x00f7, 0x4000 }, + { 0x8500, 0x00f3, 0x3fe0 }, + { 0x8500, 0x00f1, 0x2fe0 }, + { 0x0500, 0x00f0, 0x0fe0 }, + { 0x0500, 0x00f2, 0x0fe0 }, + { 0x8500, 0x00f5, 0x2fe0 }, + { 0x0500, 0x00f4, 0x0fe0 }, + { 0x0500, 0x00f6, 0x0fe0 }, + { 0x8500, 0x00fb, 0x3fe0 }, + { 0x8500, 0x00f9, 0x2fe0 }, + { 0x0500, 0x00f8, 0x0fe0 }, + { 0x0500, 0x00fa, 0x0fe0 }, + { 0x8500, 0x00fd, 0x2fe0 }, + { 0x0500, 0x00fc, 0x0fe0 }, + { 0x0500, 0x00fe, 0x0fe0 }, + { 0x8500, 0x017f, 0x8ed4 }, + { 0x8900, 0x013f, 0x7001 }, + { 0x8500, 0x011f, 0x6fff }, + { 0x8500, 0x010f, 0x5fff }, + { 0x8500, 0x0107, 0x4fff }, + { 0x8500, 0x0103, 0x3fff }, + { 0x8500, 0x0101, 0x2fff }, + { 0x0900, 0x0100, 0x0001 }, + { 0x0900, 0x0102, 0x0001 }, + { 0x8500, 0x0105, 0x2fff }, + { 0x0900, 0x0104, 0x0001 }, + { 0x0900, 0x0106, 0x0001 }, + { 0x8500, 0x010b, 0x3fff }, + { 0x8500, 0x0109, 0x2fff }, + { 0x0900, 0x0108, 0x0001 }, + { 0x0900, 0x010a, 0x0001 }, + { 0x8500, 0x010d, 0x2fff }, + { 0x0900, 0x010c, 0x0001 }, + { 0x0900, 0x010e, 0x0001 }, + { 0x8500, 0x0117, 0x4fff }, + { 0x8500, 0x0113, 0x3fff }, + { 0x8500, 0x0111, 0x2fff }, + { 0x0900, 0x0110, 0x0001 }, + { 0x0900, 0x0112, 0x0001 }, + { 0x8500, 0x0115, 0x2fff }, + { 0x0900, 0x0114, 0x0001 }, + { 0x0900, 0x0116, 0x0001 }, + { 0x8500, 0x011b, 0x3fff }, + { 0x8500, 0x0119, 0x2fff }, + { 0x0900, 0x0118, 0x0001 }, + { 0x0900, 0x011a, 0x0001 }, + { 0x8500, 0x011d, 0x2fff }, + { 0x0900, 0x011c, 0x0001 }, + { 0x0900, 0x011e, 0x0001 }, + { 0x8500, 0x012f, 0x5fff }, + { 0x8500, 0x0127, 0x4fff }, + { 0x8500, 0x0123, 0x3fff }, + { 0x8500, 0x0121, 0x2fff }, + { 0x0900, 0x0120, 0x0001 }, + { 0x0900, 0x0122, 0x0001 }, + { 0x8500, 0x0125, 0x2fff }, + { 0x0900, 0x0124, 0x0001 }, + { 0x0900, 0x0126, 0x0001 }, + { 0x8500, 0x012b, 0x3fff }, + { 0x8500, 0x0129, 0x2fff }, + { 0x0900, 0x0128, 0x0001 }, + { 0x0900, 0x012a, 0x0001 }, + { 0x8500, 0x012d, 0x2fff }, + { 0x0900, 0x012c, 0x0001 }, + { 0x0900, 0x012e, 0x0001 }, + { 0x8500, 0x0137, 0x4fff }, + { 0x8500, 0x0133, 0x3fff }, + { 0x8500, 0x0131, 0x2f18 }, + { 0x0900, 0x0130, 0x0f39 }, + { 0x0900, 0x0132, 0x0001 }, + { 0x8500, 0x0135, 0x2fff }, + { 0x0900, 0x0134, 0x0001 }, + { 0x0900, 0x0136, 0x0001 }, + { 0x8900, 0x013b, 0x3001 }, + { 0x8900, 0x0139, 0x2001 }, + { 0x0500, 0x0138, 0x0000 }, + { 0x0500, 0x013a, 0x0fff }, + { 0x8900, 0x013d, 0x2001 }, + { 0x0500, 0x013c, 0x0fff }, + { 0x0500, 0x013e, 0x0fff }, + { 0x8500, 0x015f, 0x6fff }, + { 0x8500, 0x014f, 0x5fff }, + { 0x8900, 0x0147, 0x4001 }, + { 0x8900, 0x0143, 0x3001 }, + { 0x8900, 0x0141, 0x2001 }, + { 0x0500, 0x0140, 0x0fff }, + { 0x0500, 0x0142, 0x0fff }, + { 0x8900, 0x0145, 0x2001 }, + { 0x0500, 0x0144, 0x0fff }, + { 0x0500, 0x0146, 0x0fff }, + { 0x8500, 0x014b, 0x3fff }, + { 0x8500, 0x0149, 0x2000 }, + { 0x0500, 0x0148, 0x0fff }, + { 0x0900, 0x014a, 0x0001 }, + { 0x8500, 0x014d, 0x2fff }, + { 0x0900, 0x014c, 0x0001 }, + { 0x0900, 0x014e, 0x0001 }, + { 0x8500, 0x0157, 0x4fff }, + { 0x8500, 0x0153, 0x3fff }, + { 0x8500, 0x0151, 0x2fff }, + { 0x0900, 0x0150, 0x0001 }, + { 0x0900, 0x0152, 0x0001 }, + { 0x8500, 0x0155, 0x2fff }, + { 0x0900, 0x0154, 0x0001 }, + { 0x0900, 0x0156, 0x0001 }, + { 0x8500, 0x015b, 0x3fff }, + { 0x8500, 0x0159, 0x2fff }, + { 0x0900, 0x0158, 0x0001 }, + { 0x0900, 0x015a, 0x0001 }, + { 0x8500, 0x015d, 0x2fff }, + { 0x0900, 0x015c, 0x0001 }, + { 0x0900, 0x015e, 0x0001 }, + { 0x8500, 0x016f, 0x5fff }, + { 0x8500, 0x0167, 0x4fff }, + { 0x8500, 0x0163, 0x3fff }, + { 0x8500, 0x0161, 0x2fff }, + { 0x0900, 0x0160, 0x0001 }, + { 0x0900, 0x0162, 0x0001 }, + { 0x8500, 0x0165, 0x2fff }, + { 0x0900, 0x0164, 0x0001 }, + { 0x0900, 0x0166, 0x0001 }, + { 0x8500, 0x016b, 0x3fff }, + { 0x8500, 0x0169, 0x2fff }, + { 0x0900, 0x0168, 0x0001 }, + { 0x0900, 0x016a, 0x0001 }, + { 0x8500, 0x016d, 0x2fff }, + { 0x0900, 0x016c, 0x0001 }, + { 0x0900, 0x016e, 0x0001 }, + { 0x8500, 0x0177, 0x4fff }, + { 0x8500, 0x0173, 0x3fff }, + { 0x8500, 0x0171, 0x2fff }, + { 0x0900, 0x0170, 0x0001 }, + { 0x0900, 0x0172, 0x0001 }, + { 0x8500, 0x0175, 0x2fff }, + { 0x0900, 0x0174, 0x0001 }, + { 0x0900, 0x0176, 0x0001 }, + { 0x8900, 0x017b, 0x3001 }, + { 0x8900, 0x0179, 0x2001 }, + { 0x0900, 0x0178, 0x0f87 }, + { 0x0500, 0x017a, 0x0fff }, + { 0x8900, 0x017d, 0x2001 }, + { 0x0500, 0x017c, 0x0fff }, + { 0x0500, 0x017e, 0x0fff }, + { 0x8500, 0x01bf, 0x7038 }, + { 0x8900, 0x019f, 0x60d6 }, + { 0x8900, 0x018f, 0x50ca }, + { 0x8900, 0x0187, 0x4001 }, + { 0x8500, 0x0183, 0x3fff }, + { 0x8900, 0x0181, 0x20d2 }, + { 0x0500, 0x0180, 0x0000 }, + { 0x0900, 0x0182, 0x0001 }, + { 0x8500, 0x0185, 0x2fff }, + { 0x0900, 0x0184, 0x0001 }, + { 0x0900, 0x0186, 0x00ce }, + { 0x8900, 0x018b, 0x3001 }, + { 0x8900, 0x0189, 0x20cd }, + { 0x0500, 0x0188, 0x0fff }, + { 0x0900, 0x018a, 0x00cd }, + { 0x8500, 0x018d, 0x2000 }, + { 0x0500, 0x018c, 0x0fff }, + { 0x0900, 0x018e, 0x004f }, + { 0x8900, 0x0197, 0x40d1 }, + { 0x8900, 0x0193, 0x30cd }, + { 0x8900, 0x0191, 0x2001 }, + { 0x0900, 0x0190, 0x00cb }, + { 0x0500, 0x0192, 0x0fff }, + { 0x8500, 0x0195, 0x2061 }, + { 0x0900, 0x0194, 0x00cf }, + { 0x0900, 0x0196, 0x00d3 }, + { 0x8500, 0x019b, 0x3000 }, + { 0x8500, 0x0199, 0x2fff }, + { 0x0900, 0x0198, 0x0001 }, + { 0x0500, 0x019a, 0x0000 }, + { 0x8900, 0x019d, 0x20d5 }, + { 0x0900, 0x019c, 0x00d3 }, + { 0x0500, 0x019e, 0x0082 }, + { 0x8900, 0x01af, 0x5001 }, + { 0x8900, 0x01a7, 0x4001 }, + { 0x8500, 0x01a3, 0x3fff }, + { 0x8500, 0x01a1, 0x2fff }, + { 0x0900, 0x01a0, 0x0001 }, + { 0x0900, 0x01a2, 0x0001 }, + { 0x8500, 0x01a5, 0x2fff }, + { 0x0900, 0x01a4, 0x0001 }, + { 0x0900, 0x01a6, 0x00da }, + { 0x8500, 0x01ab, 0x3000 }, + { 0x8900, 0x01a9, 0x20da }, + { 0x0500, 0x01a8, 0x0fff }, + { 0x0500, 0x01aa, 0x0000 }, + { 0x8500, 0x01ad, 0x2fff }, + { 0x0900, 0x01ac, 0x0001 }, + { 0x0900, 0x01ae, 0x00da }, + { 0x8900, 0x01b7, 0x40db }, + { 0x8900, 0x01b3, 0x3001 }, + { 0x8900, 0x01b1, 0x20d9 }, + { 0x0500, 0x01b0, 0x0fff }, + { 0x0900, 0x01b2, 0x00d9 }, + { 0x8900, 0x01b5, 0x2001 }, + { 0x0500, 0x01b4, 0x0fff }, + { 0x0500, 0x01b6, 0x0fff }, + { 0x8700, 0x01bb, 0x3000 }, + { 0x8500, 0x01b9, 0x2fff }, + { 0x0900, 0x01b8, 0x0001 }, + { 0x0500, 0x01ba, 0x0000 }, + { 0x8500, 0x01bd, 0x2fff }, + { 0x0900, 0x01bc, 0x0001 }, + { 0x0500, 0x01be, 0x0000 }, + { 0x8500, 0x01df, 0x6fff }, + { 0x8900, 0x01cf, 0x5001 }, + { 0x8900, 0x01c7, 0x4002 }, + { 0x8700, 0x01c3, 0x3000 }, + { 0x8700, 0x01c1, 0x2000 }, + { 0x0700, 0x01c0, 0x0000 }, + { 0x0700, 0x01c2, 0x0000 }, + { 0x8800, 0x01c5, 0x2000 }, + { 0x0900, 0x01c4, 0x0002 }, + { 0x0500, 0x01c6, 0x0ffe }, + { 0x8800, 0x01cb, 0x3000 }, + { 0x8500, 0x01c9, 0x2ffe }, + { 0x0800, 0x01c8, 0x0000 }, + { 0x0900, 0x01ca, 0x0002 }, + { 0x8900, 0x01cd, 0x2001 }, + { 0x0500, 0x01cc, 0x0ffe }, + { 0x0500, 0x01ce, 0x0fff }, + { 0x8900, 0x01d7, 0x4001 }, + { 0x8900, 0x01d3, 0x3001 }, + { 0x8900, 0x01d1, 0x2001 }, + { 0x0500, 0x01d0, 0x0fff }, + { 0x0500, 0x01d2, 0x0fff }, + { 0x8900, 0x01d5, 0x2001 }, + { 0x0500, 0x01d4, 0x0fff }, + { 0x0500, 0x01d6, 0x0fff }, + { 0x8900, 0x01db, 0x3001 }, + { 0x8900, 0x01d9, 0x2001 }, + { 0x0500, 0x01d8, 0x0fff }, + { 0x0500, 0x01da, 0x0fff }, + { 0x8500, 0x01dd, 0x2fb1 }, + { 0x0500, 0x01dc, 0x0fff }, + { 0x0900, 0x01de, 0x0001 }, + { 0x8500, 0x01ef, 0x5fff }, + { 0x8500, 0x01e7, 0x4fff }, + { 0x8500, 0x01e3, 0x3fff }, + { 0x8500, 0x01e1, 0x2fff }, + { 0x0900, 0x01e0, 0x0001 }, + { 0x0900, 0x01e2, 0x0001 }, + { 0x8500, 0x01e5, 0x2fff }, + { 0x0900, 0x01e4, 0x0001 }, + { 0x0900, 0x01e6, 0x0001 }, + { 0x8500, 0x01eb, 0x3fff }, + { 0x8500, 0x01e9, 0x2fff }, + { 0x0900, 0x01e8, 0x0001 }, + { 0x0900, 0x01ea, 0x0001 }, + { 0x8500, 0x01ed, 0x2fff }, + { 0x0900, 0x01ec, 0x0001 }, + { 0x0900, 0x01ee, 0x0001 }, + { 0x8900, 0x01f7, 0x4fc8 }, + { 0x8500, 0x01f3, 0x3ffe }, + { 0x8900, 0x01f1, 0x2002 }, + { 0x0500, 0x01f0, 0x0000 }, + { 0x0800, 0x01f2, 0x0000 }, + { 0x8500, 0x01f5, 0x2fff }, + { 0x0900, 0x01f4, 0x0001 }, + { 0x0900, 0x01f6, 0x0f9f }, + { 0x8500, 0x01fb, 0x3fff }, + { 0x8500, 0x01f9, 0x2fff }, + { 0x0900, 0x01f8, 0x0001 }, + { 0x0900, 0x01fa, 0x0001 }, + { 0x8500, 0x01fd, 0x2fff }, + { 0x0900, 0x01fc, 0x0001 }, + { 0x0900, 0x01fe, 0x0001 }, + { 0x8c00, 0x0318, 0x9000 }, + { 0x8500, 0x0298, 0x8000 }, + { 0x8500, 0x0258, 0x7000 }, + { 0x8500, 0x021f, 0x6fff }, + { 0x8500, 0x020f, 0x5fff }, + { 0x8500, 0x0207, 0x4fff }, + { 0x8500, 0x0203, 0x3fff }, + { 0x8500, 0x0201, 0x2fff }, + { 0x0900, 0x0200, 0x0001 }, + { 0x0900, 0x0202, 0x0001 }, + { 0x8500, 0x0205, 0x2fff }, + { 0x0900, 0x0204, 0x0001 }, + { 0x0900, 0x0206, 0x0001 }, + { 0x8500, 0x020b, 0x3fff }, + { 0x8500, 0x0209, 0x2fff }, + { 0x0900, 0x0208, 0x0001 }, + { 0x0900, 0x020a, 0x0001 }, + { 0x8500, 0x020d, 0x2fff }, + { 0x0900, 0x020c, 0x0001 }, + { 0x0900, 0x020e, 0x0001 }, + { 0x8500, 0x0217, 0x4fff }, + { 0x8500, 0x0213, 0x3fff }, + { 0x8500, 0x0211, 0x2fff }, + { 0x0900, 0x0210, 0x0001 }, + { 0x0900, 0x0212, 0x0001 }, + { 0x8500, 0x0215, 0x2fff }, + { 0x0900, 0x0214, 0x0001 }, + { 0x0900, 0x0216, 0x0001 }, + { 0x8500, 0x021b, 0x3fff }, + { 0x8500, 0x0219, 0x2fff }, + { 0x0900, 0x0218, 0x0001 }, + { 0x0900, 0x021a, 0x0001 }, + { 0x8500, 0x021d, 0x2fff }, + { 0x0900, 0x021c, 0x0001 }, + { 0x0900, 0x021e, 0x0001 }, + { 0x8500, 0x022f, 0x5fff }, + { 0x8500, 0x0227, 0x4fff }, + { 0x8500, 0x0223, 0x3fff }, + { 0x8500, 0x0221, 0x2000 }, + { 0x0900, 0x0220, 0x0f7e }, + { 0x0900, 0x0222, 0x0001 }, + { 0x8500, 0x0225, 0x2fff }, + { 0x0900, 0x0224, 0x0001 }, + { 0x0900, 0x0226, 0x0001 }, + { 0x8500, 0x022b, 0x3fff }, + { 0x8500, 0x0229, 0x2fff }, + { 0x0900, 0x0228, 0x0001 }, + { 0x0900, 0x022a, 0x0001 }, + { 0x8500, 0x022d, 0x2fff }, + { 0x0900, 0x022c, 0x0001 }, + { 0x0900, 0x022e, 0x0001 }, + { 0x8500, 0x0250, 0x4000 }, + { 0x8500, 0x0233, 0x3fff }, + { 0x8500, 0x0231, 0x2fff }, + { 0x0900, 0x0230, 0x0001 }, + { 0x0900, 0x0232, 0x0001 }, + { 0x8500, 0x0235, 0x2000 }, + { 0x0500, 0x0234, 0x0000 }, + { 0x0500, 0x0236, 0x0000 }, + { 0x8500, 0x0254, 0x3f32 }, + { 0x8500, 0x0252, 0x2000 }, + { 0x0500, 0x0251, 0x0000 }, + { 0x0500, 0x0253, 0x0f2e }, + { 0x8500, 0x0256, 0x2f33 }, + { 0x0500, 0x0255, 0x0000 }, + { 0x0500, 0x0257, 0x0f33 }, + { 0x8500, 0x0278, 0x6000 }, + { 0x8500, 0x0268, 0x5f2f }, + { 0x8500, 0x0260, 0x4f33 }, + { 0x8500, 0x025c, 0x3000 }, + { 0x8500, 0x025a, 0x2000 }, + { 0x0500, 0x0259, 0x0f36 }, + { 0x0500, 0x025b, 0x0f35 }, + { 0x8500, 0x025e, 0x2000 }, + { 0x0500, 0x025d, 0x0000 }, + { 0x0500, 0x025f, 0x0000 }, + { 0x8500, 0x0264, 0x3000 }, + { 0x8500, 0x0262, 0x2000 }, + { 0x0500, 0x0261, 0x0000 }, + { 0x0500, 0x0263, 0x0f31 }, + { 0x8500, 0x0266, 0x2000 }, + { 0x0500, 0x0265, 0x0000 }, + { 0x0500, 0x0267, 0x0000 }, + { 0x8500, 0x0270, 0x4000 }, + { 0x8500, 0x026c, 0x3000 }, + { 0x8500, 0x026a, 0x2000 }, + { 0x0500, 0x0269, 0x0f2d }, + { 0x0500, 0x026b, 0x0000 }, + { 0x8500, 0x026e, 0x2000 }, + { 0x0500, 0x026d, 0x0000 }, + { 0x0500, 0x026f, 0x0f2d }, + { 0x8500, 0x0274, 0x3000 }, + { 0x8500, 0x0272, 0x2f2b }, + { 0x0500, 0x0271, 0x0000 }, + { 0x0500, 0x0273, 0x0000 }, + { 0x8500, 0x0276, 0x2000 }, + { 0x0500, 0x0275, 0x0f2a }, + { 0x0500, 0x0277, 0x0000 }, + { 0x8500, 0x0288, 0x5f26 }, + { 0x8500, 0x0280, 0x4f26 }, + { 0x8500, 0x027c, 0x3000 }, + { 0x8500, 0x027a, 0x2000 }, + { 0x0500, 0x0279, 0x0000 }, + { 0x0500, 0x027b, 0x0000 }, + { 0x8500, 0x027e, 0x2000 }, + { 0x0500, 0x027d, 0x0000 }, + { 0x0500, 0x027f, 0x0000 }, + { 0x8500, 0x0284, 0x3000 }, + { 0x8500, 0x0282, 0x2000 }, + { 0x0500, 0x0281, 0x0000 }, + { 0x0500, 0x0283, 0x0f26 }, + { 0x8500, 0x0286, 0x2000 }, + { 0x0500, 0x0285, 0x0000 }, + { 0x0500, 0x0287, 0x0000 }, + { 0x8500, 0x0290, 0x4000 }, + { 0x8500, 0x028c, 0x3000 }, + { 0x8500, 0x028a, 0x2f27 }, + { 0x0500, 0x0289, 0x0000 }, + { 0x0500, 0x028b, 0x0f27 }, + { 0x8500, 0x028e, 0x2000 }, + { 0x0500, 0x028d, 0x0000 }, + { 0x0500, 0x028f, 0x0000 }, + { 0x8500, 0x0294, 0x3000 }, + { 0x8500, 0x0292, 0x2f25 }, + { 0x0500, 0x0291, 0x0000 }, + { 0x0500, 0x0293, 0x0000 }, + { 0x8500, 0x0296, 0x2000 }, + { 0x0500, 0x0295, 0x0000 }, + { 0x0500, 0x0297, 0x0000 }, + { 0x9800, 0x02d8, 0x7000 }, + { 0x8600, 0x02b8, 0x6000 }, + { 0x8500, 0x02a8, 0x5000 }, + { 0x8500, 0x02a0, 0x4000 }, + { 0x8500, 0x029c, 0x3000 }, + { 0x8500, 0x029a, 0x2000 }, + { 0x0500, 0x0299, 0x0000 }, + { 0x0500, 0x029b, 0x0000 }, + { 0x8500, 0x029e, 0x2000 }, + { 0x0500, 0x029d, 0x0000 }, + { 0x0500, 0x029f, 0x0000 }, + { 0x8500, 0x02a4, 0x3000 }, + { 0x8500, 0x02a2, 0x2000 }, + { 0x0500, 0x02a1, 0x0000 }, + { 0x0500, 0x02a3, 0x0000 }, + { 0x8500, 0x02a6, 0x2000 }, + { 0x0500, 0x02a5, 0x0000 }, + { 0x0500, 0x02a7, 0x0000 }, + { 0x8600, 0x02b0, 0x4000 }, + { 0x8500, 0x02ac, 0x3000 }, + { 0x8500, 0x02aa, 0x2000 }, + { 0x0500, 0x02a9, 0x0000 }, + { 0x0500, 0x02ab, 0x0000 }, + { 0x8500, 0x02ae, 0x2000 }, + { 0x0500, 0x02ad, 0x0000 }, + { 0x0500, 0x02af, 0x0000 }, + { 0x8600, 0x02b4, 0x3000 }, + { 0x8600, 0x02b2, 0x2000 }, + { 0x0600, 0x02b1, 0x0000 }, + { 0x0600, 0x02b3, 0x0000 }, + { 0x8600, 0x02b6, 0x2000 }, + { 0x0600, 0x02b5, 0x0000 }, + { 0x0600, 0x02b7, 0x0000 }, + { 0x8600, 0x02c8, 0x5000 }, + { 0x8600, 0x02c0, 0x4000 }, + { 0x8600, 0x02bc, 0x3000 }, + { 0x8600, 0x02ba, 0x2000 }, + { 0x0600, 0x02b9, 0x0000 }, + { 0x0600, 0x02bb, 0x0000 }, + { 0x8600, 0x02be, 0x2000 }, + { 0x0600, 0x02bd, 0x0000 }, + { 0x0600, 0x02bf, 0x0000 }, + { 0x9800, 0x02c4, 0x3000 }, + { 0x9800, 0x02c2, 0x2000 }, + { 0x0600, 0x02c1, 0x0000 }, + { 0x1800, 0x02c3, 0x0000 }, + { 0x8600, 0x02c6, 0x2000 }, + { 0x1800, 0x02c5, 0x0000 }, + { 0x0600, 0x02c7, 0x0000 }, + { 0x8600, 0x02d0, 0x4000 }, + { 0x8600, 0x02cc, 0x3000 }, + { 0x8600, 0x02ca, 0x2000 }, + { 0x0600, 0x02c9, 0x0000 }, + { 0x0600, 0x02cb, 0x0000 }, + { 0x8600, 0x02ce, 0x2000 }, + { 0x0600, 0x02cd, 0x0000 }, + { 0x0600, 0x02cf, 0x0000 }, + { 0x9800, 0x02d4, 0x3000 }, + { 0x9800, 0x02d2, 0x2000 }, + { 0x0600, 0x02d1, 0x0000 }, + { 0x1800, 0x02d3, 0x0000 }, + { 0x9800, 0x02d6, 0x2000 }, + { 0x1800, 0x02d5, 0x0000 }, + { 0x1800, 0x02d7, 0x0000 }, + { 0x9800, 0x02f8, 0x6000 }, + { 0x9800, 0x02e8, 0x5000 }, + { 0x8600, 0x02e0, 0x4000 }, + { 0x9800, 0x02dc, 0x3000 }, + { 0x9800, 0x02da, 0x2000 }, + { 0x1800, 0x02d9, 0x0000 }, + { 0x1800, 0x02db, 0x0000 }, + { 0x9800, 0x02de, 0x2000 }, + { 0x1800, 0x02dd, 0x0000 }, + { 0x1800, 0x02df, 0x0000 }, + { 0x8600, 0x02e4, 0x3000 }, + { 0x8600, 0x02e2, 0x2000 }, + { 0x0600, 0x02e1, 0x0000 }, + { 0x0600, 0x02e3, 0x0000 }, + { 0x9800, 0x02e6, 0x2000 }, + { 0x1800, 0x02e5, 0x0000 }, + { 0x1800, 0x02e7, 0x0000 }, + { 0x9800, 0x02f0, 0x4000 }, + { 0x9800, 0x02ec, 0x3000 }, + { 0x9800, 0x02ea, 0x2000 }, + { 0x1800, 0x02e9, 0x0000 }, + { 0x1800, 0x02eb, 0x0000 }, + { 0x8600, 0x02ee, 0x2000 }, + { 0x1800, 0x02ed, 0x0000 }, + { 0x1800, 0x02ef, 0x0000 }, + { 0x9800, 0x02f4, 0x3000 }, + { 0x9800, 0x02f2, 0x2000 }, + { 0x1800, 0x02f1, 0x0000 }, + { 0x1800, 0x02f3, 0x0000 }, + { 0x9800, 0x02f6, 0x2000 }, + { 0x1800, 0x02f5, 0x0000 }, + { 0x1800, 0x02f7, 0x0000 }, + { 0x8c00, 0x0308, 0x5000 }, + { 0x8c00, 0x0300, 0x4000 }, + { 0x9800, 0x02fc, 0x3000 }, + { 0x9800, 0x02fa, 0x2000 }, + { 0x1800, 0x02f9, 0x0000 }, + { 0x1800, 0x02fb, 0x0000 }, + { 0x9800, 0x02fe, 0x2000 }, + { 0x1800, 0x02fd, 0x0000 }, + { 0x1800, 0x02ff, 0x0000 }, + { 0x8c00, 0x0304, 0x3000 }, + { 0x8c00, 0x0302, 0x2000 }, + { 0x0c00, 0x0301, 0x0000 }, + { 0x0c00, 0x0303, 0x0000 }, + { 0x8c00, 0x0306, 0x2000 }, + { 0x0c00, 0x0305, 0x0000 }, + { 0x0c00, 0x0307, 0x0000 }, + { 0x8c00, 0x0310, 0x4000 }, + { 0x8c00, 0x030c, 0x3000 }, + { 0x8c00, 0x030a, 0x2000 }, + { 0x0c00, 0x0309, 0x0000 }, + { 0x0c00, 0x030b, 0x0000 }, + { 0x8c00, 0x030e, 0x2000 }, + { 0x0c00, 0x030d, 0x0000 }, + { 0x0c00, 0x030f, 0x0000 }, + { 0x8c00, 0x0314, 0x3000 }, + { 0x8c00, 0x0312, 0x2000 }, + { 0x0c00, 0x0311, 0x0000 }, + { 0x0c00, 0x0313, 0x0000 }, + { 0x8c00, 0x0316, 0x2000 }, + { 0x0c00, 0x0315, 0x0000 }, + { 0x0c00, 0x0317, 0x0000 }, + { 0x8500, 0x03b0, 0x8000 }, + { 0x8c00, 0x035d, 0x7000 }, + { 0x8c00, 0x0338, 0x6000 }, + { 0x8c00, 0x0328, 0x5000 }, + { 0x8c00, 0x0320, 0x4000 }, + { 0x8c00, 0x031c, 0x3000 }, + { 0x8c00, 0x031a, 0x2000 }, + { 0x0c00, 0x0319, 0x0000 }, + { 0x0c00, 0x031b, 0x0000 }, + { 0x8c00, 0x031e, 0x2000 }, + { 0x0c00, 0x031d, 0x0000 }, + { 0x0c00, 0x031f, 0x0000 }, + { 0x8c00, 0x0324, 0x3000 }, + { 0x8c00, 0x0322, 0x2000 }, + { 0x0c00, 0x0321, 0x0000 }, + { 0x0c00, 0x0323, 0x0000 }, + { 0x8c00, 0x0326, 0x2000 }, + { 0x0c00, 0x0325, 0x0000 }, + { 0x0c00, 0x0327, 0x0000 }, + { 0x8c00, 0x0330, 0x4000 }, + { 0x8c00, 0x032c, 0x3000 }, + { 0x8c00, 0x032a, 0x2000 }, + { 0x0c00, 0x0329, 0x0000 }, + { 0x0c00, 0x032b, 0x0000 }, + { 0x8c00, 0x032e, 0x2000 }, + { 0x0c00, 0x032d, 0x0000 }, + { 0x0c00, 0x032f, 0x0000 }, + { 0x8c00, 0x0334, 0x3000 }, + { 0x8c00, 0x0332, 0x2000 }, + { 0x0c00, 0x0331, 0x0000 }, + { 0x0c00, 0x0333, 0x0000 }, + { 0x8c00, 0x0336, 0x2000 }, + { 0x0c00, 0x0335, 0x0000 }, + { 0x0c00, 0x0337, 0x0000 }, + { 0x8c00, 0x0348, 0x5000 }, + { 0x8c00, 0x0340, 0x4000 }, + { 0x8c00, 0x033c, 0x3000 }, + { 0x8c00, 0x033a, 0x2000 }, + { 0x0c00, 0x0339, 0x0000 }, + { 0x0c00, 0x033b, 0x0000 }, + { 0x8c00, 0x033e, 0x2000 }, + { 0x0c00, 0x033d, 0x0000 }, + { 0x0c00, 0x033f, 0x0000 }, + { 0x8c00, 0x0344, 0x3000 }, + { 0x8c00, 0x0342, 0x2000 }, + { 0x0c00, 0x0341, 0x0000 }, + { 0x0c00, 0x0343, 0x0000 }, + { 0x8c00, 0x0346, 0x2000 }, + { 0x0c00, 0x0345, 0x0000 }, + { 0x0c00, 0x0347, 0x0000 }, + { 0x8c00, 0x0350, 0x4000 }, + { 0x8c00, 0x034c, 0x3000 }, + { 0x8c00, 0x034a, 0x2000 }, + { 0x0c00, 0x0349, 0x0000 }, + { 0x0c00, 0x034b, 0x0000 }, + { 0x8c00, 0x034e, 0x2000 }, + { 0x0c00, 0x034d, 0x0000 }, + { 0x0c00, 0x034f, 0x0000 }, + { 0x8c00, 0x0354, 0x3000 }, + { 0x8c00, 0x0352, 0x2000 }, + { 0x0c00, 0x0351, 0x0000 }, + { 0x0c00, 0x0353, 0x0000 }, + { 0x8c00, 0x0356, 0x2000 }, + { 0x0c00, 0x0355, 0x0000 }, + { 0x0c00, 0x0357, 0x0000 }, + { 0x8900, 0x038f, 0x603f }, + { 0x8c00, 0x036d, 0x5000 }, + { 0x8c00, 0x0365, 0x4000 }, + { 0x8c00, 0x0361, 0x3000 }, + { 0x8c00, 0x035f, 0x2000 }, + { 0x0c00, 0x035e, 0x0000 }, + { 0x0c00, 0x0360, 0x0000 }, + { 0x8c00, 0x0363, 0x2000 }, + { 0x0c00, 0x0362, 0x0000 }, + { 0x0c00, 0x0364, 0x0000 }, + { 0x8c00, 0x0369, 0x3000 }, + { 0x8c00, 0x0367, 0x2000 }, + { 0x0c00, 0x0366, 0x0000 }, + { 0x0c00, 0x0368, 0x0000 }, + { 0x8c00, 0x036b, 0x2000 }, + { 0x0c00, 0x036a, 0x0000 }, + { 0x0c00, 0x036c, 0x0000 }, + { 0x9800, 0x0385, 0x4000 }, + { 0x9800, 0x0375, 0x3000 }, + { 0x8c00, 0x036f, 0x2000 }, + { 0x0c00, 0x036e, 0x0000 }, + { 0x1800, 0x0374, 0x0000 }, + { 0x9500, 0x037e, 0x2000 }, + { 0x0600, 0x037a, 0x0000 }, + { 0x1800, 0x0384, 0x0000 }, + { 0x8900, 0x0389, 0x3025 }, + { 0x9500, 0x0387, 0x2000 }, + { 0x0900, 0x0386, 0x0026 }, + { 0x0900, 0x0388, 0x0025 }, + { 0x8900, 0x038c, 0x2040 }, + { 0x0900, 0x038a, 0x0025 }, + { 0x0900, 0x038e, 0x003f }, + { 0x8900, 0x039f, 0x5020 }, + { 0x8900, 0x0397, 0x4020 }, + { 0x8900, 0x0393, 0x3020 }, + { 0x8900, 0x0391, 0x2020 }, + { 0x0500, 0x0390, 0x0000 }, + { 0x0900, 0x0392, 0x0020 }, + { 0x8900, 0x0395, 0x2020 }, + { 0x0900, 0x0394, 0x0020 }, + { 0x0900, 0x0396, 0x0020 }, + { 0x8900, 0x039b, 0x3020 }, + { 0x8900, 0x0399, 0x2020 }, + { 0x0900, 0x0398, 0x0020 }, + { 0x0900, 0x039a, 0x0020 }, + { 0x8900, 0x039d, 0x2020 }, + { 0x0900, 0x039c, 0x0020 }, + { 0x0900, 0x039e, 0x0020 }, + { 0x8900, 0x03a8, 0x4020 }, + { 0x8900, 0x03a4, 0x3020 }, + { 0x8900, 0x03a1, 0x2020 }, + { 0x0900, 0x03a0, 0x0020 }, + { 0x0900, 0x03a3, 0x0020 }, + { 0x8900, 0x03a6, 0x2020 }, + { 0x0900, 0x03a5, 0x0020 }, + { 0x0900, 0x03a7, 0x0020 }, + { 0x8500, 0x03ac, 0x3fda }, + { 0x8900, 0x03aa, 0x2020 }, + { 0x0900, 0x03a9, 0x0020 }, + { 0x0900, 0x03ab, 0x0020 }, + { 0x8500, 0x03ae, 0x2fdb }, + { 0x0500, 0x03ad, 0x0fdb }, + { 0x0500, 0x03af, 0x0fdb }, + { 0x8500, 0x03f1, 0x7fb0 }, + { 0x8500, 0x03d1, 0x6fc7 }, + { 0x8500, 0x03c0, 0x5fe0 }, + { 0x8500, 0x03b8, 0x4fe0 }, + { 0x8500, 0x03b4, 0x3fe0 }, + { 0x8500, 0x03b2, 0x2fe0 }, + { 0x0500, 0x03b1, 0x0fe0 }, + { 0x0500, 0x03b3, 0x0fe0 }, + { 0x8500, 0x03b6, 0x2fe0 }, + { 0x0500, 0x03b5, 0x0fe0 }, + { 0x0500, 0x03b7, 0x0fe0 }, + { 0x8500, 0x03bc, 0x3fe0 }, + { 0x8500, 0x03ba, 0x2fe0 }, + { 0x0500, 0x03b9, 0x0fe0 }, + { 0x0500, 0x03bb, 0x0fe0 }, + { 0x8500, 0x03be, 0x2fe0 }, + { 0x0500, 0x03bd, 0x0fe0 }, + { 0x0500, 0x03bf, 0x0fe0 }, + { 0x8500, 0x03c8, 0x4fe0 }, + { 0x8500, 0x03c4, 0x3fe0 }, + { 0x8500, 0x03c2, 0x2fe1 }, + { 0x0500, 0x03c1, 0x0fe0 }, + { 0x0500, 0x03c3, 0x0fe0 }, + { 0x8500, 0x03c6, 0x2fe0 }, + { 0x0500, 0x03c5, 0x0fe0 }, + { 0x0500, 0x03c7, 0x0fe0 }, + { 0x8500, 0x03cc, 0x3fc0 }, + { 0x8500, 0x03ca, 0x2fe0 }, + { 0x0500, 0x03c9, 0x0fe0 }, + { 0x0500, 0x03cb, 0x0fe0 }, + { 0x8500, 0x03ce, 0x2fc1 }, + { 0x0500, 0x03cd, 0x0fc1 }, + { 0x0500, 0x03d0, 0x0fc2 }, + { 0x8500, 0x03e1, 0x5fff }, + { 0x8500, 0x03d9, 0x4fff }, + { 0x8500, 0x03d5, 0x3fd1 }, + { 0x8900, 0x03d3, 0x2000 }, + { 0x0900, 0x03d2, 0x0000 }, + { 0x0900, 0x03d4, 0x0000 }, + { 0x8500, 0x03d7, 0x2000 }, + { 0x0500, 0x03d6, 0x0fca }, + { 0x0900, 0x03d8, 0x0001 }, + { 0x8500, 0x03dd, 0x3fff }, + { 0x8500, 0x03db, 0x2fff }, + { 0x0900, 0x03da, 0x0001 }, + { 0x0900, 0x03dc, 0x0001 }, + { 0x8500, 0x03df, 0x2fff }, + { 0x0900, 0x03de, 0x0001 }, + { 0x0900, 0x03e0, 0x0001 }, + { 0x8500, 0x03e9, 0x4fff }, + { 0x8500, 0x03e5, 0x3fff }, + { 0x8500, 0x03e3, 0x2fff }, + { 0x0900, 0x03e2, 0x0001 }, + { 0x0900, 0x03e4, 0x0001 }, + { 0x8500, 0x03e7, 0x2fff }, + { 0x0900, 0x03e6, 0x0001 }, + { 0x0900, 0x03e8, 0x0001 }, + { 0x8500, 0x03ed, 0x3fff }, + { 0x8500, 0x03eb, 0x2fff }, + { 0x0900, 0x03ea, 0x0001 }, + { 0x0900, 0x03ec, 0x0001 }, + { 0x8500, 0x03ef, 0x2fff }, + { 0x0900, 0x03ee, 0x0001 }, + { 0x0500, 0x03f0, 0x0faa }, + { 0x8900, 0x0415, 0x6020 }, + { 0x8900, 0x0405, 0x5050 }, + { 0x8900, 0x03f9, 0x4ff9 }, + { 0x8500, 0x03f5, 0x3fa0 }, + { 0x8500, 0x03f3, 0x2000 }, + { 0x0500, 0x03f2, 0x0007 }, + { 0x0900, 0x03f4, 0x0fc4 }, + { 0x8900, 0x03f7, 0x2001 }, + { 0x1900, 0x03f6, 0x0000 }, + { 0x0500, 0x03f8, 0x0fff }, + { 0x8900, 0x0401, 0x3050 }, + { 0x8500, 0x03fb, 0x2fff }, + { 0x0900, 0x03fa, 0x0001 }, + { 0x0900, 0x0400, 0x0050 }, + { 0x8900, 0x0403, 0x2050 }, + { 0x0900, 0x0402, 0x0050 }, + { 0x0900, 0x0404, 0x0050 }, + { 0x8900, 0x040d, 0x4050 }, + { 0x8900, 0x0409, 0x3050 }, + { 0x8900, 0x0407, 0x2050 }, + { 0x0900, 0x0406, 0x0050 }, + { 0x0900, 0x0408, 0x0050 }, + { 0x8900, 0x040b, 0x2050 }, + { 0x0900, 0x040a, 0x0050 }, + { 0x0900, 0x040c, 0x0050 }, + { 0x8900, 0x0411, 0x3020 }, + { 0x8900, 0x040f, 0x2050 }, + { 0x0900, 0x040e, 0x0050 }, + { 0x0900, 0x0410, 0x0020 }, + { 0x8900, 0x0413, 0x2020 }, + { 0x0900, 0x0412, 0x0020 }, + { 0x0900, 0x0414, 0x0020 }, + { 0x8900, 0x0425, 0x5020 }, + { 0x8900, 0x041d, 0x4020 }, + { 0x8900, 0x0419, 0x3020 }, + { 0x8900, 0x0417, 0x2020 }, + { 0x0900, 0x0416, 0x0020 }, + { 0x0900, 0x0418, 0x0020 }, + { 0x8900, 0x041b, 0x2020 }, + { 0x0900, 0x041a, 0x0020 }, + { 0x0900, 0x041c, 0x0020 }, + { 0x8900, 0x0421, 0x3020 }, + { 0x8900, 0x041f, 0x2020 }, + { 0x0900, 0x041e, 0x0020 }, + { 0x0900, 0x0420, 0x0020 }, + { 0x8900, 0x0423, 0x2020 }, + { 0x0900, 0x0422, 0x0020 }, + { 0x0900, 0x0424, 0x0020 }, + { 0x8900, 0x042d, 0x4020 }, + { 0x8900, 0x0429, 0x3020 }, + { 0x8900, 0x0427, 0x2020 }, + { 0x0900, 0x0426, 0x0020 }, + { 0x0900, 0x0428, 0x0020 }, + { 0x8900, 0x042b, 0x2020 }, + { 0x0900, 0x042a, 0x0020 }, + { 0x0900, 0x042c, 0x0020 }, + { 0x8500, 0x0431, 0x3fe0 }, + { 0x8900, 0x042f, 0x2020 }, + { 0x0900, 0x042e, 0x0020 }, + { 0x0500, 0x0430, 0x0fe0 }, + { 0x8500, 0x0433, 0x2fe0 }, + { 0x0500, 0x0432, 0x0fe0 }, + { 0x0500, 0x0434, 0x0fe0 }, + { 0x8700, 0x06a4, 0xa000 }, + { 0x8500, 0x0563, 0x9fd0 }, + { 0x8900, 0x04b6, 0x8001 }, + { 0x8500, 0x0475, 0x7fff }, + { 0x8500, 0x0455, 0x6fb0 }, + { 0x8500, 0x0445, 0x5fe0 }, + { 0x8500, 0x043d, 0x4fe0 }, + { 0x8500, 0x0439, 0x3fe0 }, + { 0x8500, 0x0437, 0x2fe0 }, + { 0x0500, 0x0436, 0x0fe0 }, + { 0x0500, 0x0438, 0x0fe0 }, + { 0x8500, 0x043b, 0x2fe0 }, + { 0x0500, 0x043a, 0x0fe0 }, + { 0x0500, 0x043c, 0x0fe0 }, + { 0x8500, 0x0441, 0x3fe0 }, + { 0x8500, 0x043f, 0x2fe0 }, + { 0x0500, 0x043e, 0x0fe0 }, + { 0x0500, 0x0440, 0x0fe0 }, + { 0x8500, 0x0443, 0x2fe0 }, + { 0x0500, 0x0442, 0x0fe0 }, + { 0x0500, 0x0444, 0x0fe0 }, + { 0x8500, 0x044d, 0x4fe0 }, + { 0x8500, 0x0449, 0x3fe0 }, + { 0x8500, 0x0447, 0x2fe0 }, + { 0x0500, 0x0446, 0x0fe0 }, + { 0x0500, 0x0448, 0x0fe0 }, + { 0x8500, 0x044b, 0x2fe0 }, + { 0x0500, 0x044a, 0x0fe0 }, + { 0x0500, 0x044c, 0x0fe0 }, + { 0x8500, 0x0451, 0x3fb0 }, + { 0x8500, 0x044f, 0x2fe0 }, + { 0x0500, 0x044e, 0x0fe0 }, + { 0x0500, 0x0450, 0x0fb0 }, + { 0x8500, 0x0453, 0x2fb0 }, + { 0x0500, 0x0452, 0x0fb0 }, + { 0x0500, 0x0454, 0x0fb0 }, + { 0x8500, 0x0465, 0x5fff }, + { 0x8500, 0x045d, 0x4fb0 }, + { 0x8500, 0x0459, 0x3fb0 }, + { 0x8500, 0x0457, 0x2fb0 }, + { 0x0500, 0x0456, 0x0fb0 }, + { 0x0500, 0x0458, 0x0fb0 }, + { 0x8500, 0x045b, 0x2fb0 }, + { 0x0500, 0x045a, 0x0fb0 }, + { 0x0500, 0x045c, 0x0fb0 }, + { 0x8500, 0x0461, 0x3fff }, + { 0x8500, 0x045f, 0x2fb0 }, + { 0x0500, 0x045e, 0x0fb0 }, + { 0x0900, 0x0460, 0x0001 }, + { 0x8500, 0x0463, 0x2fff }, + { 0x0900, 0x0462, 0x0001 }, + { 0x0900, 0x0464, 0x0001 }, + { 0x8500, 0x046d, 0x4fff }, + { 0x8500, 0x0469, 0x3fff }, + { 0x8500, 0x0467, 0x2fff }, + { 0x0900, 0x0466, 0x0001 }, + { 0x0900, 0x0468, 0x0001 }, + { 0x8500, 0x046b, 0x2fff }, + { 0x0900, 0x046a, 0x0001 }, + { 0x0900, 0x046c, 0x0001 }, + { 0x8500, 0x0471, 0x3fff }, + { 0x8500, 0x046f, 0x2fff }, + { 0x0900, 0x046e, 0x0001 }, + { 0x0900, 0x0470, 0x0001 }, + { 0x8500, 0x0473, 0x2fff }, + { 0x0900, 0x0472, 0x0001 }, + { 0x0900, 0x0474, 0x0001 }, + { 0x8900, 0x0496, 0x6001 }, + { 0x8c00, 0x0485, 0x5000 }, + { 0x8500, 0x047d, 0x4fff }, + { 0x8500, 0x0479, 0x3fff }, + { 0x8500, 0x0477, 0x2fff }, + { 0x0900, 0x0476, 0x0001 }, + { 0x0900, 0x0478, 0x0001 }, + { 0x8500, 0x047b, 0x2fff }, + { 0x0900, 0x047a, 0x0001 }, + { 0x0900, 0x047c, 0x0001 }, + { 0x8500, 0x0481, 0x3fff }, + { 0x8500, 0x047f, 0x2fff }, + { 0x0900, 0x047e, 0x0001 }, + { 0x0900, 0x0480, 0x0001 }, + { 0x8c00, 0x0483, 0x2000 }, + { 0x1a00, 0x0482, 0x0000 }, + { 0x0c00, 0x0484, 0x0000 }, + { 0x8900, 0x048e, 0x4001 }, + { 0x8900, 0x048a, 0x3001 }, + { 0x8b00, 0x0488, 0x2000 }, + { 0x0c00, 0x0486, 0x0000 }, + { 0x0b00, 0x0489, 0x0000 }, + { 0x8900, 0x048c, 0x2001 }, + { 0x0500, 0x048b, 0x0fff }, + { 0x0500, 0x048d, 0x0fff }, + { 0x8900, 0x0492, 0x3001 }, + { 0x8900, 0x0490, 0x2001 }, + { 0x0500, 0x048f, 0x0fff }, + { 0x0500, 0x0491, 0x0fff }, + { 0x8900, 0x0494, 0x2001 }, + { 0x0500, 0x0493, 0x0fff }, + { 0x0500, 0x0495, 0x0fff }, + { 0x8900, 0x04a6, 0x5001 }, + { 0x8900, 0x049e, 0x4001 }, + { 0x8900, 0x049a, 0x3001 }, + { 0x8900, 0x0498, 0x2001 }, + { 0x0500, 0x0497, 0x0fff }, + { 0x0500, 0x0499, 0x0fff }, + { 0x8900, 0x049c, 0x2001 }, + { 0x0500, 0x049b, 0x0fff }, + { 0x0500, 0x049d, 0x0fff }, + { 0x8900, 0x04a2, 0x3001 }, + { 0x8900, 0x04a0, 0x2001 }, + { 0x0500, 0x049f, 0x0fff }, + { 0x0500, 0x04a1, 0x0fff }, + { 0x8900, 0x04a4, 0x2001 }, + { 0x0500, 0x04a3, 0x0fff }, + { 0x0500, 0x04a5, 0x0fff }, + { 0x8900, 0x04ae, 0x4001 }, + { 0x8900, 0x04aa, 0x3001 }, + { 0x8900, 0x04a8, 0x2001 }, + { 0x0500, 0x04a7, 0x0fff }, + { 0x0500, 0x04a9, 0x0fff }, + { 0x8900, 0x04ac, 0x2001 }, + { 0x0500, 0x04ab, 0x0fff }, + { 0x0500, 0x04ad, 0x0fff }, + { 0x8900, 0x04b2, 0x3001 }, + { 0x8900, 0x04b0, 0x2001 }, + { 0x0500, 0x04af, 0x0fff }, + { 0x0500, 0x04b1, 0x0fff }, + { 0x8900, 0x04b4, 0x2001 }, + { 0x0500, 0x04b3, 0x0fff }, + { 0x0500, 0x04b5, 0x0fff }, + { 0x8500, 0x04f9, 0x7fff }, + { 0x8500, 0x04d7, 0x6fff }, + { 0x8500, 0x04c6, 0x5fff }, + { 0x8900, 0x04be, 0x4001 }, + { 0x8900, 0x04ba, 0x3001 }, + { 0x8900, 0x04b8, 0x2001 }, + { 0x0500, 0x04b7, 0x0fff }, + { 0x0500, 0x04b9, 0x0fff }, + { 0x8900, 0x04bc, 0x2001 }, + { 0x0500, 0x04bb, 0x0fff }, + { 0x0500, 0x04bd, 0x0fff }, + { 0x8500, 0x04c2, 0x3fff }, + { 0x8900, 0x04c0, 0x2000 }, + { 0x0500, 0x04bf, 0x0fff }, + { 0x0900, 0x04c1, 0x0001 }, + { 0x8500, 0x04c4, 0x2fff }, + { 0x0900, 0x04c3, 0x0001 }, + { 0x0900, 0x04c5, 0x0001 }, + { 0x8500, 0x04ce, 0x4fff }, + { 0x8500, 0x04ca, 0x3fff }, + { 0x8500, 0x04c8, 0x2fff }, + { 0x0900, 0x04c7, 0x0001 }, + { 0x0900, 0x04c9, 0x0001 }, + { 0x8500, 0x04cc, 0x2fff }, + { 0x0900, 0x04cb, 0x0001 }, + { 0x0900, 0x04cd, 0x0001 }, + { 0x8500, 0x04d3, 0x3fff }, + { 0x8500, 0x04d1, 0x2fff }, + { 0x0900, 0x04d0, 0x0001 }, + { 0x0900, 0x04d2, 0x0001 }, + { 0x8500, 0x04d5, 0x2fff }, + { 0x0900, 0x04d4, 0x0001 }, + { 0x0900, 0x04d6, 0x0001 }, + { 0x8500, 0x04e7, 0x5fff }, + { 0x8500, 0x04df, 0x4fff }, + { 0x8500, 0x04db, 0x3fff }, + { 0x8500, 0x04d9, 0x2fff }, + { 0x0900, 0x04d8, 0x0001 }, + { 0x0900, 0x04da, 0x0001 }, + { 0x8500, 0x04dd, 0x2fff }, + { 0x0900, 0x04dc, 0x0001 }, + { 0x0900, 0x04de, 0x0001 }, + { 0x8500, 0x04e3, 0x3fff }, + { 0x8500, 0x04e1, 0x2fff }, + { 0x0900, 0x04e0, 0x0001 }, + { 0x0900, 0x04e2, 0x0001 }, + { 0x8500, 0x04e5, 0x2fff }, + { 0x0900, 0x04e4, 0x0001 }, + { 0x0900, 0x04e6, 0x0001 }, + { 0x8500, 0x04ef, 0x4fff }, + { 0x8500, 0x04eb, 0x3fff }, + { 0x8500, 0x04e9, 0x2fff }, + { 0x0900, 0x04e8, 0x0001 }, + { 0x0900, 0x04ea, 0x0001 }, + { 0x8500, 0x04ed, 0x2fff }, + { 0x0900, 0x04ec, 0x0001 }, + { 0x0900, 0x04ee, 0x0001 }, + { 0x8500, 0x04f3, 0x3fff }, + { 0x8500, 0x04f1, 0x2fff }, + { 0x0900, 0x04f0, 0x0001 }, + { 0x0900, 0x04f2, 0x0001 }, + { 0x8500, 0x04f5, 0x2fff }, + { 0x0900, 0x04f4, 0x0001 }, + { 0x0900, 0x04f8, 0x0001 }, + { 0x8900, 0x0540, 0x6030 }, + { 0x8500, 0x050f, 0x5fff }, + { 0x8500, 0x0507, 0x4fff }, + { 0x8500, 0x0503, 0x3fff }, + { 0x8500, 0x0501, 0x2fff }, + { 0x0900, 0x0500, 0x0001 }, + { 0x0900, 0x0502, 0x0001 }, + { 0x8500, 0x0505, 0x2fff }, + { 0x0900, 0x0504, 0x0001 }, + { 0x0900, 0x0506, 0x0001 }, + { 0x8500, 0x050b, 0x3fff }, + { 0x8500, 0x0509, 0x2fff }, + { 0x0900, 0x0508, 0x0001 }, + { 0x0900, 0x050a, 0x0001 }, + { 0x8500, 0x050d, 0x2fff }, + { 0x0900, 0x050c, 0x0001 }, + { 0x0900, 0x050e, 0x0001 }, + { 0x8900, 0x0538, 0x4030 }, + { 0x8900, 0x0534, 0x3030 }, + { 0x8900, 0x0532, 0x2030 }, + { 0x0900, 0x0531, 0x0030 }, + { 0x0900, 0x0533, 0x0030 }, + { 0x8900, 0x0536, 0x2030 }, + { 0x0900, 0x0535, 0x0030 }, + { 0x0900, 0x0537, 0x0030 }, + { 0x8900, 0x053c, 0x3030 }, + { 0x8900, 0x053a, 0x2030 }, + { 0x0900, 0x0539, 0x0030 }, + { 0x0900, 0x053b, 0x0030 }, + { 0x8900, 0x053e, 0x2030 }, + { 0x0900, 0x053d, 0x0030 }, + { 0x0900, 0x053f, 0x0030 }, + { 0x8900, 0x0550, 0x5030 }, + { 0x8900, 0x0548, 0x4030 }, + { 0x8900, 0x0544, 0x3030 }, + { 0x8900, 0x0542, 0x2030 }, + { 0x0900, 0x0541, 0x0030 }, + { 0x0900, 0x0543, 0x0030 }, + { 0x8900, 0x0546, 0x2030 }, + { 0x0900, 0x0545, 0x0030 }, + { 0x0900, 0x0547, 0x0030 }, + { 0x8900, 0x054c, 0x3030 }, + { 0x8900, 0x054a, 0x2030 }, + { 0x0900, 0x0549, 0x0030 }, + { 0x0900, 0x054b, 0x0030 }, + { 0x8900, 0x054e, 0x2030 }, + { 0x0900, 0x054d, 0x0030 }, + { 0x0900, 0x054f, 0x0030 }, + { 0x9500, 0x055a, 0x4000 }, + { 0x8900, 0x0554, 0x3030 }, + { 0x8900, 0x0552, 0x2030 }, + { 0x0900, 0x0551, 0x0030 }, + { 0x0900, 0x0553, 0x0030 }, + { 0x8900, 0x0556, 0x2030 }, + { 0x0900, 0x0555, 0x0030 }, + { 0x0600, 0x0559, 0x0000 }, + { 0x9500, 0x055e, 0x3000 }, + { 0x9500, 0x055c, 0x2000 }, + { 0x1500, 0x055b, 0x0000 }, + { 0x1500, 0x055d, 0x0000 }, + { 0x8500, 0x0561, 0x2fd0 }, + { 0x1500, 0x055f, 0x0000 }, + { 0x0500, 0x0562, 0x0fd0 }, + { 0x9a00, 0x060f, 0x8000 }, + { 0x8c00, 0x05ab, 0x7000 }, + { 0x8500, 0x0583, 0x6fd0 }, + { 0x8500, 0x0573, 0x5fd0 }, + { 0x8500, 0x056b, 0x4fd0 }, + { 0x8500, 0x0567, 0x3fd0 }, + { 0x8500, 0x0565, 0x2fd0 }, + { 0x0500, 0x0564, 0x0fd0 }, + { 0x0500, 0x0566, 0x0fd0 }, + { 0x8500, 0x0569, 0x2fd0 }, + { 0x0500, 0x0568, 0x0fd0 }, + { 0x0500, 0x056a, 0x0fd0 }, + { 0x8500, 0x056f, 0x3fd0 }, + { 0x8500, 0x056d, 0x2fd0 }, + { 0x0500, 0x056c, 0x0fd0 }, + { 0x0500, 0x056e, 0x0fd0 }, + { 0x8500, 0x0571, 0x2fd0 }, + { 0x0500, 0x0570, 0x0fd0 }, + { 0x0500, 0x0572, 0x0fd0 }, + { 0x8500, 0x057b, 0x4fd0 }, + { 0x8500, 0x0577, 0x3fd0 }, + { 0x8500, 0x0575, 0x2fd0 }, + { 0x0500, 0x0574, 0x0fd0 }, + { 0x0500, 0x0576, 0x0fd0 }, + { 0x8500, 0x0579, 0x2fd0 }, + { 0x0500, 0x0578, 0x0fd0 }, + { 0x0500, 0x057a, 0x0fd0 }, + { 0x8500, 0x057f, 0x3fd0 }, + { 0x8500, 0x057d, 0x2fd0 }, + { 0x0500, 0x057c, 0x0fd0 }, + { 0x0500, 0x057e, 0x0fd0 }, + { 0x8500, 0x0581, 0x2fd0 }, + { 0x0500, 0x0580, 0x0fd0 }, + { 0x0500, 0x0582, 0x0fd0 }, + { 0x8c00, 0x059a, 0x5000 }, + { 0x8c00, 0x0592, 0x4000 }, + { 0x8500, 0x0587, 0x3000 }, + { 0x8500, 0x0585, 0x2fd0 }, + { 0x0500, 0x0584, 0x0fd0 }, + { 0x0500, 0x0586, 0x0fd0 }, + { 0x9100, 0x058a, 0x2000 }, + { 0x1500, 0x0589, 0x0000 }, + { 0x0c00, 0x0591, 0x0000 }, + { 0x8c00, 0x0596, 0x3000 }, + { 0x8c00, 0x0594, 0x2000 }, + { 0x0c00, 0x0593, 0x0000 }, + { 0x0c00, 0x0595, 0x0000 }, + { 0x8c00, 0x0598, 0x2000 }, + { 0x0c00, 0x0597, 0x0000 }, + { 0x0c00, 0x0599, 0x0000 }, + { 0x8c00, 0x05a3, 0x4000 }, + { 0x8c00, 0x059e, 0x3000 }, + { 0x8c00, 0x059c, 0x2000 }, + { 0x0c00, 0x059b, 0x0000 }, + { 0x0c00, 0x059d, 0x0000 }, + { 0x8c00, 0x05a0, 0x2000 }, + { 0x0c00, 0x059f, 0x0000 }, + { 0x0c00, 0x05a1, 0x0000 }, + { 0x8c00, 0x05a7, 0x3000 }, + { 0x8c00, 0x05a5, 0x2000 }, + { 0x0c00, 0x05a4, 0x0000 }, + { 0x0c00, 0x05a6, 0x0000 }, + { 0x8c00, 0x05a9, 0x2000 }, + { 0x0c00, 0x05a8, 0x0000 }, + { 0x0c00, 0x05aa, 0x0000 }, + { 0x8700, 0x05d7, 0x6000 }, + { 0x8c00, 0x05bc, 0x5000 }, + { 0x8c00, 0x05b3, 0x4000 }, + { 0x8c00, 0x05af, 0x3000 }, + { 0x8c00, 0x05ad, 0x2000 }, + { 0x0c00, 0x05ac, 0x0000 }, + { 0x0c00, 0x05ae, 0x0000 }, + { 0x8c00, 0x05b1, 0x2000 }, + { 0x0c00, 0x05b0, 0x0000 }, + { 0x0c00, 0x05b2, 0x0000 }, + { 0x8c00, 0x05b7, 0x3000 }, + { 0x8c00, 0x05b5, 0x2000 }, + { 0x0c00, 0x05b4, 0x0000 }, + { 0x0c00, 0x05b6, 0x0000 }, + { 0x8c00, 0x05b9, 0x2000 }, + { 0x0c00, 0x05b8, 0x0000 }, + { 0x0c00, 0x05bb, 0x0000 }, + { 0x8c00, 0x05c4, 0x4000 }, + { 0x9500, 0x05c0, 0x3000 }, + { 0x9500, 0x05be, 0x2000 }, + { 0x0c00, 0x05bd, 0x0000 }, + { 0x0c00, 0x05bf, 0x0000 }, + { 0x8c00, 0x05c2, 0x2000 }, + { 0x0c00, 0x05c1, 0x0000 }, + { 0x1500, 0x05c3, 0x0000 }, + { 0x8700, 0x05d3, 0x3000 }, + { 0x8700, 0x05d1, 0x2000 }, + { 0x0700, 0x05d0, 0x0000 }, + { 0x0700, 0x05d2, 0x0000 }, + { 0x8700, 0x05d5, 0x2000 }, + { 0x0700, 0x05d4, 0x0000 }, + { 0x0700, 0x05d6, 0x0000 }, + { 0x8700, 0x05e7, 0x5000 }, + { 0x8700, 0x05df, 0x4000 }, + { 0x8700, 0x05db, 0x3000 }, + { 0x8700, 0x05d9, 0x2000 }, + { 0x0700, 0x05d8, 0x0000 }, + { 0x0700, 0x05da, 0x0000 }, + { 0x8700, 0x05dd, 0x2000 }, + { 0x0700, 0x05dc, 0x0000 }, + { 0x0700, 0x05de, 0x0000 }, + { 0x8700, 0x05e3, 0x3000 }, + { 0x8700, 0x05e1, 0x2000 }, + { 0x0700, 0x05e0, 0x0000 }, + { 0x0700, 0x05e2, 0x0000 }, + { 0x8700, 0x05e5, 0x2000 }, + { 0x0700, 0x05e4, 0x0000 }, + { 0x0700, 0x05e6, 0x0000 }, + { 0x9500, 0x05f4, 0x4000 }, + { 0x8700, 0x05f0, 0x3000 }, + { 0x8700, 0x05e9, 0x2000 }, + { 0x0700, 0x05e8, 0x0000 }, + { 0x0700, 0x05ea, 0x0000 }, + { 0x8700, 0x05f2, 0x2000 }, + { 0x0700, 0x05f1, 0x0000 }, + { 0x1500, 0x05f3, 0x0000 }, + { 0x8100, 0x0603, 0x3000 }, + { 0x8100, 0x0601, 0x2000 }, + { 0x0100, 0x0600, 0x0000 }, + { 0x0100, 0x0602, 0x0000 }, + { 0x9500, 0x060d, 0x2000 }, + { 0x1500, 0x060c, 0x0000 }, + { 0x1a00, 0x060e, 0x0000 }, + { 0x8d00, 0x0664, 0x7000 }, + { 0x8700, 0x0638, 0x6000 }, + { 0x8700, 0x0628, 0x5000 }, + { 0x9500, 0x061f, 0x4000 }, + { 0x8c00, 0x0613, 0x3000 }, + { 0x8c00, 0x0611, 0x2000 }, + { 0x0c00, 0x0610, 0x0000 }, + { 0x0c00, 0x0612, 0x0000 }, + { 0x8c00, 0x0615, 0x2000 }, + { 0x0c00, 0x0614, 0x0000 }, + { 0x1500, 0x061b, 0x0000 }, + { 0x8700, 0x0624, 0x3000 }, + { 0x8700, 0x0622, 0x2000 }, + { 0x0700, 0x0621, 0x0000 }, + { 0x0700, 0x0623, 0x0000 }, + { 0x8700, 0x0626, 0x2000 }, + { 0x0700, 0x0625, 0x0000 }, + { 0x0700, 0x0627, 0x0000 }, + { 0x8700, 0x0630, 0x4000 }, + { 0x8700, 0x062c, 0x3000 }, + { 0x8700, 0x062a, 0x2000 }, + { 0x0700, 0x0629, 0x0000 }, + { 0x0700, 0x062b, 0x0000 }, + { 0x8700, 0x062e, 0x2000 }, + { 0x0700, 0x062d, 0x0000 }, + { 0x0700, 0x062f, 0x0000 }, + { 0x8700, 0x0634, 0x3000 }, + { 0x8700, 0x0632, 0x2000 }, + { 0x0700, 0x0631, 0x0000 }, + { 0x0700, 0x0633, 0x0000 }, + { 0x8700, 0x0636, 0x2000 }, + { 0x0700, 0x0635, 0x0000 }, + { 0x0700, 0x0637, 0x0000 }, + { 0x8c00, 0x064d, 0x5000 }, + { 0x8700, 0x0645, 0x4000 }, + { 0x8700, 0x0641, 0x3000 }, + { 0x8700, 0x063a, 0x2000 }, + { 0x0700, 0x0639, 0x0000 }, + { 0x0600, 0x0640, 0x0000 }, + { 0x8700, 0x0643, 0x2000 }, + { 0x0700, 0x0642, 0x0000 }, + { 0x0700, 0x0644, 0x0000 }, + { 0x8700, 0x0649, 0x3000 }, + { 0x8700, 0x0647, 0x2000 }, + { 0x0700, 0x0646, 0x0000 }, + { 0x0700, 0x0648, 0x0000 }, + { 0x8c00, 0x064b, 0x2000 }, + { 0x0700, 0x064a, 0x0000 }, + { 0x0c00, 0x064c, 0x0000 }, + { 0x8c00, 0x0655, 0x4000 }, + { 0x8c00, 0x0651, 0x3000 }, + { 0x8c00, 0x064f, 0x2000 }, + { 0x0c00, 0x064e, 0x0000 }, + { 0x0c00, 0x0650, 0x0000 }, + { 0x8c00, 0x0653, 0x2000 }, + { 0x0c00, 0x0652, 0x0000 }, + { 0x0c00, 0x0654, 0x0000 }, + { 0x8d00, 0x0660, 0x3000 }, + { 0x8c00, 0x0657, 0x2000 }, + { 0x0c00, 0x0656, 0x0000 }, + { 0x0c00, 0x0658, 0x0000 }, + { 0x8d00, 0x0662, 0x2000 }, + { 0x0d00, 0x0661, 0x0000 }, + { 0x0d00, 0x0663, 0x0000 }, + { 0x8700, 0x0684, 0x6000 }, + { 0x8700, 0x0674, 0x5000 }, + { 0x9500, 0x066c, 0x4000 }, + { 0x8d00, 0x0668, 0x3000 }, + { 0x8d00, 0x0666, 0x2000 }, + { 0x0d00, 0x0665, 0x0000 }, + { 0x0d00, 0x0667, 0x0000 }, + { 0x9500, 0x066a, 0x2000 }, + { 0x0d00, 0x0669, 0x0000 }, + { 0x1500, 0x066b, 0x0000 }, + { 0x8c00, 0x0670, 0x3000 }, + { 0x8700, 0x066e, 0x2000 }, + { 0x1500, 0x066d, 0x0000 }, + { 0x0700, 0x066f, 0x0000 }, + { 0x8700, 0x0672, 0x2000 }, + { 0x0700, 0x0671, 0x0000 }, + { 0x0700, 0x0673, 0x0000 }, + { 0x8700, 0x067c, 0x4000 }, + { 0x8700, 0x0678, 0x3000 }, + { 0x8700, 0x0676, 0x2000 }, + { 0x0700, 0x0675, 0x0000 }, + { 0x0700, 0x0677, 0x0000 }, + { 0x8700, 0x067a, 0x2000 }, + { 0x0700, 0x0679, 0x0000 }, + { 0x0700, 0x067b, 0x0000 }, + { 0x8700, 0x0680, 0x3000 }, + { 0x8700, 0x067e, 0x2000 }, + { 0x0700, 0x067d, 0x0000 }, + { 0x0700, 0x067f, 0x0000 }, + { 0x8700, 0x0682, 0x2000 }, + { 0x0700, 0x0681, 0x0000 }, + { 0x0700, 0x0683, 0x0000 }, + { 0x8700, 0x0694, 0x5000 }, + { 0x8700, 0x068c, 0x4000 }, + { 0x8700, 0x0688, 0x3000 }, + { 0x8700, 0x0686, 0x2000 }, + { 0x0700, 0x0685, 0x0000 }, + { 0x0700, 0x0687, 0x0000 }, + { 0x8700, 0x068a, 0x2000 }, + { 0x0700, 0x0689, 0x0000 }, + { 0x0700, 0x068b, 0x0000 }, + { 0x8700, 0x0690, 0x3000 }, + { 0x8700, 0x068e, 0x2000 }, + { 0x0700, 0x068d, 0x0000 }, + { 0x0700, 0x068f, 0x0000 }, + { 0x8700, 0x0692, 0x2000 }, + { 0x0700, 0x0691, 0x0000 }, + { 0x0700, 0x0693, 0x0000 }, + { 0x8700, 0x069c, 0x4000 }, + { 0x8700, 0x0698, 0x3000 }, + { 0x8700, 0x0696, 0x2000 }, + { 0x0700, 0x0695, 0x0000 }, + { 0x0700, 0x0697, 0x0000 }, + { 0x8700, 0x069a, 0x2000 }, + { 0x0700, 0x0699, 0x0000 }, + { 0x0700, 0x069b, 0x0000 }, + { 0x8700, 0x06a0, 0x3000 }, + { 0x8700, 0x069e, 0x2000 }, + { 0x0700, 0x069d, 0x0000 }, + { 0x0700, 0x069f, 0x0000 }, + { 0x8700, 0x06a2, 0x2000 }, + { 0x0700, 0x06a1, 0x0000 }, + { 0x0700, 0x06a3, 0x0000 }, + { 0x8700, 0x0926, 0x9000 }, + { 0x8700, 0x0725, 0x8000 }, + { 0x8c00, 0x06e4, 0x7000 }, + { 0x8700, 0x06c4, 0x6000 }, + { 0x8700, 0x06b4, 0x5000 }, + { 0x8700, 0x06ac, 0x4000 }, + { 0x8700, 0x06a8, 0x3000 }, + { 0x8700, 0x06a6, 0x2000 }, + { 0x0700, 0x06a5, 0x0000 }, + { 0x0700, 0x06a7, 0x0000 }, + { 0x8700, 0x06aa, 0x2000 }, + { 0x0700, 0x06a9, 0x0000 }, + { 0x0700, 0x06ab, 0x0000 }, + { 0x8700, 0x06b0, 0x3000 }, + { 0x8700, 0x06ae, 0x2000 }, + { 0x0700, 0x06ad, 0x0000 }, + { 0x0700, 0x06af, 0x0000 }, + { 0x8700, 0x06b2, 0x2000 }, + { 0x0700, 0x06b1, 0x0000 }, + { 0x0700, 0x06b3, 0x0000 }, + { 0x8700, 0x06bc, 0x4000 }, + { 0x8700, 0x06b8, 0x3000 }, + { 0x8700, 0x06b6, 0x2000 }, + { 0x0700, 0x06b5, 0x0000 }, + { 0x0700, 0x06b7, 0x0000 }, + { 0x8700, 0x06ba, 0x2000 }, + { 0x0700, 0x06b9, 0x0000 }, + { 0x0700, 0x06bb, 0x0000 }, + { 0x8700, 0x06c0, 0x3000 }, + { 0x8700, 0x06be, 0x2000 }, + { 0x0700, 0x06bd, 0x0000 }, + { 0x0700, 0x06bf, 0x0000 }, + { 0x8700, 0x06c2, 0x2000 }, + { 0x0700, 0x06c1, 0x0000 }, + { 0x0700, 0x06c3, 0x0000 }, + { 0x9500, 0x06d4, 0x5000 }, + { 0x8700, 0x06cc, 0x4000 }, + { 0x8700, 0x06c8, 0x3000 }, + { 0x8700, 0x06c6, 0x2000 }, + { 0x0700, 0x06c5, 0x0000 }, + { 0x0700, 0x06c7, 0x0000 }, + { 0x8700, 0x06ca, 0x2000 }, + { 0x0700, 0x06c9, 0x0000 }, + { 0x0700, 0x06cb, 0x0000 }, + { 0x8700, 0x06d0, 0x3000 }, + { 0x8700, 0x06ce, 0x2000 }, + { 0x0700, 0x06cd, 0x0000 }, + { 0x0700, 0x06cf, 0x0000 }, + { 0x8700, 0x06d2, 0x2000 }, + { 0x0700, 0x06d1, 0x0000 }, + { 0x0700, 0x06d3, 0x0000 }, + { 0x8c00, 0x06dc, 0x4000 }, + { 0x8c00, 0x06d8, 0x3000 }, + { 0x8c00, 0x06d6, 0x2000 }, + { 0x0700, 0x06d5, 0x0000 }, + { 0x0c00, 0x06d7, 0x0000 }, + { 0x8c00, 0x06da, 0x2000 }, + { 0x0c00, 0x06d9, 0x0000 }, + { 0x0c00, 0x06db, 0x0000 }, + { 0x8c00, 0x06e0, 0x3000 }, + { 0x8b00, 0x06de, 0x2000 }, + { 0x0100, 0x06dd, 0x0000 }, + { 0x0c00, 0x06df, 0x0000 }, + { 0x8c00, 0x06e2, 0x2000 }, + { 0x0c00, 0x06e1, 0x0000 }, + { 0x0c00, 0x06e3, 0x0000 }, + { 0x9500, 0x0704, 0x6000 }, + { 0x8d00, 0x06f4, 0x5000 }, + { 0x8c00, 0x06ec, 0x4000 }, + { 0x8c00, 0x06e8, 0x3000 }, + { 0x8600, 0x06e6, 0x2000 }, + { 0x0600, 0x06e5, 0x0000 }, + { 0x0c00, 0x06e7, 0x0000 }, + { 0x8c00, 0x06ea, 0x2000 }, + { 0x1a00, 0x06e9, 0x0000 }, + { 0x0c00, 0x06eb, 0x0000 }, + { 0x8d00, 0x06f0, 0x3000 }, + { 0x8700, 0x06ee, 0x2000 }, + { 0x0c00, 0x06ed, 0x0000 }, + { 0x0700, 0x06ef, 0x0000 }, + { 0x8d00, 0x06f2, 0x2000 }, + { 0x0d00, 0x06f1, 0x0000 }, + { 0x0d00, 0x06f3, 0x0000 }, + { 0x8700, 0x06fc, 0x4000 }, + { 0x8d00, 0x06f8, 0x3000 }, + { 0x8d00, 0x06f6, 0x2000 }, + { 0x0d00, 0x06f5, 0x0000 }, + { 0x0d00, 0x06f7, 0x0000 }, + { 0x8700, 0x06fa, 0x2000 }, + { 0x0d00, 0x06f9, 0x0000 }, + { 0x0700, 0x06fb, 0x0000 }, + { 0x9500, 0x0700, 0x3000 }, + { 0x9a00, 0x06fe, 0x2000 }, + { 0x1a00, 0x06fd, 0x0000 }, + { 0x0700, 0x06ff, 0x0000 }, + { 0x9500, 0x0702, 0x2000 }, + { 0x1500, 0x0701, 0x0000 }, + { 0x1500, 0x0703, 0x0000 }, + { 0x8700, 0x0715, 0x5000 }, + { 0x9500, 0x070c, 0x4000 }, + { 0x9500, 0x0708, 0x3000 }, + { 0x9500, 0x0706, 0x2000 }, + { 0x1500, 0x0705, 0x0000 }, + { 0x1500, 0x0707, 0x0000 }, + { 0x9500, 0x070a, 0x2000 }, + { 0x1500, 0x0709, 0x0000 }, + { 0x1500, 0x070b, 0x0000 }, + { 0x8c00, 0x0711, 0x3000 }, + { 0x8100, 0x070f, 0x2000 }, + { 0x1500, 0x070d, 0x0000 }, + { 0x0700, 0x0710, 0x0000 }, + { 0x8700, 0x0713, 0x2000 }, + { 0x0700, 0x0712, 0x0000 }, + { 0x0700, 0x0714, 0x0000 }, + { 0x8700, 0x071d, 0x4000 }, + { 0x8700, 0x0719, 0x3000 }, + { 0x8700, 0x0717, 0x2000 }, + { 0x0700, 0x0716, 0x0000 }, + { 0x0700, 0x0718, 0x0000 }, + { 0x8700, 0x071b, 0x2000 }, + { 0x0700, 0x071a, 0x0000 }, + { 0x0700, 0x071c, 0x0000 }, + { 0x8700, 0x0721, 0x3000 }, + { 0x8700, 0x071f, 0x2000 }, + { 0x0700, 0x071e, 0x0000 }, + { 0x0700, 0x0720, 0x0000 }, + { 0x8700, 0x0723, 0x2000 }, + { 0x0700, 0x0722, 0x0000 }, + { 0x0700, 0x0724, 0x0000 }, + { 0x8700, 0x0797, 0x7000 }, + { 0x8c00, 0x0745, 0x6000 }, + { 0x8c00, 0x0735, 0x5000 }, + { 0x8700, 0x072d, 0x4000 }, + { 0x8700, 0x0729, 0x3000 }, + { 0x8700, 0x0727, 0x2000 }, + { 0x0700, 0x0726, 0x0000 }, + { 0x0700, 0x0728, 0x0000 }, + { 0x8700, 0x072b, 0x2000 }, + { 0x0700, 0x072a, 0x0000 }, + { 0x0700, 0x072c, 0x0000 }, + { 0x8c00, 0x0731, 0x3000 }, + { 0x8700, 0x072f, 0x2000 }, + { 0x0700, 0x072e, 0x0000 }, + { 0x0c00, 0x0730, 0x0000 }, + { 0x8c00, 0x0733, 0x2000 }, + { 0x0c00, 0x0732, 0x0000 }, + { 0x0c00, 0x0734, 0x0000 }, + { 0x8c00, 0x073d, 0x4000 }, + { 0x8c00, 0x0739, 0x3000 }, + { 0x8c00, 0x0737, 0x2000 }, + { 0x0c00, 0x0736, 0x0000 }, + { 0x0c00, 0x0738, 0x0000 }, + { 0x8c00, 0x073b, 0x2000 }, + { 0x0c00, 0x073a, 0x0000 }, + { 0x0c00, 0x073c, 0x0000 }, + { 0x8c00, 0x0741, 0x3000 }, + { 0x8c00, 0x073f, 0x2000 }, + { 0x0c00, 0x073e, 0x0000 }, + { 0x0c00, 0x0740, 0x0000 }, + { 0x8c00, 0x0743, 0x2000 }, + { 0x0c00, 0x0742, 0x0000 }, + { 0x0c00, 0x0744, 0x0000 }, + { 0x8700, 0x0787, 0x5000 }, + { 0x8700, 0x074f, 0x4000 }, + { 0x8c00, 0x0749, 0x3000 }, + { 0x8c00, 0x0747, 0x2000 }, + { 0x0c00, 0x0746, 0x0000 }, + { 0x0c00, 0x0748, 0x0000 }, + { 0x8700, 0x074d, 0x2000 }, + { 0x0c00, 0x074a, 0x0000 }, + { 0x0700, 0x074e, 0x0000 }, + { 0x8700, 0x0783, 0x3000 }, + { 0x8700, 0x0781, 0x2000 }, + { 0x0700, 0x0780, 0x0000 }, + { 0x0700, 0x0782, 0x0000 }, + { 0x8700, 0x0785, 0x2000 }, + { 0x0700, 0x0784, 0x0000 }, + { 0x0700, 0x0786, 0x0000 }, + { 0x8700, 0x078f, 0x4000 }, + { 0x8700, 0x078b, 0x3000 }, + { 0x8700, 0x0789, 0x2000 }, + { 0x0700, 0x0788, 0x0000 }, + { 0x0700, 0x078a, 0x0000 }, + { 0x8700, 0x078d, 0x2000 }, + { 0x0700, 0x078c, 0x0000 }, + { 0x0700, 0x078e, 0x0000 }, + { 0x8700, 0x0793, 0x3000 }, + { 0x8700, 0x0791, 0x2000 }, + { 0x0700, 0x0790, 0x0000 }, + { 0x0700, 0x0792, 0x0000 }, + { 0x8700, 0x0795, 0x2000 }, + { 0x0700, 0x0794, 0x0000 }, + { 0x0700, 0x0796, 0x0000 }, + { 0x8700, 0x0906, 0x6000 }, + { 0x8c00, 0x07a7, 0x5000 }, + { 0x8700, 0x079f, 0x4000 }, + { 0x8700, 0x079b, 0x3000 }, + { 0x8700, 0x0799, 0x2000 }, + { 0x0700, 0x0798, 0x0000 }, + { 0x0700, 0x079a, 0x0000 }, + { 0x8700, 0x079d, 0x2000 }, + { 0x0700, 0x079c, 0x0000 }, + { 0x0700, 0x079e, 0x0000 }, + { 0x8700, 0x07a3, 0x3000 }, + { 0x8700, 0x07a1, 0x2000 }, + { 0x0700, 0x07a0, 0x0000 }, + { 0x0700, 0x07a2, 0x0000 }, + { 0x8700, 0x07a5, 0x2000 }, + { 0x0700, 0x07a4, 0x0000 }, + { 0x0c00, 0x07a6, 0x0000 }, + { 0x8c00, 0x07af, 0x4000 }, + { 0x8c00, 0x07ab, 0x3000 }, + { 0x8c00, 0x07a9, 0x2000 }, + { 0x0c00, 0x07a8, 0x0000 }, + { 0x0c00, 0x07aa, 0x0000 }, + { 0x8c00, 0x07ad, 0x2000 }, + { 0x0c00, 0x07ac, 0x0000 }, + { 0x0c00, 0x07ae, 0x0000 }, + { 0x8c00, 0x0902, 0x3000 }, + { 0x8700, 0x07b1, 0x2000 }, + { 0x0c00, 0x07b0, 0x0000 }, + { 0x0c00, 0x0901, 0x0000 }, + { 0x8700, 0x0904, 0x2000 }, + { 0x0a00, 0x0903, 0x0000 }, + { 0x0700, 0x0905, 0x0000 }, + { 0x8700, 0x0916, 0x5000 }, + { 0x8700, 0x090e, 0x4000 }, + { 0x8700, 0x090a, 0x3000 }, + { 0x8700, 0x0908, 0x2000 }, + { 0x0700, 0x0907, 0x0000 }, + { 0x0700, 0x0909, 0x0000 }, + { 0x8700, 0x090c, 0x2000 }, + { 0x0700, 0x090b, 0x0000 }, + { 0x0700, 0x090d, 0x0000 }, + { 0x8700, 0x0912, 0x3000 }, + { 0x8700, 0x0910, 0x2000 }, + { 0x0700, 0x090f, 0x0000 }, + { 0x0700, 0x0911, 0x0000 }, + { 0x8700, 0x0914, 0x2000 }, + { 0x0700, 0x0913, 0x0000 }, + { 0x0700, 0x0915, 0x0000 }, + { 0x8700, 0x091e, 0x4000 }, + { 0x8700, 0x091a, 0x3000 }, + { 0x8700, 0x0918, 0x2000 }, + { 0x0700, 0x0917, 0x0000 }, + { 0x0700, 0x0919, 0x0000 }, + { 0x8700, 0x091c, 0x2000 }, + { 0x0700, 0x091b, 0x0000 }, + { 0x0700, 0x091d, 0x0000 }, + { 0x8700, 0x0922, 0x3000 }, + { 0x8700, 0x0920, 0x2000 }, + { 0x0700, 0x091f, 0x0000 }, + { 0x0700, 0x0921, 0x0000 }, + { 0x8700, 0x0924, 0x2000 }, + { 0x0700, 0x0923, 0x0000 }, + { 0x0700, 0x0925, 0x0000 }, + { 0x8c00, 0x09cd, 0x8000 }, + { 0x8d00, 0x096d, 0x7000 }, + { 0x8c00, 0x0948, 0x6000 }, + { 0x8700, 0x0936, 0x5000 }, + { 0x8700, 0x092e, 0x4000 }, + { 0x8700, 0x092a, 0x3000 }, + { 0x8700, 0x0928, 0x2000 }, + { 0x0700, 0x0927, 0x0000 }, + { 0x0700, 0x0929, 0x0000 }, + { 0x8700, 0x092c, 0x2000 }, + { 0x0700, 0x092b, 0x0000 }, + { 0x0700, 0x092d, 0x0000 }, + { 0x8700, 0x0932, 0x3000 }, + { 0x8700, 0x0930, 0x2000 }, + { 0x0700, 0x092f, 0x0000 }, + { 0x0700, 0x0931, 0x0000 }, + { 0x8700, 0x0934, 0x2000 }, + { 0x0700, 0x0933, 0x0000 }, + { 0x0700, 0x0935, 0x0000 }, + { 0x8a00, 0x0940, 0x4000 }, + { 0x8c00, 0x093c, 0x3000 }, + { 0x8700, 0x0938, 0x2000 }, + { 0x0700, 0x0937, 0x0000 }, + { 0x0700, 0x0939, 0x0000 }, + { 0x8a00, 0x093e, 0x2000 }, + { 0x0700, 0x093d, 0x0000 }, + { 0x0a00, 0x093f, 0x0000 }, + { 0x8c00, 0x0944, 0x3000 }, + { 0x8c00, 0x0942, 0x2000 }, + { 0x0c00, 0x0941, 0x0000 }, + { 0x0c00, 0x0943, 0x0000 }, + { 0x8c00, 0x0946, 0x2000 }, + { 0x0c00, 0x0945, 0x0000 }, + { 0x0c00, 0x0947, 0x0000 }, + { 0x8700, 0x095d, 0x5000 }, + { 0x8c00, 0x0952, 0x4000 }, + { 0x8a00, 0x094c, 0x3000 }, + { 0x8a00, 0x094a, 0x2000 }, + { 0x0a00, 0x0949, 0x0000 }, + { 0x0a00, 0x094b, 0x0000 }, + { 0x8700, 0x0950, 0x2000 }, + { 0x0c00, 0x094d, 0x0000 }, + { 0x0c00, 0x0951, 0x0000 }, + { 0x8700, 0x0959, 0x3000 }, + { 0x8c00, 0x0954, 0x2000 }, + { 0x0c00, 0x0953, 0x0000 }, + { 0x0700, 0x0958, 0x0000 }, + { 0x8700, 0x095b, 0x2000 }, + { 0x0700, 0x095a, 0x0000 }, + { 0x0700, 0x095c, 0x0000 }, + { 0x9500, 0x0965, 0x4000 }, + { 0x8700, 0x0961, 0x3000 }, + { 0x8700, 0x095f, 0x2000 }, + { 0x0700, 0x095e, 0x0000 }, + { 0x0700, 0x0960, 0x0000 }, + { 0x8c00, 0x0963, 0x2000 }, + { 0x0c00, 0x0962, 0x0000 }, + { 0x1500, 0x0964, 0x0000 }, + { 0x8d00, 0x0969, 0x3000 }, + { 0x8d00, 0x0967, 0x2000 }, + { 0x0d00, 0x0966, 0x0000 }, + { 0x0d00, 0x0968, 0x0000 }, + { 0x8d00, 0x096b, 0x2000 }, + { 0x0d00, 0x096a, 0x0000 }, + { 0x0d00, 0x096c, 0x0000 }, + { 0x8700, 0x09a2, 0x6000 }, + { 0x8700, 0x0990, 0x5000 }, + { 0x8700, 0x0986, 0x4000 }, + { 0x8c00, 0x0981, 0x3000 }, + { 0x8d00, 0x096f, 0x2000 }, + { 0x0d00, 0x096e, 0x0000 }, + { 0x1500, 0x0970, 0x0000 }, + { 0x8a00, 0x0983, 0x2000 }, + { 0x0a00, 0x0982, 0x0000 }, + { 0x0700, 0x0985, 0x0000 }, + { 0x8700, 0x098a, 0x3000 }, + { 0x8700, 0x0988, 0x2000 }, + { 0x0700, 0x0987, 0x0000 }, + { 0x0700, 0x0989, 0x0000 }, + { 0x8700, 0x098c, 0x2000 }, + { 0x0700, 0x098b, 0x0000 }, + { 0x0700, 0x098f, 0x0000 }, + { 0x8700, 0x099a, 0x4000 }, + { 0x8700, 0x0996, 0x3000 }, + { 0x8700, 0x0994, 0x2000 }, + { 0x0700, 0x0993, 0x0000 }, + { 0x0700, 0x0995, 0x0000 }, + { 0x8700, 0x0998, 0x2000 }, + { 0x0700, 0x0997, 0x0000 }, + { 0x0700, 0x0999, 0x0000 }, + { 0x8700, 0x099e, 0x3000 }, + { 0x8700, 0x099c, 0x2000 }, + { 0x0700, 0x099b, 0x0000 }, + { 0x0700, 0x099d, 0x0000 }, + { 0x8700, 0x09a0, 0x2000 }, + { 0x0700, 0x099f, 0x0000 }, + { 0x0700, 0x09a1, 0x0000 }, + { 0x8700, 0x09b7, 0x5000 }, + { 0x8700, 0x09ab, 0x4000 }, + { 0x8700, 0x09a6, 0x3000 }, + { 0x8700, 0x09a4, 0x2000 }, + { 0x0700, 0x09a3, 0x0000 }, + { 0x0700, 0x09a5, 0x0000 }, + { 0x8700, 0x09a8, 0x2000 }, + { 0x0700, 0x09a7, 0x0000 }, + { 0x0700, 0x09aa, 0x0000 }, + { 0x8700, 0x09af, 0x3000 }, + { 0x8700, 0x09ad, 0x2000 }, + { 0x0700, 0x09ac, 0x0000 }, + { 0x0700, 0x09ae, 0x0000 }, + { 0x8700, 0x09b2, 0x2000 }, + { 0x0700, 0x09b0, 0x0000 }, + { 0x0700, 0x09b6, 0x0000 }, + { 0x8c00, 0x09c1, 0x4000 }, + { 0x8700, 0x09bd, 0x3000 }, + { 0x8700, 0x09b9, 0x2000 }, + { 0x0700, 0x09b8, 0x0000 }, + { 0x0c00, 0x09bc, 0x0000 }, + { 0x8a00, 0x09bf, 0x2000 }, + { 0x0a00, 0x09be, 0x0000 }, + { 0x0a00, 0x09c0, 0x0000 }, + { 0x8a00, 0x09c7, 0x3000 }, + { 0x8c00, 0x09c3, 0x2000 }, + { 0x0c00, 0x09c2, 0x0000 }, + { 0x0c00, 0x09c4, 0x0000 }, + { 0x8a00, 0x09cb, 0x2000 }, + { 0x0a00, 0x09c8, 0x0000 }, + { 0x0a00, 0x09cc, 0x0000 }, + { 0x8700, 0x0a2b, 0x7000 }, + { 0x8a00, 0x0a03, 0x6000 }, + { 0x8d00, 0x09ed, 0x5000 }, + { 0x8c00, 0x09e3, 0x4000 }, + { 0x8700, 0x09df, 0x3000 }, + { 0x8700, 0x09dc, 0x2000 }, + { 0x0a00, 0x09d7, 0x0000 }, + { 0x0700, 0x09dd, 0x0000 }, + { 0x8700, 0x09e1, 0x2000 }, + { 0x0700, 0x09e0, 0x0000 }, + { 0x0c00, 0x09e2, 0x0000 }, + { 0x8d00, 0x09e9, 0x3000 }, + { 0x8d00, 0x09e7, 0x2000 }, + { 0x0d00, 0x09e6, 0x0000 }, + { 0x0d00, 0x09e8, 0x0000 }, + { 0x8d00, 0x09eb, 0x2000 }, + { 0x0d00, 0x09ea, 0x0000 }, + { 0x0d00, 0x09ec, 0x0000 }, + { 0x8f00, 0x09f5, 0x4000 }, + { 0x8700, 0x09f1, 0x3000 }, + { 0x8d00, 0x09ef, 0x2000 }, + { 0x0d00, 0x09ee, 0x0000 }, + { 0x0700, 0x09f0, 0x0000 }, + { 0x9700, 0x09f3, 0x2000 }, + { 0x1700, 0x09f2, 0x0000 }, + { 0x0f00, 0x09f4, 0x0000 }, + { 0x8f00, 0x09f9, 0x3000 }, + { 0x8f00, 0x09f7, 0x2000 }, + { 0x0f00, 0x09f6, 0x0000 }, + { 0x0f00, 0x09f8, 0x0000 }, + { 0x8c00, 0x0a01, 0x2000 }, + { 0x1a00, 0x09fa, 0x0000 }, + { 0x0c00, 0x0a02, 0x0000 }, + { 0x8700, 0x0a1a, 0x5000 }, + { 0x8700, 0x0a10, 0x4000 }, + { 0x8700, 0x0a08, 0x3000 }, + { 0x8700, 0x0a06, 0x2000 }, + { 0x0700, 0x0a05, 0x0000 }, + { 0x0700, 0x0a07, 0x0000 }, + { 0x8700, 0x0a0a, 0x2000 }, + { 0x0700, 0x0a09, 0x0000 }, + { 0x0700, 0x0a0f, 0x0000 }, + { 0x8700, 0x0a16, 0x3000 }, + { 0x8700, 0x0a14, 0x2000 }, + { 0x0700, 0x0a13, 0x0000 }, + { 0x0700, 0x0a15, 0x0000 }, + { 0x8700, 0x0a18, 0x2000 }, + { 0x0700, 0x0a17, 0x0000 }, + { 0x0700, 0x0a19, 0x0000 }, + { 0x8700, 0x0a22, 0x4000 }, + { 0x8700, 0x0a1e, 0x3000 }, + { 0x8700, 0x0a1c, 0x2000 }, + { 0x0700, 0x0a1b, 0x0000 }, + { 0x0700, 0x0a1d, 0x0000 }, + { 0x8700, 0x0a20, 0x2000 }, + { 0x0700, 0x0a1f, 0x0000 }, + { 0x0700, 0x0a21, 0x0000 }, + { 0x8700, 0x0a26, 0x3000 }, + { 0x8700, 0x0a24, 0x2000 }, + { 0x0700, 0x0a23, 0x0000 }, + { 0x0700, 0x0a25, 0x0000 }, + { 0x8700, 0x0a28, 0x2000 }, + { 0x0700, 0x0a27, 0x0000 }, + { 0x0700, 0x0a2a, 0x0000 }, + { 0x8d00, 0x0a6a, 0x6000 }, + { 0x8c00, 0x0a41, 0x5000 }, + { 0x8700, 0x0a35, 0x4000 }, + { 0x8700, 0x0a2f, 0x3000 }, + { 0x8700, 0x0a2d, 0x2000 }, + { 0x0700, 0x0a2c, 0x0000 }, + { 0x0700, 0x0a2e, 0x0000 }, + { 0x8700, 0x0a32, 0x2000 }, + { 0x0700, 0x0a30, 0x0000 }, + { 0x0700, 0x0a33, 0x0000 }, + { 0x8c00, 0x0a3c, 0x3000 }, + { 0x8700, 0x0a38, 0x2000 }, + { 0x0700, 0x0a36, 0x0000 }, + { 0x0700, 0x0a39, 0x0000 }, + { 0x8a00, 0x0a3f, 0x2000 }, + { 0x0a00, 0x0a3e, 0x0000 }, + { 0x0a00, 0x0a40, 0x0000 }, + { 0x8700, 0x0a5a, 0x4000 }, + { 0x8c00, 0x0a4b, 0x3000 }, + { 0x8c00, 0x0a47, 0x2000 }, + { 0x0c00, 0x0a42, 0x0000 }, + { 0x0c00, 0x0a48, 0x0000 }, + { 0x8c00, 0x0a4d, 0x2000 }, + { 0x0c00, 0x0a4c, 0x0000 }, + { 0x0700, 0x0a59, 0x0000 }, + { 0x8d00, 0x0a66, 0x3000 }, + { 0x8700, 0x0a5c, 0x2000 }, + { 0x0700, 0x0a5b, 0x0000 }, + { 0x0700, 0x0a5e, 0x0000 }, + { 0x8d00, 0x0a68, 0x2000 }, + { 0x0d00, 0x0a67, 0x0000 }, + { 0x0d00, 0x0a69, 0x0000 }, + { 0x8700, 0x0a87, 0x5000 }, + { 0x8700, 0x0a72, 0x4000 }, + { 0x8d00, 0x0a6e, 0x3000 }, + { 0x8d00, 0x0a6c, 0x2000 }, + { 0x0d00, 0x0a6b, 0x0000 }, + { 0x0d00, 0x0a6d, 0x0000 }, + { 0x8c00, 0x0a70, 0x2000 }, + { 0x0d00, 0x0a6f, 0x0000 }, + { 0x0c00, 0x0a71, 0x0000 }, + { 0x8c00, 0x0a82, 0x3000 }, + { 0x8700, 0x0a74, 0x2000 }, + { 0x0700, 0x0a73, 0x0000 }, + { 0x0c00, 0x0a81, 0x0000 }, + { 0x8700, 0x0a85, 0x2000 }, + { 0x0a00, 0x0a83, 0x0000 }, + { 0x0700, 0x0a86, 0x0000 }, + { 0x8700, 0x0a90, 0x4000 }, + { 0x8700, 0x0a8b, 0x3000 }, + { 0x8700, 0x0a89, 0x2000 }, + { 0x0700, 0x0a88, 0x0000 }, + { 0x0700, 0x0a8a, 0x0000 }, + { 0x8700, 0x0a8d, 0x2000 }, + { 0x0700, 0x0a8c, 0x0000 }, + { 0x0700, 0x0a8f, 0x0000 }, + { 0x8700, 0x0a95, 0x3000 }, + { 0x8700, 0x0a93, 0x2000 }, + { 0x0700, 0x0a91, 0x0000 }, + { 0x0700, 0x0a94, 0x0000 }, + { 0x8700, 0x0a97, 0x2000 }, + { 0x0700, 0x0a96, 0x0000 }, + { 0x0700, 0x0a98, 0x0000 }, + { 0x8700, 0x10ef, 0xb000 }, + { 0x8700, 0x0dc6, 0xa000 }, + { 0x8700, 0x0c31, 0x9000 }, + { 0x8700, 0x0b5f, 0x8000 }, + { 0x8a00, 0x0b03, 0x7000 }, + { 0x8a00, 0x0abe, 0x6000 }, + { 0x8700, 0x0aaa, 0x5000 }, + { 0x8700, 0x0aa1, 0x4000 }, + { 0x8700, 0x0a9d, 0x3000 }, + { 0x8700, 0x0a9b, 0x2000 }, + { 0x0700, 0x0a9a, 0x0000 }, + { 0x0700, 0x0a9c, 0x0000 }, + { 0x8700, 0x0a9f, 0x2000 }, + { 0x0700, 0x0a9e, 0x0000 }, + { 0x0700, 0x0aa0, 0x0000 }, + { 0x8700, 0x0aa5, 0x3000 }, + { 0x8700, 0x0aa3, 0x2000 }, + { 0x0700, 0x0aa2, 0x0000 }, + { 0x0700, 0x0aa4, 0x0000 }, + { 0x8700, 0x0aa7, 0x2000 }, + { 0x0700, 0x0aa6, 0x0000 }, + { 0x0700, 0x0aa8, 0x0000 }, + { 0x8700, 0x0ab3, 0x4000 }, + { 0x8700, 0x0aae, 0x3000 }, + { 0x8700, 0x0aac, 0x2000 }, + { 0x0700, 0x0aab, 0x0000 }, + { 0x0700, 0x0aad, 0x0000 }, + { 0x8700, 0x0ab0, 0x2000 }, + { 0x0700, 0x0aaf, 0x0000 }, + { 0x0700, 0x0ab2, 0x0000 }, + { 0x8700, 0x0ab8, 0x3000 }, + { 0x8700, 0x0ab6, 0x2000 }, + { 0x0700, 0x0ab5, 0x0000 }, + { 0x0700, 0x0ab7, 0x0000 }, + { 0x8c00, 0x0abc, 0x2000 }, + { 0x0700, 0x0ab9, 0x0000 }, + { 0x0700, 0x0abd, 0x0000 }, + { 0x8700, 0x0ae1, 0x5000 }, + { 0x8c00, 0x0ac7, 0x4000 }, + { 0x8c00, 0x0ac2, 0x3000 }, + { 0x8a00, 0x0ac0, 0x2000 }, + { 0x0a00, 0x0abf, 0x0000 }, + { 0x0c00, 0x0ac1, 0x0000 }, + { 0x8c00, 0x0ac4, 0x2000 }, + { 0x0c00, 0x0ac3, 0x0000 }, + { 0x0c00, 0x0ac5, 0x0000 }, + { 0x8a00, 0x0acc, 0x3000 }, + { 0x8a00, 0x0ac9, 0x2000 }, + { 0x0c00, 0x0ac8, 0x0000 }, + { 0x0a00, 0x0acb, 0x0000 }, + { 0x8700, 0x0ad0, 0x2000 }, + { 0x0c00, 0x0acd, 0x0000 }, + { 0x0700, 0x0ae0, 0x0000 }, + { 0x8d00, 0x0aeb, 0x4000 }, + { 0x8d00, 0x0ae7, 0x3000 }, + { 0x8c00, 0x0ae3, 0x2000 }, + { 0x0c00, 0x0ae2, 0x0000 }, + { 0x0d00, 0x0ae6, 0x0000 }, + { 0x8d00, 0x0ae9, 0x2000 }, + { 0x0d00, 0x0ae8, 0x0000 }, + { 0x0d00, 0x0aea, 0x0000 }, + { 0x8d00, 0x0aef, 0x3000 }, + { 0x8d00, 0x0aed, 0x2000 }, + { 0x0d00, 0x0aec, 0x0000 }, + { 0x0d00, 0x0aee, 0x0000 }, + { 0x8c00, 0x0b01, 0x2000 }, + { 0x1700, 0x0af1, 0x0000 }, + { 0x0a00, 0x0b02, 0x0000 }, + { 0x8700, 0x0b28, 0x6000 }, + { 0x8700, 0x0b18, 0x5000 }, + { 0x8700, 0x0b0c, 0x4000 }, + { 0x8700, 0x0b08, 0x3000 }, + { 0x8700, 0x0b06, 0x2000 }, + { 0x0700, 0x0b05, 0x0000 }, + { 0x0700, 0x0b07, 0x0000 }, + { 0x8700, 0x0b0a, 0x2000 }, + { 0x0700, 0x0b09, 0x0000 }, + { 0x0700, 0x0b0b, 0x0000 }, + { 0x8700, 0x0b14, 0x3000 }, + { 0x8700, 0x0b10, 0x2000 }, + { 0x0700, 0x0b0f, 0x0000 }, + { 0x0700, 0x0b13, 0x0000 }, + { 0x8700, 0x0b16, 0x2000 }, + { 0x0700, 0x0b15, 0x0000 }, + { 0x0700, 0x0b17, 0x0000 }, + { 0x8700, 0x0b20, 0x4000 }, + { 0x8700, 0x0b1c, 0x3000 }, + { 0x8700, 0x0b1a, 0x2000 }, + { 0x0700, 0x0b19, 0x0000 }, + { 0x0700, 0x0b1b, 0x0000 }, + { 0x8700, 0x0b1e, 0x2000 }, + { 0x0700, 0x0b1d, 0x0000 }, + { 0x0700, 0x0b1f, 0x0000 }, + { 0x8700, 0x0b24, 0x3000 }, + { 0x8700, 0x0b22, 0x2000 }, + { 0x0700, 0x0b21, 0x0000 }, + { 0x0700, 0x0b23, 0x0000 }, + { 0x8700, 0x0b26, 0x2000 }, + { 0x0700, 0x0b25, 0x0000 }, + { 0x0700, 0x0b27, 0x0000 }, + { 0x8700, 0x0b3d, 0x5000 }, + { 0x8700, 0x0b32, 0x4000 }, + { 0x8700, 0x0b2d, 0x3000 }, + { 0x8700, 0x0b2b, 0x2000 }, + { 0x0700, 0x0b2a, 0x0000 }, + { 0x0700, 0x0b2c, 0x0000 }, + { 0x8700, 0x0b2f, 0x2000 }, + { 0x0700, 0x0b2e, 0x0000 }, + { 0x0700, 0x0b30, 0x0000 }, + { 0x8700, 0x0b37, 0x3000 }, + { 0x8700, 0x0b35, 0x2000 }, + { 0x0700, 0x0b33, 0x0000 }, + { 0x0700, 0x0b36, 0x0000 }, + { 0x8700, 0x0b39, 0x2000 }, + { 0x0700, 0x0b38, 0x0000 }, + { 0x0c00, 0x0b3c, 0x0000 }, + { 0x8a00, 0x0b48, 0x4000 }, + { 0x8c00, 0x0b41, 0x3000 }, + { 0x8c00, 0x0b3f, 0x2000 }, + { 0x0a00, 0x0b3e, 0x0000 }, + { 0x0a00, 0x0b40, 0x0000 }, + { 0x8c00, 0x0b43, 0x2000 }, + { 0x0c00, 0x0b42, 0x0000 }, + { 0x0a00, 0x0b47, 0x0000 }, + { 0x8c00, 0x0b56, 0x3000 }, + { 0x8a00, 0x0b4c, 0x2000 }, + { 0x0a00, 0x0b4b, 0x0000 }, + { 0x0c00, 0x0b4d, 0x0000 }, + { 0x8700, 0x0b5c, 0x2000 }, + { 0x0a00, 0x0b57, 0x0000 }, + { 0x0700, 0x0b5d, 0x0000 }, + { 0x8d00, 0x0be7, 0x7000 }, + { 0x8700, 0x0b9c, 0x6000 }, + { 0x8700, 0x0b83, 0x5000 }, + { 0x8d00, 0x0b6b, 0x4000 }, + { 0x8d00, 0x0b67, 0x3000 }, + { 0x8700, 0x0b61, 0x2000 }, + { 0x0700, 0x0b60, 0x0000 }, + { 0x0d00, 0x0b66, 0x0000 }, + { 0x8d00, 0x0b69, 0x2000 }, + { 0x0d00, 0x0b68, 0x0000 }, + { 0x0d00, 0x0b6a, 0x0000 }, + { 0x8d00, 0x0b6f, 0x3000 }, + { 0x8d00, 0x0b6d, 0x2000 }, + { 0x0d00, 0x0b6c, 0x0000 }, + { 0x0d00, 0x0b6e, 0x0000 }, + { 0x8700, 0x0b71, 0x2000 }, + { 0x1a00, 0x0b70, 0x0000 }, + { 0x0c00, 0x0b82, 0x0000 }, + { 0x8700, 0x0b8f, 0x4000 }, + { 0x8700, 0x0b88, 0x3000 }, + { 0x8700, 0x0b86, 0x2000 }, + { 0x0700, 0x0b85, 0x0000 }, + { 0x0700, 0x0b87, 0x0000 }, + { 0x8700, 0x0b8a, 0x2000 }, + { 0x0700, 0x0b89, 0x0000 }, + { 0x0700, 0x0b8e, 0x0000 }, + { 0x8700, 0x0b94, 0x3000 }, + { 0x8700, 0x0b92, 0x2000 }, + { 0x0700, 0x0b90, 0x0000 }, + { 0x0700, 0x0b93, 0x0000 }, + { 0x8700, 0x0b99, 0x2000 }, + { 0x0700, 0x0b95, 0x0000 }, + { 0x0700, 0x0b9a, 0x0000 }, + { 0x8700, 0x0bb7, 0x5000 }, + { 0x8700, 0x0bae, 0x4000 }, + { 0x8700, 0x0ba4, 0x3000 }, + { 0x8700, 0x0b9f, 0x2000 }, + { 0x0700, 0x0b9e, 0x0000 }, + { 0x0700, 0x0ba3, 0x0000 }, + { 0x8700, 0x0ba9, 0x2000 }, + { 0x0700, 0x0ba8, 0x0000 }, + { 0x0700, 0x0baa, 0x0000 }, + { 0x8700, 0x0bb2, 0x3000 }, + { 0x8700, 0x0bb0, 0x2000 }, + { 0x0700, 0x0baf, 0x0000 }, + { 0x0700, 0x0bb1, 0x0000 }, + { 0x8700, 0x0bb4, 0x2000 }, + { 0x0700, 0x0bb3, 0x0000 }, + { 0x0700, 0x0bb5, 0x0000 }, + { 0x8a00, 0x0bc6, 0x4000 }, + { 0x8a00, 0x0bbf, 0x3000 }, + { 0x8700, 0x0bb9, 0x2000 }, + { 0x0700, 0x0bb8, 0x0000 }, + { 0x0a00, 0x0bbe, 0x0000 }, + { 0x8a00, 0x0bc1, 0x2000 }, + { 0x0c00, 0x0bc0, 0x0000 }, + { 0x0a00, 0x0bc2, 0x0000 }, + { 0x8a00, 0x0bcb, 0x3000 }, + { 0x8a00, 0x0bc8, 0x2000 }, + { 0x0a00, 0x0bc7, 0x0000 }, + { 0x0a00, 0x0bca, 0x0000 }, + { 0x8c00, 0x0bcd, 0x2000 }, + { 0x0a00, 0x0bcc, 0x0000 }, + { 0x0a00, 0x0bd7, 0x0000 }, + { 0x8700, 0x0c0f, 0x6000 }, + { 0x9a00, 0x0bf7, 0x5000 }, + { 0x8d00, 0x0bef, 0x4000 }, + { 0x8d00, 0x0beb, 0x3000 }, + { 0x8d00, 0x0be9, 0x2000 }, + { 0x0d00, 0x0be8, 0x0000 }, + { 0x0d00, 0x0bea, 0x0000 }, + { 0x8d00, 0x0bed, 0x2000 }, + { 0x0d00, 0x0bec, 0x0000 }, + { 0x0d00, 0x0bee, 0x0000 }, + { 0x9a00, 0x0bf3, 0x3000 }, + { 0x8f00, 0x0bf1, 0x2000 }, + { 0x0f00, 0x0bf0, 0x0000 }, + { 0x0f00, 0x0bf2, 0x0000 }, + { 0x9a00, 0x0bf5, 0x2000 }, + { 0x1a00, 0x0bf4, 0x0000 }, + { 0x1a00, 0x0bf6, 0x0000 }, + { 0x8700, 0x0c06, 0x4000 }, + { 0x8a00, 0x0c01, 0x3000 }, + { 0x9700, 0x0bf9, 0x2000 }, + { 0x1a00, 0x0bf8, 0x0000 }, + { 0x1a00, 0x0bfa, 0x0000 }, + { 0x8a00, 0x0c03, 0x2000 }, + { 0x0a00, 0x0c02, 0x0000 }, + { 0x0700, 0x0c05, 0x0000 }, + { 0x8700, 0x0c0a, 0x3000 }, + { 0x8700, 0x0c08, 0x2000 }, + { 0x0700, 0x0c07, 0x0000 }, + { 0x0700, 0x0c09, 0x0000 }, + { 0x8700, 0x0c0c, 0x2000 }, + { 0x0700, 0x0c0b, 0x0000 }, + { 0x0700, 0x0c0e, 0x0000 }, + { 0x8700, 0x0c20, 0x5000 }, + { 0x8700, 0x0c18, 0x4000 }, + { 0x8700, 0x0c14, 0x3000 }, + { 0x8700, 0x0c12, 0x2000 }, + { 0x0700, 0x0c10, 0x0000 }, + { 0x0700, 0x0c13, 0x0000 }, + { 0x8700, 0x0c16, 0x2000 }, + { 0x0700, 0x0c15, 0x0000 }, + { 0x0700, 0x0c17, 0x0000 }, + { 0x8700, 0x0c1c, 0x3000 }, + { 0x8700, 0x0c1a, 0x2000 }, + { 0x0700, 0x0c19, 0x0000 }, + { 0x0700, 0x0c1b, 0x0000 }, + { 0x8700, 0x0c1e, 0x2000 }, + { 0x0700, 0x0c1d, 0x0000 }, + { 0x0700, 0x0c1f, 0x0000 }, + { 0x8700, 0x0c28, 0x4000 }, + { 0x8700, 0x0c24, 0x3000 }, + { 0x8700, 0x0c22, 0x2000 }, + { 0x0700, 0x0c21, 0x0000 }, + { 0x0700, 0x0c23, 0x0000 }, + { 0x8700, 0x0c26, 0x2000 }, + { 0x0700, 0x0c25, 0x0000 }, + { 0x0700, 0x0c27, 0x0000 }, + { 0x8700, 0x0c2d, 0x3000 }, + { 0x8700, 0x0c2b, 0x2000 }, + { 0x0700, 0x0c2a, 0x0000 }, + { 0x0700, 0x0c2c, 0x0000 }, + { 0x8700, 0x0c2f, 0x2000 }, + { 0x0700, 0x0c2e, 0x0000 }, + { 0x0700, 0x0c30, 0x0000 }, + { 0x8700, 0x0d0e, 0x8000 }, + { 0x8700, 0x0ca1, 0x7000 }, + { 0x8d00, 0x0c6c, 0x6000 }, + { 0x8c00, 0x0c47, 0x5000 }, + { 0x8c00, 0x0c3e, 0x4000 }, + { 0x8700, 0x0c36, 0x3000 }, + { 0x8700, 0x0c33, 0x2000 }, + { 0x0700, 0x0c32, 0x0000 }, + { 0x0700, 0x0c35, 0x0000 }, + { 0x8700, 0x0c38, 0x2000 }, + { 0x0700, 0x0c37, 0x0000 }, + { 0x0700, 0x0c39, 0x0000 }, + { 0x8a00, 0x0c42, 0x3000 }, + { 0x8c00, 0x0c40, 0x2000 }, + { 0x0c00, 0x0c3f, 0x0000 }, + { 0x0a00, 0x0c41, 0x0000 }, + { 0x8a00, 0x0c44, 0x2000 }, + { 0x0a00, 0x0c43, 0x0000 }, + { 0x0c00, 0x0c46, 0x0000 }, + { 0x8700, 0x0c60, 0x4000 }, + { 0x8c00, 0x0c4c, 0x3000 }, + { 0x8c00, 0x0c4a, 0x2000 }, + { 0x0c00, 0x0c48, 0x0000 }, + { 0x0c00, 0x0c4b, 0x0000 }, + { 0x8c00, 0x0c55, 0x2000 }, + { 0x0c00, 0x0c4d, 0x0000 }, + { 0x0c00, 0x0c56, 0x0000 }, + { 0x8d00, 0x0c68, 0x3000 }, + { 0x8d00, 0x0c66, 0x2000 }, + { 0x0700, 0x0c61, 0x0000 }, + { 0x0d00, 0x0c67, 0x0000 }, + { 0x8d00, 0x0c6a, 0x2000 }, + { 0x0d00, 0x0c69, 0x0000 }, + { 0x0d00, 0x0c6b, 0x0000 }, + { 0x8700, 0x0c90, 0x5000 }, + { 0x8700, 0x0c87, 0x4000 }, + { 0x8a00, 0x0c82, 0x3000 }, + { 0x8d00, 0x0c6e, 0x2000 }, + { 0x0d00, 0x0c6d, 0x0000 }, + { 0x0d00, 0x0c6f, 0x0000 }, + { 0x8700, 0x0c85, 0x2000 }, + { 0x0a00, 0x0c83, 0x0000 }, + { 0x0700, 0x0c86, 0x0000 }, + { 0x8700, 0x0c8b, 0x3000 }, + { 0x8700, 0x0c89, 0x2000 }, + { 0x0700, 0x0c88, 0x0000 }, + { 0x0700, 0x0c8a, 0x0000 }, + { 0x8700, 0x0c8e, 0x2000 }, + { 0x0700, 0x0c8c, 0x0000 }, + { 0x0700, 0x0c8f, 0x0000 }, + { 0x8700, 0x0c99, 0x4000 }, + { 0x8700, 0x0c95, 0x3000 }, + { 0x8700, 0x0c93, 0x2000 }, + { 0x0700, 0x0c92, 0x0000 }, + { 0x0700, 0x0c94, 0x0000 }, + { 0x8700, 0x0c97, 0x2000 }, + { 0x0700, 0x0c96, 0x0000 }, + { 0x0700, 0x0c98, 0x0000 }, + { 0x8700, 0x0c9d, 0x3000 }, + { 0x8700, 0x0c9b, 0x2000 }, + { 0x0700, 0x0c9a, 0x0000 }, + { 0x0700, 0x0c9c, 0x0000 }, + { 0x8700, 0x0c9f, 0x2000 }, + { 0x0700, 0x0c9e, 0x0000 }, + { 0x0700, 0x0ca0, 0x0000 }, + { 0x8c00, 0x0cc6, 0x6000 }, + { 0x8700, 0x0cb2, 0x5000 }, + { 0x8700, 0x0caa, 0x4000 }, + { 0x8700, 0x0ca5, 0x3000 }, + { 0x8700, 0x0ca3, 0x2000 }, + { 0x0700, 0x0ca2, 0x0000 }, + { 0x0700, 0x0ca4, 0x0000 }, + { 0x8700, 0x0ca7, 0x2000 }, + { 0x0700, 0x0ca6, 0x0000 }, + { 0x0700, 0x0ca8, 0x0000 }, + { 0x8700, 0x0cae, 0x3000 }, + { 0x8700, 0x0cac, 0x2000 }, + { 0x0700, 0x0cab, 0x0000 }, + { 0x0700, 0x0cad, 0x0000 }, + { 0x8700, 0x0cb0, 0x2000 }, + { 0x0700, 0x0caf, 0x0000 }, + { 0x0700, 0x0cb1, 0x0000 }, + { 0x8700, 0x0cbd, 0x4000 }, + { 0x8700, 0x0cb7, 0x3000 }, + { 0x8700, 0x0cb5, 0x2000 }, + { 0x0700, 0x0cb3, 0x0000 }, + { 0x0700, 0x0cb6, 0x0000 }, + { 0x8700, 0x0cb9, 0x2000 }, + { 0x0700, 0x0cb8, 0x0000 }, + { 0x0c00, 0x0cbc, 0x0000 }, + { 0x8a00, 0x0cc1, 0x3000 }, + { 0x8c00, 0x0cbf, 0x2000 }, + { 0x0a00, 0x0cbe, 0x0000 }, + { 0x0a00, 0x0cc0, 0x0000 }, + { 0x8a00, 0x0cc3, 0x2000 }, + { 0x0a00, 0x0cc2, 0x0000 }, + { 0x0a00, 0x0cc4, 0x0000 }, + { 0x8d00, 0x0cea, 0x5000 }, + { 0x8a00, 0x0cd6, 0x4000 }, + { 0x8a00, 0x0ccb, 0x3000 }, + { 0x8a00, 0x0cc8, 0x2000 }, + { 0x0a00, 0x0cc7, 0x0000 }, + { 0x0a00, 0x0cca, 0x0000 }, + { 0x8c00, 0x0ccd, 0x2000 }, + { 0x0c00, 0x0ccc, 0x0000 }, + { 0x0a00, 0x0cd5, 0x0000 }, + { 0x8d00, 0x0ce6, 0x3000 }, + { 0x8700, 0x0ce0, 0x2000 }, + { 0x0700, 0x0cde, 0x0000 }, + { 0x0700, 0x0ce1, 0x0000 }, + { 0x8d00, 0x0ce8, 0x2000 }, + { 0x0d00, 0x0ce7, 0x0000 }, + { 0x0d00, 0x0ce9, 0x0000 }, + { 0x8700, 0x0d05, 0x4000 }, + { 0x8d00, 0x0cee, 0x3000 }, + { 0x8d00, 0x0cec, 0x2000 }, + { 0x0d00, 0x0ceb, 0x0000 }, + { 0x0d00, 0x0ced, 0x0000 }, + { 0x8a00, 0x0d02, 0x2000 }, + { 0x0d00, 0x0cef, 0x0000 }, + { 0x0a00, 0x0d03, 0x0000 }, + { 0x8700, 0x0d09, 0x3000 }, + { 0x8700, 0x0d07, 0x2000 }, + { 0x0700, 0x0d06, 0x0000 }, + { 0x0700, 0x0d08, 0x0000 }, + { 0x8700, 0x0d0b, 0x2000 }, + { 0x0700, 0x0d0a, 0x0000 }, + { 0x0700, 0x0d0c, 0x0000 }, + { 0x8d00, 0x0d6c, 0x7000 }, + { 0x8700, 0x0d30, 0x6000 }, + { 0x8700, 0x0d1f, 0x5000 }, + { 0x8700, 0x0d17, 0x4000 }, + { 0x8700, 0x0d13, 0x3000 }, + { 0x8700, 0x0d10, 0x2000 }, + { 0x0700, 0x0d0f, 0x0000 }, + { 0x0700, 0x0d12, 0x0000 }, + { 0x8700, 0x0d15, 0x2000 }, + { 0x0700, 0x0d14, 0x0000 }, + { 0x0700, 0x0d16, 0x0000 }, + { 0x8700, 0x0d1b, 0x3000 }, + { 0x8700, 0x0d19, 0x2000 }, + { 0x0700, 0x0d18, 0x0000 }, + { 0x0700, 0x0d1a, 0x0000 }, + { 0x8700, 0x0d1d, 0x2000 }, + { 0x0700, 0x0d1c, 0x0000 }, + { 0x0700, 0x0d1e, 0x0000 }, + { 0x8700, 0x0d27, 0x4000 }, + { 0x8700, 0x0d23, 0x3000 }, + { 0x8700, 0x0d21, 0x2000 }, + { 0x0700, 0x0d20, 0x0000 }, + { 0x0700, 0x0d22, 0x0000 }, + { 0x8700, 0x0d25, 0x2000 }, + { 0x0700, 0x0d24, 0x0000 }, + { 0x0700, 0x0d26, 0x0000 }, + { 0x8700, 0x0d2c, 0x3000 }, + { 0x8700, 0x0d2a, 0x2000 }, + { 0x0700, 0x0d28, 0x0000 }, + { 0x0700, 0x0d2b, 0x0000 }, + { 0x8700, 0x0d2e, 0x2000 }, + { 0x0700, 0x0d2d, 0x0000 }, + { 0x0700, 0x0d2f, 0x0000 }, + { 0x8a00, 0x0d46, 0x5000 }, + { 0x8700, 0x0d38, 0x4000 }, + { 0x8700, 0x0d34, 0x3000 }, + { 0x8700, 0x0d32, 0x2000 }, + { 0x0700, 0x0d31, 0x0000 }, + { 0x0700, 0x0d33, 0x0000 }, + { 0x8700, 0x0d36, 0x2000 }, + { 0x0700, 0x0d35, 0x0000 }, + { 0x0700, 0x0d37, 0x0000 }, + { 0x8a00, 0x0d40, 0x3000 }, + { 0x8a00, 0x0d3e, 0x2000 }, + { 0x0700, 0x0d39, 0x0000 }, + { 0x0a00, 0x0d3f, 0x0000 }, + { 0x8c00, 0x0d42, 0x2000 }, + { 0x0c00, 0x0d41, 0x0000 }, + { 0x0c00, 0x0d43, 0x0000 }, + { 0x8700, 0x0d60, 0x4000 }, + { 0x8a00, 0x0d4b, 0x3000 }, + { 0x8a00, 0x0d48, 0x2000 }, + { 0x0a00, 0x0d47, 0x0000 }, + { 0x0a00, 0x0d4a, 0x0000 }, + { 0x8c00, 0x0d4d, 0x2000 }, + { 0x0a00, 0x0d4c, 0x0000 }, + { 0x0a00, 0x0d57, 0x0000 }, + { 0x8d00, 0x0d68, 0x3000 }, + { 0x8d00, 0x0d66, 0x2000 }, + { 0x0700, 0x0d61, 0x0000 }, + { 0x0d00, 0x0d67, 0x0000 }, + { 0x8d00, 0x0d6a, 0x2000 }, + { 0x0d00, 0x0d69, 0x0000 }, + { 0x0d00, 0x0d6b, 0x0000 }, + { 0x8700, 0x0da2, 0x6000 }, + { 0x8700, 0x0d8f, 0x5000 }, + { 0x8700, 0x0d87, 0x4000 }, + { 0x8a00, 0x0d82, 0x3000 }, + { 0x8d00, 0x0d6e, 0x2000 }, + { 0x0d00, 0x0d6d, 0x0000 }, + { 0x0d00, 0x0d6f, 0x0000 }, + { 0x8700, 0x0d85, 0x2000 }, + { 0x0a00, 0x0d83, 0x0000 }, + { 0x0700, 0x0d86, 0x0000 }, + { 0x8700, 0x0d8b, 0x3000 }, + { 0x8700, 0x0d89, 0x2000 }, + { 0x0700, 0x0d88, 0x0000 }, + { 0x0700, 0x0d8a, 0x0000 }, + { 0x8700, 0x0d8d, 0x2000 }, + { 0x0700, 0x0d8c, 0x0000 }, + { 0x0700, 0x0d8e, 0x0000 }, + { 0x8700, 0x0d9a, 0x4000 }, + { 0x8700, 0x0d93, 0x3000 }, + { 0x8700, 0x0d91, 0x2000 }, + { 0x0700, 0x0d90, 0x0000 }, + { 0x0700, 0x0d92, 0x0000 }, + { 0x8700, 0x0d95, 0x2000 }, + { 0x0700, 0x0d94, 0x0000 }, + { 0x0700, 0x0d96, 0x0000 }, + { 0x8700, 0x0d9e, 0x3000 }, + { 0x8700, 0x0d9c, 0x2000 }, + { 0x0700, 0x0d9b, 0x0000 }, + { 0x0700, 0x0d9d, 0x0000 }, + { 0x8700, 0x0da0, 0x2000 }, + { 0x0700, 0x0d9f, 0x0000 }, + { 0x0700, 0x0da1, 0x0000 }, + { 0x8700, 0x0db3, 0x5000 }, + { 0x8700, 0x0daa, 0x4000 }, + { 0x8700, 0x0da6, 0x3000 }, + { 0x8700, 0x0da4, 0x2000 }, + { 0x0700, 0x0da3, 0x0000 }, + { 0x0700, 0x0da5, 0x0000 }, + { 0x8700, 0x0da8, 0x2000 }, + { 0x0700, 0x0da7, 0x0000 }, + { 0x0700, 0x0da9, 0x0000 }, + { 0x8700, 0x0dae, 0x3000 }, + { 0x8700, 0x0dac, 0x2000 }, + { 0x0700, 0x0dab, 0x0000 }, + { 0x0700, 0x0dad, 0x0000 }, + { 0x8700, 0x0db0, 0x2000 }, + { 0x0700, 0x0daf, 0x0000 }, + { 0x0700, 0x0db1, 0x0000 }, + { 0x8700, 0x0dbb, 0x4000 }, + { 0x8700, 0x0db7, 0x3000 }, + { 0x8700, 0x0db5, 0x2000 }, + { 0x0700, 0x0db4, 0x0000 }, + { 0x0700, 0x0db6, 0x0000 }, + { 0x8700, 0x0db9, 0x2000 }, + { 0x0700, 0x0db8, 0x0000 }, + { 0x0700, 0x0dba, 0x0000 }, + { 0x8700, 0x0dc2, 0x3000 }, + { 0x8700, 0x0dc0, 0x2000 }, + { 0x0700, 0x0dbd, 0x0000 }, + { 0x0700, 0x0dc1, 0x0000 }, + { 0x8700, 0x0dc4, 0x2000 }, + { 0x0700, 0x0dc3, 0x0000 }, + { 0x0700, 0x0dc5, 0x0000 }, + { 0x8700, 0x0f55, 0x9000 }, + { 0x8700, 0x0ea5, 0x8000 }, + { 0x8700, 0x0e2d, 0x7000 }, + { 0x8700, 0x0e0d, 0x6000 }, + { 0x8a00, 0x0ddf, 0x5000 }, + { 0x8c00, 0x0dd6, 0x4000 }, + { 0x8a00, 0x0dd1, 0x3000 }, + { 0x8a00, 0x0dcf, 0x2000 }, + { 0x0c00, 0x0dca, 0x0000 }, + { 0x0a00, 0x0dd0, 0x0000 }, + { 0x8c00, 0x0dd3, 0x2000 }, + { 0x0c00, 0x0dd2, 0x0000 }, + { 0x0c00, 0x0dd4, 0x0000 }, + { 0x8a00, 0x0ddb, 0x3000 }, + { 0x8a00, 0x0dd9, 0x2000 }, + { 0x0a00, 0x0dd8, 0x0000 }, + { 0x0a00, 0x0dda, 0x0000 }, + { 0x8a00, 0x0ddd, 0x2000 }, + { 0x0a00, 0x0ddc, 0x0000 }, + { 0x0a00, 0x0dde, 0x0000 }, + { 0x8700, 0x0e05, 0x4000 }, + { 0x8700, 0x0e01, 0x3000 }, + { 0x8a00, 0x0df3, 0x2000 }, + { 0x0a00, 0x0df2, 0x0000 }, + { 0x1500, 0x0df4, 0x0000 }, + { 0x8700, 0x0e03, 0x2000 }, + { 0x0700, 0x0e02, 0x0000 }, + { 0x0700, 0x0e04, 0x0000 }, + { 0x8700, 0x0e09, 0x3000 }, + { 0x8700, 0x0e07, 0x2000 }, + { 0x0700, 0x0e06, 0x0000 }, + { 0x0700, 0x0e08, 0x0000 }, + { 0x8700, 0x0e0b, 0x2000 }, + { 0x0700, 0x0e0a, 0x0000 }, + { 0x0700, 0x0e0c, 0x0000 }, + { 0x8700, 0x0e1d, 0x5000 }, + { 0x8700, 0x0e15, 0x4000 }, + { 0x8700, 0x0e11, 0x3000 }, + { 0x8700, 0x0e0f, 0x2000 }, + { 0x0700, 0x0e0e, 0x0000 }, + { 0x0700, 0x0e10, 0x0000 }, + { 0x8700, 0x0e13, 0x2000 }, + { 0x0700, 0x0e12, 0x0000 }, + { 0x0700, 0x0e14, 0x0000 }, + { 0x8700, 0x0e19, 0x3000 }, + { 0x8700, 0x0e17, 0x2000 }, + { 0x0700, 0x0e16, 0x0000 }, + { 0x0700, 0x0e18, 0x0000 }, + { 0x8700, 0x0e1b, 0x2000 }, + { 0x0700, 0x0e1a, 0x0000 }, + { 0x0700, 0x0e1c, 0x0000 }, + { 0x8700, 0x0e25, 0x4000 }, + { 0x8700, 0x0e21, 0x3000 }, + { 0x8700, 0x0e1f, 0x2000 }, + { 0x0700, 0x0e1e, 0x0000 }, + { 0x0700, 0x0e20, 0x0000 }, + { 0x8700, 0x0e23, 0x2000 }, + { 0x0700, 0x0e22, 0x0000 }, + { 0x0700, 0x0e24, 0x0000 }, + { 0x8700, 0x0e29, 0x3000 }, + { 0x8700, 0x0e27, 0x2000 }, + { 0x0700, 0x0e26, 0x0000 }, + { 0x0700, 0x0e28, 0x0000 }, + { 0x8700, 0x0e2b, 0x2000 }, + { 0x0700, 0x0e2a, 0x0000 }, + { 0x0700, 0x0e2c, 0x0000 }, + { 0x8d00, 0x0e51, 0x6000 }, + { 0x8700, 0x0e41, 0x5000 }, + { 0x8c00, 0x0e35, 0x4000 }, + { 0x8c00, 0x0e31, 0x3000 }, + { 0x8700, 0x0e2f, 0x2000 }, + { 0x0700, 0x0e2e, 0x0000 }, + { 0x0700, 0x0e30, 0x0000 }, + { 0x8700, 0x0e33, 0x2000 }, + { 0x0700, 0x0e32, 0x0000 }, + { 0x0c00, 0x0e34, 0x0000 }, + { 0x8c00, 0x0e39, 0x3000 }, + { 0x8c00, 0x0e37, 0x2000 }, + { 0x0c00, 0x0e36, 0x0000 }, + { 0x0c00, 0x0e38, 0x0000 }, + { 0x9700, 0x0e3f, 0x2000 }, + { 0x0c00, 0x0e3a, 0x0000 }, + { 0x0700, 0x0e40, 0x0000 }, + { 0x8c00, 0x0e49, 0x4000 }, + { 0x8700, 0x0e45, 0x3000 }, + { 0x8700, 0x0e43, 0x2000 }, + { 0x0700, 0x0e42, 0x0000 }, + { 0x0700, 0x0e44, 0x0000 }, + { 0x8c00, 0x0e47, 0x2000 }, + { 0x0600, 0x0e46, 0x0000 }, + { 0x0c00, 0x0e48, 0x0000 }, + { 0x8c00, 0x0e4d, 0x3000 }, + { 0x8c00, 0x0e4b, 0x2000 }, + { 0x0c00, 0x0e4a, 0x0000 }, + { 0x0c00, 0x0e4c, 0x0000 }, + { 0x9500, 0x0e4f, 0x2000 }, + { 0x0c00, 0x0e4e, 0x0000 }, + { 0x0d00, 0x0e50, 0x0000 }, + { 0x8700, 0x0e8a, 0x5000 }, + { 0x8d00, 0x0e59, 0x4000 }, + { 0x8d00, 0x0e55, 0x3000 }, + { 0x8d00, 0x0e53, 0x2000 }, + { 0x0d00, 0x0e52, 0x0000 }, + { 0x0d00, 0x0e54, 0x0000 }, + { 0x8d00, 0x0e57, 0x2000 }, + { 0x0d00, 0x0e56, 0x0000 }, + { 0x0d00, 0x0e58, 0x0000 }, + { 0x8700, 0x0e82, 0x3000 }, + { 0x9500, 0x0e5b, 0x2000 }, + { 0x1500, 0x0e5a, 0x0000 }, + { 0x0700, 0x0e81, 0x0000 }, + { 0x8700, 0x0e87, 0x2000 }, + { 0x0700, 0x0e84, 0x0000 }, + { 0x0700, 0x0e88, 0x0000 }, + { 0x8700, 0x0e9b, 0x4000 }, + { 0x8700, 0x0e96, 0x3000 }, + { 0x8700, 0x0e94, 0x2000 }, + { 0x0700, 0x0e8d, 0x0000 }, + { 0x0700, 0x0e95, 0x0000 }, + { 0x8700, 0x0e99, 0x2000 }, + { 0x0700, 0x0e97, 0x0000 }, + { 0x0700, 0x0e9a, 0x0000 }, + { 0x8700, 0x0e9f, 0x3000 }, + { 0x8700, 0x0e9d, 0x2000 }, + { 0x0700, 0x0e9c, 0x0000 }, + { 0x0700, 0x0e9e, 0x0000 }, + { 0x8700, 0x0ea2, 0x2000 }, + { 0x0700, 0x0ea1, 0x0000 }, + { 0x0700, 0x0ea3, 0x0000 }, + { 0x9a00, 0x0f14, 0x7000 }, + { 0x8d00, 0x0ed0, 0x6000 }, + { 0x8c00, 0x0eb9, 0x5000 }, + { 0x8c00, 0x0eb1, 0x4000 }, + { 0x8700, 0x0ead, 0x3000 }, + { 0x8700, 0x0eaa, 0x2000 }, + { 0x0700, 0x0ea7, 0x0000 }, + { 0x0700, 0x0eab, 0x0000 }, + { 0x8700, 0x0eaf, 0x2000 }, + { 0x0700, 0x0eae, 0x0000 }, + { 0x0700, 0x0eb0, 0x0000 }, + { 0x8c00, 0x0eb5, 0x3000 }, + { 0x8700, 0x0eb3, 0x2000 }, + { 0x0700, 0x0eb2, 0x0000 }, + { 0x0c00, 0x0eb4, 0x0000 }, + { 0x8c00, 0x0eb7, 0x2000 }, + { 0x0c00, 0x0eb6, 0x0000 }, + { 0x0c00, 0x0eb8, 0x0000 }, + { 0x8700, 0x0ec4, 0x4000 }, + { 0x8700, 0x0ec0, 0x3000 }, + { 0x8c00, 0x0ebc, 0x2000 }, + { 0x0c00, 0x0ebb, 0x0000 }, + { 0x0700, 0x0ebd, 0x0000 }, + { 0x8700, 0x0ec2, 0x2000 }, + { 0x0700, 0x0ec1, 0x0000 }, + { 0x0700, 0x0ec3, 0x0000 }, + { 0x8c00, 0x0eca, 0x3000 }, + { 0x8c00, 0x0ec8, 0x2000 }, + { 0x0600, 0x0ec6, 0x0000 }, + { 0x0c00, 0x0ec9, 0x0000 }, + { 0x8c00, 0x0ecc, 0x2000 }, + { 0x0c00, 0x0ecb, 0x0000 }, + { 0x0c00, 0x0ecd, 0x0000 }, + { 0x9500, 0x0f04, 0x5000 }, + { 0x8d00, 0x0ed8, 0x4000 }, + { 0x8d00, 0x0ed4, 0x3000 }, + { 0x8d00, 0x0ed2, 0x2000 }, + { 0x0d00, 0x0ed1, 0x0000 }, + { 0x0d00, 0x0ed3, 0x0000 }, + { 0x8d00, 0x0ed6, 0x2000 }, + { 0x0d00, 0x0ed5, 0x0000 }, + { 0x0d00, 0x0ed7, 0x0000 }, + { 0x8700, 0x0f00, 0x3000 }, + { 0x8700, 0x0edc, 0x2000 }, + { 0x0d00, 0x0ed9, 0x0000 }, + { 0x0700, 0x0edd, 0x0000 }, + { 0x9a00, 0x0f02, 0x2000 }, + { 0x1a00, 0x0f01, 0x0000 }, + { 0x1a00, 0x0f03, 0x0000 }, + { 0x9500, 0x0f0c, 0x4000 }, + { 0x9500, 0x0f08, 0x3000 }, + { 0x9500, 0x0f06, 0x2000 }, + { 0x1500, 0x0f05, 0x0000 }, + { 0x1500, 0x0f07, 0x0000 }, + { 0x9500, 0x0f0a, 0x2000 }, + { 0x1500, 0x0f09, 0x0000 }, + { 0x1500, 0x0f0b, 0x0000 }, + { 0x9500, 0x0f10, 0x3000 }, + { 0x9500, 0x0f0e, 0x2000 }, + { 0x1500, 0x0f0d, 0x0000 }, + { 0x1500, 0x0f0f, 0x0000 }, + { 0x9500, 0x0f12, 0x2000 }, + { 0x1500, 0x0f11, 0x0000 }, + { 0x1a00, 0x0f13, 0x0000 }, + { 0x9a00, 0x0f34, 0x6000 }, + { 0x8d00, 0x0f24, 0x5000 }, + { 0x9a00, 0x0f1c, 0x4000 }, + { 0x8c00, 0x0f18, 0x3000 }, + { 0x9a00, 0x0f16, 0x2000 }, + { 0x1a00, 0x0f15, 0x0000 }, + { 0x1a00, 0x0f17, 0x0000 }, + { 0x9a00, 0x0f1a, 0x2000 }, + { 0x0c00, 0x0f19, 0x0000 }, + { 0x1a00, 0x0f1b, 0x0000 }, + { 0x8d00, 0x0f20, 0x3000 }, + { 0x9a00, 0x0f1e, 0x2000 }, + { 0x1a00, 0x0f1d, 0x0000 }, + { 0x1a00, 0x0f1f, 0x0000 }, + { 0x8d00, 0x0f22, 0x2000 }, + { 0x0d00, 0x0f21, 0x0000 }, + { 0x0d00, 0x0f23, 0x0000 }, + { 0x8f00, 0x0f2c, 0x4000 }, + { 0x8d00, 0x0f28, 0x3000 }, + { 0x8d00, 0x0f26, 0x2000 }, + { 0x0d00, 0x0f25, 0x0000 }, + { 0x0d00, 0x0f27, 0x0000 }, + { 0x8f00, 0x0f2a, 0x2000 }, + { 0x0d00, 0x0f29, 0x0000 }, + { 0x0f00, 0x0f2b, 0x0000 }, + { 0x8f00, 0x0f30, 0x3000 }, + { 0x8f00, 0x0f2e, 0x2000 }, + { 0x0f00, 0x0f2d, 0x0000 }, + { 0x0f00, 0x0f2f, 0x0000 }, + { 0x8f00, 0x0f32, 0x2000 }, + { 0x0f00, 0x0f31, 0x0000 }, + { 0x0f00, 0x0f33, 0x0000 }, + { 0x8700, 0x0f44, 0x5000 }, + { 0x9600, 0x0f3c, 0x4000 }, + { 0x9a00, 0x0f38, 0x3000 }, + { 0x9a00, 0x0f36, 0x2000 }, + { 0x0c00, 0x0f35, 0x0000 }, + { 0x0c00, 0x0f37, 0x0000 }, + { 0x9600, 0x0f3a, 0x2000 }, + { 0x0c00, 0x0f39, 0x0000 }, + { 0x1200, 0x0f3b, 0x0000 }, + { 0x8700, 0x0f40, 0x3000 }, + { 0x8a00, 0x0f3e, 0x2000 }, + { 0x1200, 0x0f3d, 0x0000 }, + { 0x0a00, 0x0f3f, 0x0000 }, + { 0x8700, 0x0f42, 0x2000 }, + { 0x0700, 0x0f41, 0x0000 }, + { 0x0700, 0x0f43, 0x0000 }, + { 0x8700, 0x0f4d, 0x4000 }, + { 0x8700, 0x0f49, 0x3000 }, + { 0x8700, 0x0f46, 0x2000 }, + { 0x0700, 0x0f45, 0x0000 }, + { 0x0700, 0x0f47, 0x0000 }, + { 0x8700, 0x0f4b, 0x2000 }, + { 0x0700, 0x0f4a, 0x0000 }, + { 0x0700, 0x0f4c, 0x0000 }, + { 0x8700, 0x0f51, 0x3000 }, + { 0x8700, 0x0f4f, 0x2000 }, + { 0x0700, 0x0f4e, 0x0000 }, + { 0x0700, 0x0f50, 0x0000 }, + { 0x8700, 0x0f53, 0x2000 }, + { 0x0700, 0x0f52, 0x0000 }, + { 0x0700, 0x0f54, 0x0000 }, + { 0x8700, 0x1013, 0x8000 }, + { 0x8c00, 0x0fa0, 0x7000 }, + { 0x8c00, 0x0f7b, 0x6000 }, + { 0x8700, 0x0f65, 0x5000 }, + { 0x8700, 0x0f5d, 0x4000 }, + { 0x8700, 0x0f59, 0x3000 }, + { 0x8700, 0x0f57, 0x2000 }, + { 0x0700, 0x0f56, 0x0000 }, + { 0x0700, 0x0f58, 0x0000 }, + { 0x8700, 0x0f5b, 0x2000 }, + { 0x0700, 0x0f5a, 0x0000 }, + { 0x0700, 0x0f5c, 0x0000 }, + { 0x8700, 0x0f61, 0x3000 }, + { 0x8700, 0x0f5f, 0x2000 }, + { 0x0700, 0x0f5e, 0x0000 }, + { 0x0700, 0x0f60, 0x0000 }, + { 0x8700, 0x0f63, 0x2000 }, + { 0x0700, 0x0f62, 0x0000 }, + { 0x0700, 0x0f64, 0x0000 }, + { 0x8c00, 0x0f73, 0x4000 }, + { 0x8700, 0x0f69, 0x3000 }, + { 0x8700, 0x0f67, 0x2000 }, + { 0x0700, 0x0f66, 0x0000 }, + { 0x0700, 0x0f68, 0x0000 }, + { 0x8c00, 0x0f71, 0x2000 }, + { 0x0700, 0x0f6a, 0x0000 }, + { 0x0c00, 0x0f72, 0x0000 }, + { 0x8c00, 0x0f77, 0x3000 }, + { 0x8c00, 0x0f75, 0x2000 }, + { 0x0c00, 0x0f74, 0x0000 }, + { 0x0c00, 0x0f76, 0x0000 }, + { 0x8c00, 0x0f79, 0x2000 }, + { 0x0c00, 0x0f78, 0x0000 }, + { 0x0c00, 0x0f7a, 0x0000 }, + { 0x8700, 0x0f8b, 0x5000 }, + { 0x8c00, 0x0f83, 0x4000 }, + { 0x8a00, 0x0f7f, 0x3000 }, + { 0x8c00, 0x0f7d, 0x2000 }, + { 0x0c00, 0x0f7c, 0x0000 }, + { 0x0c00, 0x0f7e, 0x0000 }, + { 0x8c00, 0x0f81, 0x2000 }, + { 0x0c00, 0x0f80, 0x0000 }, + { 0x0c00, 0x0f82, 0x0000 }, + { 0x8c00, 0x0f87, 0x3000 }, + { 0x9500, 0x0f85, 0x2000 }, + { 0x0c00, 0x0f84, 0x0000 }, + { 0x0c00, 0x0f86, 0x0000 }, + { 0x8700, 0x0f89, 0x2000 }, + { 0x0700, 0x0f88, 0x0000 }, + { 0x0700, 0x0f8a, 0x0000 }, + { 0x8c00, 0x0f97, 0x4000 }, + { 0x8c00, 0x0f93, 0x3000 }, + { 0x8c00, 0x0f91, 0x2000 }, + { 0x0c00, 0x0f90, 0x0000 }, + { 0x0c00, 0x0f92, 0x0000 }, + { 0x8c00, 0x0f95, 0x2000 }, + { 0x0c00, 0x0f94, 0x0000 }, + { 0x0c00, 0x0f96, 0x0000 }, + { 0x8c00, 0x0f9c, 0x3000 }, + { 0x8c00, 0x0f9a, 0x2000 }, + { 0x0c00, 0x0f99, 0x0000 }, + { 0x0c00, 0x0f9b, 0x0000 }, + { 0x8c00, 0x0f9e, 0x2000 }, + { 0x0c00, 0x0f9d, 0x0000 }, + { 0x0c00, 0x0f9f, 0x0000 }, + { 0x9a00, 0x0fc1, 0x6000 }, + { 0x8c00, 0x0fb0, 0x5000 }, + { 0x8c00, 0x0fa8, 0x4000 }, + { 0x8c00, 0x0fa4, 0x3000 }, + { 0x8c00, 0x0fa2, 0x2000 }, + { 0x0c00, 0x0fa1, 0x0000 }, + { 0x0c00, 0x0fa3, 0x0000 }, + { 0x8c00, 0x0fa6, 0x2000 }, + { 0x0c00, 0x0fa5, 0x0000 }, + { 0x0c00, 0x0fa7, 0x0000 }, + { 0x8c00, 0x0fac, 0x3000 }, + { 0x8c00, 0x0faa, 0x2000 }, + { 0x0c00, 0x0fa9, 0x0000 }, + { 0x0c00, 0x0fab, 0x0000 }, + { 0x8c00, 0x0fae, 0x2000 }, + { 0x0c00, 0x0fad, 0x0000 }, + { 0x0c00, 0x0faf, 0x0000 }, + { 0x8c00, 0x0fb8, 0x4000 }, + { 0x8c00, 0x0fb4, 0x3000 }, + { 0x8c00, 0x0fb2, 0x2000 }, + { 0x0c00, 0x0fb1, 0x0000 }, + { 0x0c00, 0x0fb3, 0x0000 }, + { 0x8c00, 0x0fb6, 0x2000 }, + { 0x0c00, 0x0fb5, 0x0000 }, + { 0x0c00, 0x0fb7, 0x0000 }, + { 0x8c00, 0x0fbc, 0x3000 }, + { 0x8c00, 0x0fba, 0x2000 }, + { 0x0c00, 0x0fb9, 0x0000 }, + { 0x0c00, 0x0fbb, 0x0000 }, + { 0x9a00, 0x0fbf, 0x2000 }, + { 0x1a00, 0x0fbe, 0x0000 }, + { 0x1a00, 0x0fc0, 0x0000 }, + { 0x8700, 0x1003, 0x5000 }, + { 0x9a00, 0x0fc9, 0x4000 }, + { 0x9a00, 0x0fc5, 0x3000 }, + { 0x9a00, 0x0fc3, 0x2000 }, + { 0x1a00, 0x0fc2, 0x0000 }, + { 0x1a00, 0x0fc4, 0x0000 }, + { 0x9a00, 0x0fc7, 0x2000 }, + { 0x0c00, 0x0fc6, 0x0000 }, + { 0x1a00, 0x0fc8, 0x0000 }, + { 0x9a00, 0x0fcf, 0x3000 }, + { 0x9a00, 0x0fcb, 0x2000 }, + { 0x1a00, 0x0fca, 0x0000 }, + { 0x1a00, 0x0fcc, 0x0000 }, + { 0x8700, 0x1001, 0x2000 }, + { 0x0700, 0x1000, 0x0000 }, + { 0x0700, 0x1002, 0x0000 }, + { 0x8700, 0x100b, 0x4000 }, + { 0x8700, 0x1007, 0x3000 }, + { 0x8700, 0x1005, 0x2000 }, + { 0x0700, 0x1004, 0x0000 }, + { 0x0700, 0x1006, 0x0000 }, + { 0x8700, 0x1009, 0x2000 }, + { 0x0700, 0x1008, 0x0000 }, + { 0x0700, 0x100a, 0x0000 }, + { 0x8700, 0x100f, 0x3000 }, + { 0x8700, 0x100d, 0x2000 }, + { 0x0700, 0x100c, 0x0000 }, + { 0x0700, 0x100e, 0x0000 }, + { 0x8700, 0x1011, 0x2000 }, + { 0x0700, 0x1010, 0x0000 }, + { 0x0700, 0x1012, 0x0000 }, + { 0x8900, 0x10a5, 0x7000 }, + { 0x8c00, 0x1039, 0x6000 }, + { 0x8700, 0x1024, 0x5000 }, + { 0x8700, 0x101b, 0x4000 }, + { 0x8700, 0x1017, 0x3000 }, + { 0x8700, 0x1015, 0x2000 }, + { 0x0700, 0x1014, 0x0000 }, + { 0x0700, 0x1016, 0x0000 }, + { 0x8700, 0x1019, 0x2000 }, + { 0x0700, 0x1018, 0x0000 }, + { 0x0700, 0x101a, 0x0000 }, + { 0x8700, 0x101f, 0x3000 }, + { 0x8700, 0x101d, 0x2000 }, + { 0x0700, 0x101c, 0x0000 }, + { 0x0700, 0x101e, 0x0000 }, + { 0x8700, 0x1021, 0x2000 }, + { 0x0700, 0x1020, 0x0000 }, + { 0x0700, 0x1023, 0x0000 }, + { 0x8c00, 0x102e, 0x4000 }, + { 0x8700, 0x1029, 0x3000 }, + { 0x8700, 0x1026, 0x2000 }, + { 0x0700, 0x1025, 0x0000 }, + { 0x0700, 0x1027, 0x0000 }, + { 0x8a00, 0x102c, 0x2000 }, + { 0x0700, 0x102a, 0x0000 }, + { 0x0c00, 0x102d, 0x0000 }, + { 0x8c00, 0x1032, 0x3000 }, + { 0x8c00, 0x1030, 0x2000 }, + { 0x0c00, 0x102f, 0x0000 }, + { 0x0a00, 0x1031, 0x0000 }, + { 0x8c00, 0x1037, 0x2000 }, + { 0x0c00, 0x1036, 0x0000 }, + { 0x0a00, 0x1038, 0x0000 }, + { 0x9500, 0x104f, 0x5000 }, + { 0x8d00, 0x1047, 0x4000 }, + { 0x8d00, 0x1043, 0x3000 }, + { 0x8d00, 0x1041, 0x2000 }, + { 0x0d00, 0x1040, 0x0000 }, + { 0x0d00, 0x1042, 0x0000 }, + { 0x8d00, 0x1045, 0x2000 }, + { 0x0d00, 0x1044, 0x0000 }, + { 0x0d00, 0x1046, 0x0000 }, + { 0x9500, 0x104b, 0x3000 }, + { 0x8d00, 0x1049, 0x2000 }, + { 0x0d00, 0x1048, 0x0000 }, + { 0x1500, 0x104a, 0x0000 }, + { 0x9500, 0x104d, 0x2000 }, + { 0x1500, 0x104c, 0x0000 }, + { 0x1500, 0x104e, 0x0000 }, + { 0x8a00, 0x1057, 0x4000 }, + { 0x8700, 0x1053, 0x3000 }, + { 0x8700, 0x1051, 0x2000 }, + { 0x0700, 0x1050, 0x0000 }, + { 0x0700, 0x1052, 0x0000 }, + { 0x8700, 0x1055, 0x2000 }, + { 0x0700, 0x1054, 0x0000 }, + { 0x0a00, 0x1056, 0x0000 }, + { 0x8900, 0x10a1, 0x3000 }, + { 0x8c00, 0x1059, 0x2000 }, + { 0x0c00, 0x1058, 0x0000 }, + { 0x0900, 0x10a0, 0x0000 }, + { 0x8900, 0x10a3, 0x2000 }, + { 0x0900, 0x10a2, 0x0000 }, + { 0x0900, 0x10a4, 0x0000 }, + { 0x8900, 0x10c5, 0x6000 }, + { 0x8900, 0x10b5, 0x5000 }, + { 0x8900, 0x10ad, 0x4000 }, + { 0x8900, 0x10a9, 0x3000 }, + { 0x8900, 0x10a7, 0x2000 }, + { 0x0900, 0x10a6, 0x0000 }, + { 0x0900, 0x10a8, 0x0000 }, + { 0x8900, 0x10ab, 0x2000 }, + { 0x0900, 0x10aa, 0x0000 }, + { 0x0900, 0x10ac, 0x0000 }, + { 0x8900, 0x10b1, 0x3000 }, + { 0x8900, 0x10af, 0x2000 }, + { 0x0900, 0x10ae, 0x0000 }, + { 0x0900, 0x10b0, 0x0000 }, + { 0x8900, 0x10b3, 0x2000 }, + { 0x0900, 0x10b2, 0x0000 }, + { 0x0900, 0x10b4, 0x0000 }, + { 0x8900, 0x10bd, 0x4000 }, + { 0x8900, 0x10b9, 0x3000 }, + { 0x8900, 0x10b7, 0x2000 }, + { 0x0900, 0x10b6, 0x0000 }, + { 0x0900, 0x10b8, 0x0000 }, + { 0x8900, 0x10bb, 0x2000 }, + { 0x0900, 0x10ba, 0x0000 }, + { 0x0900, 0x10bc, 0x0000 }, + { 0x8900, 0x10c1, 0x3000 }, + { 0x8900, 0x10bf, 0x2000 }, + { 0x0900, 0x10be, 0x0000 }, + { 0x0900, 0x10c0, 0x0000 }, + { 0x8900, 0x10c3, 0x2000 }, + { 0x0900, 0x10c2, 0x0000 }, + { 0x0900, 0x10c4, 0x0000 }, + { 0x8700, 0x10df, 0x5000 }, + { 0x8700, 0x10d7, 0x4000 }, + { 0x8700, 0x10d3, 0x3000 }, + { 0x8700, 0x10d1, 0x2000 }, + { 0x0700, 0x10d0, 0x0000 }, + { 0x0700, 0x10d2, 0x0000 }, + { 0x8700, 0x10d5, 0x2000 }, + { 0x0700, 0x10d4, 0x0000 }, + { 0x0700, 0x10d6, 0x0000 }, + { 0x8700, 0x10db, 0x3000 }, + { 0x8700, 0x10d9, 0x2000 }, + { 0x0700, 0x10d8, 0x0000 }, + { 0x0700, 0x10da, 0x0000 }, + { 0x8700, 0x10dd, 0x2000 }, + { 0x0700, 0x10dc, 0x0000 }, + { 0x0700, 0x10de, 0x0000 }, + { 0x8700, 0x10e7, 0x4000 }, + { 0x8700, 0x10e3, 0x3000 }, + { 0x8700, 0x10e1, 0x2000 }, + { 0x0700, 0x10e0, 0x0000 }, + { 0x0700, 0x10e2, 0x0000 }, + { 0x8700, 0x10e5, 0x2000 }, + { 0x0700, 0x10e4, 0x0000 }, + { 0x0700, 0x10e6, 0x0000 }, + { 0x8700, 0x10eb, 0x3000 }, + { 0x8700, 0x10e9, 0x2000 }, + { 0x0700, 0x10e8, 0x0000 }, + { 0x0700, 0x10ea, 0x0000 }, + { 0x8700, 0x10ed, 0x2000 }, + { 0x0700, 0x10ec, 0x0000 }, + { 0x0700, 0x10ee, 0x0000 }, + { 0x8700, 0x1322, 0xa000 }, + { 0x8700, 0x1205, 0x9000 }, + { 0x8700, 0x117a, 0x8000 }, + { 0x8700, 0x1135, 0x7000 }, + { 0x8700, 0x1115, 0x6000 }, + { 0x8700, 0x1105, 0x5000 }, + { 0x8700, 0x10f7, 0x4000 }, + { 0x8700, 0x10f3, 0x3000 }, + { 0x8700, 0x10f1, 0x2000 }, + { 0x0700, 0x10f0, 0x0000 }, + { 0x0700, 0x10f2, 0x0000 }, + { 0x8700, 0x10f5, 0x2000 }, + { 0x0700, 0x10f4, 0x0000 }, + { 0x0700, 0x10f6, 0x0000 }, + { 0x8700, 0x1101, 0x3000 }, + { 0x9500, 0x10fb, 0x2000 }, + { 0x0700, 0x10f8, 0x0000 }, + { 0x0700, 0x1100, 0x0000 }, + { 0x8700, 0x1103, 0x2000 }, + { 0x0700, 0x1102, 0x0000 }, + { 0x0700, 0x1104, 0x0000 }, + { 0x8700, 0x110d, 0x4000 }, + { 0x8700, 0x1109, 0x3000 }, + { 0x8700, 0x1107, 0x2000 }, + { 0x0700, 0x1106, 0x0000 }, + { 0x0700, 0x1108, 0x0000 }, + { 0x8700, 0x110b, 0x2000 }, + { 0x0700, 0x110a, 0x0000 }, + { 0x0700, 0x110c, 0x0000 }, + { 0x8700, 0x1111, 0x3000 }, + { 0x8700, 0x110f, 0x2000 }, + { 0x0700, 0x110e, 0x0000 }, + { 0x0700, 0x1110, 0x0000 }, + { 0x8700, 0x1113, 0x2000 }, + { 0x0700, 0x1112, 0x0000 }, + { 0x0700, 0x1114, 0x0000 }, + { 0x8700, 0x1125, 0x5000 }, + { 0x8700, 0x111d, 0x4000 }, + { 0x8700, 0x1119, 0x3000 }, + { 0x8700, 0x1117, 0x2000 }, + { 0x0700, 0x1116, 0x0000 }, + { 0x0700, 0x1118, 0x0000 }, + { 0x8700, 0x111b, 0x2000 }, + { 0x0700, 0x111a, 0x0000 }, + { 0x0700, 0x111c, 0x0000 }, + { 0x8700, 0x1121, 0x3000 }, + { 0x8700, 0x111f, 0x2000 }, + { 0x0700, 0x111e, 0x0000 }, + { 0x0700, 0x1120, 0x0000 }, + { 0x8700, 0x1123, 0x2000 }, + { 0x0700, 0x1122, 0x0000 }, + { 0x0700, 0x1124, 0x0000 }, + { 0x8700, 0x112d, 0x4000 }, + { 0x8700, 0x1129, 0x3000 }, + { 0x8700, 0x1127, 0x2000 }, + { 0x0700, 0x1126, 0x0000 }, + { 0x0700, 0x1128, 0x0000 }, + { 0x8700, 0x112b, 0x2000 }, + { 0x0700, 0x112a, 0x0000 }, + { 0x0700, 0x112c, 0x0000 }, + { 0x8700, 0x1131, 0x3000 }, + { 0x8700, 0x112f, 0x2000 }, + { 0x0700, 0x112e, 0x0000 }, + { 0x0700, 0x1130, 0x0000 }, + { 0x8700, 0x1133, 0x2000 }, + { 0x0700, 0x1132, 0x0000 }, + { 0x0700, 0x1134, 0x0000 }, + { 0x8700, 0x1155, 0x6000 }, + { 0x8700, 0x1145, 0x5000 }, + { 0x8700, 0x113d, 0x4000 }, + { 0x8700, 0x1139, 0x3000 }, + { 0x8700, 0x1137, 0x2000 }, + { 0x0700, 0x1136, 0x0000 }, + { 0x0700, 0x1138, 0x0000 }, + { 0x8700, 0x113b, 0x2000 }, + { 0x0700, 0x113a, 0x0000 }, + { 0x0700, 0x113c, 0x0000 }, + { 0x8700, 0x1141, 0x3000 }, + { 0x8700, 0x113f, 0x2000 }, + { 0x0700, 0x113e, 0x0000 }, + { 0x0700, 0x1140, 0x0000 }, + { 0x8700, 0x1143, 0x2000 }, + { 0x0700, 0x1142, 0x0000 }, + { 0x0700, 0x1144, 0x0000 }, + { 0x8700, 0x114d, 0x4000 }, + { 0x8700, 0x1149, 0x3000 }, + { 0x8700, 0x1147, 0x2000 }, + { 0x0700, 0x1146, 0x0000 }, + { 0x0700, 0x1148, 0x0000 }, + { 0x8700, 0x114b, 0x2000 }, + { 0x0700, 0x114a, 0x0000 }, + { 0x0700, 0x114c, 0x0000 }, + { 0x8700, 0x1151, 0x3000 }, + { 0x8700, 0x114f, 0x2000 }, + { 0x0700, 0x114e, 0x0000 }, + { 0x0700, 0x1150, 0x0000 }, + { 0x8700, 0x1153, 0x2000 }, + { 0x0700, 0x1152, 0x0000 }, + { 0x0700, 0x1154, 0x0000 }, + { 0x8700, 0x116a, 0x5000 }, + { 0x8700, 0x1162, 0x4000 }, + { 0x8700, 0x1159, 0x3000 }, + { 0x8700, 0x1157, 0x2000 }, + { 0x0700, 0x1156, 0x0000 }, + { 0x0700, 0x1158, 0x0000 }, + { 0x8700, 0x1160, 0x2000 }, + { 0x0700, 0x115f, 0x0000 }, + { 0x0700, 0x1161, 0x0000 }, + { 0x8700, 0x1166, 0x3000 }, + { 0x8700, 0x1164, 0x2000 }, + { 0x0700, 0x1163, 0x0000 }, + { 0x0700, 0x1165, 0x0000 }, + { 0x8700, 0x1168, 0x2000 }, + { 0x0700, 0x1167, 0x0000 }, + { 0x0700, 0x1169, 0x0000 }, + { 0x8700, 0x1172, 0x4000 }, + { 0x8700, 0x116e, 0x3000 }, + { 0x8700, 0x116c, 0x2000 }, + { 0x0700, 0x116b, 0x0000 }, + { 0x0700, 0x116d, 0x0000 }, + { 0x8700, 0x1170, 0x2000 }, + { 0x0700, 0x116f, 0x0000 }, + { 0x0700, 0x1171, 0x0000 }, + { 0x8700, 0x1176, 0x3000 }, + { 0x8700, 0x1174, 0x2000 }, + { 0x0700, 0x1173, 0x0000 }, + { 0x0700, 0x1175, 0x0000 }, + { 0x8700, 0x1178, 0x2000 }, + { 0x0700, 0x1177, 0x0000 }, + { 0x0700, 0x1179, 0x0000 }, + { 0x8700, 0x11bf, 0x7000 }, + { 0x8700, 0x119a, 0x6000 }, + { 0x8700, 0x118a, 0x5000 }, + { 0x8700, 0x1182, 0x4000 }, + { 0x8700, 0x117e, 0x3000 }, + { 0x8700, 0x117c, 0x2000 }, + { 0x0700, 0x117b, 0x0000 }, + { 0x0700, 0x117d, 0x0000 }, + { 0x8700, 0x1180, 0x2000 }, + { 0x0700, 0x117f, 0x0000 }, + { 0x0700, 0x1181, 0x0000 }, + { 0x8700, 0x1186, 0x3000 }, + { 0x8700, 0x1184, 0x2000 }, + { 0x0700, 0x1183, 0x0000 }, + { 0x0700, 0x1185, 0x0000 }, + { 0x8700, 0x1188, 0x2000 }, + { 0x0700, 0x1187, 0x0000 }, + { 0x0700, 0x1189, 0x0000 }, + { 0x8700, 0x1192, 0x4000 }, + { 0x8700, 0x118e, 0x3000 }, + { 0x8700, 0x118c, 0x2000 }, + { 0x0700, 0x118b, 0x0000 }, + { 0x0700, 0x118d, 0x0000 }, + { 0x8700, 0x1190, 0x2000 }, + { 0x0700, 0x118f, 0x0000 }, + { 0x0700, 0x1191, 0x0000 }, + { 0x8700, 0x1196, 0x3000 }, + { 0x8700, 0x1194, 0x2000 }, + { 0x0700, 0x1193, 0x0000 }, + { 0x0700, 0x1195, 0x0000 }, + { 0x8700, 0x1198, 0x2000 }, + { 0x0700, 0x1197, 0x0000 }, + { 0x0700, 0x1199, 0x0000 }, + { 0x8700, 0x11af, 0x5000 }, + { 0x8700, 0x11a2, 0x4000 }, + { 0x8700, 0x119e, 0x3000 }, + { 0x8700, 0x119c, 0x2000 }, + { 0x0700, 0x119b, 0x0000 }, + { 0x0700, 0x119d, 0x0000 }, + { 0x8700, 0x11a0, 0x2000 }, + { 0x0700, 0x119f, 0x0000 }, + { 0x0700, 0x11a1, 0x0000 }, + { 0x8700, 0x11ab, 0x3000 }, + { 0x8700, 0x11a9, 0x2000 }, + { 0x0700, 0x11a8, 0x0000 }, + { 0x0700, 0x11aa, 0x0000 }, + { 0x8700, 0x11ad, 0x2000 }, + { 0x0700, 0x11ac, 0x0000 }, + { 0x0700, 0x11ae, 0x0000 }, + { 0x8700, 0x11b7, 0x4000 }, + { 0x8700, 0x11b3, 0x3000 }, + { 0x8700, 0x11b1, 0x2000 }, + { 0x0700, 0x11b0, 0x0000 }, + { 0x0700, 0x11b2, 0x0000 }, + { 0x8700, 0x11b5, 0x2000 }, + { 0x0700, 0x11b4, 0x0000 }, + { 0x0700, 0x11b6, 0x0000 }, + { 0x8700, 0x11bb, 0x3000 }, + { 0x8700, 0x11b9, 0x2000 }, + { 0x0700, 0x11b8, 0x0000 }, + { 0x0700, 0x11ba, 0x0000 }, + { 0x8700, 0x11bd, 0x2000 }, + { 0x0700, 0x11bc, 0x0000 }, + { 0x0700, 0x11be, 0x0000 }, + { 0x8700, 0x11df, 0x6000 }, + { 0x8700, 0x11cf, 0x5000 }, + { 0x8700, 0x11c7, 0x4000 }, + { 0x8700, 0x11c3, 0x3000 }, + { 0x8700, 0x11c1, 0x2000 }, + { 0x0700, 0x11c0, 0x0000 }, + { 0x0700, 0x11c2, 0x0000 }, + { 0x8700, 0x11c5, 0x2000 }, + { 0x0700, 0x11c4, 0x0000 }, + { 0x0700, 0x11c6, 0x0000 }, + { 0x8700, 0x11cb, 0x3000 }, + { 0x8700, 0x11c9, 0x2000 }, + { 0x0700, 0x11c8, 0x0000 }, + { 0x0700, 0x11ca, 0x0000 }, + { 0x8700, 0x11cd, 0x2000 }, + { 0x0700, 0x11cc, 0x0000 }, + { 0x0700, 0x11ce, 0x0000 }, + { 0x8700, 0x11d7, 0x4000 }, + { 0x8700, 0x11d3, 0x3000 }, + { 0x8700, 0x11d1, 0x2000 }, + { 0x0700, 0x11d0, 0x0000 }, + { 0x0700, 0x11d2, 0x0000 }, + { 0x8700, 0x11d5, 0x2000 }, + { 0x0700, 0x11d4, 0x0000 }, + { 0x0700, 0x11d6, 0x0000 }, + { 0x8700, 0x11db, 0x3000 }, + { 0x8700, 0x11d9, 0x2000 }, + { 0x0700, 0x11d8, 0x0000 }, + { 0x0700, 0x11da, 0x0000 }, + { 0x8700, 0x11dd, 0x2000 }, + { 0x0700, 0x11dc, 0x0000 }, + { 0x0700, 0x11de, 0x0000 }, + { 0x8700, 0x11ef, 0x5000 }, + { 0x8700, 0x11e7, 0x4000 }, + { 0x8700, 0x11e3, 0x3000 }, + { 0x8700, 0x11e1, 0x2000 }, + { 0x0700, 0x11e0, 0x0000 }, + { 0x0700, 0x11e2, 0x0000 }, + { 0x8700, 0x11e5, 0x2000 }, + { 0x0700, 0x11e4, 0x0000 }, + { 0x0700, 0x11e6, 0x0000 }, + { 0x8700, 0x11eb, 0x3000 }, + { 0x8700, 0x11e9, 0x2000 }, + { 0x0700, 0x11e8, 0x0000 }, + { 0x0700, 0x11ea, 0x0000 }, + { 0x8700, 0x11ed, 0x2000 }, + { 0x0700, 0x11ec, 0x0000 }, + { 0x0700, 0x11ee, 0x0000 }, + { 0x8700, 0x11f7, 0x4000 }, + { 0x8700, 0x11f3, 0x3000 }, + { 0x8700, 0x11f1, 0x2000 }, + { 0x0700, 0x11f0, 0x0000 }, + { 0x0700, 0x11f2, 0x0000 }, + { 0x8700, 0x11f5, 0x2000 }, + { 0x0700, 0x11f4, 0x0000 }, + { 0x0700, 0x11f6, 0x0000 }, + { 0x8700, 0x1201, 0x3000 }, + { 0x8700, 0x11f9, 0x2000 }, + { 0x0700, 0x11f8, 0x0000 }, + { 0x0700, 0x1200, 0x0000 }, + { 0x8700, 0x1203, 0x2000 }, + { 0x0700, 0x1202, 0x0000 }, + { 0x0700, 0x1204, 0x0000 }, + { 0x8700, 0x1292, 0x8000 }, + { 0x8700, 0x1246, 0x7000 }, + { 0x8700, 0x1226, 0x6000 }, + { 0x8700, 0x1216, 0x5000 }, + { 0x8700, 0x120e, 0x4000 }, + { 0x8700, 0x120a, 0x3000 }, + { 0x8700, 0x1208, 0x2000 }, + { 0x0700, 0x1206, 0x0000 }, + { 0x0700, 0x1209, 0x0000 }, + { 0x8700, 0x120c, 0x2000 }, + { 0x0700, 0x120b, 0x0000 }, + { 0x0700, 0x120d, 0x0000 }, + { 0x8700, 0x1212, 0x3000 }, + { 0x8700, 0x1210, 0x2000 }, + { 0x0700, 0x120f, 0x0000 }, + { 0x0700, 0x1211, 0x0000 }, + { 0x8700, 0x1214, 0x2000 }, + { 0x0700, 0x1213, 0x0000 }, + { 0x0700, 0x1215, 0x0000 }, + { 0x8700, 0x121e, 0x4000 }, + { 0x8700, 0x121a, 0x3000 }, + { 0x8700, 0x1218, 0x2000 }, + { 0x0700, 0x1217, 0x0000 }, + { 0x0700, 0x1219, 0x0000 }, + { 0x8700, 0x121c, 0x2000 }, + { 0x0700, 0x121b, 0x0000 }, + { 0x0700, 0x121d, 0x0000 }, + { 0x8700, 0x1222, 0x3000 }, + { 0x8700, 0x1220, 0x2000 }, + { 0x0700, 0x121f, 0x0000 }, + { 0x0700, 0x1221, 0x0000 }, + { 0x8700, 0x1224, 0x2000 }, + { 0x0700, 0x1223, 0x0000 }, + { 0x0700, 0x1225, 0x0000 }, + { 0x8700, 0x1236, 0x5000 }, + { 0x8700, 0x122e, 0x4000 }, + { 0x8700, 0x122a, 0x3000 }, + { 0x8700, 0x1228, 0x2000 }, + { 0x0700, 0x1227, 0x0000 }, + { 0x0700, 0x1229, 0x0000 }, + { 0x8700, 0x122c, 0x2000 }, + { 0x0700, 0x122b, 0x0000 }, + { 0x0700, 0x122d, 0x0000 }, + { 0x8700, 0x1232, 0x3000 }, + { 0x8700, 0x1230, 0x2000 }, + { 0x0700, 0x122f, 0x0000 }, + { 0x0700, 0x1231, 0x0000 }, + { 0x8700, 0x1234, 0x2000 }, + { 0x0700, 0x1233, 0x0000 }, + { 0x0700, 0x1235, 0x0000 }, + { 0x8700, 0x123e, 0x4000 }, + { 0x8700, 0x123a, 0x3000 }, + { 0x8700, 0x1238, 0x2000 }, + { 0x0700, 0x1237, 0x0000 }, + { 0x0700, 0x1239, 0x0000 }, + { 0x8700, 0x123c, 0x2000 }, + { 0x0700, 0x123b, 0x0000 }, + { 0x0700, 0x123d, 0x0000 }, + { 0x8700, 0x1242, 0x3000 }, + { 0x8700, 0x1240, 0x2000 }, + { 0x0700, 0x123f, 0x0000 }, + { 0x0700, 0x1241, 0x0000 }, + { 0x8700, 0x1244, 0x2000 }, + { 0x0700, 0x1243, 0x0000 }, + { 0x0700, 0x1245, 0x0000 }, + { 0x8700, 0x126e, 0x6000 }, + { 0x8700, 0x125c, 0x5000 }, + { 0x8700, 0x1252, 0x4000 }, + { 0x8700, 0x124c, 0x3000 }, + { 0x8700, 0x124a, 0x2000 }, + { 0x0700, 0x1248, 0x0000 }, + { 0x0700, 0x124b, 0x0000 }, + { 0x8700, 0x1250, 0x2000 }, + { 0x0700, 0x124d, 0x0000 }, + { 0x0700, 0x1251, 0x0000 }, + { 0x8700, 0x1256, 0x3000 }, + { 0x8700, 0x1254, 0x2000 }, + { 0x0700, 0x1253, 0x0000 }, + { 0x0700, 0x1255, 0x0000 }, + { 0x8700, 0x125a, 0x2000 }, + { 0x0700, 0x1258, 0x0000 }, + { 0x0700, 0x125b, 0x0000 }, + { 0x8700, 0x1266, 0x4000 }, + { 0x8700, 0x1262, 0x3000 }, + { 0x8700, 0x1260, 0x2000 }, + { 0x0700, 0x125d, 0x0000 }, + { 0x0700, 0x1261, 0x0000 }, + { 0x8700, 0x1264, 0x2000 }, + { 0x0700, 0x1263, 0x0000 }, + { 0x0700, 0x1265, 0x0000 }, + { 0x8700, 0x126a, 0x3000 }, + { 0x8700, 0x1268, 0x2000 }, + { 0x0700, 0x1267, 0x0000 }, + { 0x0700, 0x1269, 0x0000 }, + { 0x8700, 0x126c, 0x2000 }, + { 0x0700, 0x126b, 0x0000 }, + { 0x0700, 0x126d, 0x0000 }, + { 0x8700, 0x127e, 0x5000 }, + { 0x8700, 0x1276, 0x4000 }, + { 0x8700, 0x1272, 0x3000 }, + { 0x8700, 0x1270, 0x2000 }, + { 0x0700, 0x126f, 0x0000 }, + { 0x0700, 0x1271, 0x0000 }, + { 0x8700, 0x1274, 0x2000 }, + { 0x0700, 0x1273, 0x0000 }, + { 0x0700, 0x1275, 0x0000 }, + { 0x8700, 0x127a, 0x3000 }, + { 0x8700, 0x1278, 0x2000 }, + { 0x0700, 0x1277, 0x0000 }, + { 0x0700, 0x1279, 0x0000 }, + { 0x8700, 0x127c, 0x2000 }, + { 0x0700, 0x127b, 0x0000 }, + { 0x0700, 0x127d, 0x0000 }, + { 0x8700, 0x1286, 0x4000 }, + { 0x8700, 0x1282, 0x3000 }, + { 0x8700, 0x1280, 0x2000 }, + { 0x0700, 0x127f, 0x0000 }, + { 0x0700, 0x1281, 0x0000 }, + { 0x8700, 0x1284, 0x2000 }, + { 0x0700, 0x1283, 0x0000 }, + { 0x0700, 0x1285, 0x0000 }, + { 0x8700, 0x128c, 0x3000 }, + { 0x8700, 0x128a, 0x2000 }, + { 0x0700, 0x1288, 0x0000 }, + { 0x0700, 0x128b, 0x0000 }, + { 0x8700, 0x1290, 0x2000 }, + { 0x0700, 0x128d, 0x0000 }, + { 0x0700, 0x1291, 0x0000 }, + { 0x8700, 0x12dc, 0x7000 }, + { 0x8700, 0x12b4, 0x6000 }, + { 0x8700, 0x12a2, 0x5000 }, + { 0x8700, 0x129a, 0x4000 }, + { 0x8700, 0x1296, 0x3000 }, + { 0x8700, 0x1294, 0x2000 }, + { 0x0700, 0x1293, 0x0000 }, + { 0x0700, 0x1295, 0x0000 }, + { 0x8700, 0x1298, 0x2000 }, + { 0x0700, 0x1297, 0x0000 }, + { 0x0700, 0x1299, 0x0000 }, + { 0x8700, 0x129e, 0x3000 }, + { 0x8700, 0x129c, 0x2000 }, + { 0x0700, 0x129b, 0x0000 }, + { 0x0700, 0x129d, 0x0000 }, + { 0x8700, 0x12a0, 0x2000 }, + { 0x0700, 0x129f, 0x0000 }, + { 0x0700, 0x12a1, 0x0000 }, + { 0x8700, 0x12aa, 0x4000 }, + { 0x8700, 0x12a6, 0x3000 }, + { 0x8700, 0x12a4, 0x2000 }, + { 0x0700, 0x12a3, 0x0000 }, + { 0x0700, 0x12a5, 0x0000 }, + { 0x8700, 0x12a8, 0x2000 }, + { 0x0700, 0x12a7, 0x0000 }, + { 0x0700, 0x12a9, 0x0000 }, + { 0x8700, 0x12ae, 0x3000 }, + { 0x8700, 0x12ac, 0x2000 }, + { 0x0700, 0x12ab, 0x0000 }, + { 0x0700, 0x12ad, 0x0000 }, + { 0x8700, 0x12b2, 0x2000 }, + { 0x0700, 0x12b0, 0x0000 }, + { 0x0700, 0x12b3, 0x0000 }, + { 0x8700, 0x12ca, 0x5000 }, + { 0x8700, 0x12be, 0x4000 }, + { 0x8700, 0x12ba, 0x3000 }, + { 0x8700, 0x12b8, 0x2000 }, + { 0x0700, 0x12b5, 0x0000 }, + { 0x0700, 0x12b9, 0x0000 }, + { 0x8700, 0x12bc, 0x2000 }, + { 0x0700, 0x12bb, 0x0000 }, + { 0x0700, 0x12bd, 0x0000 }, + { 0x8700, 0x12c4, 0x3000 }, + { 0x8700, 0x12c2, 0x2000 }, + { 0x0700, 0x12c0, 0x0000 }, + { 0x0700, 0x12c3, 0x0000 }, + { 0x8700, 0x12c8, 0x2000 }, + { 0x0700, 0x12c5, 0x0000 }, + { 0x0700, 0x12c9, 0x0000 }, + { 0x8700, 0x12d3, 0x4000 }, + { 0x8700, 0x12ce, 0x3000 }, + { 0x8700, 0x12cc, 0x2000 }, + { 0x0700, 0x12cb, 0x0000 }, + { 0x0700, 0x12cd, 0x0000 }, + { 0x8700, 0x12d1, 0x2000 }, + { 0x0700, 0x12d0, 0x0000 }, + { 0x0700, 0x12d2, 0x0000 }, + { 0x8700, 0x12d8, 0x3000 }, + { 0x8700, 0x12d5, 0x2000 }, + { 0x0700, 0x12d4, 0x0000 }, + { 0x0700, 0x12d6, 0x0000 }, + { 0x8700, 0x12da, 0x2000 }, + { 0x0700, 0x12d9, 0x0000 }, + { 0x0700, 0x12db, 0x0000 }, + { 0x8700, 0x12fd, 0x6000 }, + { 0x8700, 0x12ec, 0x5000 }, + { 0x8700, 0x12e4, 0x4000 }, + { 0x8700, 0x12e0, 0x3000 }, + { 0x8700, 0x12de, 0x2000 }, + { 0x0700, 0x12dd, 0x0000 }, + { 0x0700, 0x12df, 0x0000 }, + { 0x8700, 0x12e2, 0x2000 }, + { 0x0700, 0x12e1, 0x0000 }, + { 0x0700, 0x12e3, 0x0000 }, + { 0x8700, 0x12e8, 0x3000 }, + { 0x8700, 0x12e6, 0x2000 }, + { 0x0700, 0x12e5, 0x0000 }, + { 0x0700, 0x12e7, 0x0000 }, + { 0x8700, 0x12ea, 0x2000 }, + { 0x0700, 0x12e9, 0x0000 }, + { 0x0700, 0x12eb, 0x0000 }, + { 0x8700, 0x12f5, 0x4000 }, + { 0x8700, 0x12f1, 0x3000 }, + { 0x8700, 0x12ee, 0x2000 }, + { 0x0700, 0x12ed, 0x0000 }, + { 0x0700, 0x12f0, 0x0000 }, + { 0x8700, 0x12f3, 0x2000 }, + { 0x0700, 0x12f2, 0x0000 }, + { 0x0700, 0x12f4, 0x0000 }, + { 0x8700, 0x12f9, 0x3000 }, + { 0x8700, 0x12f7, 0x2000 }, + { 0x0700, 0x12f6, 0x0000 }, + { 0x0700, 0x12f8, 0x0000 }, + { 0x8700, 0x12fb, 0x2000 }, + { 0x0700, 0x12fa, 0x0000 }, + { 0x0700, 0x12fc, 0x0000 }, + { 0x8700, 0x130d, 0x5000 }, + { 0x8700, 0x1305, 0x4000 }, + { 0x8700, 0x1301, 0x3000 }, + { 0x8700, 0x12ff, 0x2000 }, + { 0x0700, 0x12fe, 0x0000 }, + { 0x0700, 0x1300, 0x0000 }, + { 0x8700, 0x1303, 0x2000 }, + { 0x0700, 0x1302, 0x0000 }, + { 0x0700, 0x1304, 0x0000 }, + { 0x8700, 0x1309, 0x3000 }, + { 0x8700, 0x1307, 0x2000 }, + { 0x0700, 0x1306, 0x0000 }, + { 0x0700, 0x1308, 0x0000 }, + { 0x8700, 0x130b, 0x2000 }, + { 0x0700, 0x130a, 0x0000 }, + { 0x0700, 0x130c, 0x0000 }, + { 0x8700, 0x1319, 0x4000 }, + { 0x8700, 0x1313, 0x3000 }, + { 0x8700, 0x1310, 0x2000 }, + { 0x0700, 0x130e, 0x0000 }, + { 0x0700, 0x1312, 0x0000 }, + { 0x8700, 0x1315, 0x2000 }, + { 0x0700, 0x1314, 0x0000 }, + { 0x0700, 0x1318, 0x0000 }, + { 0x8700, 0x131d, 0x3000 }, + { 0x8700, 0x131b, 0x2000 }, + { 0x0700, 0x131a, 0x0000 }, + { 0x0700, 0x131c, 0x0000 }, + { 0x8700, 0x1320, 0x2000 }, + { 0x0700, 0x131e, 0x0000 }, + { 0x0700, 0x1321, 0x0000 }, + { 0x8700, 0x1458, 0x9000 }, + { 0x8700, 0x13cc, 0x8000 }, + { 0x8d00, 0x1369, 0x7000 }, + { 0x8700, 0x1342, 0x6000 }, + { 0x8700, 0x1332, 0x5000 }, + { 0x8700, 0x132a, 0x4000 }, + { 0x8700, 0x1326, 0x3000 }, + { 0x8700, 0x1324, 0x2000 }, + { 0x0700, 0x1323, 0x0000 }, + { 0x0700, 0x1325, 0x0000 }, + { 0x8700, 0x1328, 0x2000 }, + { 0x0700, 0x1327, 0x0000 }, + { 0x0700, 0x1329, 0x0000 }, + { 0x8700, 0x132e, 0x3000 }, + { 0x8700, 0x132c, 0x2000 }, + { 0x0700, 0x132b, 0x0000 }, + { 0x0700, 0x132d, 0x0000 }, + { 0x8700, 0x1330, 0x2000 }, + { 0x0700, 0x132f, 0x0000 }, + { 0x0700, 0x1331, 0x0000 }, + { 0x8700, 0x133a, 0x4000 }, + { 0x8700, 0x1336, 0x3000 }, + { 0x8700, 0x1334, 0x2000 }, + { 0x0700, 0x1333, 0x0000 }, + { 0x0700, 0x1335, 0x0000 }, + { 0x8700, 0x1338, 0x2000 }, + { 0x0700, 0x1337, 0x0000 }, + { 0x0700, 0x1339, 0x0000 }, + { 0x8700, 0x133e, 0x3000 }, + { 0x8700, 0x133c, 0x2000 }, + { 0x0700, 0x133b, 0x0000 }, + { 0x0700, 0x133d, 0x0000 }, + { 0x8700, 0x1340, 0x2000 }, + { 0x0700, 0x133f, 0x0000 }, + { 0x0700, 0x1341, 0x0000 }, + { 0x8700, 0x1353, 0x5000 }, + { 0x8700, 0x134b, 0x4000 }, + { 0x8700, 0x1346, 0x3000 }, + { 0x8700, 0x1344, 0x2000 }, + { 0x0700, 0x1343, 0x0000 }, + { 0x0700, 0x1345, 0x0000 }, + { 0x8700, 0x1349, 0x2000 }, + { 0x0700, 0x1348, 0x0000 }, + { 0x0700, 0x134a, 0x0000 }, + { 0x8700, 0x134f, 0x3000 }, + { 0x8700, 0x134d, 0x2000 }, + { 0x0700, 0x134c, 0x0000 }, + { 0x0700, 0x134e, 0x0000 }, + { 0x8700, 0x1351, 0x2000 }, + { 0x0700, 0x1350, 0x0000 }, + { 0x0700, 0x1352, 0x0000 }, + { 0x9500, 0x1361, 0x4000 }, + { 0x8700, 0x1357, 0x3000 }, + { 0x8700, 0x1355, 0x2000 }, + { 0x0700, 0x1354, 0x0000 }, + { 0x0700, 0x1356, 0x0000 }, + { 0x8700, 0x1359, 0x2000 }, + { 0x0700, 0x1358, 0x0000 }, + { 0x0700, 0x135a, 0x0000 }, + { 0x9500, 0x1365, 0x3000 }, + { 0x9500, 0x1363, 0x2000 }, + { 0x1500, 0x1362, 0x0000 }, + { 0x1500, 0x1364, 0x0000 }, + { 0x9500, 0x1367, 0x2000 }, + { 0x1500, 0x1366, 0x0000 }, + { 0x1500, 0x1368, 0x0000 }, + { 0x8700, 0x13ac, 0x6000 }, + { 0x8f00, 0x1379, 0x5000 }, + { 0x8d00, 0x1371, 0x4000 }, + { 0x8d00, 0x136d, 0x3000 }, + { 0x8d00, 0x136b, 0x2000 }, + { 0x0d00, 0x136a, 0x0000 }, + { 0x0d00, 0x136c, 0x0000 }, + { 0x8d00, 0x136f, 0x2000 }, + { 0x0d00, 0x136e, 0x0000 }, + { 0x0d00, 0x1370, 0x0000 }, + { 0x8f00, 0x1375, 0x3000 }, + { 0x8f00, 0x1373, 0x2000 }, + { 0x0f00, 0x1372, 0x0000 }, + { 0x0f00, 0x1374, 0x0000 }, + { 0x8f00, 0x1377, 0x2000 }, + { 0x0f00, 0x1376, 0x0000 }, + { 0x0f00, 0x1378, 0x0000 }, + { 0x8700, 0x13a4, 0x4000 }, + { 0x8700, 0x13a0, 0x3000 }, + { 0x8f00, 0x137b, 0x2000 }, + { 0x0f00, 0x137a, 0x0000 }, + { 0x0f00, 0x137c, 0x0000 }, + { 0x8700, 0x13a2, 0x2000 }, + { 0x0700, 0x13a1, 0x0000 }, + { 0x0700, 0x13a3, 0x0000 }, + { 0x8700, 0x13a8, 0x3000 }, + { 0x8700, 0x13a6, 0x2000 }, + { 0x0700, 0x13a5, 0x0000 }, + { 0x0700, 0x13a7, 0x0000 }, + { 0x8700, 0x13aa, 0x2000 }, + { 0x0700, 0x13a9, 0x0000 }, + { 0x0700, 0x13ab, 0x0000 }, + { 0x8700, 0x13bc, 0x5000 }, + { 0x8700, 0x13b4, 0x4000 }, + { 0x8700, 0x13b0, 0x3000 }, + { 0x8700, 0x13ae, 0x2000 }, + { 0x0700, 0x13ad, 0x0000 }, + { 0x0700, 0x13af, 0x0000 }, + { 0x8700, 0x13b2, 0x2000 }, + { 0x0700, 0x13b1, 0x0000 }, + { 0x0700, 0x13b3, 0x0000 }, + { 0x8700, 0x13b8, 0x3000 }, + { 0x8700, 0x13b6, 0x2000 }, + { 0x0700, 0x13b5, 0x0000 }, + { 0x0700, 0x13b7, 0x0000 }, + { 0x8700, 0x13ba, 0x2000 }, + { 0x0700, 0x13b9, 0x0000 }, + { 0x0700, 0x13bb, 0x0000 }, + { 0x8700, 0x13c4, 0x4000 }, + { 0x8700, 0x13c0, 0x3000 }, + { 0x8700, 0x13be, 0x2000 }, + { 0x0700, 0x13bd, 0x0000 }, + { 0x0700, 0x13bf, 0x0000 }, + { 0x8700, 0x13c2, 0x2000 }, + { 0x0700, 0x13c1, 0x0000 }, + { 0x0700, 0x13c3, 0x0000 }, + { 0x8700, 0x13c8, 0x3000 }, + { 0x8700, 0x13c6, 0x2000 }, + { 0x0700, 0x13c5, 0x0000 }, + { 0x0700, 0x13c7, 0x0000 }, + { 0x8700, 0x13ca, 0x2000 }, + { 0x0700, 0x13c9, 0x0000 }, + { 0x0700, 0x13cb, 0x0000 }, + { 0x8700, 0x1418, 0x7000 }, + { 0x8700, 0x13ec, 0x6000 }, + { 0x8700, 0x13dc, 0x5000 }, + { 0x8700, 0x13d4, 0x4000 }, + { 0x8700, 0x13d0, 0x3000 }, + { 0x8700, 0x13ce, 0x2000 }, + { 0x0700, 0x13cd, 0x0000 }, + { 0x0700, 0x13cf, 0x0000 }, + { 0x8700, 0x13d2, 0x2000 }, + { 0x0700, 0x13d1, 0x0000 }, + { 0x0700, 0x13d3, 0x0000 }, + { 0x8700, 0x13d8, 0x3000 }, + { 0x8700, 0x13d6, 0x2000 }, + { 0x0700, 0x13d5, 0x0000 }, + { 0x0700, 0x13d7, 0x0000 }, + { 0x8700, 0x13da, 0x2000 }, + { 0x0700, 0x13d9, 0x0000 }, + { 0x0700, 0x13db, 0x0000 }, + { 0x8700, 0x13e4, 0x4000 }, + { 0x8700, 0x13e0, 0x3000 }, + { 0x8700, 0x13de, 0x2000 }, + { 0x0700, 0x13dd, 0x0000 }, + { 0x0700, 0x13df, 0x0000 }, + { 0x8700, 0x13e2, 0x2000 }, + { 0x0700, 0x13e1, 0x0000 }, + { 0x0700, 0x13e3, 0x0000 }, + { 0x8700, 0x13e8, 0x3000 }, + { 0x8700, 0x13e6, 0x2000 }, + { 0x0700, 0x13e5, 0x0000 }, + { 0x0700, 0x13e7, 0x0000 }, + { 0x8700, 0x13ea, 0x2000 }, + { 0x0700, 0x13e9, 0x0000 }, + { 0x0700, 0x13eb, 0x0000 }, + { 0x8700, 0x1408, 0x5000 }, + { 0x8700, 0x13f4, 0x4000 }, + { 0x8700, 0x13f0, 0x3000 }, + { 0x8700, 0x13ee, 0x2000 }, + { 0x0700, 0x13ed, 0x0000 }, + { 0x0700, 0x13ef, 0x0000 }, + { 0x8700, 0x13f2, 0x2000 }, + { 0x0700, 0x13f1, 0x0000 }, + { 0x0700, 0x13f3, 0x0000 }, + { 0x8700, 0x1404, 0x3000 }, + { 0x8700, 0x1402, 0x2000 }, + { 0x0700, 0x1401, 0x0000 }, + { 0x0700, 0x1403, 0x0000 }, + { 0x8700, 0x1406, 0x2000 }, + { 0x0700, 0x1405, 0x0000 }, + { 0x0700, 0x1407, 0x0000 }, + { 0x8700, 0x1410, 0x4000 }, + { 0x8700, 0x140c, 0x3000 }, + { 0x8700, 0x140a, 0x2000 }, + { 0x0700, 0x1409, 0x0000 }, + { 0x0700, 0x140b, 0x0000 }, + { 0x8700, 0x140e, 0x2000 }, + { 0x0700, 0x140d, 0x0000 }, + { 0x0700, 0x140f, 0x0000 }, + { 0x8700, 0x1414, 0x3000 }, + { 0x8700, 0x1412, 0x2000 }, + { 0x0700, 0x1411, 0x0000 }, + { 0x0700, 0x1413, 0x0000 }, + { 0x8700, 0x1416, 0x2000 }, + { 0x0700, 0x1415, 0x0000 }, + { 0x0700, 0x1417, 0x0000 }, + { 0x8700, 0x1438, 0x6000 }, + { 0x8700, 0x1428, 0x5000 }, + { 0x8700, 0x1420, 0x4000 }, + { 0x8700, 0x141c, 0x3000 }, + { 0x8700, 0x141a, 0x2000 }, + { 0x0700, 0x1419, 0x0000 }, + { 0x0700, 0x141b, 0x0000 }, + { 0x8700, 0x141e, 0x2000 }, + { 0x0700, 0x141d, 0x0000 }, + { 0x0700, 0x141f, 0x0000 }, + { 0x8700, 0x1424, 0x3000 }, + { 0x8700, 0x1422, 0x2000 }, + { 0x0700, 0x1421, 0x0000 }, + { 0x0700, 0x1423, 0x0000 }, + { 0x8700, 0x1426, 0x2000 }, + { 0x0700, 0x1425, 0x0000 }, + { 0x0700, 0x1427, 0x0000 }, + { 0x8700, 0x1430, 0x4000 }, + { 0x8700, 0x142c, 0x3000 }, + { 0x8700, 0x142a, 0x2000 }, + { 0x0700, 0x1429, 0x0000 }, + { 0x0700, 0x142b, 0x0000 }, + { 0x8700, 0x142e, 0x2000 }, + { 0x0700, 0x142d, 0x0000 }, + { 0x0700, 0x142f, 0x0000 }, + { 0x8700, 0x1434, 0x3000 }, + { 0x8700, 0x1432, 0x2000 }, + { 0x0700, 0x1431, 0x0000 }, + { 0x0700, 0x1433, 0x0000 }, + { 0x8700, 0x1436, 0x2000 }, + { 0x0700, 0x1435, 0x0000 }, + { 0x0700, 0x1437, 0x0000 }, + { 0x8700, 0x1448, 0x5000 }, + { 0x8700, 0x1440, 0x4000 }, + { 0x8700, 0x143c, 0x3000 }, + { 0x8700, 0x143a, 0x2000 }, + { 0x0700, 0x1439, 0x0000 }, + { 0x0700, 0x143b, 0x0000 }, + { 0x8700, 0x143e, 0x2000 }, + { 0x0700, 0x143d, 0x0000 }, + { 0x0700, 0x143f, 0x0000 }, + { 0x8700, 0x1444, 0x3000 }, + { 0x8700, 0x1442, 0x2000 }, + { 0x0700, 0x1441, 0x0000 }, + { 0x0700, 0x1443, 0x0000 }, + { 0x8700, 0x1446, 0x2000 }, + { 0x0700, 0x1445, 0x0000 }, + { 0x0700, 0x1447, 0x0000 }, + { 0x8700, 0x1450, 0x4000 }, + { 0x8700, 0x144c, 0x3000 }, + { 0x8700, 0x144a, 0x2000 }, + { 0x0700, 0x1449, 0x0000 }, + { 0x0700, 0x144b, 0x0000 }, + { 0x8700, 0x144e, 0x2000 }, + { 0x0700, 0x144d, 0x0000 }, + { 0x0700, 0x144f, 0x0000 }, + { 0x8700, 0x1454, 0x3000 }, + { 0x8700, 0x1452, 0x2000 }, + { 0x0700, 0x1451, 0x0000 }, + { 0x0700, 0x1453, 0x0000 }, + { 0x8700, 0x1456, 0x2000 }, + { 0x0700, 0x1455, 0x0000 }, + { 0x0700, 0x1457, 0x0000 }, + { 0x8700, 0x14d8, 0x8000 }, + { 0x8700, 0x1498, 0x7000 }, + { 0x8700, 0x1478, 0x6000 }, + { 0x8700, 0x1468, 0x5000 }, + { 0x8700, 0x1460, 0x4000 }, + { 0x8700, 0x145c, 0x3000 }, + { 0x8700, 0x145a, 0x2000 }, + { 0x0700, 0x1459, 0x0000 }, + { 0x0700, 0x145b, 0x0000 }, + { 0x8700, 0x145e, 0x2000 }, + { 0x0700, 0x145d, 0x0000 }, + { 0x0700, 0x145f, 0x0000 }, + { 0x8700, 0x1464, 0x3000 }, + { 0x8700, 0x1462, 0x2000 }, + { 0x0700, 0x1461, 0x0000 }, + { 0x0700, 0x1463, 0x0000 }, + { 0x8700, 0x1466, 0x2000 }, + { 0x0700, 0x1465, 0x0000 }, + { 0x0700, 0x1467, 0x0000 }, + { 0x8700, 0x1470, 0x4000 }, + { 0x8700, 0x146c, 0x3000 }, + { 0x8700, 0x146a, 0x2000 }, + { 0x0700, 0x1469, 0x0000 }, + { 0x0700, 0x146b, 0x0000 }, + { 0x8700, 0x146e, 0x2000 }, + { 0x0700, 0x146d, 0x0000 }, + { 0x0700, 0x146f, 0x0000 }, + { 0x8700, 0x1474, 0x3000 }, + { 0x8700, 0x1472, 0x2000 }, + { 0x0700, 0x1471, 0x0000 }, + { 0x0700, 0x1473, 0x0000 }, + { 0x8700, 0x1476, 0x2000 }, + { 0x0700, 0x1475, 0x0000 }, + { 0x0700, 0x1477, 0x0000 }, + { 0x8700, 0x1488, 0x5000 }, + { 0x8700, 0x1480, 0x4000 }, + { 0x8700, 0x147c, 0x3000 }, + { 0x8700, 0x147a, 0x2000 }, + { 0x0700, 0x1479, 0x0000 }, + { 0x0700, 0x147b, 0x0000 }, + { 0x8700, 0x147e, 0x2000 }, + { 0x0700, 0x147d, 0x0000 }, + { 0x0700, 0x147f, 0x0000 }, + { 0x8700, 0x1484, 0x3000 }, + { 0x8700, 0x1482, 0x2000 }, + { 0x0700, 0x1481, 0x0000 }, + { 0x0700, 0x1483, 0x0000 }, + { 0x8700, 0x1486, 0x2000 }, + { 0x0700, 0x1485, 0x0000 }, + { 0x0700, 0x1487, 0x0000 }, + { 0x8700, 0x1490, 0x4000 }, + { 0x8700, 0x148c, 0x3000 }, + { 0x8700, 0x148a, 0x2000 }, + { 0x0700, 0x1489, 0x0000 }, + { 0x0700, 0x148b, 0x0000 }, + { 0x8700, 0x148e, 0x2000 }, + { 0x0700, 0x148d, 0x0000 }, + { 0x0700, 0x148f, 0x0000 }, + { 0x8700, 0x1494, 0x3000 }, + { 0x8700, 0x1492, 0x2000 }, + { 0x0700, 0x1491, 0x0000 }, + { 0x0700, 0x1493, 0x0000 }, + { 0x8700, 0x1496, 0x2000 }, + { 0x0700, 0x1495, 0x0000 }, + { 0x0700, 0x1497, 0x0000 }, + { 0x8700, 0x14b8, 0x6000 }, + { 0x8700, 0x14a8, 0x5000 }, + { 0x8700, 0x14a0, 0x4000 }, + { 0x8700, 0x149c, 0x3000 }, + { 0x8700, 0x149a, 0x2000 }, + { 0x0700, 0x1499, 0x0000 }, + { 0x0700, 0x149b, 0x0000 }, + { 0x8700, 0x149e, 0x2000 }, + { 0x0700, 0x149d, 0x0000 }, + { 0x0700, 0x149f, 0x0000 }, + { 0x8700, 0x14a4, 0x3000 }, + { 0x8700, 0x14a2, 0x2000 }, + { 0x0700, 0x14a1, 0x0000 }, + { 0x0700, 0x14a3, 0x0000 }, + { 0x8700, 0x14a6, 0x2000 }, + { 0x0700, 0x14a5, 0x0000 }, + { 0x0700, 0x14a7, 0x0000 }, + { 0x8700, 0x14b0, 0x4000 }, + { 0x8700, 0x14ac, 0x3000 }, + { 0x8700, 0x14aa, 0x2000 }, + { 0x0700, 0x14a9, 0x0000 }, + { 0x0700, 0x14ab, 0x0000 }, + { 0x8700, 0x14ae, 0x2000 }, + { 0x0700, 0x14ad, 0x0000 }, + { 0x0700, 0x14af, 0x0000 }, + { 0x8700, 0x14b4, 0x3000 }, + { 0x8700, 0x14b2, 0x2000 }, + { 0x0700, 0x14b1, 0x0000 }, + { 0x0700, 0x14b3, 0x0000 }, + { 0x8700, 0x14b6, 0x2000 }, + { 0x0700, 0x14b5, 0x0000 }, + { 0x0700, 0x14b7, 0x0000 }, + { 0x8700, 0x14c8, 0x5000 }, + { 0x8700, 0x14c0, 0x4000 }, + { 0x8700, 0x14bc, 0x3000 }, + { 0x8700, 0x14ba, 0x2000 }, + { 0x0700, 0x14b9, 0x0000 }, + { 0x0700, 0x14bb, 0x0000 }, + { 0x8700, 0x14be, 0x2000 }, + { 0x0700, 0x14bd, 0x0000 }, + { 0x0700, 0x14bf, 0x0000 }, + { 0x8700, 0x14c4, 0x3000 }, + { 0x8700, 0x14c2, 0x2000 }, + { 0x0700, 0x14c1, 0x0000 }, + { 0x0700, 0x14c3, 0x0000 }, + { 0x8700, 0x14c6, 0x2000 }, + { 0x0700, 0x14c5, 0x0000 }, + { 0x0700, 0x14c7, 0x0000 }, + { 0x8700, 0x14d0, 0x4000 }, + { 0x8700, 0x14cc, 0x3000 }, + { 0x8700, 0x14ca, 0x2000 }, + { 0x0700, 0x14c9, 0x0000 }, + { 0x0700, 0x14cb, 0x0000 }, + { 0x8700, 0x14ce, 0x2000 }, + { 0x0700, 0x14cd, 0x0000 }, + { 0x0700, 0x14cf, 0x0000 }, + { 0x8700, 0x14d4, 0x3000 }, + { 0x8700, 0x14d2, 0x2000 }, + { 0x0700, 0x14d1, 0x0000 }, + { 0x0700, 0x14d3, 0x0000 }, + { 0x8700, 0x14d6, 0x2000 }, + { 0x0700, 0x14d5, 0x0000 }, + { 0x0700, 0x14d7, 0x0000 }, + { 0x8700, 0x1518, 0x7000 }, + { 0x8700, 0x14f8, 0x6000 }, + { 0x8700, 0x14e8, 0x5000 }, + { 0x8700, 0x14e0, 0x4000 }, + { 0x8700, 0x14dc, 0x3000 }, + { 0x8700, 0x14da, 0x2000 }, + { 0x0700, 0x14d9, 0x0000 }, + { 0x0700, 0x14db, 0x0000 }, + { 0x8700, 0x14de, 0x2000 }, + { 0x0700, 0x14dd, 0x0000 }, + { 0x0700, 0x14df, 0x0000 }, + { 0x8700, 0x14e4, 0x3000 }, + { 0x8700, 0x14e2, 0x2000 }, + { 0x0700, 0x14e1, 0x0000 }, + { 0x0700, 0x14e3, 0x0000 }, + { 0x8700, 0x14e6, 0x2000 }, + { 0x0700, 0x14e5, 0x0000 }, + { 0x0700, 0x14e7, 0x0000 }, + { 0x8700, 0x14f0, 0x4000 }, + { 0x8700, 0x14ec, 0x3000 }, + { 0x8700, 0x14ea, 0x2000 }, + { 0x0700, 0x14e9, 0x0000 }, + { 0x0700, 0x14eb, 0x0000 }, + { 0x8700, 0x14ee, 0x2000 }, + { 0x0700, 0x14ed, 0x0000 }, + { 0x0700, 0x14ef, 0x0000 }, + { 0x8700, 0x14f4, 0x3000 }, + { 0x8700, 0x14f2, 0x2000 }, + { 0x0700, 0x14f1, 0x0000 }, + { 0x0700, 0x14f3, 0x0000 }, + { 0x8700, 0x14f6, 0x2000 }, + { 0x0700, 0x14f5, 0x0000 }, + { 0x0700, 0x14f7, 0x0000 }, + { 0x8700, 0x1508, 0x5000 }, + { 0x8700, 0x1500, 0x4000 }, + { 0x8700, 0x14fc, 0x3000 }, + { 0x8700, 0x14fa, 0x2000 }, + { 0x0700, 0x14f9, 0x0000 }, + { 0x0700, 0x14fb, 0x0000 }, + { 0x8700, 0x14fe, 0x2000 }, + { 0x0700, 0x14fd, 0x0000 }, + { 0x0700, 0x14ff, 0x0000 }, + { 0x8700, 0x1504, 0x3000 }, + { 0x8700, 0x1502, 0x2000 }, + { 0x0700, 0x1501, 0x0000 }, + { 0x0700, 0x1503, 0x0000 }, + { 0x8700, 0x1506, 0x2000 }, + { 0x0700, 0x1505, 0x0000 }, + { 0x0700, 0x1507, 0x0000 }, + { 0x8700, 0x1510, 0x4000 }, + { 0x8700, 0x150c, 0x3000 }, + { 0x8700, 0x150a, 0x2000 }, + { 0x0700, 0x1509, 0x0000 }, + { 0x0700, 0x150b, 0x0000 }, + { 0x8700, 0x150e, 0x2000 }, + { 0x0700, 0x150d, 0x0000 }, + { 0x0700, 0x150f, 0x0000 }, + { 0x8700, 0x1514, 0x3000 }, + { 0x8700, 0x1512, 0x2000 }, + { 0x0700, 0x1511, 0x0000 }, + { 0x0700, 0x1513, 0x0000 }, + { 0x8700, 0x1516, 0x2000 }, + { 0x0700, 0x1515, 0x0000 }, + { 0x0700, 0x1517, 0x0000 }, + { 0x8700, 0x1538, 0x6000 }, + { 0x8700, 0x1528, 0x5000 }, + { 0x8700, 0x1520, 0x4000 }, + { 0x8700, 0x151c, 0x3000 }, + { 0x8700, 0x151a, 0x2000 }, + { 0x0700, 0x1519, 0x0000 }, + { 0x0700, 0x151b, 0x0000 }, + { 0x8700, 0x151e, 0x2000 }, + { 0x0700, 0x151d, 0x0000 }, + { 0x0700, 0x151f, 0x0000 }, + { 0x8700, 0x1524, 0x3000 }, + { 0x8700, 0x1522, 0x2000 }, + { 0x0700, 0x1521, 0x0000 }, + { 0x0700, 0x1523, 0x0000 }, + { 0x8700, 0x1526, 0x2000 }, + { 0x0700, 0x1525, 0x0000 }, + { 0x0700, 0x1527, 0x0000 }, + { 0x8700, 0x1530, 0x4000 }, + { 0x8700, 0x152c, 0x3000 }, + { 0x8700, 0x152a, 0x2000 }, + { 0x0700, 0x1529, 0x0000 }, + { 0x0700, 0x152b, 0x0000 }, + { 0x8700, 0x152e, 0x2000 }, + { 0x0700, 0x152d, 0x0000 }, + { 0x0700, 0x152f, 0x0000 }, + { 0x8700, 0x1534, 0x3000 }, + { 0x8700, 0x1532, 0x2000 }, + { 0x0700, 0x1531, 0x0000 }, + { 0x0700, 0x1533, 0x0000 }, + { 0x8700, 0x1536, 0x2000 }, + { 0x0700, 0x1535, 0x0000 }, + { 0x0700, 0x1537, 0x0000 }, + { 0x8700, 0x1548, 0x5000 }, + { 0x8700, 0x1540, 0x4000 }, + { 0x8700, 0x153c, 0x3000 }, + { 0x8700, 0x153a, 0x2000 }, + { 0x0700, 0x1539, 0x0000 }, + { 0x0700, 0x153b, 0x0000 }, + { 0x8700, 0x153e, 0x2000 }, + { 0x0700, 0x153d, 0x0000 }, + { 0x0700, 0x153f, 0x0000 }, + { 0x8700, 0x1544, 0x3000 }, + { 0x8700, 0x1542, 0x2000 }, + { 0x0700, 0x1541, 0x0000 }, + { 0x0700, 0x1543, 0x0000 }, + { 0x8700, 0x1546, 0x2000 }, + { 0x0700, 0x1545, 0x0000 }, + { 0x0700, 0x1547, 0x0000 }, + { 0x8700, 0x1550, 0x4000 }, + { 0x8700, 0x154c, 0x3000 }, + { 0x8700, 0x154a, 0x2000 }, + { 0x0700, 0x1549, 0x0000 }, + { 0x0700, 0x154b, 0x0000 }, + { 0x8700, 0x154e, 0x2000 }, + { 0x0700, 0x154d, 0x0000 }, + { 0x0700, 0x154f, 0x0000 }, + { 0x8700, 0x1554, 0x3000 }, + { 0x8700, 0x1552, 0x2000 }, + { 0x0700, 0x1551, 0x0000 }, + { 0x0700, 0x1553, 0x0000 }, + { 0x8700, 0x1556, 0x2000 }, + { 0x0700, 0x1555, 0x0000 }, + { 0x0700, 0x1557, 0x0000 }, + { 0x9900, 0x22ae, 0xc000 }, + { 0x8900, 0x1e24, 0xb001 }, + { 0x8700, 0x17a2, 0xa000 }, + { 0x8700, 0x1658, 0x9000 }, + { 0x8700, 0x15d8, 0x8000 }, + { 0x8700, 0x1598, 0x7000 }, + { 0x8700, 0x1578, 0x6000 }, + { 0x8700, 0x1568, 0x5000 }, + { 0x8700, 0x1560, 0x4000 }, + { 0x8700, 0x155c, 0x3000 }, + { 0x8700, 0x155a, 0x2000 }, + { 0x0700, 0x1559, 0x0000 }, + { 0x0700, 0x155b, 0x0000 }, + { 0x8700, 0x155e, 0x2000 }, + { 0x0700, 0x155d, 0x0000 }, + { 0x0700, 0x155f, 0x0000 }, + { 0x8700, 0x1564, 0x3000 }, + { 0x8700, 0x1562, 0x2000 }, + { 0x0700, 0x1561, 0x0000 }, + { 0x0700, 0x1563, 0x0000 }, + { 0x8700, 0x1566, 0x2000 }, + { 0x0700, 0x1565, 0x0000 }, + { 0x0700, 0x1567, 0x0000 }, + { 0x8700, 0x1570, 0x4000 }, + { 0x8700, 0x156c, 0x3000 }, + { 0x8700, 0x156a, 0x2000 }, + { 0x0700, 0x1569, 0x0000 }, + { 0x0700, 0x156b, 0x0000 }, + { 0x8700, 0x156e, 0x2000 }, + { 0x0700, 0x156d, 0x0000 }, + { 0x0700, 0x156f, 0x0000 }, + { 0x8700, 0x1574, 0x3000 }, + { 0x8700, 0x1572, 0x2000 }, + { 0x0700, 0x1571, 0x0000 }, + { 0x0700, 0x1573, 0x0000 }, + { 0x8700, 0x1576, 0x2000 }, + { 0x0700, 0x1575, 0x0000 }, + { 0x0700, 0x1577, 0x0000 }, + { 0x8700, 0x1588, 0x5000 }, + { 0x8700, 0x1580, 0x4000 }, + { 0x8700, 0x157c, 0x3000 }, + { 0x8700, 0x157a, 0x2000 }, + { 0x0700, 0x1579, 0x0000 }, + { 0x0700, 0x157b, 0x0000 }, + { 0x8700, 0x157e, 0x2000 }, + { 0x0700, 0x157d, 0x0000 }, + { 0x0700, 0x157f, 0x0000 }, + { 0x8700, 0x1584, 0x3000 }, + { 0x8700, 0x1582, 0x2000 }, + { 0x0700, 0x1581, 0x0000 }, + { 0x0700, 0x1583, 0x0000 }, + { 0x8700, 0x1586, 0x2000 }, + { 0x0700, 0x1585, 0x0000 }, + { 0x0700, 0x1587, 0x0000 }, + { 0x8700, 0x1590, 0x4000 }, + { 0x8700, 0x158c, 0x3000 }, + { 0x8700, 0x158a, 0x2000 }, + { 0x0700, 0x1589, 0x0000 }, + { 0x0700, 0x158b, 0x0000 }, + { 0x8700, 0x158e, 0x2000 }, + { 0x0700, 0x158d, 0x0000 }, + { 0x0700, 0x158f, 0x0000 }, + { 0x8700, 0x1594, 0x3000 }, + { 0x8700, 0x1592, 0x2000 }, + { 0x0700, 0x1591, 0x0000 }, + { 0x0700, 0x1593, 0x0000 }, + { 0x8700, 0x1596, 0x2000 }, + { 0x0700, 0x1595, 0x0000 }, + { 0x0700, 0x1597, 0x0000 }, + { 0x8700, 0x15b8, 0x6000 }, + { 0x8700, 0x15a8, 0x5000 }, + { 0x8700, 0x15a0, 0x4000 }, + { 0x8700, 0x159c, 0x3000 }, + { 0x8700, 0x159a, 0x2000 }, + { 0x0700, 0x1599, 0x0000 }, + { 0x0700, 0x159b, 0x0000 }, + { 0x8700, 0x159e, 0x2000 }, + { 0x0700, 0x159d, 0x0000 }, + { 0x0700, 0x159f, 0x0000 }, + { 0x8700, 0x15a4, 0x3000 }, + { 0x8700, 0x15a2, 0x2000 }, + { 0x0700, 0x15a1, 0x0000 }, + { 0x0700, 0x15a3, 0x0000 }, + { 0x8700, 0x15a6, 0x2000 }, + { 0x0700, 0x15a5, 0x0000 }, + { 0x0700, 0x15a7, 0x0000 }, + { 0x8700, 0x15b0, 0x4000 }, + { 0x8700, 0x15ac, 0x3000 }, + { 0x8700, 0x15aa, 0x2000 }, + { 0x0700, 0x15a9, 0x0000 }, + { 0x0700, 0x15ab, 0x0000 }, + { 0x8700, 0x15ae, 0x2000 }, + { 0x0700, 0x15ad, 0x0000 }, + { 0x0700, 0x15af, 0x0000 }, + { 0x8700, 0x15b4, 0x3000 }, + { 0x8700, 0x15b2, 0x2000 }, + { 0x0700, 0x15b1, 0x0000 }, + { 0x0700, 0x15b3, 0x0000 }, + { 0x8700, 0x15b6, 0x2000 }, + { 0x0700, 0x15b5, 0x0000 }, + { 0x0700, 0x15b7, 0x0000 }, + { 0x8700, 0x15c8, 0x5000 }, + { 0x8700, 0x15c0, 0x4000 }, + { 0x8700, 0x15bc, 0x3000 }, + { 0x8700, 0x15ba, 0x2000 }, + { 0x0700, 0x15b9, 0x0000 }, + { 0x0700, 0x15bb, 0x0000 }, + { 0x8700, 0x15be, 0x2000 }, + { 0x0700, 0x15bd, 0x0000 }, + { 0x0700, 0x15bf, 0x0000 }, + { 0x8700, 0x15c4, 0x3000 }, + { 0x8700, 0x15c2, 0x2000 }, + { 0x0700, 0x15c1, 0x0000 }, + { 0x0700, 0x15c3, 0x0000 }, + { 0x8700, 0x15c6, 0x2000 }, + { 0x0700, 0x15c5, 0x0000 }, + { 0x0700, 0x15c7, 0x0000 }, + { 0x8700, 0x15d0, 0x4000 }, + { 0x8700, 0x15cc, 0x3000 }, + { 0x8700, 0x15ca, 0x2000 }, + { 0x0700, 0x15c9, 0x0000 }, + { 0x0700, 0x15cb, 0x0000 }, + { 0x8700, 0x15ce, 0x2000 }, + { 0x0700, 0x15cd, 0x0000 }, + { 0x0700, 0x15cf, 0x0000 }, + { 0x8700, 0x15d4, 0x3000 }, + { 0x8700, 0x15d2, 0x2000 }, + { 0x0700, 0x15d1, 0x0000 }, + { 0x0700, 0x15d3, 0x0000 }, + { 0x8700, 0x15d6, 0x2000 }, + { 0x0700, 0x15d5, 0x0000 }, + { 0x0700, 0x15d7, 0x0000 }, + { 0x8700, 0x1618, 0x7000 }, + { 0x8700, 0x15f8, 0x6000 }, + { 0x8700, 0x15e8, 0x5000 }, + { 0x8700, 0x15e0, 0x4000 }, + { 0x8700, 0x15dc, 0x3000 }, + { 0x8700, 0x15da, 0x2000 }, + { 0x0700, 0x15d9, 0x0000 }, + { 0x0700, 0x15db, 0x0000 }, + { 0x8700, 0x15de, 0x2000 }, + { 0x0700, 0x15dd, 0x0000 }, + { 0x0700, 0x15df, 0x0000 }, + { 0x8700, 0x15e4, 0x3000 }, + { 0x8700, 0x15e2, 0x2000 }, + { 0x0700, 0x15e1, 0x0000 }, + { 0x0700, 0x15e3, 0x0000 }, + { 0x8700, 0x15e6, 0x2000 }, + { 0x0700, 0x15e5, 0x0000 }, + { 0x0700, 0x15e7, 0x0000 }, + { 0x8700, 0x15f0, 0x4000 }, + { 0x8700, 0x15ec, 0x3000 }, + { 0x8700, 0x15ea, 0x2000 }, + { 0x0700, 0x15e9, 0x0000 }, + { 0x0700, 0x15eb, 0x0000 }, + { 0x8700, 0x15ee, 0x2000 }, + { 0x0700, 0x15ed, 0x0000 }, + { 0x0700, 0x15ef, 0x0000 }, + { 0x8700, 0x15f4, 0x3000 }, + { 0x8700, 0x15f2, 0x2000 }, + { 0x0700, 0x15f1, 0x0000 }, + { 0x0700, 0x15f3, 0x0000 }, + { 0x8700, 0x15f6, 0x2000 }, + { 0x0700, 0x15f5, 0x0000 }, + { 0x0700, 0x15f7, 0x0000 }, + { 0x8700, 0x1608, 0x5000 }, + { 0x8700, 0x1600, 0x4000 }, + { 0x8700, 0x15fc, 0x3000 }, + { 0x8700, 0x15fa, 0x2000 }, + { 0x0700, 0x15f9, 0x0000 }, + { 0x0700, 0x15fb, 0x0000 }, + { 0x8700, 0x15fe, 0x2000 }, + { 0x0700, 0x15fd, 0x0000 }, + { 0x0700, 0x15ff, 0x0000 }, + { 0x8700, 0x1604, 0x3000 }, + { 0x8700, 0x1602, 0x2000 }, + { 0x0700, 0x1601, 0x0000 }, + { 0x0700, 0x1603, 0x0000 }, + { 0x8700, 0x1606, 0x2000 }, + { 0x0700, 0x1605, 0x0000 }, + { 0x0700, 0x1607, 0x0000 }, + { 0x8700, 0x1610, 0x4000 }, + { 0x8700, 0x160c, 0x3000 }, + { 0x8700, 0x160a, 0x2000 }, + { 0x0700, 0x1609, 0x0000 }, + { 0x0700, 0x160b, 0x0000 }, + { 0x8700, 0x160e, 0x2000 }, + { 0x0700, 0x160d, 0x0000 }, + { 0x0700, 0x160f, 0x0000 }, + { 0x8700, 0x1614, 0x3000 }, + { 0x8700, 0x1612, 0x2000 }, + { 0x0700, 0x1611, 0x0000 }, + { 0x0700, 0x1613, 0x0000 }, + { 0x8700, 0x1616, 0x2000 }, + { 0x0700, 0x1615, 0x0000 }, + { 0x0700, 0x1617, 0x0000 }, + { 0x8700, 0x1638, 0x6000 }, + { 0x8700, 0x1628, 0x5000 }, + { 0x8700, 0x1620, 0x4000 }, + { 0x8700, 0x161c, 0x3000 }, + { 0x8700, 0x161a, 0x2000 }, + { 0x0700, 0x1619, 0x0000 }, + { 0x0700, 0x161b, 0x0000 }, + { 0x8700, 0x161e, 0x2000 }, + { 0x0700, 0x161d, 0x0000 }, + { 0x0700, 0x161f, 0x0000 }, + { 0x8700, 0x1624, 0x3000 }, + { 0x8700, 0x1622, 0x2000 }, + { 0x0700, 0x1621, 0x0000 }, + { 0x0700, 0x1623, 0x0000 }, + { 0x8700, 0x1626, 0x2000 }, + { 0x0700, 0x1625, 0x0000 }, + { 0x0700, 0x1627, 0x0000 }, + { 0x8700, 0x1630, 0x4000 }, + { 0x8700, 0x162c, 0x3000 }, + { 0x8700, 0x162a, 0x2000 }, + { 0x0700, 0x1629, 0x0000 }, + { 0x0700, 0x162b, 0x0000 }, + { 0x8700, 0x162e, 0x2000 }, + { 0x0700, 0x162d, 0x0000 }, + { 0x0700, 0x162f, 0x0000 }, + { 0x8700, 0x1634, 0x3000 }, + { 0x8700, 0x1632, 0x2000 }, + { 0x0700, 0x1631, 0x0000 }, + { 0x0700, 0x1633, 0x0000 }, + { 0x8700, 0x1636, 0x2000 }, + { 0x0700, 0x1635, 0x0000 }, + { 0x0700, 0x1637, 0x0000 }, + { 0x8700, 0x1648, 0x5000 }, + { 0x8700, 0x1640, 0x4000 }, + { 0x8700, 0x163c, 0x3000 }, + { 0x8700, 0x163a, 0x2000 }, + { 0x0700, 0x1639, 0x0000 }, + { 0x0700, 0x163b, 0x0000 }, + { 0x8700, 0x163e, 0x2000 }, + { 0x0700, 0x163d, 0x0000 }, + { 0x0700, 0x163f, 0x0000 }, + { 0x8700, 0x1644, 0x3000 }, + { 0x8700, 0x1642, 0x2000 }, + { 0x0700, 0x1641, 0x0000 }, + { 0x0700, 0x1643, 0x0000 }, + { 0x8700, 0x1646, 0x2000 }, + { 0x0700, 0x1645, 0x0000 }, + { 0x0700, 0x1647, 0x0000 }, + { 0x8700, 0x1650, 0x4000 }, + { 0x8700, 0x164c, 0x3000 }, + { 0x8700, 0x164a, 0x2000 }, + { 0x0700, 0x1649, 0x0000 }, + { 0x0700, 0x164b, 0x0000 }, + { 0x8700, 0x164e, 0x2000 }, + { 0x0700, 0x164d, 0x0000 }, + { 0x0700, 0x164f, 0x0000 }, + { 0x8700, 0x1654, 0x3000 }, + { 0x8700, 0x1652, 0x2000 }, + { 0x0700, 0x1651, 0x0000 }, + { 0x0700, 0x1653, 0x0000 }, + { 0x8700, 0x1656, 0x2000 }, + { 0x0700, 0x1655, 0x0000 }, + { 0x0700, 0x1657, 0x0000 }, + { 0x8700, 0x16e4, 0x8000 }, + { 0x8700, 0x16a4, 0x7000 }, + { 0x8700, 0x1681, 0x6000 }, + { 0x8700, 0x1668, 0x5000 }, + { 0x8700, 0x1660, 0x4000 }, + { 0x8700, 0x165c, 0x3000 }, + { 0x8700, 0x165a, 0x2000 }, + { 0x0700, 0x1659, 0x0000 }, + { 0x0700, 0x165b, 0x0000 }, + { 0x8700, 0x165e, 0x2000 }, + { 0x0700, 0x165d, 0x0000 }, + { 0x0700, 0x165f, 0x0000 }, + { 0x8700, 0x1664, 0x3000 }, + { 0x8700, 0x1662, 0x2000 }, + { 0x0700, 0x1661, 0x0000 }, + { 0x0700, 0x1663, 0x0000 }, + { 0x8700, 0x1666, 0x2000 }, + { 0x0700, 0x1665, 0x0000 }, + { 0x0700, 0x1667, 0x0000 }, + { 0x8700, 0x1670, 0x4000 }, + { 0x8700, 0x166c, 0x3000 }, + { 0x8700, 0x166a, 0x2000 }, + { 0x0700, 0x1669, 0x0000 }, + { 0x0700, 0x166b, 0x0000 }, + { 0x9500, 0x166e, 0x2000 }, + { 0x1500, 0x166d, 0x0000 }, + { 0x0700, 0x166f, 0x0000 }, + { 0x8700, 0x1674, 0x3000 }, + { 0x8700, 0x1672, 0x2000 }, + { 0x0700, 0x1671, 0x0000 }, + { 0x0700, 0x1673, 0x0000 }, + { 0x8700, 0x1676, 0x2000 }, + { 0x0700, 0x1675, 0x0000 }, + { 0x1d00, 0x1680, 0x0000 }, + { 0x8700, 0x1691, 0x5000 }, + { 0x8700, 0x1689, 0x4000 }, + { 0x8700, 0x1685, 0x3000 }, + { 0x8700, 0x1683, 0x2000 }, + { 0x0700, 0x1682, 0x0000 }, + { 0x0700, 0x1684, 0x0000 }, + { 0x8700, 0x1687, 0x2000 }, + { 0x0700, 0x1686, 0x0000 }, + { 0x0700, 0x1688, 0x0000 }, + { 0x8700, 0x168d, 0x3000 }, + { 0x8700, 0x168b, 0x2000 }, + { 0x0700, 0x168a, 0x0000 }, + { 0x0700, 0x168c, 0x0000 }, + { 0x8700, 0x168f, 0x2000 }, + { 0x0700, 0x168e, 0x0000 }, + { 0x0700, 0x1690, 0x0000 }, + { 0x8700, 0x1699, 0x4000 }, + { 0x8700, 0x1695, 0x3000 }, + { 0x8700, 0x1693, 0x2000 }, + { 0x0700, 0x1692, 0x0000 }, + { 0x0700, 0x1694, 0x0000 }, + { 0x8700, 0x1697, 0x2000 }, + { 0x0700, 0x1696, 0x0000 }, + { 0x0700, 0x1698, 0x0000 }, + { 0x8700, 0x16a0, 0x3000 }, + { 0x9600, 0x169b, 0x2000 }, + { 0x0700, 0x169a, 0x0000 }, + { 0x1200, 0x169c, 0x0000 }, + { 0x8700, 0x16a2, 0x2000 }, + { 0x0700, 0x16a1, 0x0000 }, + { 0x0700, 0x16a3, 0x0000 }, + { 0x8700, 0x16c4, 0x6000 }, + { 0x8700, 0x16b4, 0x5000 }, + { 0x8700, 0x16ac, 0x4000 }, + { 0x8700, 0x16a8, 0x3000 }, + { 0x8700, 0x16a6, 0x2000 }, + { 0x0700, 0x16a5, 0x0000 }, + { 0x0700, 0x16a7, 0x0000 }, + { 0x8700, 0x16aa, 0x2000 }, + { 0x0700, 0x16a9, 0x0000 }, + { 0x0700, 0x16ab, 0x0000 }, + { 0x8700, 0x16b0, 0x3000 }, + { 0x8700, 0x16ae, 0x2000 }, + { 0x0700, 0x16ad, 0x0000 }, + { 0x0700, 0x16af, 0x0000 }, + { 0x8700, 0x16b2, 0x2000 }, + { 0x0700, 0x16b1, 0x0000 }, + { 0x0700, 0x16b3, 0x0000 }, + { 0x8700, 0x16bc, 0x4000 }, + { 0x8700, 0x16b8, 0x3000 }, + { 0x8700, 0x16b6, 0x2000 }, + { 0x0700, 0x16b5, 0x0000 }, + { 0x0700, 0x16b7, 0x0000 }, + { 0x8700, 0x16ba, 0x2000 }, + { 0x0700, 0x16b9, 0x0000 }, + { 0x0700, 0x16bb, 0x0000 }, + { 0x8700, 0x16c0, 0x3000 }, + { 0x8700, 0x16be, 0x2000 }, + { 0x0700, 0x16bd, 0x0000 }, + { 0x0700, 0x16bf, 0x0000 }, + { 0x8700, 0x16c2, 0x2000 }, + { 0x0700, 0x16c1, 0x0000 }, + { 0x0700, 0x16c3, 0x0000 }, + { 0x8700, 0x16d4, 0x5000 }, + { 0x8700, 0x16cc, 0x4000 }, + { 0x8700, 0x16c8, 0x3000 }, + { 0x8700, 0x16c6, 0x2000 }, + { 0x0700, 0x16c5, 0x0000 }, + { 0x0700, 0x16c7, 0x0000 }, + { 0x8700, 0x16ca, 0x2000 }, + { 0x0700, 0x16c9, 0x0000 }, + { 0x0700, 0x16cb, 0x0000 }, + { 0x8700, 0x16d0, 0x3000 }, + { 0x8700, 0x16ce, 0x2000 }, + { 0x0700, 0x16cd, 0x0000 }, + { 0x0700, 0x16cf, 0x0000 }, + { 0x8700, 0x16d2, 0x2000 }, + { 0x0700, 0x16d1, 0x0000 }, + { 0x0700, 0x16d3, 0x0000 }, + { 0x8700, 0x16dc, 0x4000 }, + { 0x8700, 0x16d8, 0x3000 }, + { 0x8700, 0x16d6, 0x2000 }, + { 0x0700, 0x16d5, 0x0000 }, + { 0x0700, 0x16d7, 0x0000 }, + { 0x8700, 0x16da, 0x2000 }, + { 0x0700, 0x16d9, 0x0000 }, + { 0x0700, 0x16db, 0x0000 }, + { 0x8700, 0x16e0, 0x3000 }, + { 0x8700, 0x16de, 0x2000 }, + { 0x0700, 0x16dd, 0x0000 }, + { 0x0700, 0x16df, 0x0000 }, + { 0x8700, 0x16e2, 0x2000 }, + { 0x0700, 0x16e1, 0x0000 }, + { 0x0700, 0x16e3, 0x0000 }, + { 0x8700, 0x1748, 0x7000 }, + { 0x8c00, 0x1714, 0x6000 }, + { 0x8700, 0x1703, 0x5000 }, + { 0x9500, 0x16ec, 0x4000 }, + { 0x8700, 0x16e8, 0x3000 }, + { 0x8700, 0x16e6, 0x2000 }, + { 0x0700, 0x16e5, 0x0000 }, + { 0x0700, 0x16e7, 0x0000 }, + { 0x8700, 0x16ea, 0x2000 }, + { 0x0700, 0x16e9, 0x0000 }, + { 0x1500, 0x16eb, 0x0000 }, + { 0x8e00, 0x16f0, 0x3000 }, + { 0x8e00, 0x16ee, 0x2000 }, + { 0x1500, 0x16ed, 0x0000 }, + { 0x0e00, 0x16ef, 0x0000 }, + { 0x8700, 0x1701, 0x2000 }, + { 0x0700, 0x1700, 0x0000 }, + { 0x0700, 0x1702, 0x0000 }, + { 0x8700, 0x170b, 0x4000 }, + { 0x8700, 0x1707, 0x3000 }, + { 0x8700, 0x1705, 0x2000 }, + { 0x0700, 0x1704, 0x0000 }, + { 0x0700, 0x1706, 0x0000 }, + { 0x8700, 0x1709, 0x2000 }, + { 0x0700, 0x1708, 0x0000 }, + { 0x0700, 0x170a, 0x0000 }, + { 0x8700, 0x1710, 0x3000 }, + { 0x8700, 0x170e, 0x2000 }, + { 0x0700, 0x170c, 0x0000 }, + { 0x0700, 0x170f, 0x0000 }, + { 0x8c00, 0x1712, 0x2000 }, + { 0x0700, 0x1711, 0x0000 }, + { 0x0c00, 0x1713, 0x0000 }, + { 0x8700, 0x172f, 0x5000 }, + { 0x8700, 0x1727, 0x4000 }, + { 0x8700, 0x1723, 0x3000 }, + { 0x8700, 0x1721, 0x2000 }, + { 0x0700, 0x1720, 0x0000 }, + { 0x0700, 0x1722, 0x0000 }, + { 0x8700, 0x1725, 0x2000 }, + { 0x0700, 0x1724, 0x0000 }, + { 0x0700, 0x1726, 0x0000 }, + { 0x8700, 0x172b, 0x3000 }, + { 0x8700, 0x1729, 0x2000 }, + { 0x0700, 0x1728, 0x0000 }, + { 0x0700, 0x172a, 0x0000 }, + { 0x8700, 0x172d, 0x2000 }, + { 0x0700, 0x172c, 0x0000 }, + { 0x0700, 0x172e, 0x0000 }, + { 0x8700, 0x1740, 0x4000 }, + { 0x8c00, 0x1733, 0x3000 }, + { 0x8700, 0x1731, 0x2000 }, + { 0x0700, 0x1730, 0x0000 }, + { 0x0c00, 0x1732, 0x0000 }, + { 0x9500, 0x1735, 0x2000 }, + { 0x0c00, 0x1734, 0x0000 }, + { 0x1500, 0x1736, 0x0000 }, + { 0x8700, 0x1744, 0x3000 }, + { 0x8700, 0x1742, 0x2000 }, + { 0x0700, 0x1741, 0x0000 }, + { 0x0700, 0x1743, 0x0000 }, + { 0x8700, 0x1746, 0x2000 }, + { 0x0700, 0x1745, 0x0000 }, + { 0x0700, 0x1747, 0x0000 }, + { 0x8700, 0x1782, 0x6000 }, + { 0x8700, 0x1764, 0x5000 }, + { 0x8700, 0x1750, 0x4000 }, + { 0x8700, 0x174c, 0x3000 }, + { 0x8700, 0x174a, 0x2000 }, + { 0x0700, 0x1749, 0x0000 }, + { 0x0700, 0x174b, 0x0000 }, + { 0x8700, 0x174e, 0x2000 }, + { 0x0700, 0x174d, 0x0000 }, + { 0x0700, 0x174f, 0x0000 }, + { 0x8700, 0x1760, 0x3000 }, + { 0x8c00, 0x1752, 0x2000 }, + { 0x0700, 0x1751, 0x0000 }, + { 0x0c00, 0x1753, 0x0000 }, + { 0x8700, 0x1762, 0x2000 }, + { 0x0700, 0x1761, 0x0000 }, + { 0x0700, 0x1763, 0x0000 }, + { 0x8700, 0x176c, 0x4000 }, + { 0x8700, 0x1768, 0x3000 }, + { 0x8700, 0x1766, 0x2000 }, + { 0x0700, 0x1765, 0x0000 }, + { 0x0700, 0x1767, 0x0000 }, + { 0x8700, 0x176a, 0x2000 }, + { 0x0700, 0x1769, 0x0000 }, + { 0x0700, 0x176b, 0x0000 }, + { 0x8c00, 0x1772, 0x3000 }, + { 0x8700, 0x176f, 0x2000 }, + { 0x0700, 0x176e, 0x0000 }, + { 0x0700, 0x1770, 0x0000 }, + { 0x8700, 0x1780, 0x2000 }, + { 0x0c00, 0x1773, 0x0000 }, + { 0x0700, 0x1781, 0x0000 }, + { 0x8700, 0x1792, 0x5000 }, + { 0x8700, 0x178a, 0x4000 }, + { 0x8700, 0x1786, 0x3000 }, + { 0x8700, 0x1784, 0x2000 }, + { 0x0700, 0x1783, 0x0000 }, + { 0x0700, 0x1785, 0x0000 }, + { 0x8700, 0x1788, 0x2000 }, + { 0x0700, 0x1787, 0x0000 }, + { 0x0700, 0x1789, 0x0000 }, + { 0x8700, 0x178e, 0x3000 }, + { 0x8700, 0x178c, 0x2000 }, + { 0x0700, 0x178b, 0x0000 }, + { 0x0700, 0x178d, 0x0000 }, + { 0x8700, 0x1790, 0x2000 }, + { 0x0700, 0x178f, 0x0000 }, + { 0x0700, 0x1791, 0x0000 }, + { 0x8700, 0x179a, 0x4000 }, + { 0x8700, 0x1796, 0x3000 }, + { 0x8700, 0x1794, 0x2000 }, + { 0x0700, 0x1793, 0x0000 }, + { 0x0700, 0x1795, 0x0000 }, + { 0x8700, 0x1798, 0x2000 }, + { 0x0700, 0x1797, 0x0000 }, + { 0x0700, 0x1799, 0x0000 }, + { 0x8700, 0x179e, 0x3000 }, + { 0x8700, 0x179c, 0x2000 }, + { 0x0700, 0x179b, 0x0000 }, + { 0x0700, 0x179d, 0x0000 }, + { 0x8700, 0x17a0, 0x2000 }, + { 0x0700, 0x179f, 0x0000 }, + { 0x0700, 0x17a1, 0x0000 }, + { 0x8700, 0x1915, 0x9000 }, + { 0x8700, 0x1837, 0x8000 }, + { 0x8d00, 0x17e4, 0x7000 }, + { 0x8a00, 0x17c2, 0x6000 }, + { 0x8700, 0x17b2, 0x5000 }, + { 0x8700, 0x17aa, 0x4000 }, + { 0x8700, 0x17a6, 0x3000 }, + { 0x8700, 0x17a4, 0x2000 }, + { 0x0700, 0x17a3, 0x0000 }, + { 0x0700, 0x17a5, 0x0000 }, + { 0x8700, 0x17a8, 0x2000 }, + { 0x0700, 0x17a7, 0x0000 }, + { 0x0700, 0x17a9, 0x0000 }, + { 0x8700, 0x17ae, 0x3000 }, + { 0x8700, 0x17ac, 0x2000 }, + { 0x0700, 0x17ab, 0x0000 }, + { 0x0700, 0x17ad, 0x0000 }, + { 0x8700, 0x17b0, 0x2000 }, + { 0x0700, 0x17af, 0x0000 }, + { 0x0700, 0x17b1, 0x0000 }, + { 0x8c00, 0x17ba, 0x4000 }, + { 0x8a00, 0x17b6, 0x3000 }, + { 0x8100, 0x17b4, 0x2000 }, + { 0x0700, 0x17b3, 0x0000 }, + { 0x0100, 0x17b5, 0x0000 }, + { 0x8c00, 0x17b8, 0x2000 }, + { 0x0c00, 0x17b7, 0x0000 }, + { 0x0c00, 0x17b9, 0x0000 }, + { 0x8a00, 0x17be, 0x3000 }, + { 0x8c00, 0x17bc, 0x2000 }, + { 0x0c00, 0x17bb, 0x0000 }, + { 0x0c00, 0x17bd, 0x0000 }, + { 0x8a00, 0x17c0, 0x2000 }, + { 0x0a00, 0x17bf, 0x0000 }, + { 0x0a00, 0x17c1, 0x0000 }, + { 0x8c00, 0x17d2, 0x5000 }, + { 0x8c00, 0x17ca, 0x4000 }, + { 0x8c00, 0x17c6, 0x3000 }, + { 0x8a00, 0x17c4, 0x2000 }, + { 0x0a00, 0x17c3, 0x0000 }, + { 0x0a00, 0x17c5, 0x0000 }, + { 0x8a00, 0x17c8, 0x2000 }, + { 0x0a00, 0x17c7, 0x0000 }, + { 0x0c00, 0x17c9, 0x0000 }, + { 0x8c00, 0x17ce, 0x3000 }, + { 0x8c00, 0x17cc, 0x2000 }, + { 0x0c00, 0x17cb, 0x0000 }, + { 0x0c00, 0x17cd, 0x0000 }, + { 0x8c00, 0x17d0, 0x2000 }, + { 0x0c00, 0x17cf, 0x0000 }, + { 0x0c00, 0x17d1, 0x0000 }, + { 0x9500, 0x17da, 0x4000 }, + { 0x9500, 0x17d6, 0x3000 }, + { 0x9500, 0x17d4, 0x2000 }, + { 0x0c00, 0x17d3, 0x0000 }, + { 0x1500, 0x17d5, 0x0000 }, + { 0x9500, 0x17d8, 0x2000 }, + { 0x0600, 0x17d7, 0x0000 }, + { 0x1500, 0x17d9, 0x0000 }, + { 0x8d00, 0x17e0, 0x3000 }, + { 0x8700, 0x17dc, 0x2000 }, + { 0x1700, 0x17db, 0x0000 }, + { 0x0c00, 0x17dd, 0x0000 }, + { 0x8d00, 0x17e2, 0x2000 }, + { 0x0d00, 0x17e1, 0x0000 }, + { 0x0d00, 0x17e3, 0x0000 }, + { 0x8d00, 0x1811, 0x6000 }, + { 0x9500, 0x1800, 0x5000 }, + { 0x8f00, 0x17f2, 0x4000 }, + { 0x8d00, 0x17e8, 0x3000 }, + { 0x8d00, 0x17e6, 0x2000 }, + { 0x0d00, 0x17e5, 0x0000 }, + { 0x0d00, 0x17e7, 0x0000 }, + { 0x8f00, 0x17f0, 0x2000 }, + { 0x0d00, 0x17e9, 0x0000 }, + { 0x0f00, 0x17f1, 0x0000 }, + { 0x8f00, 0x17f6, 0x3000 }, + { 0x8f00, 0x17f4, 0x2000 }, + { 0x0f00, 0x17f3, 0x0000 }, + { 0x0f00, 0x17f5, 0x0000 }, + { 0x8f00, 0x17f8, 0x2000 }, + { 0x0f00, 0x17f7, 0x0000 }, + { 0x0f00, 0x17f9, 0x0000 }, + { 0x9500, 0x1808, 0x4000 }, + { 0x9500, 0x1804, 0x3000 }, + { 0x9500, 0x1802, 0x2000 }, + { 0x1500, 0x1801, 0x0000 }, + { 0x1500, 0x1803, 0x0000 }, + { 0x9100, 0x1806, 0x2000 }, + { 0x1500, 0x1805, 0x0000 }, + { 0x1500, 0x1807, 0x0000 }, + { 0x8c00, 0x180c, 0x3000 }, + { 0x9500, 0x180a, 0x2000 }, + { 0x1500, 0x1809, 0x0000 }, + { 0x0c00, 0x180b, 0x0000 }, + { 0x9d00, 0x180e, 0x2000 }, + { 0x0c00, 0x180d, 0x0000 }, + { 0x0d00, 0x1810, 0x0000 }, + { 0x8700, 0x1827, 0x5000 }, + { 0x8d00, 0x1819, 0x4000 }, + { 0x8d00, 0x1815, 0x3000 }, + { 0x8d00, 0x1813, 0x2000 }, + { 0x0d00, 0x1812, 0x0000 }, + { 0x0d00, 0x1814, 0x0000 }, + { 0x8d00, 0x1817, 0x2000 }, + { 0x0d00, 0x1816, 0x0000 }, + { 0x0d00, 0x1818, 0x0000 }, + { 0x8700, 0x1823, 0x3000 }, + { 0x8700, 0x1821, 0x2000 }, + { 0x0700, 0x1820, 0x0000 }, + { 0x0700, 0x1822, 0x0000 }, + { 0x8700, 0x1825, 0x2000 }, + { 0x0700, 0x1824, 0x0000 }, + { 0x0700, 0x1826, 0x0000 }, + { 0x8700, 0x182f, 0x4000 }, + { 0x8700, 0x182b, 0x3000 }, + { 0x8700, 0x1829, 0x2000 }, + { 0x0700, 0x1828, 0x0000 }, + { 0x0700, 0x182a, 0x0000 }, + { 0x8700, 0x182d, 0x2000 }, + { 0x0700, 0x182c, 0x0000 }, + { 0x0700, 0x182e, 0x0000 }, + { 0x8700, 0x1833, 0x3000 }, + { 0x8700, 0x1831, 0x2000 }, + { 0x0700, 0x1830, 0x0000 }, + { 0x0700, 0x1832, 0x0000 }, + { 0x8700, 0x1835, 0x2000 }, + { 0x0700, 0x1834, 0x0000 }, + { 0x0700, 0x1836, 0x0000 }, + { 0x8700, 0x1877, 0x7000 }, + { 0x8700, 0x1857, 0x6000 }, + { 0x8700, 0x1847, 0x5000 }, + { 0x8700, 0x183f, 0x4000 }, + { 0x8700, 0x183b, 0x3000 }, + { 0x8700, 0x1839, 0x2000 }, + { 0x0700, 0x1838, 0x0000 }, + { 0x0700, 0x183a, 0x0000 }, + { 0x8700, 0x183d, 0x2000 }, + { 0x0700, 0x183c, 0x0000 }, + { 0x0700, 0x183e, 0x0000 }, + { 0x8600, 0x1843, 0x3000 }, + { 0x8700, 0x1841, 0x2000 }, + { 0x0700, 0x1840, 0x0000 }, + { 0x0700, 0x1842, 0x0000 }, + { 0x8700, 0x1845, 0x2000 }, + { 0x0700, 0x1844, 0x0000 }, + { 0x0700, 0x1846, 0x0000 }, + { 0x8700, 0x184f, 0x4000 }, + { 0x8700, 0x184b, 0x3000 }, + { 0x8700, 0x1849, 0x2000 }, + { 0x0700, 0x1848, 0x0000 }, + { 0x0700, 0x184a, 0x0000 }, + { 0x8700, 0x184d, 0x2000 }, + { 0x0700, 0x184c, 0x0000 }, + { 0x0700, 0x184e, 0x0000 }, + { 0x8700, 0x1853, 0x3000 }, + { 0x8700, 0x1851, 0x2000 }, + { 0x0700, 0x1850, 0x0000 }, + { 0x0700, 0x1852, 0x0000 }, + { 0x8700, 0x1855, 0x2000 }, + { 0x0700, 0x1854, 0x0000 }, + { 0x0700, 0x1856, 0x0000 }, + { 0x8700, 0x1867, 0x5000 }, + { 0x8700, 0x185f, 0x4000 }, + { 0x8700, 0x185b, 0x3000 }, + { 0x8700, 0x1859, 0x2000 }, + { 0x0700, 0x1858, 0x0000 }, + { 0x0700, 0x185a, 0x0000 }, + { 0x8700, 0x185d, 0x2000 }, + { 0x0700, 0x185c, 0x0000 }, + { 0x0700, 0x185e, 0x0000 }, + { 0x8700, 0x1863, 0x3000 }, + { 0x8700, 0x1861, 0x2000 }, + { 0x0700, 0x1860, 0x0000 }, + { 0x0700, 0x1862, 0x0000 }, + { 0x8700, 0x1865, 0x2000 }, + { 0x0700, 0x1864, 0x0000 }, + { 0x0700, 0x1866, 0x0000 }, + { 0x8700, 0x186f, 0x4000 }, + { 0x8700, 0x186b, 0x3000 }, + { 0x8700, 0x1869, 0x2000 }, + { 0x0700, 0x1868, 0x0000 }, + { 0x0700, 0x186a, 0x0000 }, + { 0x8700, 0x186d, 0x2000 }, + { 0x0700, 0x186c, 0x0000 }, + { 0x0700, 0x186e, 0x0000 }, + { 0x8700, 0x1873, 0x3000 }, + { 0x8700, 0x1871, 0x2000 }, + { 0x0700, 0x1870, 0x0000 }, + { 0x0700, 0x1872, 0x0000 }, + { 0x8700, 0x1875, 0x2000 }, + { 0x0700, 0x1874, 0x0000 }, + { 0x0700, 0x1876, 0x0000 }, + { 0x8700, 0x189f, 0x6000 }, + { 0x8700, 0x188f, 0x5000 }, + { 0x8700, 0x1887, 0x4000 }, + { 0x8700, 0x1883, 0x3000 }, + { 0x8700, 0x1881, 0x2000 }, + { 0x0700, 0x1880, 0x0000 }, + { 0x0700, 0x1882, 0x0000 }, + { 0x8700, 0x1885, 0x2000 }, + { 0x0700, 0x1884, 0x0000 }, + { 0x0700, 0x1886, 0x0000 }, + { 0x8700, 0x188b, 0x3000 }, + { 0x8700, 0x1889, 0x2000 }, + { 0x0700, 0x1888, 0x0000 }, + { 0x0700, 0x188a, 0x0000 }, + { 0x8700, 0x188d, 0x2000 }, + { 0x0700, 0x188c, 0x0000 }, + { 0x0700, 0x188e, 0x0000 }, + { 0x8700, 0x1897, 0x4000 }, + { 0x8700, 0x1893, 0x3000 }, + { 0x8700, 0x1891, 0x2000 }, + { 0x0700, 0x1890, 0x0000 }, + { 0x0700, 0x1892, 0x0000 }, + { 0x8700, 0x1895, 0x2000 }, + { 0x0700, 0x1894, 0x0000 }, + { 0x0700, 0x1896, 0x0000 }, + { 0x8700, 0x189b, 0x3000 }, + { 0x8700, 0x1899, 0x2000 }, + { 0x0700, 0x1898, 0x0000 }, + { 0x0700, 0x189a, 0x0000 }, + { 0x8700, 0x189d, 0x2000 }, + { 0x0700, 0x189c, 0x0000 }, + { 0x0700, 0x189e, 0x0000 }, + { 0x8700, 0x1905, 0x5000 }, + { 0x8700, 0x18a7, 0x4000 }, + { 0x8700, 0x18a3, 0x3000 }, + { 0x8700, 0x18a1, 0x2000 }, + { 0x0700, 0x18a0, 0x0000 }, + { 0x0700, 0x18a2, 0x0000 }, + { 0x8700, 0x18a5, 0x2000 }, + { 0x0700, 0x18a4, 0x0000 }, + { 0x0700, 0x18a6, 0x0000 }, + { 0x8700, 0x1901, 0x3000 }, + { 0x8c00, 0x18a9, 0x2000 }, + { 0x0700, 0x18a8, 0x0000 }, + { 0x0700, 0x1900, 0x0000 }, + { 0x8700, 0x1903, 0x2000 }, + { 0x0700, 0x1902, 0x0000 }, + { 0x0700, 0x1904, 0x0000 }, + { 0x8700, 0x190d, 0x4000 }, + { 0x8700, 0x1909, 0x3000 }, + { 0x8700, 0x1907, 0x2000 }, + { 0x0700, 0x1906, 0x0000 }, + { 0x0700, 0x1908, 0x0000 }, + { 0x8700, 0x190b, 0x2000 }, + { 0x0700, 0x190a, 0x0000 }, + { 0x0700, 0x190c, 0x0000 }, + { 0x8700, 0x1911, 0x3000 }, + { 0x8700, 0x190f, 0x2000 }, + { 0x0700, 0x190e, 0x0000 }, + { 0x0700, 0x1910, 0x0000 }, + { 0x8700, 0x1913, 0x2000 }, + { 0x0700, 0x1912, 0x0000 }, + { 0x0700, 0x1914, 0x0000 }, + { 0x8500, 0x1d10, 0x8000 }, + { 0x8700, 0x1963, 0x7000 }, + { 0x9a00, 0x1940, 0x6000 }, + { 0x8c00, 0x1928, 0x5000 }, + { 0x8c00, 0x1920, 0x4000 }, + { 0x8700, 0x1919, 0x3000 }, + { 0x8700, 0x1917, 0x2000 }, + { 0x0700, 0x1916, 0x0000 }, + { 0x0700, 0x1918, 0x0000 }, + { 0x8700, 0x191b, 0x2000 }, + { 0x0700, 0x191a, 0x0000 }, + { 0x0700, 0x191c, 0x0000 }, + { 0x8a00, 0x1924, 0x3000 }, + { 0x8c00, 0x1922, 0x2000 }, + { 0x0c00, 0x1921, 0x0000 }, + { 0x0a00, 0x1923, 0x0000 }, + { 0x8a00, 0x1926, 0x2000 }, + { 0x0a00, 0x1925, 0x0000 }, + { 0x0c00, 0x1927, 0x0000 }, + { 0x8a00, 0x1934, 0x4000 }, + { 0x8a00, 0x1930, 0x3000 }, + { 0x8a00, 0x192a, 0x2000 }, + { 0x0a00, 0x1929, 0x0000 }, + { 0x0a00, 0x192b, 0x0000 }, + { 0x8c00, 0x1932, 0x2000 }, + { 0x0a00, 0x1931, 0x0000 }, + { 0x0a00, 0x1933, 0x0000 }, + { 0x8a00, 0x1938, 0x3000 }, + { 0x8a00, 0x1936, 0x2000 }, + { 0x0a00, 0x1935, 0x0000 }, + { 0x0a00, 0x1937, 0x0000 }, + { 0x8c00, 0x193a, 0x2000 }, + { 0x0c00, 0x1939, 0x0000 }, + { 0x0c00, 0x193b, 0x0000 }, + { 0x8700, 0x1953, 0x5000 }, + { 0x8d00, 0x194b, 0x4000 }, + { 0x8d00, 0x1947, 0x3000 }, + { 0x9500, 0x1945, 0x2000 }, + { 0x1500, 0x1944, 0x0000 }, + { 0x0d00, 0x1946, 0x0000 }, + { 0x8d00, 0x1949, 0x2000 }, + { 0x0d00, 0x1948, 0x0000 }, + { 0x0d00, 0x194a, 0x0000 }, + { 0x8d00, 0x194f, 0x3000 }, + { 0x8d00, 0x194d, 0x2000 }, + { 0x0d00, 0x194c, 0x0000 }, + { 0x0d00, 0x194e, 0x0000 }, + { 0x8700, 0x1951, 0x2000 }, + { 0x0700, 0x1950, 0x0000 }, + { 0x0700, 0x1952, 0x0000 }, + { 0x8700, 0x195b, 0x4000 }, + { 0x8700, 0x1957, 0x3000 }, + { 0x8700, 0x1955, 0x2000 }, + { 0x0700, 0x1954, 0x0000 }, + { 0x0700, 0x1956, 0x0000 }, + { 0x8700, 0x1959, 0x2000 }, + { 0x0700, 0x1958, 0x0000 }, + { 0x0700, 0x195a, 0x0000 }, + { 0x8700, 0x195f, 0x3000 }, + { 0x8700, 0x195d, 0x2000 }, + { 0x0700, 0x195c, 0x0000 }, + { 0x0700, 0x195e, 0x0000 }, + { 0x8700, 0x1961, 0x2000 }, + { 0x0700, 0x1960, 0x0000 }, + { 0x0700, 0x1962, 0x0000 }, + { 0x9a00, 0x19f0, 0x6000 }, + { 0x9a00, 0x19e0, 0x5000 }, + { 0x8700, 0x196b, 0x4000 }, + { 0x8700, 0x1967, 0x3000 }, + { 0x8700, 0x1965, 0x2000 }, + { 0x0700, 0x1964, 0x0000 }, + { 0x0700, 0x1966, 0x0000 }, + { 0x8700, 0x1969, 0x2000 }, + { 0x0700, 0x1968, 0x0000 }, + { 0x0700, 0x196a, 0x0000 }, + { 0x8700, 0x1971, 0x3000 }, + { 0x8700, 0x196d, 0x2000 }, + { 0x0700, 0x196c, 0x0000 }, + { 0x0700, 0x1970, 0x0000 }, + { 0x8700, 0x1973, 0x2000 }, + { 0x0700, 0x1972, 0x0000 }, + { 0x0700, 0x1974, 0x0000 }, + { 0x9a00, 0x19e8, 0x4000 }, + { 0x9a00, 0x19e4, 0x3000 }, + { 0x9a00, 0x19e2, 0x2000 }, + { 0x1a00, 0x19e1, 0x0000 }, + { 0x1a00, 0x19e3, 0x0000 }, + { 0x9a00, 0x19e6, 0x2000 }, + { 0x1a00, 0x19e5, 0x0000 }, + { 0x1a00, 0x19e7, 0x0000 }, + { 0x9a00, 0x19ec, 0x3000 }, + { 0x9a00, 0x19ea, 0x2000 }, + { 0x1a00, 0x19e9, 0x0000 }, + { 0x1a00, 0x19eb, 0x0000 }, + { 0x9a00, 0x19ee, 0x2000 }, + { 0x1a00, 0x19ed, 0x0000 }, + { 0x1a00, 0x19ef, 0x0000 }, + { 0x8500, 0x1d00, 0x5000 }, + { 0x9a00, 0x19f8, 0x4000 }, + { 0x9a00, 0x19f4, 0x3000 }, + { 0x9a00, 0x19f2, 0x2000 }, + { 0x1a00, 0x19f1, 0x0000 }, + { 0x1a00, 0x19f3, 0x0000 }, + { 0x9a00, 0x19f6, 0x2000 }, + { 0x1a00, 0x19f5, 0x0000 }, + { 0x1a00, 0x19f7, 0x0000 }, + { 0x9a00, 0x19fc, 0x3000 }, + { 0x9a00, 0x19fa, 0x2000 }, + { 0x1a00, 0x19f9, 0x0000 }, + { 0x1a00, 0x19fb, 0x0000 }, + { 0x9a00, 0x19fe, 0x2000 }, + { 0x1a00, 0x19fd, 0x0000 }, + { 0x1a00, 0x19ff, 0x0000 }, + { 0x8500, 0x1d08, 0x4000 }, + { 0x8500, 0x1d04, 0x3000 }, + { 0x8500, 0x1d02, 0x2000 }, + { 0x0500, 0x1d01, 0x0000 }, + { 0x0500, 0x1d03, 0x0000 }, + { 0x8500, 0x1d06, 0x2000 }, + { 0x0500, 0x1d05, 0x0000 }, + { 0x0500, 0x1d07, 0x0000 }, + { 0x8500, 0x1d0c, 0x3000 }, + { 0x8500, 0x1d0a, 0x2000 }, + { 0x0500, 0x1d09, 0x0000 }, + { 0x0500, 0x1d0b, 0x0000 }, + { 0x8500, 0x1d0e, 0x2000 }, + { 0x0500, 0x1d0d, 0x0000 }, + { 0x0500, 0x1d0f, 0x0000 }, + { 0x8600, 0x1d50, 0x7000 }, + { 0x8600, 0x1d30, 0x6000 }, + { 0x8500, 0x1d20, 0x5000 }, + { 0x8500, 0x1d18, 0x4000 }, + { 0x8500, 0x1d14, 0x3000 }, + { 0x8500, 0x1d12, 0x2000 }, + { 0x0500, 0x1d11, 0x0000 }, + { 0x0500, 0x1d13, 0x0000 }, + { 0x8500, 0x1d16, 0x2000 }, + { 0x0500, 0x1d15, 0x0000 }, + { 0x0500, 0x1d17, 0x0000 }, + { 0x8500, 0x1d1c, 0x3000 }, + { 0x8500, 0x1d1a, 0x2000 }, + { 0x0500, 0x1d19, 0x0000 }, + { 0x0500, 0x1d1b, 0x0000 }, + { 0x8500, 0x1d1e, 0x2000 }, + { 0x0500, 0x1d1d, 0x0000 }, + { 0x0500, 0x1d1f, 0x0000 }, + { 0x8500, 0x1d28, 0x4000 }, + { 0x8500, 0x1d24, 0x3000 }, + { 0x8500, 0x1d22, 0x2000 }, + { 0x0500, 0x1d21, 0x0000 }, + { 0x0500, 0x1d23, 0x0000 }, + { 0x8500, 0x1d26, 0x2000 }, + { 0x0500, 0x1d25, 0x0000 }, + { 0x0500, 0x1d27, 0x0000 }, + { 0x8600, 0x1d2c, 0x3000 }, + { 0x8500, 0x1d2a, 0x2000 }, + { 0x0500, 0x1d29, 0x0000 }, + { 0x0500, 0x1d2b, 0x0000 }, + { 0x8600, 0x1d2e, 0x2000 }, + { 0x0600, 0x1d2d, 0x0000 }, + { 0x0600, 0x1d2f, 0x0000 }, + { 0x8600, 0x1d40, 0x5000 }, + { 0x8600, 0x1d38, 0x4000 }, + { 0x8600, 0x1d34, 0x3000 }, + { 0x8600, 0x1d32, 0x2000 }, + { 0x0600, 0x1d31, 0x0000 }, + { 0x0600, 0x1d33, 0x0000 }, + { 0x8600, 0x1d36, 0x2000 }, + { 0x0600, 0x1d35, 0x0000 }, + { 0x0600, 0x1d37, 0x0000 }, + { 0x8600, 0x1d3c, 0x3000 }, + { 0x8600, 0x1d3a, 0x2000 }, + { 0x0600, 0x1d39, 0x0000 }, + { 0x0600, 0x1d3b, 0x0000 }, + { 0x8600, 0x1d3e, 0x2000 }, + { 0x0600, 0x1d3d, 0x0000 }, + { 0x0600, 0x1d3f, 0x0000 }, + { 0x8600, 0x1d48, 0x4000 }, + { 0x8600, 0x1d44, 0x3000 }, + { 0x8600, 0x1d42, 0x2000 }, + { 0x0600, 0x1d41, 0x0000 }, + { 0x0600, 0x1d43, 0x0000 }, + { 0x8600, 0x1d46, 0x2000 }, + { 0x0600, 0x1d45, 0x0000 }, + { 0x0600, 0x1d47, 0x0000 }, + { 0x8600, 0x1d4c, 0x3000 }, + { 0x8600, 0x1d4a, 0x2000 }, + { 0x0600, 0x1d49, 0x0000 }, + { 0x0600, 0x1d4b, 0x0000 }, + { 0x8600, 0x1d4e, 0x2000 }, + { 0x0600, 0x1d4d, 0x0000 }, + { 0x0600, 0x1d4f, 0x0000 }, + { 0x8900, 0x1e04, 0x6001 }, + { 0x8600, 0x1d60, 0x5000 }, + { 0x8600, 0x1d58, 0x4000 }, + { 0x8600, 0x1d54, 0x3000 }, + { 0x8600, 0x1d52, 0x2000 }, + { 0x0600, 0x1d51, 0x0000 }, + { 0x0600, 0x1d53, 0x0000 }, + { 0x8600, 0x1d56, 0x2000 }, + { 0x0600, 0x1d55, 0x0000 }, + { 0x0600, 0x1d57, 0x0000 }, + { 0x8600, 0x1d5c, 0x3000 }, + { 0x8600, 0x1d5a, 0x2000 }, + { 0x0600, 0x1d59, 0x0000 }, + { 0x0600, 0x1d5b, 0x0000 }, + { 0x8600, 0x1d5e, 0x2000 }, + { 0x0600, 0x1d5d, 0x0000 }, + { 0x0600, 0x1d5f, 0x0000 }, + { 0x8500, 0x1d68, 0x4000 }, + { 0x8500, 0x1d64, 0x3000 }, + { 0x8500, 0x1d62, 0x2000 }, + { 0x0600, 0x1d61, 0x0000 }, + { 0x0500, 0x1d63, 0x0000 }, + { 0x8500, 0x1d66, 0x2000 }, + { 0x0500, 0x1d65, 0x0000 }, + { 0x0500, 0x1d67, 0x0000 }, + { 0x8900, 0x1e00, 0x3001 }, + { 0x8500, 0x1d6a, 0x2000 }, + { 0x0500, 0x1d69, 0x0000 }, + { 0x0500, 0x1d6b, 0x0000 }, + { 0x8900, 0x1e02, 0x2001 }, + { 0x0500, 0x1e01, 0x0fff }, + { 0x0500, 0x1e03, 0x0fff }, + { 0x8900, 0x1e14, 0x5001 }, + { 0x8900, 0x1e0c, 0x4001 }, + { 0x8900, 0x1e08, 0x3001 }, + { 0x8900, 0x1e06, 0x2001 }, + { 0x0500, 0x1e05, 0x0fff }, + { 0x0500, 0x1e07, 0x0fff }, + { 0x8900, 0x1e0a, 0x2001 }, + { 0x0500, 0x1e09, 0x0fff }, + { 0x0500, 0x1e0b, 0x0fff }, + { 0x8900, 0x1e10, 0x3001 }, + { 0x8900, 0x1e0e, 0x2001 }, + { 0x0500, 0x1e0d, 0x0fff }, + { 0x0500, 0x1e0f, 0x0fff }, + { 0x8900, 0x1e12, 0x2001 }, + { 0x0500, 0x1e11, 0x0fff }, + { 0x0500, 0x1e13, 0x0fff }, + { 0x8900, 0x1e1c, 0x4001 }, + { 0x8900, 0x1e18, 0x3001 }, + { 0x8900, 0x1e16, 0x2001 }, + { 0x0500, 0x1e15, 0x0fff }, + { 0x0500, 0x1e17, 0x0fff }, + { 0x8900, 0x1e1a, 0x2001 }, + { 0x0500, 0x1e19, 0x0fff }, + { 0x0500, 0x1e1b, 0x0fff }, + { 0x8900, 0x1e20, 0x3001 }, + { 0x8900, 0x1e1e, 0x2001 }, + { 0x0500, 0x1e1d, 0x0fff }, + { 0x0500, 0x1e1f, 0x0fff }, + { 0x8900, 0x1e22, 0x2001 }, + { 0x0500, 0x1e21, 0x0fff }, + { 0x0500, 0x1e23, 0x0fff }, + { 0x9600, 0x2045, 0xa000 }, + { 0x8500, 0x1f32, 0x9008 }, + { 0x8900, 0x1ea8, 0x8001 }, + { 0x8900, 0x1e64, 0x7001 }, + { 0x8900, 0x1e44, 0x6001 }, + { 0x8900, 0x1e34, 0x5001 }, + { 0x8900, 0x1e2c, 0x4001 }, + { 0x8900, 0x1e28, 0x3001 }, + { 0x8900, 0x1e26, 0x2001 }, + { 0x0500, 0x1e25, 0x0fff }, + { 0x0500, 0x1e27, 0x0fff }, + { 0x8900, 0x1e2a, 0x2001 }, + { 0x0500, 0x1e29, 0x0fff }, + { 0x0500, 0x1e2b, 0x0fff }, + { 0x8900, 0x1e30, 0x3001 }, + { 0x8900, 0x1e2e, 0x2001 }, + { 0x0500, 0x1e2d, 0x0fff }, + { 0x0500, 0x1e2f, 0x0fff }, + { 0x8900, 0x1e32, 0x2001 }, + { 0x0500, 0x1e31, 0x0fff }, + { 0x0500, 0x1e33, 0x0fff }, + { 0x8900, 0x1e3c, 0x4001 }, + { 0x8900, 0x1e38, 0x3001 }, + { 0x8900, 0x1e36, 0x2001 }, + { 0x0500, 0x1e35, 0x0fff }, + { 0x0500, 0x1e37, 0x0fff }, + { 0x8900, 0x1e3a, 0x2001 }, + { 0x0500, 0x1e39, 0x0fff }, + { 0x0500, 0x1e3b, 0x0fff }, + { 0x8900, 0x1e40, 0x3001 }, + { 0x8900, 0x1e3e, 0x2001 }, + { 0x0500, 0x1e3d, 0x0fff }, + { 0x0500, 0x1e3f, 0x0fff }, + { 0x8900, 0x1e42, 0x2001 }, + { 0x0500, 0x1e41, 0x0fff }, + { 0x0500, 0x1e43, 0x0fff }, + { 0x8900, 0x1e54, 0x5001 }, + { 0x8900, 0x1e4c, 0x4001 }, + { 0x8900, 0x1e48, 0x3001 }, + { 0x8900, 0x1e46, 0x2001 }, + { 0x0500, 0x1e45, 0x0fff }, + { 0x0500, 0x1e47, 0x0fff }, + { 0x8900, 0x1e4a, 0x2001 }, + { 0x0500, 0x1e49, 0x0fff }, + { 0x0500, 0x1e4b, 0x0fff }, + { 0x8900, 0x1e50, 0x3001 }, + { 0x8900, 0x1e4e, 0x2001 }, + { 0x0500, 0x1e4d, 0x0fff }, + { 0x0500, 0x1e4f, 0x0fff }, + { 0x8900, 0x1e52, 0x2001 }, + { 0x0500, 0x1e51, 0x0fff }, + { 0x0500, 0x1e53, 0x0fff }, + { 0x8900, 0x1e5c, 0x4001 }, + { 0x8900, 0x1e58, 0x3001 }, + { 0x8900, 0x1e56, 0x2001 }, + { 0x0500, 0x1e55, 0x0fff }, + { 0x0500, 0x1e57, 0x0fff }, + { 0x8900, 0x1e5a, 0x2001 }, + { 0x0500, 0x1e59, 0x0fff }, + { 0x0500, 0x1e5b, 0x0fff }, + { 0x8900, 0x1e60, 0x3001 }, + { 0x8900, 0x1e5e, 0x2001 }, + { 0x0500, 0x1e5d, 0x0fff }, + { 0x0500, 0x1e5f, 0x0fff }, + { 0x8900, 0x1e62, 0x2001 }, + { 0x0500, 0x1e61, 0x0fff }, + { 0x0500, 0x1e63, 0x0fff }, + { 0x8900, 0x1e84, 0x6001 }, + { 0x8900, 0x1e74, 0x5001 }, + { 0x8900, 0x1e6c, 0x4001 }, + { 0x8900, 0x1e68, 0x3001 }, + { 0x8900, 0x1e66, 0x2001 }, + { 0x0500, 0x1e65, 0x0fff }, + { 0x0500, 0x1e67, 0x0fff }, + { 0x8900, 0x1e6a, 0x2001 }, + { 0x0500, 0x1e69, 0x0fff }, + { 0x0500, 0x1e6b, 0x0fff }, + { 0x8900, 0x1e70, 0x3001 }, + { 0x8900, 0x1e6e, 0x2001 }, + { 0x0500, 0x1e6d, 0x0fff }, + { 0x0500, 0x1e6f, 0x0fff }, + { 0x8900, 0x1e72, 0x2001 }, + { 0x0500, 0x1e71, 0x0fff }, + { 0x0500, 0x1e73, 0x0fff }, + { 0x8900, 0x1e7c, 0x4001 }, + { 0x8900, 0x1e78, 0x3001 }, + { 0x8900, 0x1e76, 0x2001 }, + { 0x0500, 0x1e75, 0x0fff }, + { 0x0500, 0x1e77, 0x0fff }, + { 0x8900, 0x1e7a, 0x2001 }, + { 0x0500, 0x1e79, 0x0fff }, + { 0x0500, 0x1e7b, 0x0fff }, + { 0x8900, 0x1e80, 0x3001 }, + { 0x8900, 0x1e7e, 0x2001 }, + { 0x0500, 0x1e7d, 0x0fff }, + { 0x0500, 0x1e7f, 0x0fff }, + { 0x8900, 0x1e82, 0x2001 }, + { 0x0500, 0x1e81, 0x0fff }, + { 0x0500, 0x1e83, 0x0fff }, + { 0x8900, 0x1e94, 0x5001 }, + { 0x8900, 0x1e8c, 0x4001 }, + { 0x8900, 0x1e88, 0x3001 }, + { 0x8900, 0x1e86, 0x2001 }, + { 0x0500, 0x1e85, 0x0fff }, + { 0x0500, 0x1e87, 0x0fff }, + { 0x8900, 0x1e8a, 0x2001 }, + { 0x0500, 0x1e89, 0x0fff }, + { 0x0500, 0x1e8b, 0x0fff }, + { 0x8900, 0x1e90, 0x3001 }, + { 0x8900, 0x1e8e, 0x2001 }, + { 0x0500, 0x1e8d, 0x0fff }, + { 0x0500, 0x1e8f, 0x0fff }, + { 0x8900, 0x1e92, 0x2001 }, + { 0x0500, 0x1e91, 0x0fff }, + { 0x0500, 0x1e93, 0x0fff }, + { 0x8900, 0x1ea0, 0x4001 }, + { 0x8500, 0x1e98, 0x3000 }, + { 0x8500, 0x1e96, 0x2000 }, + { 0x0500, 0x1e95, 0x0fff }, + { 0x0500, 0x1e97, 0x0000 }, + { 0x8500, 0x1e9a, 0x2000 }, + { 0x0500, 0x1e99, 0x0000 }, + { 0x0500, 0x1e9b, 0x0fc5 }, + { 0x8900, 0x1ea4, 0x3001 }, + { 0x8900, 0x1ea2, 0x2001 }, + { 0x0500, 0x1ea1, 0x0fff }, + { 0x0500, 0x1ea3, 0x0fff }, + { 0x8900, 0x1ea6, 0x2001 }, + { 0x0500, 0x1ea5, 0x0fff }, + { 0x0500, 0x1ea7, 0x0fff }, + { 0x8900, 0x1ee8, 0x7001 }, + { 0x8900, 0x1ec8, 0x6001 }, + { 0x8900, 0x1eb8, 0x5001 }, + { 0x8900, 0x1eb0, 0x4001 }, + { 0x8900, 0x1eac, 0x3001 }, + { 0x8900, 0x1eaa, 0x2001 }, + { 0x0500, 0x1ea9, 0x0fff }, + { 0x0500, 0x1eab, 0x0fff }, + { 0x8900, 0x1eae, 0x2001 }, + { 0x0500, 0x1ead, 0x0fff }, + { 0x0500, 0x1eaf, 0x0fff }, + { 0x8900, 0x1eb4, 0x3001 }, + { 0x8900, 0x1eb2, 0x2001 }, + { 0x0500, 0x1eb1, 0x0fff }, + { 0x0500, 0x1eb3, 0x0fff }, + { 0x8900, 0x1eb6, 0x2001 }, + { 0x0500, 0x1eb5, 0x0fff }, + { 0x0500, 0x1eb7, 0x0fff }, + { 0x8900, 0x1ec0, 0x4001 }, + { 0x8900, 0x1ebc, 0x3001 }, + { 0x8900, 0x1eba, 0x2001 }, + { 0x0500, 0x1eb9, 0x0fff }, + { 0x0500, 0x1ebb, 0x0fff }, + { 0x8900, 0x1ebe, 0x2001 }, + { 0x0500, 0x1ebd, 0x0fff }, + { 0x0500, 0x1ebf, 0x0fff }, + { 0x8900, 0x1ec4, 0x3001 }, + { 0x8900, 0x1ec2, 0x2001 }, + { 0x0500, 0x1ec1, 0x0fff }, + { 0x0500, 0x1ec3, 0x0fff }, + { 0x8900, 0x1ec6, 0x2001 }, + { 0x0500, 0x1ec5, 0x0fff }, + { 0x0500, 0x1ec7, 0x0fff }, + { 0x8900, 0x1ed8, 0x5001 }, + { 0x8900, 0x1ed0, 0x4001 }, + { 0x8900, 0x1ecc, 0x3001 }, + { 0x8900, 0x1eca, 0x2001 }, + { 0x0500, 0x1ec9, 0x0fff }, + { 0x0500, 0x1ecb, 0x0fff }, + { 0x8900, 0x1ece, 0x2001 }, + { 0x0500, 0x1ecd, 0x0fff }, + { 0x0500, 0x1ecf, 0x0fff }, + { 0x8900, 0x1ed4, 0x3001 }, + { 0x8900, 0x1ed2, 0x2001 }, + { 0x0500, 0x1ed1, 0x0fff }, + { 0x0500, 0x1ed3, 0x0fff }, + { 0x8900, 0x1ed6, 0x2001 }, + { 0x0500, 0x1ed5, 0x0fff }, + { 0x0500, 0x1ed7, 0x0fff }, + { 0x8900, 0x1ee0, 0x4001 }, + { 0x8900, 0x1edc, 0x3001 }, + { 0x8900, 0x1eda, 0x2001 }, + { 0x0500, 0x1ed9, 0x0fff }, + { 0x0500, 0x1edb, 0x0fff }, + { 0x8900, 0x1ede, 0x2001 }, + { 0x0500, 0x1edd, 0x0fff }, + { 0x0500, 0x1edf, 0x0fff }, + { 0x8900, 0x1ee4, 0x3001 }, + { 0x8900, 0x1ee2, 0x2001 }, + { 0x0500, 0x1ee1, 0x0fff }, + { 0x0500, 0x1ee3, 0x0fff }, + { 0x8900, 0x1ee6, 0x2001 }, + { 0x0500, 0x1ee5, 0x0fff }, + { 0x0500, 0x1ee7, 0x0fff }, + { 0x8900, 0x1f0e, 0x6ff8 }, + { 0x8900, 0x1ef8, 0x5001 }, + { 0x8900, 0x1ef0, 0x4001 }, + { 0x8900, 0x1eec, 0x3001 }, + { 0x8900, 0x1eea, 0x2001 }, + { 0x0500, 0x1ee9, 0x0fff }, + { 0x0500, 0x1eeb, 0x0fff }, + { 0x8900, 0x1eee, 0x2001 }, + { 0x0500, 0x1eed, 0x0fff }, + { 0x0500, 0x1eef, 0x0fff }, + { 0x8900, 0x1ef4, 0x3001 }, + { 0x8900, 0x1ef2, 0x2001 }, + { 0x0500, 0x1ef1, 0x0fff }, + { 0x0500, 0x1ef3, 0x0fff }, + { 0x8900, 0x1ef6, 0x2001 }, + { 0x0500, 0x1ef5, 0x0fff }, + { 0x0500, 0x1ef7, 0x0fff }, + { 0x8500, 0x1f06, 0x4008 }, + { 0x8500, 0x1f02, 0x3008 }, + { 0x8500, 0x1f00, 0x2008 }, + { 0x0500, 0x1ef9, 0x0fff }, + { 0x0500, 0x1f01, 0x0008 }, + { 0x8500, 0x1f04, 0x2008 }, + { 0x0500, 0x1f03, 0x0008 }, + { 0x0500, 0x1f05, 0x0008 }, + { 0x8900, 0x1f0a, 0x3ff8 }, + { 0x8900, 0x1f08, 0x2ff8 }, + { 0x0500, 0x1f07, 0x0008 }, + { 0x0900, 0x1f09, 0x0ff8 }, + { 0x8900, 0x1f0c, 0x2ff8 }, + { 0x0900, 0x1f0b, 0x0ff8 }, + { 0x0900, 0x1f0d, 0x0ff8 }, + { 0x8500, 0x1f22, 0x5008 }, + { 0x8900, 0x1f18, 0x4ff8 }, + { 0x8500, 0x1f12, 0x3008 }, + { 0x8500, 0x1f10, 0x2008 }, + { 0x0900, 0x1f0f, 0x0ff8 }, + { 0x0500, 0x1f11, 0x0008 }, + { 0x8500, 0x1f14, 0x2008 }, + { 0x0500, 0x1f13, 0x0008 }, + { 0x0500, 0x1f15, 0x0008 }, + { 0x8900, 0x1f1c, 0x3ff8 }, + { 0x8900, 0x1f1a, 0x2ff8 }, + { 0x0900, 0x1f19, 0x0ff8 }, + { 0x0900, 0x1f1b, 0x0ff8 }, + { 0x8500, 0x1f20, 0x2008 }, + { 0x0900, 0x1f1d, 0x0ff8 }, + { 0x0500, 0x1f21, 0x0008 }, + { 0x8900, 0x1f2a, 0x4ff8 }, + { 0x8500, 0x1f26, 0x3008 }, + { 0x8500, 0x1f24, 0x2008 }, + { 0x0500, 0x1f23, 0x0008 }, + { 0x0500, 0x1f25, 0x0008 }, + { 0x8900, 0x1f28, 0x2ff8 }, + { 0x0500, 0x1f27, 0x0008 }, + { 0x0900, 0x1f29, 0x0ff8 }, + { 0x8900, 0x1f2e, 0x3ff8 }, + { 0x8900, 0x1f2c, 0x2ff8 }, + { 0x0900, 0x1f2b, 0x0ff8 }, + { 0x0900, 0x1f2d, 0x0ff8 }, + { 0x8500, 0x1f30, 0x2008 }, + { 0x0900, 0x1f2f, 0x0ff8 }, + { 0x0500, 0x1f31, 0x0008 }, + { 0x9800, 0x1fbd, 0x8000 }, + { 0x8500, 0x1f7a, 0x7070 }, + { 0x8500, 0x1f56, 0x6000 }, + { 0x8500, 0x1f42, 0x5008 }, + { 0x8900, 0x1f3a, 0x4ff8 }, + { 0x8500, 0x1f36, 0x3008 }, + { 0x8500, 0x1f34, 0x2008 }, + { 0x0500, 0x1f33, 0x0008 }, + { 0x0500, 0x1f35, 0x0008 }, + { 0x8900, 0x1f38, 0x2ff8 }, + { 0x0500, 0x1f37, 0x0008 }, + { 0x0900, 0x1f39, 0x0ff8 }, + { 0x8900, 0x1f3e, 0x3ff8 }, + { 0x8900, 0x1f3c, 0x2ff8 }, + { 0x0900, 0x1f3b, 0x0ff8 }, + { 0x0900, 0x1f3d, 0x0ff8 }, + { 0x8500, 0x1f40, 0x2008 }, + { 0x0900, 0x1f3f, 0x0ff8 }, + { 0x0500, 0x1f41, 0x0008 }, + { 0x8900, 0x1f4c, 0x4ff8 }, + { 0x8900, 0x1f48, 0x3ff8 }, + { 0x8500, 0x1f44, 0x2008 }, + { 0x0500, 0x1f43, 0x0008 }, + { 0x0500, 0x1f45, 0x0008 }, + { 0x8900, 0x1f4a, 0x2ff8 }, + { 0x0900, 0x1f49, 0x0ff8 }, + { 0x0900, 0x1f4b, 0x0ff8 }, + { 0x8500, 0x1f52, 0x3000 }, + { 0x8500, 0x1f50, 0x2000 }, + { 0x0900, 0x1f4d, 0x0ff8 }, + { 0x0500, 0x1f51, 0x0008 }, + { 0x8500, 0x1f54, 0x2000 }, + { 0x0500, 0x1f53, 0x0008 }, + { 0x0500, 0x1f55, 0x0008 }, + { 0x8900, 0x1f6a, 0x5ff8 }, + { 0x8500, 0x1f62, 0x4008 }, + { 0x8900, 0x1f5d, 0x3ff8 }, + { 0x8900, 0x1f59, 0x2ff8 }, + { 0x0500, 0x1f57, 0x0008 }, + { 0x0900, 0x1f5b, 0x0ff8 }, + { 0x8500, 0x1f60, 0x2008 }, + { 0x0900, 0x1f5f, 0x0ff8 }, + { 0x0500, 0x1f61, 0x0008 }, + { 0x8500, 0x1f66, 0x3008 }, + { 0x8500, 0x1f64, 0x2008 }, + { 0x0500, 0x1f63, 0x0008 }, + { 0x0500, 0x1f65, 0x0008 }, + { 0x8900, 0x1f68, 0x2ff8 }, + { 0x0500, 0x1f67, 0x0008 }, + { 0x0900, 0x1f69, 0x0ff8 }, + { 0x8500, 0x1f72, 0x4056 }, + { 0x8900, 0x1f6e, 0x3ff8 }, + { 0x8900, 0x1f6c, 0x2ff8 }, + { 0x0900, 0x1f6b, 0x0ff8 }, + { 0x0900, 0x1f6d, 0x0ff8 }, + { 0x8500, 0x1f70, 0x204a }, + { 0x0900, 0x1f6f, 0x0ff8 }, + { 0x0500, 0x1f71, 0x004a }, + { 0x8500, 0x1f76, 0x3064 }, + { 0x8500, 0x1f74, 0x2056 }, + { 0x0500, 0x1f73, 0x0056 }, + { 0x0500, 0x1f75, 0x0056 }, + { 0x8500, 0x1f78, 0x2080 }, + { 0x0500, 0x1f77, 0x0064 }, + { 0x0500, 0x1f79, 0x0080 }, + { 0x8800, 0x1f9c, 0x6000 }, + { 0x8800, 0x1f8c, 0x5000 }, + { 0x8500, 0x1f84, 0x4008 }, + { 0x8500, 0x1f80, 0x3008 }, + { 0x8500, 0x1f7c, 0x207e }, + { 0x0500, 0x1f7b, 0x0070 }, + { 0x0500, 0x1f7d, 0x007e }, + { 0x8500, 0x1f82, 0x2008 }, + { 0x0500, 0x1f81, 0x0008 }, + { 0x0500, 0x1f83, 0x0008 }, + { 0x8800, 0x1f88, 0x3000 }, + { 0x8500, 0x1f86, 0x2008 }, + { 0x0500, 0x1f85, 0x0008 }, + { 0x0500, 0x1f87, 0x0008 }, + { 0x8800, 0x1f8a, 0x2000 }, + { 0x0800, 0x1f89, 0x0000 }, + { 0x0800, 0x1f8b, 0x0000 }, + { 0x8500, 0x1f94, 0x4008 }, + { 0x8500, 0x1f90, 0x3008 }, + { 0x8800, 0x1f8e, 0x2000 }, + { 0x0800, 0x1f8d, 0x0000 }, + { 0x0800, 0x1f8f, 0x0000 }, + { 0x8500, 0x1f92, 0x2008 }, + { 0x0500, 0x1f91, 0x0008 }, + { 0x0500, 0x1f93, 0x0008 }, + { 0x8800, 0x1f98, 0x3000 }, + { 0x8500, 0x1f96, 0x2008 }, + { 0x0500, 0x1f95, 0x0008 }, + { 0x0500, 0x1f97, 0x0008 }, + { 0x8800, 0x1f9a, 0x2000 }, + { 0x0800, 0x1f99, 0x0000 }, + { 0x0800, 0x1f9b, 0x0000 }, + { 0x8800, 0x1fac, 0x5000 }, + { 0x8500, 0x1fa4, 0x4008 }, + { 0x8500, 0x1fa0, 0x3008 }, + { 0x8800, 0x1f9e, 0x2000 }, + { 0x0800, 0x1f9d, 0x0000 }, + { 0x0800, 0x1f9f, 0x0000 }, + { 0x8500, 0x1fa2, 0x2008 }, + { 0x0500, 0x1fa1, 0x0008 }, + { 0x0500, 0x1fa3, 0x0008 }, + { 0x8800, 0x1fa8, 0x3000 }, + { 0x8500, 0x1fa6, 0x2008 }, + { 0x0500, 0x1fa5, 0x0008 }, + { 0x0500, 0x1fa7, 0x0008 }, + { 0x8800, 0x1faa, 0x2000 }, + { 0x0800, 0x1fa9, 0x0000 }, + { 0x0800, 0x1fab, 0x0000 }, + { 0x8500, 0x1fb4, 0x4000 }, + { 0x8500, 0x1fb0, 0x3008 }, + { 0x8800, 0x1fae, 0x2000 }, + { 0x0800, 0x1fad, 0x0000 }, + { 0x0800, 0x1faf, 0x0000 }, + { 0x8500, 0x1fb2, 0x2000 }, + { 0x0500, 0x1fb1, 0x0008 }, + { 0x0500, 0x1fb3, 0x0009 }, + { 0x8900, 0x1fb9, 0x3ff8 }, + { 0x8500, 0x1fb7, 0x2000 }, + { 0x0500, 0x1fb6, 0x0000 }, + { 0x0900, 0x1fb8, 0x0ff8 }, + { 0x8900, 0x1fbb, 0x2fb6 }, + { 0x0900, 0x1fba, 0x0fb6 }, + { 0x0800, 0x1fbc, 0x0000 }, + { 0x9d00, 0x2005, 0x7000 }, + { 0x8500, 0x1fe1, 0x6008 }, + { 0x9800, 0x1fce, 0x5000 }, + { 0x8500, 0x1fc6, 0x4000 }, + { 0x9800, 0x1fc1, 0x3000 }, + { 0x9800, 0x1fbf, 0x2000 }, + { 0x0500, 0x1fbe, 0x0000 }, + { 0x1800, 0x1fc0, 0x0000 }, + { 0x8500, 0x1fc3, 0x2009 }, + { 0x0500, 0x1fc2, 0x0000 }, + { 0x0500, 0x1fc4, 0x0000 }, + { 0x8900, 0x1fca, 0x3faa }, + { 0x8900, 0x1fc8, 0x2faa }, + { 0x0500, 0x1fc7, 0x0000 }, + { 0x0900, 0x1fc9, 0x0faa }, + { 0x8800, 0x1fcc, 0x2000 }, + { 0x0900, 0x1fcb, 0x0faa }, + { 0x1800, 0x1fcd, 0x0000 }, + { 0x8900, 0x1fd8, 0x4ff8 }, + { 0x8500, 0x1fd2, 0x3000 }, + { 0x8500, 0x1fd0, 0x2008 }, + { 0x1800, 0x1fcf, 0x0000 }, + { 0x0500, 0x1fd1, 0x0008 }, + { 0x8500, 0x1fd6, 0x2000 }, + { 0x0500, 0x1fd3, 0x0000 }, + { 0x0500, 0x1fd7, 0x0000 }, + { 0x9800, 0x1fdd, 0x3000 }, + { 0x8900, 0x1fda, 0x2f9c }, + { 0x0900, 0x1fd9, 0x0ff8 }, + { 0x0900, 0x1fdb, 0x0f9c }, + { 0x9800, 0x1fdf, 0x2000 }, + { 0x1800, 0x1fde, 0x0000 }, + { 0x0500, 0x1fe0, 0x0008 }, + { 0x8500, 0x1ff3, 0x5009 }, + { 0x8900, 0x1fe9, 0x4ff8 }, + { 0x8500, 0x1fe5, 0x3007 }, + { 0x8500, 0x1fe3, 0x2000 }, + { 0x0500, 0x1fe2, 0x0000 }, + { 0x0500, 0x1fe4, 0x0000 }, + { 0x8500, 0x1fe7, 0x2000 }, + { 0x0500, 0x1fe6, 0x0000 }, + { 0x0900, 0x1fe8, 0x0ff8 }, + { 0x9800, 0x1fed, 0x3000 }, + { 0x8900, 0x1feb, 0x2f90 }, + { 0x0900, 0x1fea, 0x0f90 }, + { 0x0900, 0x1fec, 0x0ff9 }, + { 0x9800, 0x1fef, 0x2000 }, + { 0x1800, 0x1fee, 0x0000 }, + { 0x0500, 0x1ff2, 0x0000 }, + { 0x8800, 0x1ffc, 0x4000 }, + { 0x8900, 0x1ff8, 0x3f80 }, + { 0x8500, 0x1ff6, 0x2000 }, + { 0x0500, 0x1ff4, 0x0000 }, + { 0x0500, 0x1ff7, 0x0000 }, + { 0x8900, 0x1ffa, 0x2f82 }, + { 0x0900, 0x1ff9, 0x0f80 }, + { 0x0900, 0x1ffb, 0x0f82 }, + { 0x9d00, 0x2001, 0x3000 }, + { 0x9800, 0x1ffe, 0x2000 }, + { 0x1800, 0x1ffd, 0x0000 }, + { 0x1d00, 0x2000, 0x0000 }, + { 0x9d00, 0x2003, 0x2000 }, + { 0x1d00, 0x2002, 0x0000 }, + { 0x1d00, 0x2004, 0x0000 }, + { 0x9500, 0x2025, 0x6000 }, + { 0x9100, 0x2015, 0x5000 }, + { 0x8100, 0x200d, 0x4000 }, + { 0x9d00, 0x2009, 0x3000 }, + { 0x9d00, 0x2007, 0x2000 }, + { 0x1d00, 0x2006, 0x0000 }, + { 0x1d00, 0x2008, 0x0000 }, + { 0x9d00, 0x200b, 0x2000 }, + { 0x1d00, 0x200a, 0x0000 }, + { 0x0100, 0x200c, 0x0000 }, + { 0x9100, 0x2011, 0x3000 }, + { 0x8100, 0x200f, 0x2000 }, + { 0x0100, 0x200e, 0x0000 }, + { 0x1100, 0x2010, 0x0000 }, + { 0x9100, 0x2013, 0x2000 }, + { 0x1100, 0x2012, 0x0000 }, + { 0x1100, 0x2014, 0x0000 }, + { 0x9300, 0x201d, 0x4000 }, + { 0x9300, 0x2019, 0x3000 }, + { 0x9500, 0x2017, 0x2000 }, + { 0x1500, 0x2016, 0x0000 }, + { 0x1400, 0x2018, 0x0000 }, + { 0x9400, 0x201b, 0x2000 }, + { 0x1600, 0x201a, 0x0000 }, + { 0x1400, 0x201c, 0x0000 }, + { 0x9500, 0x2021, 0x3000 }, + { 0x9400, 0x201f, 0x2000 }, + { 0x1600, 0x201e, 0x0000 }, + { 0x1500, 0x2020, 0x0000 }, + { 0x9500, 0x2023, 0x2000 }, + { 0x1500, 0x2022, 0x0000 }, + { 0x1500, 0x2024, 0x0000 }, + { 0x9500, 0x2035, 0x5000 }, + { 0x8100, 0x202d, 0x4000 }, + { 0x9c00, 0x2029, 0x3000 }, + { 0x9500, 0x2027, 0x2000 }, + { 0x1500, 0x2026, 0x0000 }, + { 0x1b00, 0x2028, 0x0000 }, + { 0x8100, 0x202b, 0x2000 }, + { 0x0100, 0x202a, 0x0000 }, + { 0x0100, 0x202c, 0x0000 }, + { 0x9500, 0x2031, 0x3000 }, + { 0x9d00, 0x202f, 0x2000 }, + { 0x0100, 0x202e, 0x0000 }, + { 0x1500, 0x2030, 0x0000 }, + { 0x9500, 0x2033, 0x2000 }, + { 0x1500, 0x2032, 0x0000 }, + { 0x1500, 0x2034, 0x0000 }, + { 0x9500, 0x203d, 0x4000 }, + { 0x9400, 0x2039, 0x3000 }, + { 0x9500, 0x2037, 0x2000 }, + { 0x1500, 0x2036, 0x0000 }, + { 0x1500, 0x2038, 0x0000 }, + { 0x9500, 0x203b, 0x2000 }, + { 0x1300, 0x203a, 0x0000 }, + { 0x1500, 0x203c, 0x0000 }, + { 0x9500, 0x2041, 0x3000 }, + { 0x9000, 0x203f, 0x2000 }, + { 0x1500, 0x203e, 0x0000 }, + { 0x1000, 0x2040, 0x0000 }, + { 0x9500, 0x2043, 0x2000 }, + { 0x1500, 0x2042, 0x0000 }, + { 0x1900, 0x2044, 0x0000 }, + { 0x9900, 0x21ae, 0x9000 }, + { 0x8900, 0x211a, 0x8000 }, + { 0x9700, 0x20a7, 0x7000 }, + { 0x8f00, 0x2076, 0x6000 }, + { 0x9500, 0x2057, 0x5000 }, + { 0x9500, 0x204d, 0x4000 }, + { 0x9500, 0x2049, 0x3000 }, + { 0x9500, 0x2047, 0x2000 }, + { 0x1200, 0x2046, 0x0000 }, + { 0x1500, 0x2048, 0x0000 }, + { 0x9500, 0x204b, 0x2000 }, + { 0x1500, 0x204a, 0x0000 }, + { 0x1500, 0x204c, 0x0000 }, + { 0x9500, 0x2051, 0x3000 }, + { 0x9500, 0x204f, 0x2000 }, + { 0x1500, 0x204e, 0x0000 }, + { 0x1500, 0x2050, 0x0000 }, + { 0x9500, 0x2053, 0x2000 }, + { 0x1900, 0x2052, 0x0000 }, + { 0x1000, 0x2054, 0x0000 }, + { 0x8100, 0x206c, 0x4000 }, + { 0x8100, 0x2062, 0x3000 }, + { 0x8100, 0x2060, 0x2000 }, + { 0x1d00, 0x205f, 0x0000 }, + { 0x0100, 0x2061, 0x0000 }, + { 0x8100, 0x206a, 0x2000 }, + { 0x0100, 0x2063, 0x0000 }, + { 0x0100, 0x206b, 0x0000 }, + { 0x8f00, 0x2070, 0x3000 }, + { 0x8100, 0x206e, 0x2000 }, + { 0x0100, 0x206d, 0x0000 }, + { 0x0100, 0x206f, 0x0000 }, + { 0x8f00, 0x2074, 0x2000 }, + { 0x0500, 0x2071, 0x0000 }, + { 0x0f00, 0x2075, 0x0000 }, + { 0x8f00, 0x2086, 0x5000 }, + { 0x9200, 0x207e, 0x4000 }, + { 0x9900, 0x207a, 0x3000 }, + { 0x8f00, 0x2078, 0x2000 }, + { 0x0f00, 0x2077, 0x0000 }, + { 0x0f00, 0x2079, 0x0000 }, + { 0x9900, 0x207c, 0x2000 }, + { 0x1900, 0x207b, 0x0000 }, + { 0x1600, 0x207d, 0x0000 }, + { 0x8f00, 0x2082, 0x3000 }, + { 0x8f00, 0x2080, 0x2000 }, + { 0x0500, 0x207f, 0x0000 }, + { 0x0f00, 0x2081, 0x0000 }, + { 0x8f00, 0x2084, 0x2000 }, + { 0x0f00, 0x2083, 0x0000 }, + { 0x0f00, 0x2085, 0x0000 }, + { 0x9200, 0x208e, 0x4000 }, + { 0x9900, 0x208a, 0x3000 }, + { 0x8f00, 0x2088, 0x2000 }, + { 0x0f00, 0x2087, 0x0000 }, + { 0x0f00, 0x2089, 0x0000 }, + { 0x9900, 0x208c, 0x2000 }, + { 0x1900, 0x208b, 0x0000 }, + { 0x1600, 0x208d, 0x0000 }, + { 0x9700, 0x20a3, 0x3000 }, + { 0x9700, 0x20a1, 0x2000 }, + { 0x1700, 0x20a0, 0x0000 }, + { 0x1700, 0x20a2, 0x0000 }, + { 0x9700, 0x20a5, 0x2000 }, + { 0x1700, 0x20a4, 0x0000 }, + { 0x1700, 0x20a6, 0x0000 }, + { 0x8c00, 0x20e5, 0x6000 }, + { 0x8c00, 0x20d5, 0x5000 }, + { 0x9700, 0x20af, 0x4000 }, + { 0x9700, 0x20ab, 0x3000 }, + { 0x9700, 0x20a9, 0x2000 }, + { 0x1700, 0x20a8, 0x0000 }, + { 0x1700, 0x20aa, 0x0000 }, + { 0x9700, 0x20ad, 0x2000 }, + { 0x1700, 0x20ac, 0x0000 }, + { 0x1700, 0x20ae, 0x0000 }, + { 0x8c00, 0x20d1, 0x3000 }, + { 0x9700, 0x20b1, 0x2000 }, + { 0x1700, 0x20b0, 0x0000 }, + { 0x0c00, 0x20d0, 0x0000 }, + { 0x8c00, 0x20d3, 0x2000 }, + { 0x0c00, 0x20d2, 0x0000 }, + { 0x0c00, 0x20d4, 0x0000 }, + { 0x8b00, 0x20dd, 0x4000 }, + { 0x8c00, 0x20d9, 0x3000 }, + { 0x8c00, 0x20d7, 0x2000 }, + { 0x0c00, 0x20d6, 0x0000 }, + { 0x0c00, 0x20d8, 0x0000 }, + { 0x8c00, 0x20db, 0x2000 }, + { 0x0c00, 0x20da, 0x0000 }, + { 0x0c00, 0x20dc, 0x0000 }, + { 0x8c00, 0x20e1, 0x3000 }, + { 0x8b00, 0x20df, 0x2000 }, + { 0x0b00, 0x20de, 0x0000 }, + { 0x0b00, 0x20e0, 0x0000 }, + { 0x8b00, 0x20e3, 0x2000 }, + { 0x0b00, 0x20e2, 0x0000 }, + { 0x0b00, 0x20e4, 0x0000 }, + { 0x8500, 0x210a, 0x5000 }, + { 0x8900, 0x2102, 0x4000 }, + { 0x8c00, 0x20e9, 0x3000 }, + { 0x8c00, 0x20e7, 0x2000 }, + { 0x0c00, 0x20e6, 0x0000 }, + { 0x0c00, 0x20e8, 0x0000 }, + { 0x9a00, 0x2100, 0x2000 }, + { 0x0c00, 0x20ea, 0x0000 }, + { 0x1a00, 0x2101, 0x0000 }, + { 0x9a00, 0x2106, 0x3000 }, + { 0x9a00, 0x2104, 0x2000 }, + { 0x1a00, 0x2103, 0x0000 }, + { 0x1a00, 0x2105, 0x0000 }, + { 0x9a00, 0x2108, 0x2000 }, + { 0x0900, 0x2107, 0x0000 }, + { 0x1a00, 0x2109, 0x0000 }, + { 0x8900, 0x2112, 0x4000 }, + { 0x8500, 0x210e, 0x3000 }, + { 0x8900, 0x210c, 0x2000 }, + { 0x0900, 0x210b, 0x0000 }, + { 0x0900, 0x210d, 0x0000 }, + { 0x8900, 0x2110, 0x2000 }, + { 0x0500, 0x210f, 0x0000 }, + { 0x0900, 0x2111, 0x0000 }, + { 0x9a00, 0x2116, 0x3000 }, + { 0x9a00, 0x2114, 0x2000 }, + { 0x0500, 0x2113, 0x0000 }, + { 0x0900, 0x2115, 0x0000 }, + { 0x9a00, 0x2118, 0x2000 }, + { 0x1a00, 0x2117, 0x0000 }, + { 0x0900, 0x2119, 0x0000 }, + { 0x8e00, 0x2162, 0x7000 }, + { 0x9a00, 0x213a, 0x6000 }, + { 0x8900, 0x212a, 0x5000 }, + { 0x9a00, 0x2122, 0x4000 }, + { 0x9a00, 0x211e, 0x3000 }, + { 0x8900, 0x211c, 0x2000 }, + { 0x0900, 0x211b, 0x0000 }, + { 0x0900, 0x211d, 0x0000 }, + { 0x9a00, 0x2120, 0x2000 }, + { 0x1a00, 0x211f, 0x0000 }, + { 0x1a00, 0x2121, 0x0000 }, + { 0x8900, 0x2126, 0x3000 }, + { 0x8900, 0x2124, 0x2000 }, + { 0x1a00, 0x2123, 0x0000 }, + { 0x1a00, 0x2125, 0x0000 }, + { 0x8900, 0x2128, 0x2000 }, + { 0x1a00, 0x2127, 0x0000 }, + { 0x1a00, 0x2129, 0x0000 }, + { 0x9a00, 0x2132, 0x4000 }, + { 0x9a00, 0x212e, 0x3000 }, + { 0x8900, 0x212c, 0x2000 }, + { 0x0900, 0x212b, 0x0000 }, + { 0x0900, 0x212d, 0x0000 }, + { 0x8900, 0x2130, 0x2000 }, + { 0x0500, 0x212f, 0x0000 }, + { 0x0900, 0x2131, 0x0000 }, + { 0x8700, 0x2136, 0x3000 }, + { 0x8500, 0x2134, 0x2000 }, + { 0x0900, 0x2133, 0x0000 }, + { 0x0700, 0x2135, 0x0000 }, + { 0x8700, 0x2138, 0x2000 }, + { 0x0700, 0x2137, 0x0000 }, + { 0x0500, 0x2139, 0x0000 }, + { 0x9900, 0x214b, 0x5000 }, + { 0x9900, 0x2143, 0x4000 }, + { 0x8900, 0x213f, 0x3000 }, + { 0x8500, 0x213d, 0x2000 }, + { 0x1a00, 0x213b, 0x0000 }, + { 0x0900, 0x213e, 0x0000 }, + { 0x9900, 0x2141, 0x2000 }, + { 0x1900, 0x2140, 0x0000 }, + { 0x1900, 0x2142, 0x0000 }, + { 0x8500, 0x2147, 0x3000 }, + { 0x8900, 0x2145, 0x2000 }, + { 0x1900, 0x2144, 0x0000 }, + { 0x0500, 0x2146, 0x0000 }, + { 0x8500, 0x2149, 0x2000 }, + { 0x0500, 0x2148, 0x0000 }, + { 0x1a00, 0x214a, 0x0000 }, + { 0x8f00, 0x215a, 0x4000 }, + { 0x8f00, 0x2156, 0x3000 }, + { 0x8f00, 0x2154, 0x2000 }, + { 0x0f00, 0x2153, 0x0000 }, + { 0x0f00, 0x2155, 0x0000 }, + { 0x8f00, 0x2158, 0x2000 }, + { 0x0f00, 0x2157, 0x0000 }, + { 0x0f00, 0x2159, 0x0000 }, + { 0x8f00, 0x215e, 0x3000 }, + { 0x8f00, 0x215c, 0x2000 }, + { 0x0f00, 0x215b, 0x0000 }, + { 0x0f00, 0x215d, 0x0000 }, + { 0x8e00, 0x2160, 0x2000 }, + { 0x0f00, 0x215f, 0x0000 }, + { 0x0e00, 0x2161, 0x0000 }, + { 0x8e00, 0x2182, 0x6000 }, + { 0x8e00, 0x2172, 0x5000 }, + { 0x8e00, 0x216a, 0x4000 }, + { 0x8e00, 0x2166, 0x3000 }, + { 0x8e00, 0x2164, 0x2000 }, + { 0x0e00, 0x2163, 0x0000 }, + { 0x0e00, 0x2165, 0x0000 }, + { 0x8e00, 0x2168, 0x2000 }, + { 0x0e00, 0x2167, 0x0000 }, + { 0x0e00, 0x2169, 0x0000 }, + { 0x8e00, 0x216e, 0x3000 }, + { 0x8e00, 0x216c, 0x2000 }, + { 0x0e00, 0x216b, 0x0000 }, + { 0x0e00, 0x216d, 0x0000 }, + { 0x8e00, 0x2170, 0x2000 }, + { 0x0e00, 0x216f, 0x0000 }, + { 0x0e00, 0x2171, 0x0000 }, + { 0x8e00, 0x217a, 0x4000 }, + { 0x8e00, 0x2176, 0x3000 }, + { 0x8e00, 0x2174, 0x2000 }, + { 0x0e00, 0x2173, 0x0000 }, + { 0x0e00, 0x2175, 0x0000 }, + { 0x8e00, 0x2178, 0x2000 }, + { 0x0e00, 0x2177, 0x0000 }, + { 0x0e00, 0x2179, 0x0000 }, + { 0x8e00, 0x217e, 0x3000 }, + { 0x8e00, 0x217c, 0x2000 }, + { 0x0e00, 0x217b, 0x0000 }, + { 0x0e00, 0x217d, 0x0000 }, + { 0x8e00, 0x2180, 0x2000 }, + { 0x0e00, 0x217f, 0x0000 }, + { 0x0e00, 0x2181, 0x0000 }, + { 0x9a00, 0x219e, 0x5000 }, + { 0x9a00, 0x2196, 0x4000 }, + { 0x9900, 0x2192, 0x3000 }, + { 0x9900, 0x2190, 0x2000 }, + { 0x0e00, 0x2183, 0x0000 }, + { 0x1900, 0x2191, 0x0000 }, + { 0x9900, 0x2194, 0x2000 }, + { 0x1900, 0x2193, 0x0000 }, + { 0x1a00, 0x2195, 0x0000 }, + { 0x9900, 0x219a, 0x3000 }, + { 0x9a00, 0x2198, 0x2000 }, + { 0x1a00, 0x2197, 0x0000 }, + { 0x1a00, 0x2199, 0x0000 }, + { 0x9a00, 0x219c, 0x2000 }, + { 0x1900, 0x219b, 0x0000 }, + { 0x1a00, 0x219d, 0x0000 }, + { 0x9900, 0x21a6, 0x4000 }, + { 0x9a00, 0x21a2, 0x3000 }, + { 0x9900, 0x21a0, 0x2000 }, + { 0x1a00, 0x219f, 0x0000 }, + { 0x1a00, 0x21a1, 0x0000 }, + { 0x9a00, 0x21a4, 0x2000 }, + { 0x1900, 0x21a3, 0x0000 }, + { 0x1a00, 0x21a5, 0x0000 }, + { 0x9a00, 0x21aa, 0x3000 }, + { 0x9a00, 0x21a8, 0x2000 }, + { 0x1a00, 0x21a7, 0x0000 }, + { 0x1a00, 0x21a9, 0x0000 }, + { 0x9a00, 0x21ac, 0x2000 }, + { 0x1a00, 0x21ab, 0x0000 }, + { 0x1a00, 0x21ad, 0x0000 }, + { 0x9900, 0x222e, 0x8000 }, + { 0x9a00, 0x21ee, 0x7000 }, + { 0x9900, 0x21ce, 0x6000 }, + { 0x9a00, 0x21be, 0x5000 }, + { 0x9a00, 0x21b6, 0x4000 }, + { 0x9a00, 0x21b2, 0x3000 }, + { 0x9a00, 0x21b0, 0x2000 }, + { 0x1a00, 0x21af, 0x0000 }, + { 0x1a00, 0x21b1, 0x0000 }, + { 0x9a00, 0x21b4, 0x2000 }, + { 0x1a00, 0x21b3, 0x0000 }, + { 0x1a00, 0x21b5, 0x0000 }, + { 0x9a00, 0x21ba, 0x3000 }, + { 0x9a00, 0x21b8, 0x2000 }, + { 0x1a00, 0x21b7, 0x0000 }, + { 0x1a00, 0x21b9, 0x0000 }, + { 0x9a00, 0x21bc, 0x2000 }, + { 0x1a00, 0x21bb, 0x0000 }, + { 0x1a00, 0x21bd, 0x0000 }, + { 0x9a00, 0x21c6, 0x4000 }, + { 0x9a00, 0x21c2, 0x3000 }, + { 0x9a00, 0x21c0, 0x2000 }, + { 0x1a00, 0x21bf, 0x0000 }, + { 0x1a00, 0x21c1, 0x0000 }, + { 0x9a00, 0x21c4, 0x2000 }, + { 0x1a00, 0x21c3, 0x0000 }, + { 0x1a00, 0x21c5, 0x0000 }, + { 0x9a00, 0x21ca, 0x3000 }, + { 0x9a00, 0x21c8, 0x2000 }, + { 0x1a00, 0x21c7, 0x0000 }, + { 0x1a00, 0x21c9, 0x0000 }, + { 0x9a00, 0x21cc, 0x2000 }, + { 0x1a00, 0x21cb, 0x0000 }, + { 0x1a00, 0x21cd, 0x0000 }, + { 0x9a00, 0x21de, 0x5000 }, + { 0x9a00, 0x21d6, 0x4000 }, + { 0x9900, 0x21d2, 0x3000 }, + { 0x9a00, 0x21d0, 0x2000 }, + { 0x1900, 0x21cf, 0x0000 }, + { 0x1a00, 0x21d1, 0x0000 }, + { 0x9900, 0x21d4, 0x2000 }, + { 0x1a00, 0x21d3, 0x0000 }, + { 0x1a00, 0x21d5, 0x0000 }, + { 0x9a00, 0x21da, 0x3000 }, + { 0x9a00, 0x21d8, 0x2000 }, + { 0x1a00, 0x21d7, 0x0000 }, + { 0x1a00, 0x21d9, 0x0000 }, + { 0x9a00, 0x21dc, 0x2000 }, + { 0x1a00, 0x21db, 0x0000 }, + { 0x1a00, 0x21dd, 0x0000 }, + { 0x9a00, 0x21e6, 0x4000 }, + { 0x9a00, 0x21e2, 0x3000 }, + { 0x9a00, 0x21e0, 0x2000 }, + { 0x1a00, 0x21df, 0x0000 }, + { 0x1a00, 0x21e1, 0x0000 }, + { 0x9a00, 0x21e4, 0x2000 }, + { 0x1a00, 0x21e3, 0x0000 }, + { 0x1a00, 0x21e5, 0x0000 }, + { 0x9a00, 0x21ea, 0x3000 }, + { 0x9a00, 0x21e8, 0x2000 }, + { 0x1a00, 0x21e7, 0x0000 }, + { 0x1a00, 0x21e9, 0x0000 }, + { 0x9a00, 0x21ec, 0x2000 }, + { 0x1a00, 0x21eb, 0x0000 }, + { 0x1a00, 0x21ed, 0x0000 }, + { 0x9900, 0x220e, 0x6000 }, + { 0x9900, 0x21fe, 0x5000 }, + { 0x9900, 0x21f6, 0x4000 }, + { 0x9a00, 0x21f2, 0x3000 }, + { 0x9a00, 0x21f0, 0x2000 }, + { 0x1a00, 0x21ef, 0x0000 }, + { 0x1a00, 0x21f1, 0x0000 }, + { 0x9900, 0x21f4, 0x2000 }, + { 0x1a00, 0x21f3, 0x0000 }, + { 0x1900, 0x21f5, 0x0000 }, + { 0x9900, 0x21fa, 0x3000 }, + { 0x9900, 0x21f8, 0x2000 }, + { 0x1900, 0x21f7, 0x0000 }, + { 0x1900, 0x21f9, 0x0000 }, + { 0x9900, 0x21fc, 0x2000 }, + { 0x1900, 0x21fb, 0x0000 }, + { 0x1900, 0x21fd, 0x0000 }, + { 0x9900, 0x2206, 0x4000 }, + { 0x9900, 0x2202, 0x3000 }, + { 0x9900, 0x2200, 0x2000 }, + { 0x1900, 0x21ff, 0x0000 }, + { 0x1900, 0x2201, 0x0000 }, + { 0x9900, 0x2204, 0x2000 }, + { 0x1900, 0x2203, 0x0000 }, + { 0x1900, 0x2205, 0x0000 }, + { 0x9900, 0x220a, 0x3000 }, + { 0x9900, 0x2208, 0x2000 }, + { 0x1900, 0x2207, 0x0000 }, + { 0x1900, 0x2209, 0x0000 }, + { 0x9900, 0x220c, 0x2000 }, + { 0x1900, 0x220b, 0x0000 }, + { 0x1900, 0x220d, 0x0000 }, + { 0x9900, 0x221e, 0x5000 }, + { 0x9900, 0x2216, 0x4000 }, + { 0x9900, 0x2212, 0x3000 }, + { 0x9900, 0x2210, 0x2000 }, + { 0x1900, 0x220f, 0x0000 }, + { 0x1900, 0x2211, 0x0000 }, + { 0x9900, 0x2214, 0x2000 }, + { 0x1900, 0x2213, 0x0000 }, + { 0x1900, 0x2215, 0x0000 }, + { 0x9900, 0x221a, 0x3000 }, + { 0x9900, 0x2218, 0x2000 }, + { 0x1900, 0x2217, 0x0000 }, + { 0x1900, 0x2219, 0x0000 }, + { 0x9900, 0x221c, 0x2000 }, + { 0x1900, 0x221b, 0x0000 }, + { 0x1900, 0x221d, 0x0000 }, + { 0x9900, 0x2226, 0x4000 }, + { 0x9900, 0x2222, 0x3000 }, + { 0x9900, 0x2220, 0x2000 }, + { 0x1900, 0x221f, 0x0000 }, + { 0x1900, 0x2221, 0x0000 }, + { 0x9900, 0x2224, 0x2000 }, + { 0x1900, 0x2223, 0x0000 }, + { 0x1900, 0x2225, 0x0000 }, + { 0x9900, 0x222a, 0x3000 }, + { 0x9900, 0x2228, 0x2000 }, + { 0x1900, 0x2227, 0x0000 }, + { 0x1900, 0x2229, 0x0000 }, + { 0x9900, 0x222c, 0x2000 }, + { 0x1900, 0x222b, 0x0000 }, + { 0x1900, 0x222d, 0x0000 }, + { 0x9900, 0x226e, 0x7000 }, + { 0x9900, 0x224e, 0x6000 }, + { 0x9900, 0x223e, 0x5000 }, + { 0x9900, 0x2236, 0x4000 }, + { 0x9900, 0x2232, 0x3000 }, + { 0x9900, 0x2230, 0x2000 }, + { 0x1900, 0x222f, 0x0000 }, + { 0x1900, 0x2231, 0x0000 }, + { 0x9900, 0x2234, 0x2000 }, + { 0x1900, 0x2233, 0x0000 }, + { 0x1900, 0x2235, 0x0000 }, + { 0x9900, 0x223a, 0x3000 }, + { 0x9900, 0x2238, 0x2000 }, + { 0x1900, 0x2237, 0x0000 }, + { 0x1900, 0x2239, 0x0000 }, + { 0x9900, 0x223c, 0x2000 }, + { 0x1900, 0x223b, 0x0000 }, + { 0x1900, 0x223d, 0x0000 }, + { 0x9900, 0x2246, 0x4000 }, + { 0x9900, 0x2242, 0x3000 }, + { 0x9900, 0x2240, 0x2000 }, + { 0x1900, 0x223f, 0x0000 }, + { 0x1900, 0x2241, 0x0000 }, + { 0x9900, 0x2244, 0x2000 }, + { 0x1900, 0x2243, 0x0000 }, + { 0x1900, 0x2245, 0x0000 }, + { 0x9900, 0x224a, 0x3000 }, + { 0x9900, 0x2248, 0x2000 }, + { 0x1900, 0x2247, 0x0000 }, + { 0x1900, 0x2249, 0x0000 }, + { 0x9900, 0x224c, 0x2000 }, + { 0x1900, 0x224b, 0x0000 }, + { 0x1900, 0x224d, 0x0000 }, + { 0x9900, 0x225e, 0x5000 }, + { 0x9900, 0x2256, 0x4000 }, + { 0x9900, 0x2252, 0x3000 }, + { 0x9900, 0x2250, 0x2000 }, + { 0x1900, 0x224f, 0x0000 }, + { 0x1900, 0x2251, 0x0000 }, + { 0x9900, 0x2254, 0x2000 }, + { 0x1900, 0x2253, 0x0000 }, + { 0x1900, 0x2255, 0x0000 }, + { 0x9900, 0x225a, 0x3000 }, + { 0x9900, 0x2258, 0x2000 }, + { 0x1900, 0x2257, 0x0000 }, + { 0x1900, 0x2259, 0x0000 }, + { 0x9900, 0x225c, 0x2000 }, + { 0x1900, 0x225b, 0x0000 }, + { 0x1900, 0x225d, 0x0000 }, + { 0x9900, 0x2266, 0x4000 }, + { 0x9900, 0x2262, 0x3000 }, + { 0x9900, 0x2260, 0x2000 }, + { 0x1900, 0x225f, 0x0000 }, + { 0x1900, 0x2261, 0x0000 }, + { 0x9900, 0x2264, 0x2000 }, + { 0x1900, 0x2263, 0x0000 }, + { 0x1900, 0x2265, 0x0000 }, + { 0x9900, 0x226a, 0x3000 }, + { 0x9900, 0x2268, 0x2000 }, + { 0x1900, 0x2267, 0x0000 }, + { 0x1900, 0x2269, 0x0000 }, + { 0x9900, 0x226c, 0x2000 }, + { 0x1900, 0x226b, 0x0000 }, + { 0x1900, 0x226d, 0x0000 }, + { 0x9900, 0x228e, 0x6000 }, + { 0x9900, 0x227e, 0x5000 }, + { 0x9900, 0x2276, 0x4000 }, + { 0x9900, 0x2272, 0x3000 }, + { 0x9900, 0x2270, 0x2000 }, + { 0x1900, 0x226f, 0x0000 }, + { 0x1900, 0x2271, 0x0000 }, + { 0x9900, 0x2274, 0x2000 }, + { 0x1900, 0x2273, 0x0000 }, + { 0x1900, 0x2275, 0x0000 }, + { 0x9900, 0x227a, 0x3000 }, + { 0x9900, 0x2278, 0x2000 }, + { 0x1900, 0x2277, 0x0000 }, + { 0x1900, 0x2279, 0x0000 }, + { 0x9900, 0x227c, 0x2000 }, + { 0x1900, 0x227b, 0x0000 }, + { 0x1900, 0x227d, 0x0000 }, + { 0x9900, 0x2286, 0x4000 }, + { 0x9900, 0x2282, 0x3000 }, + { 0x9900, 0x2280, 0x2000 }, + { 0x1900, 0x227f, 0x0000 }, + { 0x1900, 0x2281, 0x0000 }, + { 0x9900, 0x2284, 0x2000 }, + { 0x1900, 0x2283, 0x0000 }, + { 0x1900, 0x2285, 0x0000 }, + { 0x9900, 0x228a, 0x3000 }, + { 0x9900, 0x2288, 0x2000 }, + { 0x1900, 0x2287, 0x0000 }, + { 0x1900, 0x2289, 0x0000 }, + { 0x9900, 0x228c, 0x2000 }, + { 0x1900, 0x228b, 0x0000 }, + { 0x1900, 0x228d, 0x0000 }, + { 0x9900, 0x229e, 0x5000 }, + { 0x9900, 0x2296, 0x4000 }, + { 0x9900, 0x2292, 0x3000 }, + { 0x9900, 0x2290, 0x2000 }, + { 0x1900, 0x228f, 0x0000 }, + { 0x1900, 0x2291, 0x0000 }, + { 0x9900, 0x2294, 0x2000 }, + { 0x1900, 0x2293, 0x0000 }, + { 0x1900, 0x2295, 0x0000 }, + { 0x9900, 0x229a, 0x3000 }, + { 0x9900, 0x2298, 0x2000 }, + { 0x1900, 0x2297, 0x0000 }, + { 0x1900, 0x2299, 0x0000 }, + { 0x9900, 0x229c, 0x2000 }, + { 0x1900, 0x229b, 0x0000 }, + { 0x1900, 0x229d, 0x0000 }, + { 0x9900, 0x22a6, 0x4000 }, + { 0x9900, 0x22a2, 0x3000 }, + { 0x9900, 0x22a0, 0x2000 }, + { 0x1900, 0x229f, 0x0000 }, + { 0x1900, 0x22a1, 0x0000 }, + { 0x9900, 0x22a4, 0x2000 }, + { 0x1900, 0x22a3, 0x0000 }, + { 0x1900, 0x22a5, 0x0000 }, + { 0x9900, 0x22aa, 0x3000 }, + { 0x9900, 0x22a8, 0x2000 }, + { 0x1900, 0x22a7, 0x0000 }, + { 0x1900, 0x22a9, 0x0000 }, + { 0x9900, 0x22ac, 0x2000 }, + { 0x1900, 0x22ab, 0x0000 }, + { 0x1900, 0x22ad, 0x0000 }, + { 0x8f00, 0x2787, 0xb000 }, + { 0x9a00, 0x250b, 0xa000 }, + { 0x9900, 0x23ae, 0x9000 }, + { 0x9a00, 0x232e, 0x8000 }, + { 0x9900, 0x22ee, 0x7000 }, + { 0x9900, 0x22ce, 0x6000 }, + { 0x9900, 0x22be, 0x5000 }, + { 0x9900, 0x22b6, 0x4000 }, + { 0x9900, 0x22b2, 0x3000 }, + { 0x9900, 0x22b0, 0x2000 }, + { 0x1900, 0x22af, 0x0000 }, + { 0x1900, 0x22b1, 0x0000 }, + { 0x9900, 0x22b4, 0x2000 }, + { 0x1900, 0x22b3, 0x0000 }, + { 0x1900, 0x22b5, 0x0000 }, + { 0x9900, 0x22ba, 0x3000 }, + { 0x9900, 0x22b8, 0x2000 }, + { 0x1900, 0x22b7, 0x0000 }, + { 0x1900, 0x22b9, 0x0000 }, + { 0x9900, 0x22bc, 0x2000 }, + { 0x1900, 0x22bb, 0x0000 }, + { 0x1900, 0x22bd, 0x0000 }, + { 0x9900, 0x22c6, 0x4000 }, + { 0x9900, 0x22c2, 0x3000 }, + { 0x9900, 0x22c0, 0x2000 }, + { 0x1900, 0x22bf, 0x0000 }, + { 0x1900, 0x22c1, 0x0000 }, + { 0x9900, 0x22c4, 0x2000 }, + { 0x1900, 0x22c3, 0x0000 }, + { 0x1900, 0x22c5, 0x0000 }, + { 0x9900, 0x22ca, 0x3000 }, + { 0x9900, 0x22c8, 0x2000 }, + { 0x1900, 0x22c7, 0x0000 }, + { 0x1900, 0x22c9, 0x0000 }, + { 0x9900, 0x22cc, 0x2000 }, + { 0x1900, 0x22cb, 0x0000 }, + { 0x1900, 0x22cd, 0x0000 }, + { 0x9900, 0x22de, 0x5000 }, + { 0x9900, 0x22d6, 0x4000 }, + { 0x9900, 0x22d2, 0x3000 }, + { 0x9900, 0x22d0, 0x2000 }, + { 0x1900, 0x22cf, 0x0000 }, + { 0x1900, 0x22d1, 0x0000 }, + { 0x9900, 0x22d4, 0x2000 }, + { 0x1900, 0x22d3, 0x0000 }, + { 0x1900, 0x22d5, 0x0000 }, + { 0x9900, 0x22da, 0x3000 }, + { 0x9900, 0x22d8, 0x2000 }, + { 0x1900, 0x22d7, 0x0000 }, + { 0x1900, 0x22d9, 0x0000 }, + { 0x9900, 0x22dc, 0x2000 }, + { 0x1900, 0x22db, 0x0000 }, + { 0x1900, 0x22dd, 0x0000 }, + { 0x9900, 0x22e6, 0x4000 }, + { 0x9900, 0x22e2, 0x3000 }, + { 0x9900, 0x22e0, 0x2000 }, + { 0x1900, 0x22df, 0x0000 }, + { 0x1900, 0x22e1, 0x0000 }, + { 0x9900, 0x22e4, 0x2000 }, + { 0x1900, 0x22e3, 0x0000 }, + { 0x1900, 0x22e5, 0x0000 }, + { 0x9900, 0x22ea, 0x3000 }, + { 0x9900, 0x22e8, 0x2000 }, + { 0x1900, 0x22e7, 0x0000 }, + { 0x1900, 0x22e9, 0x0000 }, + { 0x9900, 0x22ec, 0x2000 }, + { 0x1900, 0x22eb, 0x0000 }, + { 0x1900, 0x22ed, 0x0000 }, + { 0x9a00, 0x230e, 0x6000 }, + { 0x9900, 0x22fe, 0x5000 }, + { 0x9900, 0x22f6, 0x4000 }, + { 0x9900, 0x22f2, 0x3000 }, + { 0x9900, 0x22f0, 0x2000 }, + { 0x1900, 0x22ef, 0x0000 }, + { 0x1900, 0x22f1, 0x0000 }, + { 0x9900, 0x22f4, 0x2000 }, + { 0x1900, 0x22f3, 0x0000 }, + { 0x1900, 0x22f5, 0x0000 }, + { 0x9900, 0x22fa, 0x3000 }, + { 0x9900, 0x22f8, 0x2000 }, + { 0x1900, 0x22f7, 0x0000 }, + { 0x1900, 0x22f9, 0x0000 }, + { 0x9900, 0x22fc, 0x2000 }, + { 0x1900, 0x22fb, 0x0000 }, + { 0x1900, 0x22fd, 0x0000 }, + { 0x9a00, 0x2306, 0x4000 }, + { 0x9a00, 0x2302, 0x3000 }, + { 0x9a00, 0x2300, 0x2000 }, + { 0x1900, 0x22ff, 0x0000 }, + { 0x1a00, 0x2301, 0x0000 }, + { 0x9a00, 0x2304, 0x2000 }, + { 0x1a00, 0x2303, 0x0000 }, + { 0x1a00, 0x2305, 0x0000 }, + { 0x9900, 0x230a, 0x3000 }, + { 0x9900, 0x2308, 0x2000 }, + { 0x1a00, 0x2307, 0x0000 }, + { 0x1900, 0x2309, 0x0000 }, + { 0x9a00, 0x230c, 0x2000 }, + { 0x1900, 0x230b, 0x0000 }, + { 0x1a00, 0x230d, 0x0000 }, + { 0x9a00, 0x231e, 0x5000 }, + { 0x9a00, 0x2316, 0x4000 }, + { 0x9a00, 0x2312, 0x3000 }, + { 0x9a00, 0x2310, 0x2000 }, + { 0x1a00, 0x230f, 0x0000 }, + { 0x1a00, 0x2311, 0x0000 }, + { 0x9a00, 0x2314, 0x2000 }, + { 0x1a00, 0x2313, 0x0000 }, + { 0x1a00, 0x2315, 0x0000 }, + { 0x9a00, 0x231a, 0x3000 }, + { 0x9a00, 0x2318, 0x2000 }, + { 0x1a00, 0x2317, 0x0000 }, + { 0x1a00, 0x2319, 0x0000 }, + { 0x9a00, 0x231c, 0x2000 }, + { 0x1a00, 0x231b, 0x0000 }, + { 0x1a00, 0x231d, 0x0000 }, + { 0x9a00, 0x2326, 0x4000 }, + { 0x9a00, 0x2322, 0x3000 }, + { 0x9900, 0x2320, 0x2000 }, + { 0x1a00, 0x231f, 0x0000 }, + { 0x1900, 0x2321, 0x0000 }, + { 0x9a00, 0x2324, 0x2000 }, + { 0x1a00, 0x2323, 0x0000 }, + { 0x1a00, 0x2325, 0x0000 }, + { 0x9200, 0x232a, 0x3000 }, + { 0x9a00, 0x2328, 0x2000 }, + { 0x1a00, 0x2327, 0x0000 }, + { 0x1600, 0x2329, 0x0000 }, + { 0x9a00, 0x232c, 0x2000 }, + { 0x1a00, 0x232b, 0x0000 }, + { 0x1a00, 0x232d, 0x0000 }, + { 0x9a00, 0x236e, 0x7000 }, + { 0x9a00, 0x234e, 0x6000 }, + { 0x9a00, 0x233e, 0x5000 }, + { 0x9a00, 0x2336, 0x4000 }, + { 0x9a00, 0x2332, 0x3000 }, + { 0x9a00, 0x2330, 0x2000 }, + { 0x1a00, 0x232f, 0x0000 }, + { 0x1a00, 0x2331, 0x0000 }, + { 0x9a00, 0x2334, 0x2000 }, + { 0x1a00, 0x2333, 0x0000 }, + { 0x1a00, 0x2335, 0x0000 }, + { 0x9a00, 0x233a, 0x3000 }, + { 0x9a00, 0x2338, 0x2000 }, + { 0x1a00, 0x2337, 0x0000 }, + { 0x1a00, 0x2339, 0x0000 }, + { 0x9a00, 0x233c, 0x2000 }, + { 0x1a00, 0x233b, 0x0000 }, + { 0x1a00, 0x233d, 0x0000 }, + { 0x9a00, 0x2346, 0x4000 }, + { 0x9a00, 0x2342, 0x3000 }, + { 0x9a00, 0x2340, 0x2000 }, + { 0x1a00, 0x233f, 0x0000 }, + { 0x1a00, 0x2341, 0x0000 }, + { 0x9a00, 0x2344, 0x2000 }, + { 0x1a00, 0x2343, 0x0000 }, + { 0x1a00, 0x2345, 0x0000 }, + { 0x9a00, 0x234a, 0x3000 }, + { 0x9a00, 0x2348, 0x2000 }, + { 0x1a00, 0x2347, 0x0000 }, + { 0x1a00, 0x2349, 0x0000 }, + { 0x9a00, 0x234c, 0x2000 }, + { 0x1a00, 0x234b, 0x0000 }, + { 0x1a00, 0x234d, 0x0000 }, + { 0x9a00, 0x235e, 0x5000 }, + { 0x9a00, 0x2356, 0x4000 }, + { 0x9a00, 0x2352, 0x3000 }, + { 0x9a00, 0x2350, 0x2000 }, + { 0x1a00, 0x234f, 0x0000 }, + { 0x1a00, 0x2351, 0x0000 }, + { 0x9a00, 0x2354, 0x2000 }, + { 0x1a00, 0x2353, 0x0000 }, + { 0x1a00, 0x2355, 0x0000 }, + { 0x9a00, 0x235a, 0x3000 }, + { 0x9a00, 0x2358, 0x2000 }, + { 0x1a00, 0x2357, 0x0000 }, + { 0x1a00, 0x2359, 0x0000 }, + { 0x9a00, 0x235c, 0x2000 }, + { 0x1a00, 0x235b, 0x0000 }, + { 0x1a00, 0x235d, 0x0000 }, + { 0x9a00, 0x2366, 0x4000 }, + { 0x9a00, 0x2362, 0x3000 }, + { 0x9a00, 0x2360, 0x2000 }, + { 0x1a00, 0x235f, 0x0000 }, + { 0x1a00, 0x2361, 0x0000 }, + { 0x9a00, 0x2364, 0x2000 }, + { 0x1a00, 0x2363, 0x0000 }, + { 0x1a00, 0x2365, 0x0000 }, + { 0x9a00, 0x236a, 0x3000 }, + { 0x9a00, 0x2368, 0x2000 }, + { 0x1a00, 0x2367, 0x0000 }, + { 0x1a00, 0x2369, 0x0000 }, + { 0x9a00, 0x236c, 0x2000 }, + { 0x1a00, 0x236b, 0x0000 }, + { 0x1a00, 0x236d, 0x0000 }, + { 0x9a00, 0x238e, 0x6000 }, + { 0x9a00, 0x237e, 0x5000 }, + { 0x9a00, 0x2376, 0x4000 }, + { 0x9a00, 0x2372, 0x3000 }, + { 0x9a00, 0x2370, 0x2000 }, + { 0x1a00, 0x236f, 0x0000 }, + { 0x1a00, 0x2371, 0x0000 }, + { 0x9a00, 0x2374, 0x2000 }, + { 0x1a00, 0x2373, 0x0000 }, + { 0x1a00, 0x2375, 0x0000 }, + { 0x9a00, 0x237a, 0x3000 }, + { 0x9a00, 0x2378, 0x2000 }, + { 0x1a00, 0x2377, 0x0000 }, + { 0x1a00, 0x2379, 0x0000 }, + { 0x9900, 0x237c, 0x2000 }, + { 0x1a00, 0x237b, 0x0000 }, + { 0x1a00, 0x237d, 0x0000 }, + { 0x9a00, 0x2386, 0x4000 }, + { 0x9a00, 0x2382, 0x3000 }, + { 0x9a00, 0x2380, 0x2000 }, + { 0x1a00, 0x237f, 0x0000 }, + { 0x1a00, 0x2381, 0x0000 }, + { 0x9a00, 0x2384, 0x2000 }, + { 0x1a00, 0x2383, 0x0000 }, + { 0x1a00, 0x2385, 0x0000 }, + { 0x9a00, 0x238a, 0x3000 }, + { 0x9a00, 0x2388, 0x2000 }, + { 0x1a00, 0x2387, 0x0000 }, + { 0x1a00, 0x2389, 0x0000 }, + { 0x9a00, 0x238c, 0x2000 }, + { 0x1a00, 0x238b, 0x0000 }, + { 0x1a00, 0x238d, 0x0000 }, + { 0x9900, 0x239e, 0x5000 }, + { 0x9a00, 0x2396, 0x4000 }, + { 0x9a00, 0x2392, 0x3000 }, + { 0x9a00, 0x2390, 0x2000 }, + { 0x1a00, 0x238f, 0x0000 }, + { 0x1a00, 0x2391, 0x0000 }, + { 0x9a00, 0x2394, 0x2000 }, + { 0x1a00, 0x2393, 0x0000 }, + { 0x1a00, 0x2395, 0x0000 }, + { 0x9a00, 0x239a, 0x3000 }, + { 0x9a00, 0x2398, 0x2000 }, + { 0x1a00, 0x2397, 0x0000 }, + { 0x1a00, 0x2399, 0x0000 }, + { 0x9900, 0x239c, 0x2000 }, + { 0x1900, 0x239b, 0x0000 }, + { 0x1900, 0x239d, 0x0000 }, + { 0x9900, 0x23a6, 0x4000 }, + { 0x9900, 0x23a2, 0x3000 }, + { 0x9900, 0x23a0, 0x2000 }, + { 0x1900, 0x239f, 0x0000 }, + { 0x1900, 0x23a1, 0x0000 }, + { 0x9900, 0x23a4, 0x2000 }, + { 0x1900, 0x23a3, 0x0000 }, + { 0x1900, 0x23a5, 0x0000 }, + { 0x9900, 0x23aa, 0x3000 }, + { 0x9900, 0x23a8, 0x2000 }, + { 0x1900, 0x23a7, 0x0000 }, + { 0x1900, 0x23a9, 0x0000 }, + { 0x9900, 0x23ac, 0x2000 }, + { 0x1900, 0x23ab, 0x0000 }, + { 0x1900, 0x23ad, 0x0000 }, + { 0x8f00, 0x248b, 0x8000 }, + { 0x9a00, 0x241d, 0x7000 }, + { 0x9a00, 0x23ce, 0x6000 }, + { 0x9a00, 0x23be, 0x5000 }, + { 0x9500, 0x23b6, 0x4000 }, + { 0x9900, 0x23b2, 0x3000 }, + { 0x9900, 0x23b0, 0x2000 }, + { 0x1900, 0x23af, 0x0000 }, + { 0x1900, 0x23b1, 0x0000 }, + { 0x9600, 0x23b4, 0x2000 }, + { 0x1900, 0x23b3, 0x0000 }, + { 0x1200, 0x23b5, 0x0000 }, + { 0x9a00, 0x23ba, 0x3000 }, + { 0x9a00, 0x23b8, 0x2000 }, + { 0x1a00, 0x23b7, 0x0000 }, + { 0x1a00, 0x23b9, 0x0000 }, + { 0x9a00, 0x23bc, 0x2000 }, + { 0x1a00, 0x23bb, 0x0000 }, + { 0x1a00, 0x23bd, 0x0000 }, + { 0x9a00, 0x23c6, 0x4000 }, + { 0x9a00, 0x23c2, 0x3000 }, + { 0x9a00, 0x23c0, 0x2000 }, + { 0x1a00, 0x23bf, 0x0000 }, + { 0x1a00, 0x23c1, 0x0000 }, + { 0x9a00, 0x23c4, 0x2000 }, + { 0x1a00, 0x23c3, 0x0000 }, + { 0x1a00, 0x23c5, 0x0000 }, + { 0x9a00, 0x23ca, 0x3000 }, + { 0x9a00, 0x23c8, 0x2000 }, + { 0x1a00, 0x23c7, 0x0000 }, + { 0x1a00, 0x23c9, 0x0000 }, + { 0x9a00, 0x23cc, 0x2000 }, + { 0x1a00, 0x23cb, 0x0000 }, + { 0x1a00, 0x23cd, 0x0000 }, + { 0x9a00, 0x240d, 0x5000 }, + { 0x9a00, 0x2405, 0x4000 }, + { 0x9a00, 0x2401, 0x3000 }, + { 0x9a00, 0x23d0, 0x2000 }, + { 0x1a00, 0x23cf, 0x0000 }, + { 0x1a00, 0x2400, 0x0000 }, + { 0x9a00, 0x2403, 0x2000 }, + { 0x1a00, 0x2402, 0x0000 }, + { 0x1a00, 0x2404, 0x0000 }, + { 0x9a00, 0x2409, 0x3000 }, + { 0x9a00, 0x2407, 0x2000 }, + { 0x1a00, 0x2406, 0x0000 }, + { 0x1a00, 0x2408, 0x0000 }, + { 0x9a00, 0x240b, 0x2000 }, + { 0x1a00, 0x240a, 0x0000 }, + { 0x1a00, 0x240c, 0x0000 }, + { 0x9a00, 0x2415, 0x4000 }, + { 0x9a00, 0x2411, 0x3000 }, + { 0x9a00, 0x240f, 0x2000 }, + { 0x1a00, 0x240e, 0x0000 }, + { 0x1a00, 0x2410, 0x0000 }, + { 0x9a00, 0x2413, 0x2000 }, + { 0x1a00, 0x2412, 0x0000 }, + { 0x1a00, 0x2414, 0x0000 }, + { 0x9a00, 0x2419, 0x3000 }, + { 0x9a00, 0x2417, 0x2000 }, + { 0x1a00, 0x2416, 0x0000 }, + { 0x1a00, 0x2418, 0x0000 }, + { 0x9a00, 0x241b, 0x2000 }, + { 0x1a00, 0x241a, 0x0000 }, + { 0x1a00, 0x241c, 0x0000 }, + { 0x8f00, 0x246b, 0x6000 }, + { 0x9a00, 0x2446, 0x5000 }, + { 0x9a00, 0x2425, 0x4000 }, + { 0x9a00, 0x2421, 0x3000 }, + { 0x9a00, 0x241f, 0x2000 }, + { 0x1a00, 0x241e, 0x0000 }, + { 0x1a00, 0x2420, 0x0000 }, + { 0x9a00, 0x2423, 0x2000 }, + { 0x1a00, 0x2422, 0x0000 }, + { 0x1a00, 0x2424, 0x0000 }, + { 0x9a00, 0x2442, 0x3000 }, + { 0x9a00, 0x2440, 0x2000 }, + { 0x1a00, 0x2426, 0x0000 }, + { 0x1a00, 0x2441, 0x0000 }, + { 0x9a00, 0x2444, 0x2000 }, + { 0x1a00, 0x2443, 0x0000 }, + { 0x1a00, 0x2445, 0x0000 }, + { 0x8f00, 0x2463, 0x4000 }, + { 0x9a00, 0x244a, 0x3000 }, + { 0x9a00, 0x2448, 0x2000 }, + { 0x1a00, 0x2447, 0x0000 }, + { 0x1a00, 0x2449, 0x0000 }, + { 0x8f00, 0x2461, 0x2000 }, + { 0x0f00, 0x2460, 0x0000 }, + { 0x0f00, 0x2462, 0x0000 }, + { 0x8f00, 0x2467, 0x3000 }, + { 0x8f00, 0x2465, 0x2000 }, + { 0x0f00, 0x2464, 0x0000 }, + { 0x0f00, 0x2466, 0x0000 }, + { 0x8f00, 0x2469, 0x2000 }, + { 0x0f00, 0x2468, 0x0000 }, + { 0x0f00, 0x246a, 0x0000 }, + { 0x8f00, 0x247b, 0x5000 }, + { 0x8f00, 0x2473, 0x4000 }, + { 0x8f00, 0x246f, 0x3000 }, + { 0x8f00, 0x246d, 0x2000 }, + { 0x0f00, 0x246c, 0x0000 }, + { 0x0f00, 0x246e, 0x0000 }, + { 0x8f00, 0x2471, 0x2000 }, + { 0x0f00, 0x2470, 0x0000 }, + { 0x0f00, 0x2472, 0x0000 }, + { 0x8f00, 0x2477, 0x3000 }, + { 0x8f00, 0x2475, 0x2000 }, + { 0x0f00, 0x2474, 0x0000 }, + { 0x0f00, 0x2476, 0x0000 }, + { 0x8f00, 0x2479, 0x2000 }, + { 0x0f00, 0x2478, 0x0000 }, + { 0x0f00, 0x247a, 0x0000 }, + { 0x8f00, 0x2483, 0x4000 }, + { 0x8f00, 0x247f, 0x3000 }, + { 0x8f00, 0x247d, 0x2000 }, + { 0x0f00, 0x247c, 0x0000 }, + { 0x0f00, 0x247e, 0x0000 }, + { 0x8f00, 0x2481, 0x2000 }, + { 0x0f00, 0x2480, 0x0000 }, + { 0x0f00, 0x2482, 0x0000 }, + { 0x8f00, 0x2487, 0x3000 }, + { 0x8f00, 0x2485, 0x2000 }, + { 0x0f00, 0x2484, 0x0000 }, + { 0x0f00, 0x2486, 0x0000 }, + { 0x8f00, 0x2489, 0x2000 }, + { 0x0f00, 0x2488, 0x0000 }, + { 0x0f00, 0x248a, 0x0000 }, + { 0x9a00, 0x24cb, 0x7000 }, + { 0x9a00, 0x24ab, 0x6000 }, + { 0x8f00, 0x249b, 0x5000 }, + { 0x8f00, 0x2493, 0x4000 }, + { 0x8f00, 0x248f, 0x3000 }, + { 0x8f00, 0x248d, 0x2000 }, + { 0x0f00, 0x248c, 0x0000 }, + { 0x0f00, 0x248e, 0x0000 }, + { 0x8f00, 0x2491, 0x2000 }, + { 0x0f00, 0x2490, 0x0000 }, + { 0x0f00, 0x2492, 0x0000 }, + { 0x8f00, 0x2497, 0x3000 }, + { 0x8f00, 0x2495, 0x2000 }, + { 0x0f00, 0x2494, 0x0000 }, + { 0x0f00, 0x2496, 0x0000 }, + { 0x8f00, 0x2499, 0x2000 }, + { 0x0f00, 0x2498, 0x0000 }, + { 0x0f00, 0x249a, 0x0000 }, + { 0x9a00, 0x24a3, 0x4000 }, + { 0x9a00, 0x249f, 0x3000 }, + { 0x9a00, 0x249d, 0x2000 }, + { 0x1a00, 0x249c, 0x0000 }, + { 0x1a00, 0x249e, 0x0000 }, + { 0x9a00, 0x24a1, 0x2000 }, + { 0x1a00, 0x24a0, 0x0000 }, + { 0x1a00, 0x24a2, 0x0000 }, + { 0x9a00, 0x24a7, 0x3000 }, + { 0x9a00, 0x24a5, 0x2000 }, + { 0x1a00, 0x24a4, 0x0000 }, + { 0x1a00, 0x24a6, 0x0000 }, + { 0x9a00, 0x24a9, 0x2000 }, + { 0x1a00, 0x24a8, 0x0000 }, + { 0x1a00, 0x24aa, 0x0000 }, + { 0x9a00, 0x24bb, 0x5000 }, + { 0x9a00, 0x24b3, 0x4000 }, + { 0x9a00, 0x24af, 0x3000 }, + { 0x9a00, 0x24ad, 0x2000 }, + { 0x1a00, 0x24ac, 0x0000 }, + { 0x1a00, 0x24ae, 0x0000 }, + { 0x9a00, 0x24b1, 0x2000 }, + { 0x1a00, 0x24b0, 0x0000 }, + { 0x1a00, 0x24b2, 0x0000 }, + { 0x9a00, 0x24b7, 0x3000 }, + { 0x9a00, 0x24b5, 0x2000 }, + { 0x1a00, 0x24b4, 0x0000 }, + { 0x1a00, 0x24b6, 0x0000 }, + { 0x9a00, 0x24b9, 0x2000 }, + { 0x1a00, 0x24b8, 0x0000 }, + { 0x1a00, 0x24ba, 0x0000 }, + { 0x9a00, 0x24c3, 0x4000 }, + { 0x9a00, 0x24bf, 0x3000 }, + { 0x9a00, 0x24bd, 0x2000 }, + { 0x1a00, 0x24bc, 0x0000 }, + { 0x1a00, 0x24be, 0x0000 }, + { 0x9a00, 0x24c1, 0x2000 }, + { 0x1a00, 0x24c0, 0x0000 }, + { 0x1a00, 0x24c2, 0x0000 }, + { 0x9a00, 0x24c7, 0x3000 }, + { 0x9a00, 0x24c5, 0x2000 }, + { 0x1a00, 0x24c4, 0x0000 }, + { 0x1a00, 0x24c6, 0x0000 }, + { 0x9a00, 0x24c9, 0x2000 }, + { 0x1a00, 0x24c8, 0x0000 }, + { 0x1a00, 0x24ca, 0x0000 }, + { 0x8f00, 0x24eb, 0x6000 }, + { 0x9a00, 0x24db, 0x5000 }, + { 0x9a00, 0x24d3, 0x4000 }, + { 0x9a00, 0x24cf, 0x3000 }, + { 0x9a00, 0x24cd, 0x2000 }, + { 0x1a00, 0x24cc, 0x0000 }, + { 0x1a00, 0x24ce, 0x0000 }, + { 0x9a00, 0x24d1, 0x2000 }, + { 0x1a00, 0x24d0, 0x0000 }, + { 0x1a00, 0x24d2, 0x0000 }, + { 0x9a00, 0x24d7, 0x3000 }, + { 0x9a00, 0x24d5, 0x2000 }, + { 0x1a00, 0x24d4, 0x0000 }, + { 0x1a00, 0x24d6, 0x0000 }, + { 0x9a00, 0x24d9, 0x2000 }, + { 0x1a00, 0x24d8, 0x0000 }, + { 0x1a00, 0x24da, 0x0000 }, + { 0x9a00, 0x24e3, 0x4000 }, + { 0x9a00, 0x24df, 0x3000 }, + { 0x9a00, 0x24dd, 0x2000 }, + { 0x1a00, 0x24dc, 0x0000 }, + { 0x1a00, 0x24de, 0x0000 }, + { 0x9a00, 0x24e1, 0x2000 }, + { 0x1a00, 0x24e0, 0x0000 }, + { 0x1a00, 0x24e2, 0x0000 }, + { 0x9a00, 0x24e7, 0x3000 }, + { 0x9a00, 0x24e5, 0x2000 }, + { 0x1a00, 0x24e4, 0x0000 }, + { 0x1a00, 0x24e6, 0x0000 }, + { 0x9a00, 0x24e9, 0x2000 }, + { 0x1a00, 0x24e8, 0x0000 }, + { 0x0f00, 0x24ea, 0x0000 }, + { 0x8f00, 0x24fb, 0x5000 }, + { 0x8f00, 0x24f3, 0x4000 }, + { 0x8f00, 0x24ef, 0x3000 }, + { 0x8f00, 0x24ed, 0x2000 }, + { 0x0f00, 0x24ec, 0x0000 }, + { 0x0f00, 0x24ee, 0x0000 }, + { 0x8f00, 0x24f1, 0x2000 }, + { 0x0f00, 0x24f0, 0x0000 }, + { 0x0f00, 0x24f2, 0x0000 }, + { 0x8f00, 0x24f7, 0x3000 }, + { 0x8f00, 0x24f5, 0x2000 }, + { 0x0f00, 0x24f4, 0x0000 }, + { 0x0f00, 0x24f6, 0x0000 }, + { 0x8f00, 0x24f9, 0x2000 }, + { 0x0f00, 0x24f8, 0x0000 }, + { 0x0f00, 0x24fa, 0x0000 }, + { 0x9a00, 0x2503, 0x4000 }, + { 0x8f00, 0x24ff, 0x3000 }, + { 0x8f00, 0x24fd, 0x2000 }, + { 0x0f00, 0x24fc, 0x0000 }, + { 0x0f00, 0x24fe, 0x0000 }, + { 0x9a00, 0x2501, 0x2000 }, + { 0x1a00, 0x2500, 0x0000 }, + { 0x1a00, 0x2502, 0x0000 }, + { 0x9a00, 0x2507, 0x3000 }, + { 0x9a00, 0x2505, 0x2000 }, + { 0x1a00, 0x2504, 0x0000 }, + { 0x1a00, 0x2506, 0x0000 }, + { 0x9a00, 0x2509, 0x2000 }, + { 0x1a00, 0x2508, 0x0000 }, + { 0x1a00, 0x250a, 0x0000 }, + { 0x9a00, 0x260b, 0x9000 }, + { 0x9a00, 0x258b, 0x8000 }, + { 0x9a00, 0x254b, 0x7000 }, + { 0x9a00, 0x252b, 0x6000 }, + { 0x9a00, 0x251b, 0x5000 }, + { 0x9a00, 0x2513, 0x4000 }, + { 0x9a00, 0x250f, 0x3000 }, + { 0x9a00, 0x250d, 0x2000 }, + { 0x1a00, 0x250c, 0x0000 }, + { 0x1a00, 0x250e, 0x0000 }, + { 0x9a00, 0x2511, 0x2000 }, + { 0x1a00, 0x2510, 0x0000 }, + { 0x1a00, 0x2512, 0x0000 }, + { 0x9a00, 0x2517, 0x3000 }, + { 0x9a00, 0x2515, 0x2000 }, + { 0x1a00, 0x2514, 0x0000 }, + { 0x1a00, 0x2516, 0x0000 }, + { 0x9a00, 0x2519, 0x2000 }, + { 0x1a00, 0x2518, 0x0000 }, + { 0x1a00, 0x251a, 0x0000 }, + { 0x9a00, 0x2523, 0x4000 }, + { 0x9a00, 0x251f, 0x3000 }, + { 0x9a00, 0x251d, 0x2000 }, + { 0x1a00, 0x251c, 0x0000 }, + { 0x1a00, 0x251e, 0x0000 }, + { 0x9a00, 0x2521, 0x2000 }, + { 0x1a00, 0x2520, 0x0000 }, + { 0x1a00, 0x2522, 0x0000 }, + { 0x9a00, 0x2527, 0x3000 }, + { 0x9a00, 0x2525, 0x2000 }, + { 0x1a00, 0x2524, 0x0000 }, + { 0x1a00, 0x2526, 0x0000 }, + { 0x9a00, 0x2529, 0x2000 }, + { 0x1a00, 0x2528, 0x0000 }, + { 0x1a00, 0x252a, 0x0000 }, + { 0x9a00, 0x253b, 0x5000 }, + { 0x9a00, 0x2533, 0x4000 }, + { 0x9a00, 0x252f, 0x3000 }, + { 0x9a00, 0x252d, 0x2000 }, + { 0x1a00, 0x252c, 0x0000 }, + { 0x1a00, 0x252e, 0x0000 }, + { 0x9a00, 0x2531, 0x2000 }, + { 0x1a00, 0x2530, 0x0000 }, + { 0x1a00, 0x2532, 0x0000 }, + { 0x9a00, 0x2537, 0x3000 }, + { 0x9a00, 0x2535, 0x2000 }, + { 0x1a00, 0x2534, 0x0000 }, + { 0x1a00, 0x2536, 0x0000 }, + { 0x9a00, 0x2539, 0x2000 }, + { 0x1a00, 0x2538, 0x0000 }, + { 0x1a00, 0x253a, 0x0000 }, + { 0x9a00, 0x2543, 0x4000 }, + { 0x9a00, 0x253f, 0x3000 }, + { 0x9a00, 0x253d, 0x2000 }, + { 0x1a00, 0x253c, 0x0000 }, + { 0x1a00, 0x253e, 0x0000 }, + { 0x9a00, 0x2541, 0x2000 }, + { 0x1a00, 0x2540, 0x0000 }, + { 0x1a00, 0x2542, 0x0000 }, + { 0x9a00, 0x2547, 0x3000 }, + { 0x9a00, 0x2545, 0x2000 }, + { 0x1a00, 0x2544, 0x0000 }, + { 0x1a00, 0x2546, 0x0000 }, + { 0x9a00, 0x2549, 0x2000 }, + { 0x1a00, 0x2548, 0x0000 }, + { 0x1a00, 0x254a, 0x0000 }, + { 0x9a00, 0x256b, 0x6000 }, + { 0x9a00, 0x255b, 0x5000 }, + { 0x9a00, 0x2553, 0x4000 }, + { 0x9a00, 0x254f, 0x3000 }, + { 0x9a00, 0x254d, 0x2000 }, + { 0x1a00, 0x254c, 0x0000 }, + { 0x1a00, 0x254e, 0x0000 }, + { 0x9a00, 0x2551, 0x2000 }, + { 0x1a00, 0x2550, 0x0000 }, + { 0x1a00, 0x2552, 0x0000 }, + { 0x9a00, 0x2557, 0x3000 }, + { 0x9a00, 0x2555, 0x2000 }, + { 0x1a00, 0x2554, 0x0000 }, + { 0x1a00, 0x2556, 0x0000 }, + { 0x9a00, 0x2559, 0x2000 }, + { 0x1a00, 0x2558, 0x0000 }, + { 0x1a00, 0x255a, 0x0000 }, + { 0x9a00, 0x2563, 0x4000 }, + { 0x9a00, 0x255f, 0x3000 }, + { 0x9a00, 0x255d, 0x2000 }, + { 0x1a00, 0x255c, 0x0000 }, + { 0x1a00, 0x255e, 0x0000 }, + { 0x9a00, 0x2561, 0x2000 }, + { 0x1a00, 0x2560, 0x0000 }, + { 0x1a00, 0x2562, 0x0000 }, + { 0x9a00, 0x2567, 0x3000 }, + { 0x9a00, 0x2565, 0x2000 }, + { 0x1a00, 0x2564, 0x0000 }, + { 0x1a00, 0x2566, 0x0000 }, + { 0x9a00, 0x2569, 0x2000 }, + { 0x1a00, 0x2568, 0x0000 }, + { 0x1a00, 0x256a, 0x0000 }, + { 0x9a00, 0x257b, 0x5000 }, + { 0x9a00, 0x2573, 0x4000 }, + { 0x9a00, 0x256f, 0x3000 }, + { 0x9a00, 0x256d, 0x2000 }, + { 0x1a00, 0x256c, 0x0000 }, + { 0x1a00, 0x256e, 0x0000 }, + { 0x9a00, 0x2571, 0x2000 }, + { 0x1a00, 0x2570, 0x0000 }, + { 0x1a00, 0x2572, 0x0000 }, + { 0x9a00, 0x2577, 0x3000 }, + { 0x9a00, 0x2575, 0x2000 }, + { 0x1a00, 0x2574, 0x0000 }, + { 0x1a00, 0x2576, 0x0000 }, + { 0x9a00, 0x2579, 0x2000 }, + { 0x1a00, 0x2578, 0x0000 }, + { 0x1a00, 0x257a, 0x0000 }, + { 0x9a00, 0x2583, 0x4000 }, + { 0x9a00, 0x257f, 0x3000 }, + { 0x9a00, 0x257d, 0x2000 }, + { 0x1a00, 0x257c, 0x0000 }, + { 0x1a00, 0x257e, 0x0000 }, + { 0x9a00, 0x2581, 0x2000 }, + { 0x1a00, 0x2580, 0x0000 }, + { 0x1a00, 0x2582, 0x0000 }, + { 0x9a00, 0x2587, 0x3000 }, + { 0x9a00, 0x2585, 0x2000 }, + { 0x1a00, 0x2584, 0x0000 }, + { 0x1a00, 0x2586, 0x0000 }, + { 0x9a00, 0x2589, 0x2000 }, + { 0x1a00, 0x2588, 0x0000 }, + { 0x1a00, 0x258a, 0x0000 }, + { 0x9a00, 0x25cb, 0x7000 }, + { 0x9a00, 0x25ab, 0x6000 }, + { 0x9a00, 0x259b, 0x5000 }, + { 0x9a00, 0x2593, 0x4000 }, + { 0x9a00, 0x258f, 0x3000 }, + { 0x9a00, 0x258d, 0x2000 }, + { 0x1a00, 0x258c, 0x0000 }, + { 0x1a00, 0x258e, 0x0000 }, + { 0x9a00, 0x2591, 0x2000 }, + { 0x1a00, 0x2590, 0x0000 }, + { 0x1a00, 0x2592, 0x0000 }, + { 0x9a00, 0x2597, 0x3000 }, + { 0x9a00, 0x2595, 0x2000 }, + { 0x1a00, 0x2594, 0x0000 }, + { 0x1a00, 0x2596, 0x0000 }, + { 0x9a00, 0x2599, 0x2000 }, + { 0x1a00, 0x2598, 0x0000 }, + { 0x1a00, 0x259a, 0x0000 }, + { 0x9a00, 0x25a3, 0x4000 }, + { 0x9a00, 0x259f, 0x3000 }, + { 0x9a00, 0x259d, 0x2000 }, + { 0x1a00, 0x259c, 0x0000 }, + { 0x1a00, 0x259e, 0x0000 }, + { 0x9a00, 0x25a1, 0x2000 }, + { 0x1a00, 0x25a0, 0x0000 }, + { 0x1a00, 0x25a2, 0x0000 }, + { 0x9a00, 0x25a7, 0x3000 }, + { 0x9a00, 0x25a5, 0x2000 }, + { 0x1a00, 0x25a4, 0x0000 }, + { 0x1a00, 0x25a6, 0x0000 }, + { 0x9a00, 0x25a9, 0x2000 }, + { 0x1a00, 0x25a8, 0x0000 }, + { 0x1a00, 0x25aa, 0x0000 }, + { 0x9a00, 0x25bb, 0x5000 }, + { 0x9a00, 0x25b3, 0x4000 }, + { 0x9a00, 0x25af, 0x3000 }, + { 0x9a00, 0x25ad, 0x2000 }, + { 0x1a00, 0x25ac, 0x0000 }, + { 0x1a00, 0x25ae, 0x0000 }, + { 0x9a00, 0x25b1, 0x2000 }, + { 0x1a00, 0x25b0, 0x0000 }, + { 0x1a00, 0x25b2, 0x0000 }, + { 0x9900, 0x25b7, 0x3000 }, + { 0x9a00, 0x25b5, 0x2000 }, + { 0x1a00, 0x25b4, 0x0000 }, + { 0x1a00, 0x25b6, 0x0000 }, + { 0x9a00, 0x25b9, 0x2000 }, + { 0x1a00, 0x25b8, 0x0000 }, + { 0x1a00, 0x25ba, 0x0000 }, + { 0x9a00, 0x25c3, 0x4000 }, + { 0x9a00, 0x25bf, 0x3000 }, + { 0x9a00, 0x25bd, 0x2000 }, + { 0x1a00, 0x25bc, 0x0000 }, + { 0x1a00, 0x25be, 0x0000 }, + { 0x9900, 0x25c1, 0x2000 }, + { 0x1a00, 0x25c0, 0x0000 }, + { 0x1a00, 0x25c2, 0x0000 }, + { 0x9a00, 0x25c7, 0x3000 }, + { 0x9a00, 0x25c5, 0x2000 }, + { 0x1a00, 0x25c4, 0x0000 }, + { 0x1a00, 0x25c6, 0x0000 }, + { 0x9a00, 0x25c9, 0x2000 }, + { 0x1a00, 0x25c8, 0x0000 }, + { 0x1a00, 0x25ca, 0x0000 }, + { 0x9a00, 0x25eb, 0x6000 }, + { 0x9a00, 0x25db, 0x5000 }, + { 0x9a00, 0x25d3, 0x4000 }, + { 0x9a00, 0x25cf, 0x3000 }, + { 0x9a00, 0x25cd, 0x2000 }, + { 0x1a00, 0x25cc, 0x0000 }, + { 0x1a00, 0x25ce, 0x0000 }, + { 0x9a00, 0x25d1, 0x2000 }, + { 0x1a00, 0x25d0, 0x0000 }, + { 0x1a00, 0x25d2, 0x0000 }, + { 0x9a00, 0x25d7, 0x3000 }, + { 0x9a00, 0x25d5, 0x2000 }, + { 0x1a00, 0x25d4, 0x0000 }, + { 0x1a00, 0x25d6, 0x0000 }, + { 0x9a00, 0x25d9, 0x2000 }, + { 0x1a00, 0x25d8, 0x0000 }, + { 0x1a00, 0x25da, 0x0000 }, + { 0x9a00, 0x25e3, 0x4000 }, + { 0x9a00, 0x25df, 0x3000 }, + { 0x9a00, 0x25dd, 0x2000 }, + { 0x1a00, 0x25dc, 0x0000 }, + { 0x1a00, 0x25de, 0x0000 }, + { 0x9a00, 0x25e1, 0x2000 }, + { 0x1a00, 0x25e0, 0x0000 }, + { 0x1a00, 0x25e2, 0x0000 }, + { 0x9a00, 0x25e7, 0x3000 }, + { 0x9a00, 0x25e5, 0x2000 }, + { 0x1a00, 0x25e4, 0x0000 }, + { 0x1a00, 0x25e6, 0x0000 }, + { 0x9a00, 0x25e9, 0x2000 }, + { 0x1a00, 0x25e8, 0x0000 }, + { 0x1a00, 0x25ea, 0x0000 }, + { 0x9900, 0x25fb, 0x5000 }, + { 0x9a00, 0x25f3, 0x4000 }, + { 0x9a00, 0x25ef, 0x3000 }, + { 0x9a00, 0x25ed, 0x2000 }, + { 0x1a00, 0x25ec, 0x0000 }, + { 0x1a00, 0x25ee, 0x0000 }, + { 0x9a00, 0x25f1, 0x2000 }, + { 0x1a00, 0x25f0, 0x0000 }, + { 0x1a00, 0x25f2, 0x0000 }, + { 0x9a00, 0x25f7, 0x3000 }, + { 0x9a00, 0x25f5, 0x2000 }, + { 0x1a00, 0x25f4, 0x0000 }, + { 0x1a00, 0x25f6, 0x0000 }, + { 0x9900, 0x25f9, 0x2000 }, + { 0x1900, 0x25f8, 0x0000 }, + { 0x1900, 0x25fa, 0x0000 }, + { 0x9a00, 0x2603, 0x4000 }, + { 0x9900, 0x25ff, 0x3000 }, + { 0x9900, 0x25fd, 0x2000 }, + { 0x1900, 0x25fc, 0x0000 }, + { 0x1900, 0x25fe, 0x0000 }, + { 0x9a00, 0x2601, 0x2000 }, + { 0x1a00, 0x2600, 0x0000 }, + { 0x1a00, 0x2602, 0x0000 }, + { 0x9a00, 0x2607, 0x3000 }, + { 0x9a00, 0x2605, 0x2000 }, + { 0x1a00, 0x2604, 0x0000 }, + { 0x1a00, 0x2606, 0x0000 }, + { 0x9a00, 0x2609, 0x2000 }, + { 0x1a00, 0x2608, 0x0000 }, + { 0x1a00, 0x260a, 0x0000 }, + { 0x9a00, 0x268e, 0x8000 }, + { 0x9a00, 0x264c, 0x7000 }, + { 0x9a00, 0x262c, 0x6000 }, + { 0x9a00, 0x261c, 0x5000 }, + { 0x9a00, 0x2613, 0x4000 }, + { 0x9a00, 0x260f, 0x3000 }, + { 0x9a00, 0x260d, 0x2000 }, + { 0x1a00, 0x260c, 0x0000 }, + { 0x1a00, 0x260e, 0x0000 }, + { 0x9a00, 0x2611, 0x2000 }, + { 0x1a00, 0x2610, 0x0000 }, + { 0x1a00, 0x2612, 0x0000 }, + { 0x9a00, 0x2617, 0x3000 }, + { 0x9a00, 0x2615, 0x2000 }, + { 0x1a00, 0x2614, 0x0000 }, + { 0x1a00, 0x2616, 0x0000 }, + { 0x9a00, 0x261a, 0x2000 }, + { 0x1a00, 0x2619, 0x0000 }, + { 0x1a00, 0x261b, 0x0000 }, + { 0x9a00, 0x2624, 0x4000 }, + { 0x9a00, 0x2620, 0x3000 }, + { 0x9a00, 0x261e, 0x2000 }, + { 0x1a00, 0x261d, 0x0000 }, + { 0x1a00, 0x261f, 0x0000 }, + { 0x9a00, 0x2622, 0x2000 }, + { 0x1a00, 0x2621, 0x0000 }, + { 0x1a00, 0x2623, 0x0000 }, + { 0x9a00, 0x2628, 0x3000 }, + { 0x9a00, 0x2626, 0x2000 }, + { 0x1a00, 0x2625, 0x0000 }, + { 0x1a00, 0x2627, 0x0000 }, + { 0x9a00, 0x262a, 0x2000 }, + { 0x1a00, 0x2629, 0x0000 }, + { 0x1a00, 0x262b, 0x0000 }, + { 0x9a00, 0x263c, 0x5000 }, + { 0x9a00, 0x2634, 0x4000 }, + { 0x9a00, 0x2630, 0x3000 }, + { 0x9a00, 0x262e, 0x2000 }, + { 0x1a00, 0x262d, 0x0000 }, + { 0x1a00, 0x262f, 0x0000 }, + { 0x9a00, 0x2632, 0x2000 }, + { 0x1a00, 0x2631, 0x0000 }, + { 0x1a00, 0x2633, 0x0000 }, + { 0x9a00, 0x2638, 0x3000 }, + { 0x9a00, 0x2636, 0x2000 }, + { 0x1a00, 0x2635, 0x0000 }, + { 0x1a00, 0x2637, 0x0000 }, + { 0x9a00, 0x263a, 0x2000 }, + { 0x1a00, 0x2639, 0x0000 }, + { 0x1a00, 0x263b, 0x0000 }, + { 0x9a00, 0x2644, 0x4000 }, + { 0x9a00, 0x2640, 0x3000 }, + { 0x9a00, 0x263e, 0x2000 }, + { 0x1a00, 0x263d, 0x0000 }, + { 0x1a00, 0x263f, 0x0000 }, + { 0x9a00, 0x2642, 0x2000 }, + { 0x1a00, 0x2641, 0x0000 }, + { 0x1a00, 0x2643, 0x0000 }, + { 0x9a00, 0x2648, 0x3000 }, + { 0x9a00, 0x2646, 0x2000 }, + { 0x1a00, 0x2645, 0x0000 }, + { 0x1a00, 0x2647, 0x0000 }, + { 0x9a00, 0x264a, 0x2000 }, + { 0x1a00, 0x2649, 0x0000 }, + { 0x1a00, 0x264b, 0x0000 }, + { 0x9a00, 0x266c, 0x6000 }, + { 0x9a00, 0x265c, 0x5000 }, + { 0x9a00, 0x2654, 0x4000 }, + { 0x9a00, 0x2650, 0x3000 }, + { 0x9a00, 0x264e, 0x2000 }, + { 0x1a00, 0x264d, 0x0000 }, + { 0x1a00, 0x264f, 0x0000 }, + { 0x9a00, 0x2652, 0x2000 }, + { 0x1a00, 0x2651, 0x0000 }, + { 0x1a00, 0x2653, 0x0000 }, + { 0x9a00, 0x2658, 0x3000 }, + { 0x9a00, 0x2656, 0x2000 }, + { 0x1a00, 0x2655, 0x0000 }, + { 0x1a00, 0x2657, 0x0000 }, + { 0x9a00, 0x265a, 0x2000 }, + { 0x1a00, 0x2659, 0x0000 }, + { 0x1a00, 0x265b, 0x0000 }, + { 0x9a00, 0x2664, 0x4000 }, + { 0x9a00, 0x2660, 0x3000 }, + { 0x9a00, 0x265e, 0x2000 }, + { 0x1a00, 0x265d, 0x0000 }, + { 0x1a00, 0x265f, 0x0000 }, + { 0x9a00, 0x2662, 0x2000 }, + { 0x1a00, 0x2661, 0x0000 }, + { 0x1a00, 0x2663, 0x0000 }, + { 0x9a00, 0x2668, 0x3000 }, + { 0x9a00, 0x2666, 0x2000 }, + { 0x1a00, 0x2665, 0x0000 }, + { 0x1a00, 0x2667, 0x0000 }, + { 0x9a00, 0x266a, 0x2000 }, + { 0x1a00, 0x2669, 0x0000 }, + { 0x1a00, 0x266b, 0x0000 }, + { 0x9a00, 0x267c, 0x5000 }, + { 0x9a00, 0x2674, 0x4000 }, + { 0x9a00, 0x2670, 0x3000 }, + { 0x9a00, 0x266e, 0x2000 }, + { 0x1a00, 0x266d, 0x0000 }, + { 0x1900, 0x266f, 0x0000 }, + { 0x9a00, 0x2672, 0x2000 }, + { 0x1a00, 0x2671, 0x0000 }, + { 0x1a00, 0x2673, 0x0000 }, + { 0x9a00, 0x2678, 0x3000 }, + { 0x9a00, 0x2676, 0x2000 }, + { 0x1a00, 0x2675, 0x0000 }, + { 0x1a00, 0x2677, 0x0000 }, + { 0x9a00, 0x267a, 0x2000 }, + { 0x1a00, 0x2679, 0x0000 }, + { 0x1a00, 0x267b, 0x0000 }, + { 0x9a00, 0x2686, 0x4000 }, + { 0x9a00, 0x2682, 0x3000 }, + { 0x9a00, 0x2680, 0x2000 }, + { 0x1a00, 0x267d, 0x0000 }, + { 0x1a00, 0x2681, 0x0000 }, + { 0x9a00, 0x2684, 0x2000 }, + { 0x1a00, 0x2683, 0x0000 }, + { 0x1a00, 0x2685, 0x0000 }, + { 0x9a00, 0x268a, 0x3000 }, + { 0x9a00, 0x2688, 0x2000 }, + { 0x1a00, 0x2687, 0x0000 }, + { 0x1a00, 0x2689, 0x0000 }, + { 0x9a00, 0x268c, 0x2000 }, + { 0x1a00, 0x268b, 0x0000 }, + { 0x1a00, 0x268d, 0x0000 }, + { 0x9a00, 0x273f, 0x7000 }, + { 0x9a00, 0x271e, 0x6000 }, + { 0x9a00, 0x270e, 0x5000 }, + { 0x9a00, 0x2703, 0x4000 }, + { 0x9a00, 0x26a0, 0x3000 }, + { 0x9a00, 0x2690, 0x2000 }, + { 0x1a00, 0x268f, 0x0000 }, + { 0x1a00, 0x2691, 0x0000 }, + { 0x9a00, 0x2701, 0x2000 }, + { 0x1a00, 0x26a1, 0x0000 }, + { 0x1a00, 0x2702, 0x0000 }, + { 0x9a00, 0x2708, 0x3000 }, + { 0x9a00, 0x2706, 0x2000 }, + { 0x1a00, 0x2704, 0x0000 }, + { 0x1a00, 0x2707, 0x0000 }, + { 0x9a00, 0x270c, 0x2000 }, + { 0x1a00, 0x2709, 0x0000 }, + { 0x1a00, 0x270d, 0x0000 }, + { 0x9a00, 0x2716, 0x4000 }, + { 0x9a00, 0x2712, 0x3000 }, + { 0x9a00, 0x2710, 0x2000 }, + { 0x1a00, 0x270f, 0x0000 }, + { 0x1a00, 0x2711, 0x0000 }, + { 0x9a00, 0x2714, 0x2000 }, + { 0x1a00, 0x2713, 0x0000 }, + { 0x1a00, 0x2715, 0x0000 }, + { 0x9a00, 0x271a, 0x3000 }, + { 0x9a00, 0x2718, 0x2000 }, + { 0x1a00, 0x2717, 0x0000 }, + { 0x1a00, 0x2719, 0x0000 }, + { 0x9a00, 0x271c, 0x2000 }, + { 0x1a00, 0x271b, 0x0000 }, + { 0x1a00, 0x271d, 0x0000 }, + { 0x9a00, 0x272f, 0x5000 }, + { 0x9a00, 0x2726, 0x4000 }, + { 0x9a00, 0x2722, 0x3000 }, + { 0x9a00, 0x2720, 0x2000 }, + { 0x1a00, 0x271f, 0x0000 }, + { 0x1a00, 0x2721, 0x0000 }, + { 0x9a00, 0x2724, 0x2000 }, + { 0x1a00, 0x2723, 0x0000 }, + { 0x1a00, 0x2725, 0x0000 }, + { 0x9a00, 0x272b, 0x3000 }, + { 0x9a00, 0x2729, 0x2000 }, + { 0x1a00, 0x2727, 0x0000 }, + { 0x1a00, 0x272a, 0x0000 }, + { 0x9a00, 0x272d, 0x2000 }, + { 0x1a00, 0x272c, 0x0000 }, + { 0x1a00, 0x272e, 0x0000 }, + { 0x9a00, 0x2737, 0x4000 }, + { 0x9a00, 0x2733, 0x3000 }, + { 0x9a00, 0x2731, 0x2000 }, + { 0x1a00, 0x2730, 0x0000 }, + { 0x1a00, 0x2732, 0x0000 }, + { 0x9a00, 0x2735, 0x2000 }, + { 0x1a00, 0x2734, 0x0000 }, + { 0x1a00, 0x2736, 0x0000 }, + { 0x9a00, 0x273b, 0x3000 }, + { 0x9a00, 0x2739, 0x2000 }, + { 0x1a00, 0x2738, 0x0000 }, + { 0x1a00, 0x273a, 0x0000 }, + { 0x9a00, 0x273d, 0x2000 }, + { 0x1a00, 0x273c, 0x0000 }, + { 0x1a00, 0x273e, 0x0000 }, + { 0x9a00, 0x2767, 0x6000 }, + { 0x9a00, 0x2751, 0x5000 }, + { 0x9a00, 0x2747, 0x4000 }, + { 0x9a00, 0x2743, 0x3000 }, + { 0x9a00, 0x2741, 0x2000 }, + { 0x1a00, 0x2740, 0x0000 }, + { 0x1a00, 0x2742, 0x0000 }, + { 0x9a00, 0x2745, 0x2000 }, + { 0x1a00, 0x2744, 0x0000 }, + { 0x1a00, 0x2746, 0x0000 }, + { 0x9a00, 0x274b, 0x3000 }, + { 0x9a00, 0x2749, 0x2000 }, + { 0x1a00, 0x2748, 0x0000 }, + { 0x1a00, 0x274a, 0x0000 }, + { 0x9a00, 0x274f, 0x2000 }, + { 0x1a00, 0x274d, 0x0000 }, + { 0x1a00, 0x2750, 0x0000 }, + { 0x9a00, 0x275d, 0x4000 }, + { 0x9a00, 0x2759, 0x3000 }, + { 0x9a00, 0x2756, 0x2000 }, + { 0x1a00, 0x2752, 0x0000 }, + { 0x1a00, 0x2758, 0x0000 }, + { 0x9a00, 0x275b, 0x2000 }, + { 0x1a00, 0x275a, 0x0000 }, + { 0x1a00, 0x275c, 0x0000 }, + { 0x9a00, 0x2763, 0x3000 }, + { 0x9a00, 0x2761, 0x2000 }, + { 0x1a00, 0x275e, 0x0000 }, + { 0x1a00, 0x2762, 0x0000 }, + { 0x9a00, 0x2765, 0x2000 }, + { 0x1a00, 0x2764, 0x0000 }, + { 0x1a00, 0x2766, 0x0000 }, + { 0x8f00, 0x2777, 0x5000 }, + { 0x9200, 0x276f, 0x4000 }, + { 0x9200, 0x276b, 0x3000 }, + { 0x9200, 0x2769, 0x2000 }, + { 0x1600, 0x2768, 0x0000 }, + { 0x1600, 0x276a, 0x0000 }, + { 0x9200, 0x276d, 0x2000 }, + { 0x1600, 0x276c, 0x0000 }, + { 0x1600, 0x276e, 0x0000 }, + { 0x9200, 0x2773, 0x3000 }, + { 0x9200, 0x2771, 0x2000 }, + { 0x1600, 0x2770, 0x0000 }, + { 0x1600, 0x2772, 0x0000 }, + { 0x9200, 0x2775, 0x2000 }, + { 0x1600, 0x2774, 0x0000 }, + { 0x0f00, 0x2776, 0x0000 }, + { 0x8f00, 0x277f, 0x4000 }, + { 0x8f00, 0x277b, 0x3000 }, + { 0x8f00, 0x2779, 0x2000 }, + { 0x0f00, 0x2778, 0x0000 }, + { 0x0f00, 0x277a, 0x0000 }, + { 0x8f00, 0x277d, 0x2000 }, + { 0x0f00, 0x277c, 0x0000 }, + { 0x0f00, 0x277e, 0x0000 }, + { 0x8f00, 0x2783, 0x3000 }, + { 0x8f00, 0x2781, 0x2000 }, + { 0x0f00, 0x2780, 0x0000 }, + { 0x0f00, 0x2782, 0x0000 }, + { 0x8f00, 0x2785, 0x2000 }, + { 0x0f00, 0x2784, 0x0000 }, + { 0x0f00, 0x2786, 0x0000 }, + { 0x9900, 0x29a0, 0xa000 }, + { 0x9a00, 0x28a0, 0x9000 }, + { 0x9a00, 0x2820, 0x8000 }, + { 0x9900, 0x27dc, 0x7000 }, + { 0x9a00, 0x27aa, 0x6000 }, + { 0x9a00, 0x279a, 0x5000 }, + { 0x8f00, 0x278f, 0x4000 }, + { 0x8f00, 0x278b, 0x3000 }, + { 0x8f00, 0x2789, 0x2000 }, + { 0x0f00, 0x2788, 0x0000 }, + { 0x0f00, 0x278a, 0x0000 }, + { 0x8f00, 0x278d, 0x2000 }, + { 0x0f00, 0x278c, 0x0000 }, + { 0x0f00, 0x278e, 0x0000 }, + { 0x8f00, 0x2793, 0x3000 }, + { 0x8f00, 0x2791, 0x2000 }, + { 0x0f00, 0x2790, 0x0000 }, + { 0x0f00, 0x2792, 0x0000 }, + { 0x9a00, 0x2798, 0x2000 }, + { 0x1a00, 0x2794, 0x0000 }, + { 0x1a00, 0x2799, 0x0000 }, + { 0x9a00, 0x27a2, 0x4000 }, + { 0x9a00, 0x279e, 0x3000 }, + { 0x9a00, 0x279c, 0x2000 }, + { 0x1a00, 0x279b, 0x0000 }, + { 0x1a00, 0x279d, 0x0000 }, + { 0x9a00, 0x27a0, 0x2000 }, + { 0x1a00, 0x279f, 0x0000 }, + { 0x1a00, 0x27a1, 0x0000 }, + { 0x9a00, 0x27a6, 0x3000 }, + { 0x9a00, 0x27a4, 0x2000 }, + { 0x1a00, 0x27a3, 0x0000 }, + { 0x1a00, 0x27a5, 0x0000 }, + { 0x9a00, 0x27a8, 0x2000 }, + { 0x1a00, 0x27a7, 0x0000 }, + { 0x1a00, 0x27a9, 0x0000 }, + { 0x9a00, 0x27bb, 0x5000 }, + { 0x9a00, 0x27b3, 0x4000 }, + { 0x9a00, 0x27ae, 0x3000 }, + { 0x9a00, 0x27ac, 0x2000 }, + { 0x1a00, 0x27ab, 0x0000 }, + { 0x1a00, 0x27ad, 0x0000 }, + { 0x9a00, 0x27b1, 0x2000 }, + { 0x1a00, 0x27af, 0x0000 }, + { 0x1a00, 0x27b2, 0x0000 }, + { 0x9a00, 0x27b7, 0x3000 }, + { 0x9a00, 0x27b5, 0x2000 }, + { 0x1a00, 0x27b4, 0x0000 }, + { 0x1a00, 0x27b6, 0x0000 }, + { 0x9a00, 0x27b9, 0x2000 }, + { 0x1a00, 0x27b8, 0x0000 }, + { 0x1a00, 0x27ba, 0x0000 }, + { 0x9900, 0x27d4, 0x4000 }, + { 0x9900, 0x27d0, 0x3000 }, + { 0x9a00, 0x27bd, 0x2000 }, + { 0x1a00, 0x27bc, 0x0000 }, + { 0x1a00, 0x27be, 0x0000 }, + { 0x9900, 0x27d2, 0x2000 }, + { 0x1900, 0x27d1, 0x0000 }, + { 0x1900, 0x27d3, 0x0000 }, + { 0x9900, 0x27d8, 0x3000 }, + { 0x9900, 0x27d6, 0x2000 }, + { 0x1900, 0x27d5, 0x0000 }, + { 0x1900, 0x27d7, 0x0000 }, + { 0x9900, 0x27da, 0x2000 }, + { 0x1900, 0x27d9, 0x0000 }, + { 0x1900, 0x27db, 0x0000 }, + { 0x9a00, 0x2800, 0x6000 }, + { 0x9900, 0x27f0, 0x5000 }, + { 0x9900, 0x27e4, 0x4000 }, + { 0x9900, 0x27e0, 0x3000 }, + { 0x9900, 0x27de, 0x2000 }, + { 0x1900, 0x27dd, 0x0000 }, + { 0x1900, 0x27df, 0x0000 }, + { 0x9900, 0x27e2, 0x2000 }, + { 0x1900, 0x27e1, 0x0000 }, + { 0x1900, 0x27e3, 0x0000 }, + { 0x9600, 0x27e8, 0x3000 }, + { 0x9600, 0x27e6, 0x2000 }, + { 0x1900, 0x27e5, 0x0000 }, + { 0x1200, 0x27e7, 0x0000 }, + { 0x9600, 0x27ea, 0x2000 }, + { 0x1200, 0x27e9, 0x0000 }, + { 0x1200, 0x27eb, 0x0000 }, + { 0x9900, 0x27f8, 0x4000 }, + { 0x9900, 0x27f4, 0x3000 }, + { 0x9900, 0x27f2, 0x2000 }, + { 0x1900, 0x27f1, 0x0000 }, + { 0x1900, 0x27f3, 0x0000 }, + { 0x9900, 0x27f6, 0x2000 }, + { 0x1900, 0x27f5, 0x0000 }, + { 0x1900, 0x27f7, 0x0000 }, + { 0x9900, 0x27fc, 0x3000 }, + { 0x9900, 0x27fa, 0x2000 }, + { 0x1900, 0x27f9, 0x0000 }, + { 0x1900, 0x27fb, 0x0000 }, + { 0x9900, 0x27fe, 0x2000 }, + { 0x1900, 0x27fd, 0x0000 }, + { 0x1900, 0x27ff, 0x0000 }, + { 0x9a00, 0x2810, 0x5000 }, + { 0x9a00, 0x2808, 0x4000 }, + { 0x9a00, 0x2804, 0x3000 }, + { 0x9a00, 0x2802, 0x2000 }, + { 0x1a00, 0x2801, 0x0000 }, + { 0x1a00, 0x2803, 0x0000 }, + { 0x9a00, 0x2806, 0x2000 }, + { 0x1a00, 0x2805, 0x0000 }, + { 0x1a00, 0x2807, 0x0000 }, + { 0x9a00, 0x280c, 0x3000 }, + { 0x9a00, 0x280a, 0x2000 }, + { 0x1a00, 0x2809, 0x0000 }, + { 0x1a00, 0x280b, 0x0000 }, + { 0x9a00, 0x280e, 0x2000 }, + { 0x1a00, 0x280d, 0x0000 }, + { 0x1a00, 0x280f, 0x0000 }, + { 0x9a00, 0x2818, 0x4000 }, + { 0x9a00, 0x2814, 0x3000 }, + { 0x9a00, 0x2812, 0x2000 }, + { 0x1a00, 0x2811, 0x0000 }, + { 0x1a00, 0x2813, 0x0000 }, + { 0x9a00, 0x2816, 0x2000 }, + { 0x1a00, 0x2815, 0x0000 }, + { 0x1a00, 0x2817, 0x0000 }, + { 0x9a00, 0x281c, 0x3000 }, + { 0x9a00, 0x281a, 0x2000 }, + { 0x1a00, 0x2819, 0x0000 }, + { 0x1a00, 0x281b, 0x0000 }, + { 0x9a00, 0x281e, 0x2000 }, + { 0x1a00, 0x281d, 0x0000 }, + { 0x1a00, 0x281f, 0x0000 }, + { 0x9a00, 0x2860, 0x7000 }, + { 0x9a00, 0x2840, 0x6000 }, + { 0x9a00, 0x2830, 0x5000 }, + { 0x9a00, 0x2828, 0x4000 }, + { 0x9a00, 0x2824, 0x3000 }, + { 0x9a00, 0x2822, 0x2000 }, + { 0x1a00, 0x2821, 0x0000 }, + { 0x1a00, 0x2823, 0x0000 }, + { 0x9a00, 0x2826, 0x2000 }, + { 0x1a00, 0x2825, 0x0000 }, + { 0x1a00, 0x2827, 0x0000 }, + { 0x9a00, 0x282c, 0x3000 }, + { 0x9a00, 0x282a, 0x2000 }, + { 0x1a00, 0x2829, 0x0000 }, + { 0x1a00, 0x282b, 0x0000 }, + { 0x9a00, 0x282e, 0x2000 }, + { 0x1a00, 0x282d, 0x0000 }, + { 0x1a00, 0x282f, 0x0000 }, + { 0x9a00, 0x2838, 0x4000 }, + { 0x9a00, 0x2834, 0x3000 }, + { 0x9a00, 0x2832, 0x2000 }, + { 0x1a00, 0x2831, 0x0000 }, + { 0x1a00, 0x2833, 0x0000 }, + { 0x9a00, 0x2836, 0x2000 }, + { 0x1a00, 0x2835, 0x0000 }, + { 0x1a00, 0x2837, 0x0000 }, + { 0x9a00, 0x283c, 0x3000 }, + { 0x9a00, 0x283a, 0x2000 }, + { 0x1a00, 0x2839, 0x0000 }, + { 0x1a00, 0x283b, 0x0000 }, + { 0x9a00, 0x283e, 0x2000 }, + { 0x1a00, 0x283d, 0x0000 }, + { 0x1a00, 0x283f, 0x0000 }, + { 0x9a00, 0x2850, 0x5000 }, + { 0x9a00, 0x2848, 0x4000 }, + { 0x9a00, 0x2844, 0x3000 }, + { 0x9a00, 0x2842, 0x2000 }, + { 0x1a00, 0x2841, 0x0000 }, + { 0x1a00, 0x2843, 0x0000 }, + { 0x9a00, 0x2846, 0x2000 }, + { 0x1a00, 0x2845, 0x0000 }, + { 0x1a00, 0x2847, 0x0000 }, + { 0x9a00, 0x284c, 0x3000 }, + { 0x9a00, 0x284a, 0x2000 }, + { 0x1a00, 0x2849, 0x0000 }, + { 0x1a00, 0x284b, 0x0000 }, + { 0x9a00, 0x284e, 0x2000 }, + { 0x1a00, 0x284d, 0x0000 }, + { 0x1a00, 0x284f, 0x0000 }, + { 0x9a00, 0x2858, 0x4000 }, + { 0x9a00, 0x2854, 0x3000 }, + { 0x9a00, 0x2852, 0x2000 }, + { 0x1a00, 0x2851, 0x0000 }, + { 0x1a00, 0x2853, 0x0000 }, + { 0x9a00, 0x2856, 0x2000 }, + { 0x1a00, 0x2855, 0x0000 }, + { 0x1a00, 0x2857, 0x0000 }, + { 0x9a00, 0x285c, 0x3000 }, + { 0x9a00, 0x285a, 0x2000 }, + { 0x1a00, 0x2859, 0x0000 }, + { 0x1a00, 0x285b, 0x0000 }, + { 0x9a00, 0x285e, 0x2000 }, + { 0x1a00, 0x285d, 0x0000 }, + { 0x1a00, 0x285f, 0x0000 }, + { 0x9a00, 0x2880, 0x6000 }, + { 0x9a00, 0x2870, 0x5000 }, + { 0x9a00, 0x2868, 0x4000 }, + { 0x9a00, 0x2864, 0x3000 }, + { 0x9a00, 0x2862, 0x2000 }, + { 0x1a00, 0x2861, 0x0000 }, + { 0x1a00, 0x2863, 0x0000 }, + { 0x9a00, 0x2866, 0x2000 }, + { 0x1a00, 0x2865, 0x0000 }, + { 0x1a00, 0x2867, 0x0000 }, + { 0x9a00, 0x286c, 0x3000 }, + { 0x9a00, 0x286a, 0x2000 }, + { 0x1a00, 0x2869, 0x0000 }, + { 0x1a00, 0x286b, 0x0000 }, + { 0x9a00, 0x286e, 0x2000 }, + { 0x1a00, 0x286d, 0x0000 }, + { 0x1a00, 0x286f, 0x0000 }, + { 0x9a00, 0x2878, 0x4000 }, + { 0x9a00, 0x2874, 0x3000 }, + { 0x9a00, 0x2872, 0x2000 }, + { 0x1a00, 0x2871, 0x0000 }, + { 0x1a00, 0x2873, 0x0000 }, + { 0x9a00, 0x2876, 0x2000 }, + { 0x1a00, 0x2875, 0x0000 }, + { 0x1a00, 0x2877, 0x0000 }, + { 0x9a00, 0x287c, 0x3000 }, + { 0x9a00, 0x287a, 0x2000 }, + { 0x1a00, 0x2879, 0x0000 }, + { 0x1a00, 0x287b, 0x0000 }, + { 0x9a00, 0x287e, 0x2000 }, + { 0x1a00, 0x287d, 0x0000 }, + { 0x1a00, 0x287f, 0x0000 }, + { 0x9a00, 0x2890, 0x5000 }, + { 0x9a00, 0x2888, 0x4000 }, + { 0x9a00, 0x2884, 0x3000 }, + { 0x9a00, 0x2882, 0x2000 }, + { 0x1a00, 0x2881, 0x0000 }, + { 0x1a00, 0x2883, 0x0000 }, + { 0x9a00, 0x2886, 0x2000 }, + { 0x1a00, 0x2885, 0x0000 }, + { 0x1a00, 0x2887, 0x0000 }, + { 0x9a00, 0x288c, 0x3000 }, + { 0x9a00, 0x288a, 0x2000 }, + { 0x1a00, 0x2889, 0x0000 }, + { 0x1a00, 0x288b, 0x0000 }, + { 0x9a00, 0x288e, 0x2000 }, + { 0x1a00, 0x288d, 0x0000 }, + { 0x1a00, 0x288f, 0x0000 }, + { 0x9a00, 0x2898, 0x4000 }, + { 0x9a00, 0x2894, 0x3000 }, + { 0x9a00, 0x2892, 0x2000 }, + { 0x1a00, 0x2891, 0x0000 }, + { 0x1a00, 0x2893, 0x0000 }, + { 0x9a00, 0x2896, 0x2000 }, + { 0x1a00, 0x2895, 0x0000 }, + { 0x1a00, 0x2897, 0x0000 }, + { 0x9a00, 0x289c, 0x3000 }, + { 0x9a00, 0x289a, 0x2000 }, + { 0x1a00, 0x2899, 0x0000 }, + { 0x1a00, 0x289b, 0x0000 }, + { 0x9a00, 0x289e, 0x2000 }, + { 0x1a00, 0x289d, 0x0000 }, + { 0x1a00, 0x289f, 0x0000 }, + { 0x9900, 0x2920, 0x8000 }, + { 0x9a00, 0x28e0, 0x7000 }, + { 0x9a00, 0x28c0, 0x6000 }, + { 0x9a00, 0x28b0, 0x5000 }, + { 0x9a00, 0x28a8, 0x4000 }, + { 0x9a00, 0x28a4, 0x3000 }, + { 0x9a00, 0x28a2, 0x2000 }, + { 0x1a00, 0x28a1, 0x0000 }, + { 0x1a00, 0x28a3, 0x0000 }, + { 0x9a00, 0x28a6, 0x2000 }, + { 0x1a00, 0x28a5, 0x0000 }, + { 0x1a00, 0x28a7, 0x0000 }, + { 0x9a00, 0x28ac, 0x3000 }, + { 0x9a00, 0x28aa, 0x2000 }, + { 0x1a00, 0x28a9, 0x0000 }, + { 0x1a00, 0x28ab, 0x0000 }, + { 0x9a00, 0x28ae, 0x2000 }, + { 0x1a00, 0x28ad, 0x0000 }, + { 0x1a00, 0x28af, 0x0000 }, + { 0x9a00, 0x28b8, 0x4000 }, + { 0x9a00, 0x28b4, 0x3000 }, + { 0x9a00, 0x28b2, 0x2000 }, + { 0x1a00, 0x28b1, 0x0000 }, + { 0x1a00, 0x28b3, 0x0000 }, + { 0x9a00, 0x28b6, 0x2000 }, + { 0x1a00, 0x28b5, 0x0000 }, + { 0x1a00, 0x28b7, 0x0000 }, + { 0x9a00, 0x28bc, 0x3000 }, + { 0x9a00, 0x28ba, 0x2000 }, + { 0x1a00, 0x28b9, 0x0000 }, + { 0x1a00, 0x28bb, 0x0000 }, + { 0x9a00, 0x28be, 0x2000 }, + { 0x1a00, 0x28bd, 0x0000 }, + { 0x1a00, 0x28bf, 0x0000 }, + { 0x9a00, 0x28d0, 0x5000 }, + { 0x9a00, 0x28c8, 0x4000 }, + { 0x9a00, 0x28c4, 0x3000 }, + { 0x9a00, 0x28c2, 0x2000 }, + { 0x1a00, 0x28c1, 0x0000 }, + { 0x1a00, 0x28c3, 0x0000 }, + { 0x9a00, 0x28c6, 0x2000 }, + { 0x1a00, 0x28c5, 0x0000 }, + { 0x1a00, 0x28c7, 0x0000 }, + { 0x9a00, 0x28cc, 0x3000 }, + { 0x9a00, 0x28ca, 0x2000 }, + { 0x1a00, 0x28c9, 0x0000 }, + { 0x1a00, 0x28cb, 0x0000 }, + { 0x9a00, 0x28ce, 0x2000 }, + { 0x1a00, 0x28cd, 0x0000 }, + { 0x1a00, 0x28cf, 0x0000 }, + { 0x9a00, 0x28d8, 0x4000 }, + { 0x9a00, 0x28d4, 0x3000 }, + { 0x9a00, 0x28d2, 0x2000 }, + { 0x1a00, 0x28d1, 0x0000 }, + { 0x1a00, 0x28d3, 0x0000 }, + { 0x9a00, 0x28d6, 0x2000 }, + { 0x1a00, 0x28d5, 0x0000 }, + { 0x1a00, 0x28d7, 0x0000 }, + { 0x9a00, 0x28dc, 0x3000 }, + { 0x9a00, 0x28da, 0x2000 }, + { 0x1a00, 0x28d9, 0x0000 }, + { 0x1a00, 0x28db, 0x0000 }, + { 0x9a00, 0x28de, 0x2000 }, + { 0x1a00, 0x28dd, 0x0000 }, + { 0x1a00, 0x28df, 0x0000 }, + { 0x9900, 0x2900, 0x6000 }, + { 0x9a00, 0x28f0, 0x5000 }, + { 0x9a00, 0x28e8, 0x4000 }, + { 0x9a00, 0x28e4, 0x3000 }, + { 0x9a00, 0x28e2, 0x2000 }, + { 0x1a00, 0x28e1, 0x0000 }, + { 0x1a00, 0x28e3, 0x0000 }, + { 0x9a00, 0x28e6, 0x2000 }, + { 0x1a00, 0x28e5, 0x0000 }, + { 0x1a00, 0x28e7, 0x0000 }, + { 0x9a00, 0x28ec, 0x3000 }, + { 0x9a00, 0x28ea, 0x2000 }, + { 0x1a00, 0x28e9, 0x0000 }, + { 0x1a00, 0x28eb, 0x0000 }, + { 0x9a00, 0x28ee, 0x2000 }, + { 0x1a00, 0x28ed, 0x0000 }, + { 0x1a00, 0x28ef, 0x0000 }, + { 0x9a00, 0x28f8, 0x4000 }, + { 0x9a00, 0x28f4, 0x3000 }, + { 0x9a00, 0x28f2, 0x2000 }, + { 0x1a00, 0x28f1, 0x0000 }, + { 0x1a00, 0x28f3, 0x0000 }, + { 0x9a00, 0x28f6, 0x2000 }, + { 0x1a00, 0x28f5, 0x0000 }, + { 0x1a00, 0x28f7, 0x0000 }, + { 0x9a00, 0x28fc, 0x3000 }, + { 0x9a00, 0x28fa, 0x2000 }, + { 0x1a00, 0x28f9, 0x0000 }, + { 0x1a00, 0x28fb, 0x0000 }, + { 0x9a00, 0x28fe, 0x2000 }, + { 0x1a00, 0x28fd, 0x0000 }, + { 0x1a00, 0x28ff, 0x0000 }, + { 0x9900, 0x2910, 0x5000 }, + { 0x9900, 0x2908, 0x4000 }, + { 0x9900, 0x2904, 0x3000 }, + { 0x9900, 0x2902, 0x2000 }, + { 0x1900, 0x2901, 0x0000 }, + { 0x1900, 0x2903, 0x0000 }, + { 0x9900, 0x2906, 0x2000 }, + { 0x1900, 0x2905, 0x0000 }, + { 0x1900, 0x2907, 0x0000 }, + { 0x9900, 0x290c, 0x3000 }, + { 0x9900, 0x290a, 0x2000 }, + { 0x1900, 0x2909, 0x0000 }, + { 0x1900, 0x290b, 0x0000 }, + { 0x9900, 0x290e, 0x2000 }, + { 0x1900, 0x290d, 0x0000 }, + { 0x1900, 0x290f, 0x0000 }, + { 0x9900, 0x2918, 0x4000 }, + { 0x9900, 0x2914, 0x3000 }, + { 0x9900, 0x2912, 0x2000 }, + { 0x1900, 0x2911, 0x0000 }, + { 0x1900, 0x2913, 0x0000 }, + { 0x9900, 0x2916, 0x2000 }, + { 0x1900, 0x2915, 0x0000 }, + { 0x1900, 0x2917, 0x0000 }, + { 0x9900, 0x291c, 0x3000 }, + { 0x9900, 0x291a, 0x2000 }, + { 0x1900, 0x2919, 0x0000 }, + { 0x1900, 0x291b, 0x0000 }, + { 0x9900, 0x291e, 0x2000 }, + { 0x1900, 0x291d, 0x0000 }, + { 0x1900, 0x291f, 0x0000 }, + { 0x9900, 0x2960, 0x7000 }, + { 0x9900, 0x2940, 0x6000 }, + { 0x9900, 0x2930, 0x5000 }, + { 0x9900, 0x2928, 0x4000 }, + { 0x9900, 0x2924, 0x3000 }, + { 0x9900, 0x2922, 0x2000 }, + { 0x1900, 0x2921, 0x0000 }, + { 0x1900, 0x2923, 0x0000 }, + { 0x9900, 0x2926, 0x2000 }, + { 0x1900, 0x2925, 0x0000 }, + { 0x1900, 0x2927, 0x0000 }, + { 0x9900, 0x292c, 0x3000 }, + { 0x9900, 0x292a, 0x2000 }, + { 0x1900, 0x2929, 0x0000 }, + { 0x1900, 0x292b, 0x0000 }, + { 0x9900, 0x292e, 0x2000 }, + { 0x1900, 0x292d, 0x0000 }, + { 0x1900, 0x292f, 0x0000 }, + { 0x9900, 0x2938, 0x4000 }, + { 0x9900, 0x2934, 0x3000 }, + { 0x9900, 0x2932, 0x2000 }, + { 0x1900, 0x2931, 0x0000 }, + { 0x1900, 0x2933, 0x0000 }, + { 0x9900, 0x2936, 0x2000 }, + { 0x1900, 0x2935, 0x0000 }, + { 0x1900, 0x2937, 0x0000 }, + { 0x9900, 0x293c, 0x3000 }, + { 0x9900, 0x293a, 0x2000 }, + { 0x1900, 0x2939, 0x0000 }, + { 0x1900, 0x293b, 0x0000 }, + { 0x9900, 0x293e, 0x2000 }, + { 0x1900, 0x293d, 0x0000 }, + { 0x1900, 0x293f, 0x0000 }, + { 0x9900, 0x2950, 0x5000 }, + { 0x9900, 0x2948, 0x4000 }, + { 0x9900, 0x2944, 0x3000 }, + { 0x9900, 0x2942, 0x2000 }, + { 0x1900, 0x2941, 0x0000 }, + { 0x1900, 0x2943, 0x0000 }, + { 0x9900, 0x2946, 0x2000 }, + { 0x1900, 0x2945, 0x0000 }, + { 0x1900, 0x2947, 0x0000 }, + { 0x9900, 0x294c, 0x3000 }, + { 0x9900, 0x294a, 0x2000 }, + { 0x1900, 0x2949, 0x0000 }, + { 0x1900, 0x294b, 0x0000 }, + { 0x9900, 0x294e, 0x2000 }, + { 0x1900, 0x294d, 0x0000 }, + { 0x1900, 0x294f, 0x0000 }, + { 0x9900, 0x2958, 0x4000 }, + { 0x9900, 0x2954, 0x3000 }, + { 0x9900, 0x2952, 0x2000 }, + { 0x1900, 0x2951, 0x0000 }, + { 0x1900, 0x2953, 0x0000 }, + { 0x9900, 0x2956, 0x2000 }, + { 0x1900, 0x2955, 0x0000 }, + { 0x1900, 0x2957, 0x0000 }, + { 0x9900, 0x295c, 0x3000 }, + { 0x9900, 0x295a, 0x2000 }, + { 0x1900, 0x2959, 0x0000 }, + { 0x1900, 0x295b, 0x0000 }, + { 0x9900, 0x295e, 0x2000 }, + { 0x1900, 0x295d, 0x0000 }, + { 0x1900, 0x295f, 0x0000 }, + { 0x9900, 0x2980, 0x6000 }, + { 0x9900, 0x2970, 0x5000 }, + { 0x9900, 0x2968, 0x4000 }, + { 0x9900, 0x2964, 0x3000 }, + { 0x9900, 0x2962, 0x2000 }, + { 0x1900, 0x2961, 0x0000 }, + { 0x1900, 0x2963, 0x0000 }, + { 0x9900, 0x2966, 0x2000 }, + { 0x1900, 0x2965, 0x0000 }, + { 0x1900, 0x2967, 0x0000 }, + { 0x9900, 0x296c, 0x3000 }, + { 0x9900, 0x296a, 0x2000 }, + { 0x1900, 0x2969, 0x0000 }, + { 0x1900, 0x296b, 0x0000 }, + { 0x9900, 0x296e, 0x2000 }, + { 0x1900, 0x296d, 0x0000 }, + { 0x1900, 0x296f, 0x0000 }, + { 0x9900, 0x2978, 0x4000 }, + { 0x9900, 0x2974, 0x3000 }, + { 0x9900, 0x2972, 0x2000 }, + { 0x1900, 0x2971, 0x0000 }, + { 0x1900, 0x2973, 0x0000 }, + { 0x9900, 0x2976, 0x2000 }, + { 0x1900, 0x2975, 0x0000 }, + { 0x1900, 0x2977, 0x0000 }, + { 0x9900, 0x297c, 0x3000 }, + { 0x9900, 0x297a, 0x2000 }, + { 0x1900, 0x2979, 0x0000 }, + { 0x1900, 0x297b, 0x0000 }, + { 0x9900, 0x297e, 0x2000 }, + { 0x1900, 0x297d, 0x0000 }, + { 0x1900, 0x297f, 0x0000 }, + { 0x9200, 0x2990, 0x5000 }, + { 0x9200, 0x2988, 0x4000 }, + { 0x9200, 0x2984, 0x3000 }, + { 0x9900, 0x2982, 0x2000 }, + { 0x1900, 0x2981, 0x0000 }, + { 0x1600, 0x2983, 0x0000 }, + { 0x9200, 0x2986, 0x2000 }, + { 0x1600, 0x2985, 0x0000 }, + { 0x1600, 0x2987, 0x0000 }, + { 0x9200, 0x298c, 0x3000 }, + { 0x9200, 0x298a, 0x2000 }, + { 0x1600, 0x2989, 0x0000 }, + { 0x1600, 0x298b, 0x0000 }, + { 0x9200, 0x298e, 0x2000 }, + { 0x1600, 0x298d, 0x0000 }, + { 0x1600, 0x298f, 0x0000 }, + { 0x9200, 0x2998, 0x4000 }, + { 0x9200, 0x2994, 0x3000 }, + { 0x9200, 0x2992, 0x2000 }, + { 0x1600, 0x2991, 0x0000 }, + { 0x1600, 0x2993, 0x0000 }, + { 0x9200, 0x2996, 0x2000 }, + { 0x1600, 0x2995, 0x0000 }, + { 0x1600, 0x2997, 0x0000 }, + { 0x9900, 0x299c, 0x3000 }, + { 0x9900, 0x299a, 0x2000 }, + { 0x1900, 0x2999, 0x0000 }, + { 0x1900, 0x299b, 0x0000 }, + { 0x9900, 0x299e, 0x2000 }, + { 0x1900, 0x299d, 0x0000 }, + { 0x1900, 0x299f, 0x0000 }, + { 0x9900, 0x2aa0, 0x9000 }, + { 0x9900, 0x2a20, 0x8000 }, + { 0x9900, 0x29e0, 0x7000 }, + { 0x9900, 0x29c0, 0x6000 }, + { 0x9900, 0x29b0, 0x5000 }, + { 0x9900, 0x29a8, 0x4000 }, + { 0x9900, 0x29a4, 0x3000 }, + { 0x9900, 0x29a2, 0x2000 }, + { 0x1900, 0x29a1, 0x0000 }, + { 0x1900, 0x29a3, 0x0000 }, + { 0x9900, 0x29a6, 0x2000 }, + { 0x1900, 0x29a5, 0x0000 }, + { 0x1900, 0x29a7, 0x0000 }, + { 0x9900, 0x29ac, 0x3000 }, + { 0x9900, 0x29aa, 0x2000 }, + { 0x1900, 0x29a9, 0x0000 }, + { 0x1900, 0x29ab, 0x0000 }, + { 0x9900, 0x29ae, 0x2000 }, + { 0x1900, 0x29ad, 0x0000 }, + { 0x1900, 0x29af, 0x0000 }, + { 0x9900, 0x29b8, 0x4000 }, + { 0x9900, 0x29b4, 0x3000 }, + { 0x9900, 0x29b2, 0x2000 }, + { 0x1900, 0x29b1, 0x0000 }, + { 0x1900, 0x29b3, 0x0000 }, + { 0x9900, 0x29b6, 0x2000 }, + { 0x1900, 0x29b5, 0x0000 }, + { 0x1900, 0x29b7, 0x0000 }, + { 0x9900, 0x29bc, 0x3000 }, + { 0x9900, 0x29ba, 0x2000 }, + { 0x1900, 0x29b9, 0x0000 }, + { 0x1900, 0x29bb, 0x0000 }, + { 0x9900, 0x29be, 0x2000 }, + { 0x1900, 0x29bd, 0x0000 }, + { 0x1900, 0x29bf, 0x0000 }, + { 0x9900, 0x29d0, 0x5000 }, + { 0x9900, 0x29c8, 0x4000 }, + { 0x9900, 0x29c4, 0x3000 }, + { 0x9900, 0x29c2, 0x2000 }, + { 0x1900, 0x29c1, 0x0000 }, + { 0x1900, 0x29c3, 0x0000 }, + { 0x9900, 0x29c6, 0x2000 }, + { 0x1900, 0x29c5, 0x0000 }, + { 0x1900, 0x29c7, 0x0000 }, + { 0x9900, 0x29cc, 0x3000 }, + { 0x9900, 0x29ca, 0x2000 }, + { 0x1900, 0x29c9, 0x0000 }, + { 0x1900, 0x29cb, 0x0000 }, + { 0x9900, 0x29ce, 0x2000 }, + { 0x1900, 0x29cd, 0x0000 }, + { 0x1900, 0x29cf, 0x0000 }, + { 0x9600, 0x29d8, 0x4000 }, + { 0x9900, 0x29d4, 0x3000 }, + { 0x9900, 0x29d2, 0x2000 }, + { 0x1900, 0x29d1, 0x0000 }, + { 0x1900, 0x29d3, 0x0000 }, + { 0x9900, 0x29d6, 0x2000 }, + { 0x1900, 0x29d5, 0x0000 }, + { 0x1900, 0x29d7, 0x0000 }, + { 0x9900, 0x29dc, 0x3000 }, + { 0x9600, 0x29da, 0x2000 }, + { 0x1200, 0x29d9, 0x0000 }, + { 0x1200, 0x29db, 0x0000 }, + { 0x9900, 0x29de, 0x2000 }, + { 0x1900, 0x29dd, 0x0000 }, + { 0x1900, 0x29df, 0x0000 }, + { 0x9900, 0x2a00, 0x6000 }, + { 0x9900, 0x29f0, 0x5000 }, + { 0x9900, 0x29e8, 0x4000 }, + { 0x9900, 0x29e4, 0x3000 }, + { 0x9900, 0x29e2, 0x2000 }, + { 0x1900, 0x29e1, 0x0000 }, + { 0x1900, 0x29e3, 0x0000 }, + { 0x9900, 0x29e6, 0x2000 }, + { 0x1900, 0x29e5, 0x0000 }, + { 0x1900, 0x29e7, 0x0000 }, + { 0x9900, 0x29ec, 0x3000 }, + { 0x9900, 0x29ea, 0x2000 }, + { 0x1900, 0x29e9, 0x0000 }, + { 0x1900, 0x29eb, 0x0000 }, + { 0x9900, 0x29ee, 0x2000 }, + { 0x1900, 0x29ed, 0x0000 }, + { 0x1900, 0x29ef, 0x0000 }, + { 0x9900, 0x29f8, 0x4000 }, + { 0x9900, 0x29f4, 0x3000 }, + { 0x9900, 0x29f2, 0x2000 }, + { 0x1900, 0x29f1, 0x0000 }, + { 0x1900, 0x29f3, 0x0000 }, + { 0x9900, 0x29f6, 0x2000 }, + { 0x1900, 0x29f5, 0x0000 }, + { 0x1900, 0x29f7, 0x0000 }, + { 0x9600, 0x29fc, 0x3000 }, + { 0x9900, 0x29fa, 0x2000 }, + { 0x1900, 0x29f9, 0x0000 }, + { 0x1900, 0x29fb, 0x0000 }, + { 0x9900, 0x29fe, 0x2000 }, + { 0x1200, 0x29fd, 0x0000 }, + { 0x1900, 0x29ff, 0x0000 }, + { 0x9900, 0x2a10, 0x5000 }, + { 0x9900, 0x2a08, 0x4000 }, + { 0x9900, 0x2a04, 0x3000 }, + { 0x9900, 0x2a02, 0x2000 }, + { 0x1900, 0x2a01, 0x0000 }, + { 0x1900, 0x2a03, 0x0000 }, + { 0x9900, 0x2a06, 0x2000 }, + { 0x1900, 0x2a05, 0x0000 }, + { 0x1900, 0x2a07, 0x0000 }, + { 0x9900, 0x2a0c, 0x3000 }, + { 0x9900, 0x2a0a, 0x2000 }, + { 0x1900, 0x2a09, 0x0000 }, + { 0x1900, 0x2a0b, 0x0000 }, + { 0x9900, 0x2a0e, 0x2000 }, + { 0x1900, 0x2a0d, 0x0000 }, + { 0x1900, 0x2a0f, 0x0000 }, + { 0x9900, 0x2a18, 0x4000 }, + { 0x9900, 0x2a14, 0x3000 }, + { 0x9900, 0x2a12, 0x2000 }, + { 0x1900, 0x2a11, 0x0000 }, + { 0x1900, 0x2a13, 0x0000 }, + { 0x9900, 0x2a16, 0x2000 }, + { 0x1900, 0x2a15, 0x0000 }, + { 0x1900, 0x2a17, 0x0000 }, + { 0x9900, 0x2a1c, 0x3000 }, + { 0x9900, 0x2a1a, 0x2000 }, + { 0x1900, 0x2a19, 0x0000 }, + { 0x1900, 0x2a1b, 0x0000 }, + { 0x9900, 0x2a1e, 0x2000 }, + { 0x1900, 0x2a1d, 0x0000 }, + { 0x1900, 0x2a1f, 0x0000 }, + { 0x9900, 0x2a60, 0x7000 }, + { 0x9900, 0x2a40, 0x6000 }, + { 0x9900, 0x2a30, 0x5000 }, + { 0x9900, 0x2a28, 0x4000 }, + { 0x9900, 0x2a24, 0x3000 }, + { 0x9900, 0x2a22, 0x2000 }, + { 0x1900, 0x2a21, 0x0000 }, + { 0x1900, 0x2a23, 0x0000 }, + { 0x9900, 0x2a26, 0x2000 }, + { 0x1900, 0x2a25, 0x0000 }, + { 0x1900, 0x2a27, 0x0000 }, + { 0x9900, 0x2a2c, 0x3000 }, + { 0x9900, 0x2a2a, 0x2000 }, + { 0x1900, 0x2a29, 0x0000 }, + { 0x1900, 0x2a2b, 0x0000 }, + { 0x9900, 0x2a2e, 0x2000 }, + { 0x1900, 0x2a2d, 0x0000 }, + { 0x1900, 0x2a2f, 0x0000 }, + { 0x9900, 0x2a38, 0x4000 }, + { 0x9900, 0x2a34, 0x3000 }, + { 0x9900, 0x2a32, 0x2000 }, + { 0x1900, 0x2a31, 0x0000 }, + { 0x1900, 0x2a33, 0x0000 }, + { 0x9900, 0x2a36, 0x2000 }, + { 0x1900, 0x2a35, 0x0000 }, + { 0x1900, 0x2a37, 0x0000 }, + { 0x9900, 0x2a3c, 0x3000 }, + { 0x9900, 0x2a3a, 0x2000 }, + { 0x1900, 0x2a39, 0x0000 }, + { 0x1900, 0x2a3b, 0x0000 }, + { 0x9900, 0x2a3e, 0x2000 }, + { 0x1900, 0x2a3d, 0x0000 }, + { 0x1900, 0x2a3f, 0x0000 }, + { 0x9900, 0x2a50, 0x5000 }, + { 0x9900, 0x2a48, 0x4000 }, + { 0x9900, 0x2a44, 0x3000 }, + { 0x9900, 0x2a42, 0x2000 }, + { 0x1900, 0x2a41, 0x0000 }, + { 0x1900, 0x2a43, 0x0000 }, + { 0x9900, 0x2a46, 0x2000 }, + { 0x1900, 0x2a45, 0x0000 }, + { 0x1900, 0x2a47, 0x0000 }, + { 0x9900, 0x2a4c, 0x3000 }, + { 0x9900, 0x2a4a, 0x2000 }, + { 0x1900, 0x2a49, 0x0000 }, + { 0x1900, 0x2a4b, 0x0000 }, + { 0x9900, 0x2a4e, 0x2000 }, + { 0x1900, 0x2a4d, 0x0000 }, + { 0x1900, 0x2a4f, 0x0000 }, + { 0x9900, 0x2a58, 0x4000 }, + { 0x9900, 0x2a54, 0x3000 }, + { 0x9900, 0x2a52, 0x2000 }, + { 0x1900, 0x2a51, 0x0000 }, + { 0x1900, 0x2a53, 0x0000 }, + { 0x9900, 0x2a56, 0x2000 }, + { 0x1900, 0x2a55, 0x0000 }, + { 0x1900, 0x2a57, 0x0000 }, + { 0x9900, 0x2a5c, 0x3000 }, + { 0x9900, 0x2a5a, 0x2000 }, + { 0x1900, 0x2a59, 0x0000 }, + { 0x1900, 0x2a5b, 0x0000 }, + { 0x9900, 0x2a5e, 0x2000 }, + { 0x1900, 0x2a5d, 0x0000 }, + { 0x1900, 0x2a5f, 0x0000 }, + { 0x9900, 0x2a80, 0x6000 }, + { 0x9900, 0x2a70, 0x5000 }, + { 0x9900, 0x2a68, 0x4000 }, + { 0x9900, 0x2a64, 0x3000 }, + { 0x9900, 0x2a62, 0x2000 }, + { 0x1900, 0x2a61, 0x0000 }, + { 0x1900, 0x2a63, 0x0000 }, + { 0x9900, 0x2a66, 0x2000 }, + { 0x1900, 0x2a65, 0x0000 }, + { 0x1900, 0x2a67, 0x0000 }, + { 0x9900, 0x2a6c, 0x3000 }, + { 0x9900, 0x2a6a, 0x2000 }, + { 0x1900, 0x2a69, 0x0000 }, + { 0x1900, 0x2a6b, 0x0000 }, + { 0x9900, 0x2a6e, 0x2000 }, + { 0x1900, 0x2a6d, 0x0000 }, + { 0x1900, 0x2a6f, 0x0000 }, + { 0x9900, 0x2a78, 0x4000 }, + { 0x9900, 0x2a74, 0x3000 }, + { 0x9900, 0x2a72, 0x2000 }, + { 0x1900, 0x2a71, 0x0000 }, + { 0x1900, 0x2a73, 0x0000 }, + { 0x9900, 0x2a76, 0x2000 }, + { 0x1900, 0x2a75, 0x0000 }, + { 0x1900, 0x2a77, 0x0000 }, + { 0x9900, 0x2a7c, 0x3000 }, + { 0x9900, 0x2a7a, 0x2000 }, + { 0x1900, 0x2a79, 0x0000 }, + { 0x1900, 0x2a7b, 0x0000 }, + { 0x9900, 0x2a7e, 0x2000 }, + { 0x1900, 0x2a7d, 0x0000 }, + { 0x1900, 0x2a7f, 0x0000 }, + { 0x9900, 0x2a90, 0x5000 }, + { 0x9900, 0x2a88, 0x4000 }, + { 0x9900, 0x2a84, 0x3000 }, + { 0x9900, 0x2a82, 0x2000 }, + { 0x1900, 0x2a81, 0x0000 }, + { 0x1900, 0x2a83, 0x0000 }, + { 0x9900, 0x2a86, 0x2000 }, + { 0x1900, 0x2a85, 0x0000 }, + { 0x1900, 0x2a87, 0x0000 }, + { 0x9900, 0x2a8c, 0x3000 }, + { 0x9900, 0x2a8a, 0x2000 }, + { 0x1900, 0x2a89, 0x0000 }, + { 0x1900, 0x2a8b, 0x0000 }, + { 0x9900, 0x2a8e, 0x2000 }, + { 0x1900, 0x2a8d, 0x0000 }, + { 0x1900, 0x2a8f, 0x0000 }, + { 0x9900, 0x2a98, 0x4000 }, + { 0x9900, 0x2a94, 0x3000 }, + { 0x9900, 0x2a92, 0x2000 }, + { 0x1900, 0x2a91, 0x0000 }, + { 0x1900, 0x2a93, 0x0000 }, + { 0x9900, 0x2a96, 0x2000 }, + { 0x1900, 0x2a95, 0x0000 }, + { 0x1900, 0x2a97, 0x0000 }, + { 0x9900, 0x2a9c, 0x3000 }, + { 0x9900, 0x2a9a, 0x2000 }, + { 0x1900, 0x2a99, 0x0000 }, + { 0x1900, 0x2a9b, 0x0000 }, + { 0x9900, 0x2a9e, 0x2000 }, + { 0x1900, 0x2a9d, 0x0000 }, + { 0x1900, 0x2a9f, 0x0000 }, + { 0x9a00, 0x2e92, 0x8000 }, + { 0x9900, 0x2ae0, 0x7000 }, + { 0x9900, 0x2ac0, 0x6000 }, + { 0x9900, 0x2ab0, 0x5000 }, + { 0x9900, 0x2aa8, 0x4000 }, + { 0x9900, 0x2aa4, 0x3000 }, + { 0x9900, 0x2aa2, 0x2000 }, + { 0x1900, 0x2aa1, 0x0000 }, + { 0x1900, 0x2aa3, 0x0000 }, + { 0x9900, 0x2aa6, 0x2000 }, + { 0x1900, 0x2aa5, 0x0000 }, + { 0x1900, 0x2aa7, 0x0000 }, + { 0x9900, 0x2aac, 0x3000 }, + { 0x9900, 0x2aaa, 0x2000 }, + { 0x1900, 0x2aa9, 0x0000 }, + { 0x1900, 0x2aab, 0x0000 }, + { 0x9900, 0x2aae, 0x2000 }, + { 0x1900, 0x2aad, 0x0000 }, + { 0x1900, 0x2aaf, 0x0000 }, + { 0x9900, 0x2ab8, 0x4000 }, + { 0x9900, 0x2ab4, 0x3000 }, + { 0x9900, 0x2ab2, 0x2000 }, + { 0x1900, 0x2ab1, 0x0000 }, + { 0x1900, 0x2ab3, 0x0000 }, + { 0x9900, 0x2ab6, 0x2000 }, + { 0x1900, 0x2ab5, 0x0000 }, + { 0x1900, 0x2ab7, 0x0000 }, + { 0x9900, 0x2abc, 0x3000 }, + { 0x9900, 0x2aba, 0x2000 }, + { 0x1900, 0x2ab9, 0x0000 }, + { 0x1900, 0x2abb, 0x0000 }, + { 0x9900, 0x2abe, 0x2000 }, + { 0x1900, 0x2abd, 0x0000 }, + { 0x1900, 0x2abf, 0x0000 }, + { 0x9900, 0x2ad0, 0x5000 }, + { 0x9900, 0x2ac8, 0x4000 }, + { 0x9900, 0x2ac4, 0x3000 }, + { 0x9900, 0x2ac2, 0x2000 }, + { 0x1900, 0x2ac1, 0x0000 }, + { 0x1900, 0x2ac3, 0x0000 }, + { 0x9900, 0x2ac6, 0x2000 }, + { 0x1900, 0x2ac5, 0x0000 }, + { 0x1900, 0x2ac7, 0x0000 }, + { 0x9900, 0x2acc, 0x3000 }, + { 0x9900, 0x2aca, 0x2000 }, + { 0x1900, 0x2ac9, 0x0000 }, + { 0x1900, 0x2acb, 0x0000 }, + { 0x9900, 0x2ace, 0x2000 }, + { 0x1900, 0x2acd, 0x0000 }, + { 0x1900, 0x2acf, 0x0000 }, + { 0x9900, 0x2ad8, 0x4000 }, + { 0x9900, 0x2ad4, 0x3000 }, + { 0x9900, 0x2ad2, 0x2000 }, + { 0x1900, 0x2ad1, 0x0000 }, + { 0x1900, 0x2ad3, 0x0000 }, + { 0x9900, 0x2ad6, 0x2000 }, + { 0x1900, 0x2ad5, 0x0000 }, + { 0x1900, 0x2ad7, 0x0000 }, + { 0x9900, 0x2adc, 0x3000 }, + { 0x9900, 0x2ada, 0x2000 }, + { 0x1900, 0x2ad9, 0x0000 }, + { 0x1900, 0x2adb, 0x0000 }, + { 0x9900, 0x2ade, 0x2000 }, + { 0x1900, 0x2add, 0x0000 }, + { 0x1900, 0x2adf, 0x0000 }, + { 0x9a00, 0x2b00, 0x6000 }, + { 0x9900, 0x2af0, 0x5000 }, + { 0x9900, 0x2ae8, 0x4000 }, + { 0x9900, 0x2ae4, 0x3000 }, + { 0x9900, 0x2ae2, 0x2000 }, + { 0x1900, 0x2ae1, 0x0000 }, + { 0x1900, 0x2ae3, 0x0000 }, + { 0x9900, 0x2ae6, 0x2000 }, + { 0x1900, 0x2ae5, 0x0000 }, + { 0x1900, 0x2ae7, 0x0000 }, + { 0x9900, 0x2aec, 0x3000 }, + { 0x9900, 0x2aea, 0x2000 }, + { 0x1900, 0x2ae9, 0x0000 }, + { 0x1900, 0x2aeb, 0x0000 }, + { 0x9900, 0x2aee, 0x2000 }, + { 0x1900, 0x2aed, 0x0000 }, + { 0x1900, 0x2aef, 0x0000 }, + { 0x9900, 0x2af8, 0x4000 }, + { 0x9900, 0x2af4, 0x3000 }, + { 0x9900, 0x2af2, 0x2000 }, + { 0x1900, 0x2af1, 0x0000 }, + { 0x1900, 0x2af3, 0x0000 }, + { 0x9900, 0x2af6, 0x2000 }, + { 0x1900, 0x2af5, 0x0000 }, + { 0x1900, 0x2af7, 0x0000 }, + { 0x9900, 0x2afc, 0x3000 }, + { 0x9900, 0x2afa, 0x2000 }, + { 0x1900, 0x2af9, 0x0000 }, + { 0x1900, 0x2afb, 0x0000 }, + { 0x9900, 0x2afe, 0x2000 }, + { 0x1900, 0x2afd, 0x0000 }, + { 0x1900, 0x2aff, 0x0000 }, + { 0x9a00, 0x2e82, 0x5000 }, + { 0x9a00, 0x2b08, 0x4000 }, + { 0x9a00, 0x2b04, 0x3000 }, + { 0x9a00, 0x2b02, 0x2000 }, + { 0x1a00, 0x2b01, 0x0000 }, + { 0x1a00, 0x2b03, 0x0000 }, + { 0x9a00, 0x2b06, 0x2000 }, + { 0x1a00, 0x2b05, 0x0000 }, + { 0x1a00, 0x2b07, 0x0000 }, + { 0x9a00, 0x2b0c, 0x3000 }, + { 0x9a00, 0x2b0a, 0x2000 }, + { 0x1a00, 0x2b09, 0x0000 }, + { 0x1a00, 0x2b0b, 0x0000 }, + { 0x9a00, 0x2e80, 0x2000 }, + { 0x1a00, 0x2b0d, 0x0000 }, + { 0x1a00, 0x2e81, 0x0000 }, + { 0x9a00, 0x2e8a, 0x4000 }, + { 0x9a00, 0x2e86, 0x3000 }, + { 0x9a00, 0x2e84, 0x2000 }, + { 0x1a00, 0x2e83, 0x0000 }, + { 0x1a00, 0x2e85, 0x0000 }, + { 0x9a00, 0x2e88, 0x2000 }, + { 0x1a00, 0x2e87, 0x0000 }, + { 0x1a00, 0x2e89, 0x0000 }, + { 0x9a00, 0x2e8e, 0x3000 }, + { 0x9a00, 0x2e8c, 0x2000 }, + { 0x1a00, 0x2e8b, 0x0000 }, + { 0x1a00, 0x2e8d, 0x0000 }, + { 0x9a00, 0x2e90, 0x2000 }, + { 0x1a00, 0x2e8f, 0x0000 }, + { 0x1a00, 0x2e91, 0x0000 }, + { 0x9a00, 0x2ed3, 0x7000 }, + { 0x9a00, 0x2eb3, 0x6000 }, + { 0x9a00, 0x2ea3, 0x5000 }, + { 0x9a00, 0x2e9b, 0x4000 }, + { 0x9a00, 0x2e96, 0x3000 }, + { 0x9a00, 0x2e94, 0x2000 }, + { 0x1a00, 0x2e93, 0x0000 }, + { 0x1a00, 0x2e95, 0x0000 }, + { 0x9a00, 0x2e98, 0x2000 }, + { 0x1a00, 0x2e97, 0x0000 }, + { 0x1a00, 0x2e99, 0x0000 }, + { 0x9a00, 0x2e9f, 0x3000 }, + { 0x9a00, 0x2e9d, 0x2000 }, + { 0x1a00, 0x2e9c, 0x0000 }, + { 0x1a00, 0x2e9e, 0x0000 }, + { 0x9a00, 0x2ea1, 0x2000 }, + { 0x1a00, 0x2ea0, 0x0000 }, + { 0x1a00, 0x2ea2, 0x0000 }, + { 0x9a00, 0x2eab, 0x4000 }, + { 0x9a00, 0x2ea7, 0x3000 }, + { 0x9a00, 0x2ea5, 0x2000 }, + { 0x1a00, 0x2ea4, 0x0000 }, + { 0x1a00, 0x2ea6, 0x0000 }, + { 0x9a00, 0x2ea9, 0x2000 }, + { 0x1a00, 0x2ea8, 0x0000 }, + { 0x1a00, 0x2eaa, 0x0000 }, + { 0x9a00, 0x2eaf, 0x3000 }, + { 0x9a00, 0x2ead, 0x2000 }, + { 0x1a00, 0x2eac, 0x0000 }, + { 0x1a00, 0x2eae, 0x0000 }, + { 0x9a00, 0x2eb1, 0x2000 }, + { 0x1a00, 0x2eb0, 0x0000 }, + { 0x1a00, 0x2eb2, 0x0000 }, + { 0x9a00, 0x2ec3, 0x5000 }, + { 0x9a00, 0x2ebb, 0x4000 }, + { 0x9a00, 0x2eb7, 0x3000 }, + { 0x9a00, 0x2eb5, 0x2000 }, + { 0x1a00, 0x2eb4, 0x0000 }, + { 0x1a00, 0x2eb6, 0x0000 }, + { 0x9a00, 0x2eb9, 0x2000 }, + { 0x1a00, 0x2eb8, 0x0000 }, + { 0x1a00, 0x2eba, 0x0000 }, + { 0x9a00, 0x2ebf, 0x3000 }, + { 0x9a00, 0x2ebd, 0x2000 }, + { 0x1a00, 0x2ebc, 0x0000 }, + { 0x1a00, 0x2ebe, 0x0000 }, + { 0x9a00, 0x2ec1, 0x2000 }, + { 0x1a00, 0x2ec0, 0x0000 }, + { 0x1a00, 0x2ec2, 0x0000 }, + { 0x9a00, 0x2ecb, 0x4000 }, + { 0x9a00, 0x2ec7, 0x3000 }, + { 0x9a00, 0x2ec5, 0x2000 }, + { 0x1a00, 0x2ec4, 0x0000 }, + { 0x1a00, 0x2ec6, 0x0000 }, + { 0x9a00, 0x2ec9, 0x2000 }, + { 0x1a00, 0x2ec8, 0x0000 }, + { 0x1a00, 0x2eca, 0x0000 }, + { 0x9a00, 0x2ecf, 0x3000 }, + { 0x9a00, 0x2ecd, 0x2000 }, + { 0x1a00, 0x2ecc, 0x0000 }, + { 0x1a00, 0x2ece, 0x0000 }, + { 0x9a00, 0x2ed1, 0x2000 }, + { 0x1a00, 0x2ed0, 0x0000 }, + { 0x1a00, 0x2ed2, 0x0000 }, + { 0x9a00, 0x2ef3, 0x6000 }, + { 0x9a00, 0x2ee3, 0x5000 }, + { 0x9a00, 0x2edb, 0x4000 }, + { 0x9a00, 0x2ed7, 0x3000 }, + { 0x9a00, 0x2ed5, 0x2000 }, + { 0x1a00, 0x2ed4, 0x0000 }, + { 0x1a00, 0x2ed6, 0x0000 }, + { 0x9a00, 0x2ed9, 0x2000 }, + { 0x1a00, 0x2ed8, 0x0000 }, + { 0x1a00, 0x2eda, 0x0000 }, + { 0x9a00, 0x2edf, 0x3000 }, + { 0x9a00, 0x2edd, 0x2000 }, + { 0x1a00, 0x2edc, 0x0000 }, + { 0x1a00, 0x2ede, 0x0000 }, + { 0x9a00, 0x2ee1, 0x2000 }, + { 0x1a00, 0x2ee0, 0x0000 }, + { 0x1a00, 0x2ee2, 0x0000 }, + { 0x9a00, 0x2eeb, 0x4000 }, + { 0x9a00, 0x2ee7, 0x3000 }, + { 0x9a00, 0x2ee5, 0x2000 }, + { 0x1a00, 0x2ee4, 0x0000 }, + { 0x1a00, 0x2ee6, 0x0000 }, + { 0x9a00, 0x2ee9, 0x2000 }, + { 0x1a00, 0x2ee8, 0x0000 }, + { 0x1a00, 0x2eea, 0x0000 }, + { 0x9a00, 0x2eef, 0x3000 }, + { 0x9a00, 0x2eed, 0x2000 }, + { 0x1a00, 0x2eec, 0x0000 }, + { 0x1a00, 0x2eee, 0x0000 }, + { 0x9a00, 0x2ef1, 0x2000 }, + { 0x1a00, 0x2ef0, 0x0000 }, + { 0x1a00, 0x2ef2, 0x0000 }, + { 0x9a00, 0x2f0f, 0x5000 }, + { 0x9a00, 0x2f07, 0x4000 }, + { 0x9a00, 0x2f03, 0x3000 }, + { 0x9a00, 0x2f01, 0x2000 }, + { 0x1a00, 0x2f00, 0x0000 }, + { 0x1a00, 0x2f02, 0x0000 }, + { 0x9a00, 0x2f05, 0x2000 }, + { 0x1a00, 0x2f04, 0x0000 }, + { 0x1a00, 0x2f06, 0x0000 }, + { 0x9a00, 0x2f0b, 0x3000 }, + { 0x9a00, 0x2f09, 0x2000 }, + { 0x1a00, 0x2f08, 0x0000 }, + { 0x1a00, 0x2f0a, 0x0000 }, + { 0x9a00, 0x2f0d, 0x2000 }, + { 0x1a00, 0x2f0c, 0x0000 }, + { 0x1a00, 0x2f0e, 0x0000 }, + { 0x9a00, 0x2f17, 0x4000 }, + { 0x9a00, 0x2f13, 0x3000 }, + { 0x9a00, 0x2f11, 0x2000 }, + { 0x1a00, 0x2f10, 0x0000 }, + { 0x1a00, 0x2f12, 0x0000 }, + { 0x9a00, 0x2f15, 0x2000 }, + { 0x1a00, 0x2f14, 0x0000 }, + { 0x1a00, 0x2f16, 0x0000 }, + { 0x9a00, 0x2f1b, 0x3000 }, + { 0x9a00, 0x2f19, 0x2000 }, + { 0x1a00, 0x2f18, 0x0000 }, + { 0x1a00, 0x2f1a, 0x0000 }, + { 0x9a00, 0x2f1d, 0x2000 }, + { 0x1a00, 0x2f1c, 0x0000 }, + { 0x1a00, 0x2f1e, 0x0000 }, + { 0x8701, 0x00f0, 0xd000 }, + { 0x8700, 0xa34d, 0xc000 }, + { 0x9a00, 0x3391, 0xb000 }, + { 0x8700, 0x3149, 0xa000 }, + { 0x9500, 0x303d, 0x9000 }, + { 0x9a00, 0x2f9f, 0x8000 }, + { 0x9a00, 0x2f5f, 0x7000 }, + { 0x9a00, 0x2f3f, 0x6000 }, + { 0x9a00, 0x2f2f, 0x5000 }, + { 0x9a00, 0x2f27, 0x4000 }, + { 0x9a00, 0x2f23, 0x3000 }, + { 0x9a00, 0x2f21, 0x2000 }, + { 0x1a00, 0x2f20, 0x0000 }, + { 0x1a00, 0x2f22, 0x0000 }, + { 0x9a00, 0x2f25, 0x2000 }, + { 0x1a00, 0x2f24, 0x0000 }, + { 0x1a00, 0x2f26, 0x0000 }, + { 0x9a00, 0x2f2b, 0x3000 }, + { 0x9a00, 0x2f29, 0x2000 }, + { 0x1a00, 0x2f28, 0x0000 }, + { 0x1a00, 0x2f2a, 0x0000 }, + { 0x9a00, 0x2f2d, 0x2000 }, + { 0x1a00, 0x2f2c, 0x0000 }, + { 0x1a00, 0x2f2e, 0x0000 }, + { 0x9a00, 0x2f37, 0x4000 }, + { 0x9a00, 0x2f33, 0x3000 }, + { 0x9a00, 0x2f31, 0x2000 }, + { 0x1a00, 0x2f30, 0x0000 }, + { 0x1a00, 0x2f32, 0x0000 }, + { 0x9a00, 0x2f35, 0x2000 }, + { 0x1a00, 0x2f34, 0x0000 }, + { 0x1a00, 0x2f36, 0x0000 }, + { 0x9a00, 0x2f3b, 0x3000 }, + { 0x9a00, 0x2f39, 0x2000 }, + { 0x1a00, 0x2f38, 0x0000 }, + { 0x1a00, 0x2f3a, 0x0000 }, + { 0x9a00, 0x2f3d, 0x2000 }, + { 0x1a00, 0x2f3c, 0x0000 }, + { 0x1a00, 0x2f3e, 0x0000 }, + { 0x9a00, 0x2f4f, 0x5000 }, + { 0x9a00, 0x2f47, 0x4000 }, + { 0x9a00, 0x2f43, 0x3000 }, + { 0x9a00, 0x2f41, 0x2000 }, + { 0x1a00, 0x2f40, 0x0000 }, + { 0x1a00, 0x2f42, 0x0000 }, + { 0x9a00, 0x2f45, 0x2000 }, + { 0x1a00, 0x2f44, 0x0000 }, + { 0x1a00, 0x2f46, 0x0000 }, + { 0x9a00, 0x2f4b, 0x3000 }, + { 0x9a00, 0x2f49, 0x2000 }, + { 0x1a00, 0x2f48, 0x0000 }, + { 0x1a00, 0x2f4a, 0x0000 }, + { 0x9a00, 0x2f4d, 0x2000 }, + { 0x1a00, 0x2f4c, 0x0000 }, + { 0x1a00, 0x2f4e, 0x0000 }, + { 0x9a00, 0x2f57, 0x4000 }, + { 0x9a00, 0x2f53, 0x3000 }, + { 0x9a00, 0x2f51, 0x2000 }, + { 0x1a00, 0x2f50, 0x0000 }, + { 0x1a00, 0x2f52, 0x0000 }, + { 0x9a00, 0x2f55, 0x2000 }, + { 0x1a00, 0x2f54, 0x0000 }, + { 0x1a00, 0x2f56, 0x0000 }, + { 0x9a00, 0x2f5b, 0x3000 }, + { 0x9a00, 0x2f59, 0x2000 }, + { 0x1a00, 0x2f58, 0x0000 }, + { 0x1a00, 0x2f5a, 0x0000 }, + { 0x9a00, 0x2f5d, 0x2000 }, + { 0x1a00, 0x2f5c, 0x0000 }, + { 0x1a00, 0x2f5e, 0x0000 }, + { 0x9a00, 0x2f7f, 0x6000 }, + { 0x9a00, 0x2f6f, 0x5000 }, + { 0x9a00, 0x2f67, 0x4000 }, + { 0x9a00, 0x2f63, 0x3000 }, + { 0x9a00, 0x2f61, 0x2000 }, + { 0x1a00, 0x2f60, 0x0000 }, + { 0x1a00, 0x2f62, 0x0000 }, + { 0x9a00, 0x2f65, 0x2000 }, + { 0x1a00, 0x2f64, 0x0000 }, + { 0x1a00, 0x2f66, 0x0000 }, + { 0x9a00, 0x2f6b, 0x3000 }, + { 0x9a00, 0x2f69, 0x2000 }, + { 0x1a00, 0x2f68, 0x0000 }, + { 0x1a00, 0x2f6a, 0x0000 }, + { 0x9a00, 0x2f6d, 0x2000 }, + { 0x1a00, 0x2f6c, 0x0000 }, + { 0x1a00, 0x2f6e, 0x0000 }, + { 0x9a00, 0x2f77, 0x4000 }, + { 0x9a00, 0x2f73, 0x3000 }, + { 0x9a00, 0x2f71, 0x2000 }, + { 0x1a00, 0x2f70, 0x0000 }, + { 0x1a00, 0x2f72, 0x0000 }, + { 0x9a00, 0x2f75, 0x2000 }, + { 0x1a00, 0x2f74, 0x0000 }, + { 0x1a00, 0x2f76, 0x0000 }, + { 0x9a00, 0x2f7b, 0x3000 }, + { 0x9a00, 0x2f79, 0x2000 }, + { 0x1a00, 0x2f78, 0x0000 }, + { 0x1a00, 0x2f7a, 0x0000 }, + { 0x9a00, 0x2f7d, 0x2000 }, + { 0x1a00, 0x2f7c, 0x0000 }, + { 0x1a00, 0x2f7e, 0x0000 }, + { 0x9a00, 0x2f8f, 0x5000 }, + { 0x9a00, 0x2f87, 0x4000 }, + { 0x9a00, 0x2f83, 0x3000 }, + { 0x9a00, 0x2f81, 0x2000 }, + { 0x1a00, 0x2f80, 0x0000 }, + { 0x1a00, 0x2f82, 0x0000 }, + { 0x9a00, 0x2f85, 0x2000 }, + { 0x1a00, 0x2f84, 0x0000 }, + { 0x1a00, 0x2f86, 0x0000 }, + { 0x9a00, 0x2f8b, 0x3000 }, + { 0x9a00, 0x2f89, 0x2000 }, + { 0x1a00, 0x2f88, 0x0000 }, + { 0x1a00, 0x2f8a, 0x0000 }, + { 0x9a00, 0x2f8d, 0x2000 }, + { 0x1a00, 0x2f8c, 0x0000 }, + { 0x1a00, 0x2f8e, 0x0000 }, + { 0x9a00, 0x2f97, 0x4000 }, + { 0x9a00, 0x2f93, 0x3000 }, + { 0x9a00, 0x2f91, 0x2000 }, + { 0x1a00, 0x2f90, 0x0000 }, + { 0x1a00, 0x2f92, 0x0000 }, + { 0x9a00, 0x2f95, 0x2000 }, + { 0x1a00, 0x2f94, 0x0000 }, + { 0x1a00, 0x2f96, 0x0000 }, + { 0x9a00, 0x2f9b, 0x3000 }, + { 0x9a00, 0x2f99, 0x2000 }, + { 0x1a00, 0x2f98, 0x0000 }, + { 0x1a00, 0x2f9a, 0x0000 }, + { 0x9a00, 0x2f9d, 0x2000 }, + { 0x1a00, 0x2f9c, 0x0000 }, + { 0x1a00, 0x2f9e, 0x0000 }, + { 0x9a00, 0x2ff9, 0x7000 }, + { 0x9a00, 0x2fbf, 0x6000 }, + { 0x9a00, 0x2faf, 0x5000 }, + { 0x9a00, 0x2fa7, 0x4000 }, + { 0x9a00, 0x2fa3, 0x3000 }, + { 0x9a00, 0x2fa1, 0x2000 }, + { 0x1a00, 0x2fa0, 0x0000 }, + { 0x1a00, 0x2fa2, 0x0000 }, + { 0x9a00, 0x2fa5, 0x2000 }, + { 0x1a00, 0x2fa4, 0x0000 }, + { 0x1a00, 0x2fa6, 0x0000 }, + { 0x9a00, 0x2fab, 0x3000 }, + { 0x9a00, 0x2fa9, 0x2000 }, + { 0x1a00, 0x2fa8, 0x0000 }, + { 0x1a00, 0x2faa, 0x0000 }, + { 0x9a00, 0x2fad, 0x2000 }, + { 0x1a00, 0x2fac, 0x0000 }, + { 0x1a00, 0x2fae, 0x0000 }, + { 0x9a00, 0x2fb7, 0x4000 }, + { 0x9a00, 0x2fb3, 0x3000 }, + { 0x9a00, 0x2fb1, 0x2000 }, + { 0x1a00, 0x2fb0, 0x0000 }, + { 0x1a00, 0x2fb2, 0x0000 }, + { 0x9a00, 0x2fb5, 0x2000 }, + { 0x1a00, 0x2fb4, 0x0000 }, + { 0x1a00, 0x2fb6, 0x0000 }, + { 0x9a00, 0x2fbb, 0x3000 }, + { 0x9a00, 0x2fb9, 0x2000 }, + { 0x1a00, 0x2fb8, 0x0000 }, + { 0x1a00, 0x2fba, 0x0000 }, + { 0x9a00, 0x2fbd, 0x2000 }, + { 0x1a00, 0x2fbc, 0x0000 }, + { 0x1a00, 0x2fbe, 0x0000 }, + { 0x9a00, 0x2fcf, 0x5000 }, + { 0x9a00, 0x2fc7, 0x4000 }, + { 0x9a00, 0x2fc3, 0x3000 }, + { 0x9a00, 0x2fc1, 0x2000 }, + { 0x1a00, 0x2fc0, 0x0000 }, + { 0x1a00, 0x2fc2, 0x0000 }, + { 0x9a00, 0x2fc5, 0x2000 }, + { 0x1a00, 0x2fc4, 0x0000 }, + { 0x1a00, 0x2fc6, 0x0000 }, + { 0x9a00, 0x2fcb, 0x3000 }, + { 0x9a00, 0x2fc9, 0x2000 }, + { 0x1a00, 0x2fc8, 0x0000 }, + { 0x1a00, 0x2fca, 0x0000 }, + { 0x9a00, 0x2fcd, 0x2000 }, + { 0x1a00, 0x2fcc, 0x0000 }, + { 0x1a00, 0x2fce, 0x0000 }, + { 0x9a00, 0x2ff1, 0x4000 }, + { 0x9a00, 0x2fd3, 0x3000 }, + { 0x9a00, 0x2fd1, 0x2000 }, + { 0x1a00, 0x2fd0, 0x0000 }, + { 0x1a00, 0x2fd2, 0x0000 }, + { 0x9a00, 0x2fd5, 0x2000 }, + { 0x1a00, 0x2fd4, 0x0000 }, + { 0x1a00, 0x2ff0, 0x0000 }, + { 0x9a00, 0x2ff5, 0x3000 }, + { 0x9a00, 0x2ff3, 0x2000 }, + { 0x1a00, 0x2ff2, 0x0000 }, + { 0x1a00, 0x2ff4, 0x0000 }, + { 0x9a00, 0x2ff7, 0x2000 }, + { 0x1a00, 0x2ff6, 0x0000 }, + { 0x1a00, 0x2ff8, 0x0000 }, + { 0x9600, 0x301d, 0x6000 }, + { 0x9200, 0x300d, 0x5000 }, + { 0x8600, 0x3005, 0x4000 }, + { 0x9500, 0x3001, 0x3000 }, + { 0x9a00, 0x2ffb, 0x2000 }, + { 0x1a00, 0x2ffa, 0x0000 }, + { 0x1d00, 0x3000, 0x0000 }, + { 0x9500, 0x3003, 0x2000 }, + { 0x1500, 0x3002, 0x0000 }, + { 0x1a00, 0x3004, 0x0000 }, + { 0x9200, 0x3009, 0x3000 }, + { 0x8e00, 0x3007, 0x2000 }, + { 0x0700, 0x3006, 0x0000 }, + { 0x1600, 0x3008, 0x0000 }, + { 0x9200, 0x300b, 0x2000 }, + { 0x1600, 0x300a, 0x0000 }, + { 0x1600, 0x300c, 0x0000 }, + { 0x9200, 0x3015, 0x4000 }, + { 0x9200, 0x3011, 0x3000 }, + { 0x9200, 0x300f, 0x2000 }, + { 0x1600, 0x300e, 0x0000 }, + { 0x1600, 0x3010, 0x0000 }, + { 0x9a00, 0x3013, 0x2000 }, + { 0x1a00, 0x3012, 0x0000 }, + { 0x1600, 0x3014, 0x0000 }, + { 0x9200, 0x3019, 0x3000 }, + { 0x9200, 0x3017, 0x2000 }, + { 0x1600, 0x3016, 0x0000 }, + { 0x1600, 0x3018, 0x0000 }, + { 0x9200, 0x301b, 0x2000 }, + { 0x1600, 0x301a, 0x0000 }, + { 0x1100, 0x301c, 0x0000 }, + { 0x8c00, 0x302d, 0x5000 }, + { 0x8e00, 0x3025, 0x4000 }, + { 0x8e00, 0x3021, 0x3000 }, + { 0x9200, 0x301f, 0x2000 }, + { 0x1200, 0x301e, 0x0000 }, + { 0x1a00, 0x3020, 0x0000 }, + { 0x8e00, 0x3023, 0x2000 }, + { 0x0e00, 0x3022, 0x0000 }, + { 0x0e00, 0x3024, 0x0000 }, + { 0x8e00, 0x3029, 0x3000 }, + { 0x8e00, 0x3027, 0x2000 }, + { 0x0e00, 0x3026, 0x0000 }, + { 0x0e00, 0x3028, 0x0000 }, + { 0x8c00, 0x302b, 0x2000 }, + { 0x0c00, 0x302a, 0x0000 }, + { 0x0c00, 0x302c, 0x0000 }, + { 0x8600, 0x3035, 0x4000 }, + { 0x8600, 0x3031, 0x3000 }, + { 0x8c00, 0x302f, 0x2000 }, + { 0x0c00, 0x302e, 0x0000 }, + { 0x1100, 0x3030, 0x0000 }, + { 0x8600, 0x3033, 0x2000 }, + { 0x0600, 0x3032, 0x0000 }, + { 0x0600, 0x3034, 0x0000 }, + { 0x8e00, 0x3039, 0x3000 }, + { 0x9a00, 0x3037, 0x2000 }, + { 0x1a00, 0x3036, 0x0000 }, + { 0x0e00, 0x3038, 0x0000 }, + { 0x8600, 0x303b, 0x2000 }, + { 0x0e00, 0x303a, 0x0000 }, + { 0x0700, 0x303c, 0x0000 }, + { 0x8700, 0x30c0, 0x8000 }, + { 0x8700, 0x307e, 0x7000 }, + { 0x8700, 0x305e, 0x6000 }, + { 0x8700, 0x304e, 0x5000 }, + { 0x8700, 0x3046, 0x4000 }, + { 0x8700, 0x3042, 0x3000 }, + { 0x9a00, 0x303f, 0x2000 }, + { 0x1a00, 0x303e, 0x0000 }, + { 0x0700, 0x3041, 0x0000 }, + { 0x8700, 0x3044, 0x2000 }, + { 0x0700, 0x3043, 0x0000 }, + { 0x0700, 0x3045, 0x0000 }, + { 0x8700, 0x304a, 0x3000 }, + { 0x8700, 0x3048, 0x2000 }, + { 0x0700, 0x3047, 0x0000 }, + { 0x0700, 0x3049, 0x0000 }, + { 0x8700, 0x304c, 0x2000 }, + { 0x0700, 0x304b, 0x0000 }, + { 0x0700, 0x304d, 0x0000 }, + { 0x8700, 0x3056, 0x4000 }, + { 0x8700, 0x3052, 0x3000 }, + { 0x8700, 0x3050, 0x2000 }, + { 0x0700, 0x304f, 0x0000 }, + { 0x0700, 0x3051, 0x0000 }, + { 0x8700, 0x3054, 0x2000 }, + { 0x0700, 0x3053, 0x0000 }, + { 0x0700, 0x3055, 0x0000 }, + { 0x8700, 0x305a, 0x3000 }, + { 0x8700, 0x3058, 0x2000 }, + { 0x0700, 0x3057, 0x0000 }, + { 0x0700, 0x3059, 0x0000 }, + { 0x8700, 0x305c, 0x2000 }, + { 0x0700, 0x305b, 0x0000 }, + { 0x0700, 0x305d, 0x0000 }, + { 0x8700, 0x306e, 0x5000 }, + { 0x8700, 0x3066, 0x4000 }, + { 0x8700, 0x3062, 0x3000 }, + { 0x8700, 0x3060, 0x2000 }, + { 0x0700, 0x305f, 0x0000 }, + { 0x0700, 0x3061, 0x0000 }, + { 0x8700, 0x3064, 0x2000 }, + { 0x0700, 0x3063, 0x0000 }, + { 0x0700, 0x3065, 0x0000 }, + { 0x8700, 0x306a, 0x3000 }, + { 0x8700, 0x3068, 0x2000 }, + { 0x0700, 0x3067, 0x0000 }, + { 0x0700, 0x3069, 0x0000 }, + { 0x8700, 0x306c, 0x2000 }, + { 0x0700, 0x306b, 0x0000 }, + { 0x0700, 0x306d, 0x0000 }, + { 0x8700, 0x3076, 0x4000 }, + { 0x8700, 0x3072, 0x3000 }, + { 0x8700, 0x3070, 0x2000 }, + { 0x0700, 0x306f, 0x0000 }, + { 0x0700, 0x3071, 0x0000 }, + { 0x8700, 0x3074, 0x2000 }, + { 0x0700, 0x3073, 0x0000 }, + { 0x0700, 0x3075, 0x0000 }, + { 0x8700, 0x307a, 0x3000 }, + { 0x8700, 0x3078, 0x2000 }, + { 0x0700, 0x3077, 0x0000 }, + { 0x0700, 0x3079, 0x0000 }, + { 0x8700, 0x307c, 0x2000 }, + { 0x0700, 0x307b, 0x0000 }, + { 0x0700, 0x307d, 0x0000 }, + { 0x9100, 0x30a0, 0x6000 }, + { 0x8700, 0x308e, 0x5000 }, + { 0x8700, 0x3086, 0x4000 }, + { 0x8700, 0x3082, 0x3000 }, + { 0x8700, 0x3080, 0x2000 }, + { 0x0700, 0x307f, 0x0000 }, + { 0x0700, 0x3081, 0x0000 }, + { 0x8700, 0x3084, 0x2000 }, + { 0x0700, 0x3083, 0x0000 }, + { 0x0700, 0x3085, 0x0000 }, + { 0x8700, 0x308a, 0x3000 }, + { 0x8700, 0x3088, 0x2000 }, + { 0x0700, 0x3087, 0x0000 }, + { 0x0700, 0x3089, 0x0000 }, + { 0x8700, 0x308c, 0x2000 }, + { 0x0700, 0x308b, 0x0000 }, + { 0x0700, 0x308d, 0x0000 }, + { 0x8700, 0x3096, 0x4000 }, + { 0x8700, 0x3092, 0x3000 }, + { 0x8700, 0x3090, 0x2000 }, + { 0x0700, 0x308f, 0x0000 }, + { 0x0700, 0x3091, 0x0000 }, + { 0x8700, 0x3094, 0x2000 }, + { 0x0700, 0x3093, 0x0000 }, + { 0x0700, 0x3095, 0x0000 }, + { 0x9800, 0x309c, 0x3000 }, + { 0x8c00, 0x309a, 0x2000 }, + { 0x0c00, 0x3099, 0x0000 }, + { 0x1800, 0x309b, 0x0000 }, + { 0x8600, 0x309e, 0x2000 }, + { 0x0600, 0x309d, 0x0000 }, + { 0x0700, 0x309f, 0x0000 }, + { 0x8700, 0x30b0, 0x5000 }, + { 0x8700, 0x30a8, 0x4000 }, + { 0x8700, 0x30a4, 0x3000 }, + { 0x8700, 0x30a2, 0x2000 }, + { 0x0700, 0x30a1, 0x0000 }, + { 0x0700, 0x30a3, 0x0000 }, + { 0x8700, 0x30a6, 0x2000 }, + { 0x0700, 0x30a5, 0x0000 }, + { 0x0700, 0x30a7, 0x0000 }, + { 0x8700, 0x30ac, 0x3000 }, + { 0x8700, 0x30aa, 0x2000 }, + { 0x0700, 0x30a9, 0x0000 }, + { 0x0700, 0x30ab, 0x0000 }, + { 0x8700, 0x30ae, 0x2000 }, + { 0x0700, 0x30ad, 0x0000 }, + { 0x0700, 0x30af, 0x0000 }, + { 0x8700, 0x30b8, 0x4000 }, + { 0x8700, 0x30b4, 0x3000 }, + { 0x8700, 0x30b2, 0x2000 }, + { 0x0700, 0x30b1, 0x0000 }, + { 0x0700, 0x30b3, 0x0000 }, + { 0x8700, 0x30b6, 0x2000 }, + { 0x0700, 0x30b5, 0x0000 }, + { 0x0700, 0x30b7, 0x0000 }, + { 0x8700, 0x30bc, 0x3000 }, + { 0x8700, 0x30ba, 0x2000 }, + { 0x0700, 0x30b9, 0x0000 }, + { 0x0700, 0x30bb, 0x0000 }, + { 0x8700, 0x30be, 0x2000 }, + { 0x0700, 0x30bd, 0x0000 }, + { 0x0700, 0x30bf, 0x0000 }, + { 0x8700, 0x3105, 0x7000 }, + { 0x8700, 0x30e0, 0x6000 }, + { 0x8700, 0x30d0, 0x5000 }, + { 0x8700, 0x30c8, 0x4000 }, + { 0x8700, 0x30c4, 0x3000 }, + { 0x8700, 0x30c2, 0x2000 }, + { 0x0700, 0x30c1, 0x0000 }, + { 0x0700, 0x30c3, 0x0000 }, + { 0x8700, 0x30c6, 0x2000 }, + { 0x0700, 0x30c5, 0x0000 }, + { 0x0700, 0x30c7, 0x0000 }, + { 0x8700, 0x30cc, 0x3000 }, + { 0x8700, 0x30ca, 0x2000 }, + { 0x0700, 0x30c9, 0x0000 }, + { 0x0700, 0x30cb, 0x0000 }, + { 0x8700, 0x30ce, 0x2000 }, + { 0x0700, 0x30cd, 0x0000 }, + { 0x0700, 0x30cf, 0x0000 }, + { 0x8700, 0x30d8, 0x4000 }, + { 0x8700, 0x30d4, 0x3000 }, + { 0x8700, 0x30d2, 0x2000 }, + { 0x0700, 0x30d1, 0x0000 }, + { 0x0700, 0x30d3, 0x0000 }, + { 0x8700, 0x30d6, 0x2000 }, + { 0x0700, 0x30d5, 0x0000 }, + { 0x0700, 0x30d7, 0x0000 }, + { 0x8700, 0x30dc, 0x3000 }, + { 0x8700, 0x30da, 0x2000 }, + { 0x0700, 0x30d9, 0x0000 }, + { 0x0700, 0x30db, 0x0000 }, + { 0x8700, 0x30de, 0x2000 }, + { 0x0700, 0x30dd, 0x0000 }, + { 0x0700, 0x30df, 0x0000 }, + { 0x8700, 0x30f0, 0x5000 }, + { 0x8700, 0x30e8, 0x4000 }, + { 0x8700, 0x30e4, 0x3000 }, + { 0x8700, 0x30e2, 0x2000 }, + { 0x0700, 0x30e1, 0x0000 }, + { 0x0700, 0x30e3, 0x0000 }, + { 0x8700, 0x30e6, 0x2000 }, + { 0x0700, 0x30e5, 0x0000 }, + { 0x0700, 0x30e7, 0x0000 }, + { 0x8700, 0x30ec, 0x3000 }, + { 0x8700, 0x30ea, 0x2000 }, + { 0x0700, 0x30e9, 0x0000 }, + { 0x0700, 0x30eb, 0x0000 }, + { 0x8700, 0x30ee, 0x2000 }, + { 0x0700, 0x30ed, 0x0000 }, + { 0x0700, 0x30ef, 0x0000 }, + { 0x8700, 0x30f8, 0x4000 }, + { 0x8700, 0x30f4, 0x3000 }, + { 0x8700, 0x30f2, 0x2000 }, + { 0x0700, 0x30f1, 0x0000 }, + { 0x0700, 0x30f3, 0x0000 }, + { 0x8700, 0x30f6, 0x2000 }, + { 0x0700, 0x30f5, 0x0000 }, + { 0x0700, 0x30f7, 0x0000 }, + { 0x8600, 0x30fc, 0x3000 }, + { 0x8700, 0x30fa, 0x2000 }, + { 0x0700, 0x30f9, 0x0000 }, + { 0x1000, 0x30fb, 0x0000 }, + { 0x8600, 0x30fe, 0x2000 }, + { 0x0600, 0x30fd, 0x0000 }, + { 0x0700, 0x30ff, 0x0000 }, + { 0x8700, 0x3125, 0x6000 }, + { 0x8700, 0x3115, 0x5000 }, + { 0x8700, 0x310d, 0x4000 }, + { 0x8700, 0x3109, 0x3000 }, + { 0x8700, 0x3107, 0x2000 }, + { 0x0700, 0x3106, 0x0000 }, + { 0x0700, 0x3108, 0x0000 }, + { 0x8700, 0x310b, 0x2000 }, + { 0x0700, 0x310a, 0x0000 }, + { 0x0700, 0x310c, 0x0000 }, + { 0x8700, 0x3111, 0x3000 }, + { 0x8700, 0x310f, 0x2000 }, + { 0x0700, 0x310e, 0x0000 }, + { 0x0700, 0x3110, 0x0000 }, + { 0x8700, 0x3113, 0x2000 }, + { 0x0700, 0x3112, 0x0000 }, + { 0x0700, 0x3114, 0x0000 }, + { 0x8700, 0x311d, 0x4000 }, + { 0x8700, 0x3119, 0x3000 }, + { 0x8700, 0x3117, 0x2000 }, + { 0x0700, 0x3116, 0x0000 }, + { 0x0700, 0x3118, 0x0000 }, + { 0x8700, 0x311b, 0x2000 }, + { 0x0700, 0x311a, 0x0000 }, + { 0x0700, 0x311c, 0x0000 }, + { 0x8700, 0x3121, 0x3000 }, + { 0x8700, 0x311f, 0x2000 }, + { 0x0700, 0x311e, 0x0000 }, + { 0x0700, 0x3120, 0x0000 }, + { 0x8700, 0x3123, 0x2000 }, + { 0x0700, 0x3122, 0x0000 }, + { 0x0700, 0x3124, 0x0000 }, + { 0x8700, 0x3139, 0x5000 }, + { 0x8700, 0x3131, 0x4000 }, + { 0x8700, 0x3129, 0x3000 }, + { 0x8700, 0x3127, 0x2000 }, + { 0x0700, 0x3126, 0x0000 }, + { 0x0700, 0x3128, 0x0000 }, + { 0x8700, 0x312b, 0x2000 }, + { 0x0700, 0x312a, 0x0000 }, + { 0x0700, 0x312c, 0x0000 }, + { 0x8700, 0x3135, 0x3000 }, + { 0x8700, 0x3133, 0x2000 }, + { 0x0700, 0x3132, 0x0000 }, + { 0x0700, 0x3134, 0x0000 }, + { 0x8700, 0x3137, 0x2000 }, + { 0x0700, 0x3136, 0x0000 }, + { 0x0700, 0x3138, 0x0000 }, + { 0x8700, 0x3141, 0x4000 }, + { 0x8700, 0x313d, 0x3000 }, + { 0x8700, 0x313b, 0x2000 }, + { 0x0700, 0x313a, 0x0000 }, + { 0x0700, 0x313c, 0x0000 }, + { 0x8700, 0x313f, 0x2000 }, + { 0x0700, 0x313e, 0x0000 }, + { 0x0700, 0x3140, 0x0000 }, + { 0x8700, 0x3145, 0x3000 }, + { 0x8700, 0x3143, 0x2000 }, + { 0x0700, 0x3142, 0x0000 }, + { 0x0700, 0x3144, 0x0000 }, + { 0x8700, 0x3147, 0x2000 }, + { 0x0700, 0x3146, 0x0000 }, + { 0x0700, 0x3148, 0x0000 }, + { 0x9a00, 0x3290, 0x9000 }, + { 0x9a00, 0x3202, 0x8000 }, + { 0x8700, 0x3189, 0x7000 }, + { 0x8700, 0x3169, 0x6000 }, + { 0x8700, 0x3159, 0x5000 }, + { 0x8700, 0x3151, 0x4000 }, + { 0x8700, 0x314d, 0x3000 }, + { 0x8700, 0x314b, 0x2000 }, + { 0x0700, 0x314a, 0x0000 }, + { 0x0700, 0x314c, 0x0000 }, + { 0x8700, 0x314f, 0x2000 }, + { 0x0700, 0x314e, 0x0000 }, + { 0x0700, 0x3150, 0x0000 }, + { 0x8700, 0x3155, 0x3000 }, + { 0x8700, 0x3153, 0x2000 }, + { 0x0700, 0x3152, 0x0000 }, + { 0x0700, 0x3154, 0x0000 }, + { 0x8700, 0x3157, 0x2000 }, + { 0x0700, 0x3156, 0x0000 }, + { 0x0700, 0x3158, 0x0000 }, + { 0x8700, 0x3161, 0x4000 }, + { 0x8700, 0x315d, 0x3000 }, + { 0x8700, 0x315b, 0x2000 }, + { 0x0700, 0x315a, 0x0000 }, + { 0x0700, 0x315c, 0x0000 }, + { 0x8700, 0x315f, 0x2000 }, + { 0x0700, 0x315e, 0x0000 }, + { 0x0700, 0x3160, 0x0000 }, + { 0x8700, 0x3165, 0x3000 }, + { 0x8700, 0x3163, 0x2000 }, + { 0x0700, 0x3162, 0x0000 }, + { 0x0700, 0x3164, 0x0000 }, + { 0x8700, 0x3167, 0x2000 }, + { 0x0700, 0x3166, 0x0000 }, + { 0x0700, 0x3168, 0x0000 }, + { 0x8700, 0x3179, 0x5000 }, + { 0x8700, 0x3171, 0x4000 }, + { 0x8700, 0x316d, 0x3000 }, + { 0x8700, 0x316b, 0x2000 }, + { 0x0700, 0x316a, 0x0000 }, + { 0x0700, 0x316c, 0x0000 }, + { 0x8700, 0x316f, 0x2000 }, + { 0x0700, 0x316e, 0x0000 }, + { 0x0700, 0x3170, 0x0000 }, + { 0x8700, 0x3175, 0x3000 }, + { 0x8700, 0x3173, 0x2000 }, + { 0x0700, 0x3172, 0x0000 }, + { 0x0700, 0x3174, 0x0000 }, + { 0x8700, 0x3177, 0x2000 }, + { 0x0700, 0x3176, 0x0000 }, + { 0x0700, 0x3178, 0x0000 }, + { 0x8700, 0x3181, 0x4000 }, + { 0x8700, 0x317d, 0x3000 }, + { 0x8700, 0x317b, 0x2000 }, + { 0x0700, 0x317a, 0x0000 }, + { 0x0700, 0x317c, 0x0000 }, + { 0x8700, 0x317f, 0x2000 }, + { 0x0700, 0x317e, 0x0000 }, + { 0x0700, 0x3180, 0x0000 }, + { 0x8700, 0x3185, 0x3000 }, + { 0x8700, 0x3183, 0x2000 }, + { 0x0700, 0x3182, 0x0000 }, + { 0x0700, 0x3184, 0x0000 }, + { 0x8700, 0x3187, 0x2000 }, + { 0x0700, 0x3186, 0x0000 }, + { 0x0700, 0x3188, 0x0000 }, + { 0x8700, 0x31aa, 0x6000 }, + { 0x9a00, 0x319a, 0x5000 }, + { 0x8f00, 0x3192, 0x4000 }, + { 0x8700, 0x318d, 0x3000 }, + { 0x8700, 0x318b, 0x2000 }, + { 0x0700, 0x318a, 0x0000 }, + { 0x0700, 0x318c, 0x0000 }, + { 0x9a00, 0x3190, 0x2000 }, + { 0x0700, 0x318e, 0x0000 }, + { 0x1a00, 0x3191, 0x0000 }, + { 0x9a00, 0x3196, 0x3000 }, + { 0x8f00, 0x3194, 0x2000 }, + { 0x0f00, 0x3193, 0x0000 }, + { 0x0f00, 0x3195, 0x0000 }, + { 0x9a00, 0x3198, 0x2000 }, + { 0x1a00, 0x3197, 0x0000 }, + { 0x1a00, 0x3199, 0x0000 }, + { 0x8700, 0x31a2, 0x4000 }, + { 0x9a00, 0x319e, 0x3000 }, + { 0x9a00, 0x319c, 0x2000 }, + { 0x1a00, 0x319b, 0x0000 }, + { 0x1a00, 0x319d, 0x0000 }, + { 0x8700, 0x31a0, 0x2000 }, + { 0x1a00, 0x319f, 0x0000 }, + { 0x0700, 0x31a1, 0x0000 }, + { 0x8700, 0x31a6, 0x3000 }, + { 0x8700, 0x31a4, 0x2000 }, + { 0x0700, 0x31a3, 0x0000 }, + { 0x0700, 0x31a5, 0x0000 }, + { 0x8700, 0x31a8, 0x2000 }, + { 0x0700, 0x31a7, 0x0000 }, + { 0x0700, 0x31a9, 0x0000 }, + { 0x8700, 0x31f2, 0x5000 }, + { 0x8700, 0x31b2, 0x4000 }, + { 0x8700, 0x31ae, 0x3000 }, + { 0x8700, 0x31ac, 0x2000 }, + { 0x0700, 0x31ab, 0x0000 }, + { 0x0700, 0x31ad, 0x0000 }, + { 0x8700, 0x31b0, 0x2000 }, + { 0x0700, 0x31af, 0x0000 }, + { 0x0700, 0x31b1, 0x0000 }, + { 0x8700, 0x31b6, 0x3000 }, + { 0x8700, 0x31b4, 0x2000 }, + { 0x0700, 0x31b3, 0x0000 }, + { 0x0700, 0x31b5, 0x0000 }, + { 0x8700, 0x31f0, 0x2000 }, + { 0x0700, 0x31b7, 0x0000 }, + { 0x0700, 0x31f1, 0x0000 }, + { 0x8700, 0x31fa, 0x4000 }, + { 0x8700, 0x31f6, 0x3000 }, + { 0x8700, 0x31f4, 0x2000 }, + { 0x0700, 0x31f3, 0x0000 }, + { 0x0700, 0x31f5, 0x0000 }, + { 0x8700, 0x31f8, 0x2000 }, + { 0x0700, 0x31f7, 0x0000 }, + { 0x0700, 0x31f9, 0x0000 }, + { 0x8700, 0x31fe, 0x3000 }, + { 0x8700, 0x31fc, 0x2000 }, + { 0x0700, 0x31fb, 0x0000 }, + { 0x0700, 0x31fd, 0x0000 }, + { 0x9a00, 0x3200, 0x2000 }, + { 0x0700, 0x31ff, 0x0000 }, + { 0x1a00, 0x3201, 0x0000 }, + { 0x9a00, 0x3243, 0x7000 }, + { 0x8f00, 0x3223, 0x6000 }, + { 0x9a00, 0x3212, 0x5000 }, + { 0x9a00, 0x320a, 0x4000 }, + { 0x9a00, 0x3206, 0x3000 }, + { 0x9a00, 0x3204, 0x2000 }, + { 0x1a00, 0x3203, 0x0000 }, + { 0x1a00, 0x3205, 0x0000 }, + { 0x9a00, 0x3208, 0x2000 }, + { 0x1a00, 0x3207, 0x0000 }, + { 0x1a00, 0x3209, 0x0000 }, + { 0x9a00, 0x320e, 0x3000 }, + { 0x9a00, 0x320c, 0x2000 }, + { 0x1a00, 0x320b, 0x0000 }, + { 0x1a00, 0x320d, 0x0000 }, + { 0x9a00, 0x3210, 0x2000 }, + { 0x1a00, 0x320f, 0x0000 }, + { 0x1a00, 0x3211, 0x0000 }, + { 0x9a00, 0x321a, 0x4000 }, + { 0x9a00, 0x3216, 0x3000 }, + { 0x9a00, 0x3214, 0x2000 }, + { 0x1a00, 0x3213, 0x0000 }, + { 0x1a00, 0x3215, 0x0000 }, + { 0x9a00, 0x3218, 0x2000 }, + { 0x1a00, 0x3217, 0x0000 }, + { 0x1a00, 0x3219, 0x0000 }, + { 0x9a00, 0x321e, 0x3000 }, + { 0x9a00, 0x321c, 0x2000 }, + { 0x1a00, 0x321b, 0x0000 }, + { 0x1a00, 0x321d, 0x0000 }, + { 0x8f00, 0x3221, 0x2000 }, + { 0x0f00, 0x3220, 0x0000 }, + { 0x0f00, 0x3222, 0x0000 }, + { 0x9a00, 0x3233, 0x5000 }, + { 0x9a00, 0x322b, 0x4000 }, + { 0x8f00, 0x3227, 0x3000 }, + { 0x8f00, 0x3225, 0x2000 }, + { 0x0f00, 0x3224, 0x0000 }, + { 0x0f00, 0x3226, 0x0000 }, + { 0x8f00, 0x3229, 0x2000 }, + { 0x0f00, 0x3228, 0x0000 }, + { 0x1a00, 0x322a, 0x0000 }, + { 0x9a00, 0x322f, 0x3000 }, + { 0x9a00, 0x322d, 0x2000 }, + { 0x1a00, 0x322c, 0x0000 }, + { 0x1a00, 0x322e, 0x0000 }, + { 0x9a00, 0x3231, 0x2000 }, + { 0x1a00, 0x3230, 0x0000 }, + { 0x1a00, 0x3232, 0x0000 }, + { 0x9a00, 0x323b, 0x4000 }, + { 0x9a00, 0x3237, 0x3000 }, + { 0x9a00, 0x3235, 0x2000 }, + { 0x1a00, 0x3234, 0x0000 }, + { 0x1a00, 0x3236, 0x0000 }, + { 0x9a00, 0x3239, 0x2000 }, + { 0x1a00, 0x3238, 0x0000 }, + { 0x1a00, 0x323a, 0x0000 }, + { 0x9a00, 0x323f, 0x3000 }, + { 0x9a00, 0x323d, 0x2000 }, + { 0x1a00, 0x323c, 0x0000 }, + { 0x1a00, 0x323e, 0x0000 }, + { 0x9a00, 0x3241, 0x2000 }, + { 0x1a00, 0x3240, 0x0000 }, + { 0x1a00, 0x3242, 0x0000 }, + { 0x9a00, 0x326f, 0x6000 }, + { 0x8f00, 0x325f, 0x5000 }, + { 0x8f00, 0x3257, 0x4000 }, + { 0x8f00, 0x3253, 0x3000 }, + { 0x8f00, 0x3251, 0x2000 }, + { 0x1a00, 0x3250, 0x0000 }, + { 0x0f00, 0x3252, 0x0000 }, + { 0x8f00, 0x3255, 0x2000 }, + { 0x0f00, 0x3254, 0x0000 }, + { 0x0f00, 0x3256, 0x0000 }, + { 0x8f00, 0x325b, 0x3000 }, + { 0x8f00, 0x3259, 0x2000 }, + { 0x0f00, 0x3258, 0x0000 }, + { 0x0f00, 0x325a, 0x0000 }, + { 0x8f00, 0x325d, 0x2000 }, + { 0x0f00, 0x325c, 0x0000 }, + { 0x0f00, 0x325e, 0x0000 }, + { 0x9a00, 0x3267, 0x4000 }, + { 0x9a00, 0x3263, 0x3000 }, + { 0x9a00, 0x3261, 0x2000 }, + { 0x1a00, 0x3260, 0x0000 }, + { 0x1a00, 0x3262, 0x0000 }, + { 0x9a00, 0x3265, 0x2000 }, + { 0x1a00, 0x3264, 0x0000 }, + { 0x1a00, 0x3266, 0x0000 }, + { 0x9a00, 0x326b, 0x3000 }, + { 0x9a00, 0x3269, 0x2000 }, + { 0x1a00, 0x3268, 0x0000 }, + { 0x1a00, 0x326a, 0x0000 }, + { 0x9a00, 0x326d, 0x2000 }, + { 0x1a00, 0x326c, 0x0000 }, + { 0x1a00, 0x326e, 0x0000 }, + { 0x8f00, 0x3280, 0x5000 }, + { 0x9a00, 0x3277, 0x4000 }, + { 0x9a00, 0x3273, 0x3000 }, + { 0x9a00, 0x3271, 0x2000 }, + { 0x1a00, 0x3270, 0x0000 }, + { 0x1a00, 0x3272, 0x0000 }, + { 0x9a00, 0x3275, 0x2000 }, + { 0x1a00, 0x3274, 0x0000 }, + { 0x1a00, 0x3276, 0x0000 }, + { 0x9a00, 0x327b, 0x3000 }, + { 0x9a00, 0x3279, 0x2000 }, + { 0x1a00, 0x3278, 0x0000 }, + { 0x1a00, 0x327a, 0x0000 }, + { 0x9a00, 0x327d, 0x2000 }, + { 0x1a00, 0x327c, 0x0000 }, + { 0x1a00, 0x327f, 0x0000 }, + { 0x8f00, 0x3288, 0x4000 }, + { 0x8f00, 0x3284, 0x3000 }, + { 0x8f00, 0x3282, 0x2000 }, + { 0x0f00, 0x3281, 0x0000 }, + { 0x0f00, 0x3283, 0x0000 }, + { 0x8f00, 0x3286, 0x2000 }, + { 0x0f00, 0x3285, 0x0000 }, + { 0x0f00, 0x3287, 0x0000 }, + { 0x9a00, 0x328c, 0x3000 }, + { 0x9a00, 0x328a, 0x2000 }, + { 0x0f00, 0x3289, 0x0000 }, + { 0x1a00, 0x328b, 0x0000 }, + { 0x9a00, 0x328e, 0x2000 }, + { 0x1a00, 0x328d, 0x0000 }, + { 0x1a00, 0x328f, 0x0000 }, + { 0x9a00, 0x3311, 0x8000 }, + { 0x9a00, 0x32d0, 0x7000 }, + { 0x9a00, 0x32b0, 0x6000 }, + { 0x9a00, 0x32a0, 0x5000 }, + { 0x9a00, 0x3298, 0x4000 }, + { 0x9a00, 0x3294, 0x3000 }, + { 0x9a00, 0x3292, 0x2000 }, + { 0x1a00, 0x3291, 0x0000 }, + { 0x1a00, 0x3293, 0x0000 }, + { 0x9a00, 0x3296, 0x2000 }, + { 0x1a00, 0x3295, 0x0000 }, + { 0x1a00, 0x3297, 0x0000 }, + { 0x9a00, 0x329c, 0x3000 }, + { 0x9a00, 0x329a, 0x2000 }, + { 0x1a00, 0x3299, 0x0000 }, + { 0x1a00, 0x329b, 0x0000 }, + { 0x9a00, 0x329e, 0x2000 }, + { 0x1a00, 0x329d, 0x0000 }, + { 0x1a00, 0x329f, 0x0000 }, + { 0x9a00, 0x32a8, 0x4000 }, + { 0x9a00, 0x32a4, 0x3000 }, + { 0x9a00, 0x32a2, 0x2000 }, + { 0x1a00, 0x32a1, 0x0000 }, + { 0x1a00, 0x32a3, 0x0000 }, + { 0x9a00, 0x32a6, 0x2000 }, + { 0x1a00, 0x32a5, 0x0000 }, + { 0x1a00, 0x32a7, 0x0000 }, + { 0x9a00, 0x32ac, 0x3000 }, + { 0x9a00, 0x32aa, 0x2000 }, + { 0x1a00, 0x32a9, 0x0000 }, + { 0x1a00, 0x32ab, 0x0000 }, + { 0x9a00, 0x32ae, 0x2000 }, + { 0x1a00, 0x32ad, 0x0000 }, + { 0x1a00, 0x32af, 0x0000 }, + { 0x9a00, 0x32c0, 0x5000 }, + { 0x8f00, 0x32b8, 0x4000 }, + { 0x8f00, 0x32b4, 0x3000 }, + { 0x8f00, 0x32b2, 0x2000 }, + { 0x0f00, 0x32b1, 0x0000 }, + { 0x0f00, 0x32b3, 0x0000 }, + { 0x8f00, 0x32b6, 0x2000 }, + { 0x0f00, 0x32b5, 0x0000 }, + { 0x0f00, 0x32b7, 0x0000 }, + { 0x8f00, 0x32bc, 0x3000 }, + { 0x8f00, 0x32ba, 0x2000 }, + { 0x0f00, 0x32b9, 0x0000 }, + { 0x0f00, 0x32bb, 0x0000 }, + { 0x8f00, 0x32be, 0x2000 }, + { 0x0f00, 0x32bd, 0x0000 }, + { 0x0f00, 0x32bf, 0x0000 }, + { 0x9a00, 0x32c8, 0x4000 }, + { 0x9a00, 0x32c4, 0x3000 }, + { 0x9a00, 0x32c2, 0x2000 }, + { 0x1a00, 0x32c1, 0x0000 }, + { 0x1a00, 0x32c3, 0x0000 }, + { 0x9a00, 0x32c6, 0x2000 }, + { 0x1a00, 0x32c5, 0x0000 }, + { 0x1a00, 0x32c7, 0x0000 }, + { 0x9a00, 0x32cc, 0x3000 }, + { 0x9a00, 0x32ca, 0x2000 }, + { 0x1a00, 0x32c9, 0x0000 }, + { 0x1a00, 0x32cb, 0x0000 }, + { 0x9a00, 0x32ce, 0x2000 }, + { 0x1a00, 0x32cd, 0x0000 }, + { 0x1a00, 0x32cf, 0x0000 }, + { 0x9a00, 0x32f0, 0x6000 }, + { 0x9a00, 0x32e0, 0x5000 }, + { 0x9a00, 0x32d8, 0x4000 }, + { 0x9a00, 0x32d4, 0x3000 }, + { 0x9a00, 0x32d2, 0x2000 }, + { 0x1a00, 0x32d1, 0x0000 }, + { 0x1a00, 0x32d3, 0x0000 }, + { 0x9a00, 0x32d6, 0x2000 }, + { 0x1a00, 0x32d5, 0x0000 }, + { 0x1a00, 0x32d7, 0x0000 }, + { 0x9a00, 0x32dc, 0x3000 }, + { 0x9a00, 0x32da, 0x2000 }, + { 0x1a00, 0x32d9, 0x0000 }, + { 0x1a00, 0x32db, 0x0000 }, + { 0x9a00, 0x32de, 0x2000 }, + { 0x1a00, 0x32dd, 0x0000 }, + { 0x1a00, 0x32df, 0x0000 }, + { 0x9a00, 0x32e8, 0x4000 }, + { 0x9a00, 0x32e4, 0x3000 }, + { 0x9a00, 0x32e2, 0x2000 }, + { 0x1a00, 0x32e1, 0x0000 }, + { 0x1a00, 0x32e3, 0x0000 }, + { 0x9a00, 0x32e6, 0x2000 }, + { 0x1a00, 0x32e5, 0x0000 }, + { 0x1a00, 0x32e7, 0x0000 }, + { 0x9a00, 0x32ec, 0x3000 }, + { 0x9a00, 0x32ea, 0x2000 }, + { 0x1a00, 0x32e9, 0x0000 }, + { 0x1a00, 0x32eb, 0x0000 }, + { 0x9a00, 0x32ee, 0x2000 }, + { 0x1a00, 0x32ed, 0x0000 }, + { 0x1a00, 0x32ef, 0x0000 }, + { 0x9a00, 0x3301, 0x5000 }, + { 0x9a00, 0x32f8, 0x4000 }, + { 0x9a00, 0x32f4, 0x3000 }, + { 0x9a00, 0x32f2, 0x2000 }, + { 0x1a00, 0x32f1, 0x0000 }, + { 0x1a00, 0x32f3, 0x0000 }, + { 0x9a00, 0x32f6, 0x2000 }, + { 0x1a00, 0x32f5, 0x0000 }, + { 0x1a00, 0x32f7, 0x0000 }, + { 0x9a00, 0x32fc, 0x3000 }, + { 0x9a00, 0x32fa, 0x2000 }, + { 0x1a00, 0x32f9, 0x0000 }, + { 0x1a00, 0x32fb, 0x0000 }, + { 0x9a00, 0x32fe, 0x2000 }, + { 0x1a00, 0x32fd, 0x0000 }, + { 0x1a00, 0x3300, 0x0000 }, + { 0x9a00, 0x3309, 0x4000 }, + { 0x9a00, 0x3305, 0x3000 }, + { 0x9a00, 0x3303, 0x2000 }, + { 0x1a00, 0x3302, 0x0000 }, + { 0x1a00, 0x3304, 0x0000 }, + { 0x9a00, 0x3307, 0x2000 }, + { 0x1a00, 0x3306, 0x0000 }, + { 0x1a00, 0x3308, 0x0000 }, + { 0x9a00, 0x330d, 0x3000 }, + { 0x9a00, 0x330b, 0x2000 }, + { 0x1a00, 0x330a, 0x0000 }, + { 0x1a00, 0x330c, 0x0000 }, + { 0x9a00, 0x330f, 0x2000 }, + { 0x1a00, 0x330e, 0x0000 }, + { 0x1a00, 0x3310, 0x0000 }, + { 0x9a00, 0x3351, 0x7000 }, + { 0x9a00, 0x3331, 0x6000 }, + { 0x9a00, 0x3321, 0x5000 }, + { 0x9a00, 0x3319, 0x4000 }, + { 0x9a00, 0x3315, 0x3000 }, + { 0x9a00, 0x3313, 0x2000 }, + { 0x1a00, 0x3312, 0x0000 }, + { 0x1a00, 0x3314, 0x0000 }, + { 0x9a00, 0x3317, 0x2000 }, + { 0x1a00, 0x3316, 0x0000 }, + { 0x1a00, 0x3318, 0x0000 }, + { 0x9a00, 0x331d, 0x3000 }, + { 0x9a00, 0x331b, 0x2000 }, + { 0x1a00, 0x331a, 0x0000 }, + { 0x1a00, 0x331c, 0x0000 }, + { 0x9a00, 0x331f, 0x2000 }, + { 0x1a00, 0x331e, 0x0000 }, + { 0x1a00, 0x3320, 0x0000 }, + { 0x9a00, 0x3329, 0x4000 }, + { 0x9a00, 0x3325, 0x3000 }, + { 0x9a00, 0x3323, 0x2000 }, + { 0x1a00, 0x3322, 0x0000 }, + { 0x1a00, 0x3324, 0x0000 }, + { 0x9a00, 0x3327, 0x2000 }, + { 0x1a00, 0x3326, 0x0000 }, + { 0x1a00, 0x3328, 0x0000 }, + { 0x9a00, 0x332d, 0x3000 }, + { 0x9a00, 0x332b, 0x2000 }, + { 0x1a00, 0x332a, 0x0000 }, + { 0x1a00, 0x332c, 0x0000 }, + { 0x9a00, 0x332f, 0x2000 }, + { 0x1a00, 0x332e, 0x0000 }, + { 0x1a00, 0x3330, 0x0000 }, + { 0x9a00, 0x3341, 0x5000 }, + { 0x9a00, 0x3339, 0x4000 }, + { 0x9a00, 0x3335, 0x3000 }, + { 0x9a00, 0x3333, 0x2000 }, + { 0x1a00, 0x3332, 0x0000 }, + { 0x1a00, 0x3334, 0x0000 }, + { 0x9a00, 0x3337, 0x2000 }, + { 0x1a00, 0x3336, 0x0000 }, + { 0x1a00, 0x3338, 0x0000 }, + { 0x9a00, 0x333d, 0x3000 }, + { 0x9a00, 0x333b, 0x2000 }, + { 0x1a00, 0x333a, 0x0000 }, + { 0x1a00, 0x333c, 0x0000 }, + { 0x9a00, 0x333f, 0x2000 }, + { 0x1a00, 0x333e, 0x0000 }, + { 0x1a00, 0x3340, 0x0000 }, + { 0x9a00, 0x3349, 0x4000 }, + { 0x9a00, 0x3345, 0x3000 }, + { 0x9a00, 0x3343, 0x2000 }, + { 0x1a00, 0x3342, 0x0000 }, + { 0x1a00, 0x3344, 0x0000 }, + { 0x9a00, 0x3347, 0x2000 }, + { 0x1a00, 0x3346, 0x0000 }, + { 0x1a00, 0x3348, 0x0000 }, + { 0x9a00, 0x334d, 0x3000 }, + { 0x9a00, 0x334b, 0x2000 }, + { 0x1a00, 0x334a, 0x0000 }, + { 0x1a00, 0x334c, 0x0000 }, + { 0x9a00, 0x334f, 0x2000 }, + { 0x1a00, 0x334e, 0x0000 }, + { 0x1a00, 0x3350, 0x0000 }, + { 0x9a00, 0x3371, 0x6000 }, + { 0x9a00, 0x3361, 0x5000 }, + { 0x9a00, 0x3359, 0x4000 }, + { 0x9a00, 0x3355, 0x3000 }, + { 0x9a00, 0x3353, 0x2000 }, + { 0x1a00, 0x3352, 0x0000 }, + { 0x1a00, 0x3354, 0x0000 }, + { 0x9a00, 0x3357, 0x2000 }, + { 0x1a00, 0x3356, 0x0000 }, + { 0x1a00, 0x3358, 0x0000 }, + { 0x9a00, 0x335d, 0x3000 }, + { 0x9a00, 0x335b, 0x2000 }, + { 0x1a00, 0x335a, 0x0000 }, + { 0x1a00, 0x335c, 0x0000 }, + { 0x9a00, 0x335f, 0x2000 }, + { 0x1a00, 0x335e, 0x0000 }, + { 0x1a00, 0x3360, 0x0000 }, + { 0x9a00, 0x3369, 0x4000 }, + { 0x9a00, 0x3365, 0x3000 }, + { 0x9a00, 0x3363, 0x2000 }, + { 0x1a00, 0x3362, 0x0000 }, + { 0x1a00, 0x3364, 0x0000 }, + { 0x9a00, 0x3367, 0x2000 }, + { 0x1a00, 0x3366, 0x0000 }, + { 0x1a00, 0x3368, 0x0000 }, + { 0x9a00, 0x336d, 0x3000 }, + { 0x9a00, 0x336b, 0x2000 }, + { 0x1a00, 0x336a, 0x0000 }, + { 0x1a00, 0x336c, 0x0000 }, + { 0x9a00, 0x336f, 0x2000 }, + { 0x1a00, 0x336e, 0x0000 }, + { 0x1a00, 0x3370, 0x0000 }, + { 0x9a00, 0x3381, 0x5000 }, + { 0x9a00, 0x3379, 0x4000 }, + { 0x9a00, 0x3375, 0x3000 }, + { 0x9a00, 0x3373, 0x2000 }, + { 0x1a00, 0x3372, 0x0000 }, + { 0x1a00, 0x3374, 0x0000 }, + { 0x9a00, 0x3377, 0x2000 }, + { 0x1a00, 0x3376, 0x0000 }, + { 0x1a00, 0x3378, 0x0000 }, + { 0x9a00, 0x337d, 0x3000 }, + { 0x9a00, 0x337b, 0x2000 }, + { 0x1a00, 0x337a, 0x0000 }, + { 0x1a00, 0x337c, 0x0000 }, + { 0x9a00, 0x337f, 0x2000 }, + { 0x1a00, 0x337e, 0x0000 }, + { 0x1a00, 0x3380, 0x0000 }, + { 0x9a00, 0x3389, 0x4000 }, + { 0x9a00, 0x3385, 0x3000 }, + { 0x9a00, 0x3383, 0x2000 }, + { 0x1a00, 0x3382, 0x0000 }, + { 0x1a00, 0x3384, 0x0000 }, + { 0x9a00, 0x3387, 0x2000 }, + { 0x1a00, 0x3386, 0x0000 }, + { 0x1a00, 0x3388, 0x0000 }, + { 0x9a00, 0x338d, 0x3000 }, + { 0x9a00, 0x338b, 0x2000 }, + { 0x1a00, 0x338a, 0x0000 }, + { 0x1a00, 0x338c, 0x0000 }, + { 0x9a00, 0x338f, 0x2000 }, + { 0x1a00, 0x338e, 0x0000 }, + { 0x1a00, 0x3390, 0x0000 }, + { 0x8700, 0xa14d, 0xa000 }, + { 0x8700, 0xa04d, 0x9000 }, + { 0x9a00, 0x4dcf, 0x8000 }, + { 0x9a00, 0x33d1, 0x7000 }, + { 0x9a00, 0x33b1, 0x6000 }, + { 0x9a00, 0x33a1, 0x5000 }, + { 0x9a00, 0x3399, 0x4000 }, + { 0x9a00, 0x3395, 0x3000 }, + { 0x9a00, 0x3393, 0x2000 }, + { 0x1a00, 0x3392, 0x0000 }, + { 0x1a00, 0x3394, 0x0000 }, + { 0x9a00, 0x3397, 0x2000 }, + { 0x1a00, 0x3396, 0x0000 }, + { 0x1a00, 0x3398, 0x0000 }, + { 0x9a00, 0x339d, 0x3000 }, + { 0x9a00, 0x339b, 0x2000 }, + { 0x1a00, 0x339a, 0x0000 }, + { 0x1a00, 0x339c, 0x0000 }, + { 0x9a00, 0x339f, 0x2000 }, + { 0x1a00, 0x339e, 0x0000 }, + { 0x1a00, 0x33a0, 0x0000 }, + { 0x9a00, 0x33a9, 0x4000 }, + { 0x9a00, 0x33a5, 0x3000 }, + { 0x9a00, 0x33a3, 0x2000 }, + { 0x1a00, 0x33a2, 0x0000 }, + { 0x1a00, 0x33a4, 0x0000 }, + { 0x9a00, 0x33a7, 0x2000 }, + { 0x1a00, 0x33a6, 0x0000 }, + { 0x1a00, 0x33a8, 0x0000 }, + { 0x9a00, 0x33ad, 0x3000 }, + { 0x9a00, 0x33ab, 0x2000 }, + { 0x1a00, 0x33aa, 0x0000 }, + { 0x1a00, 0x33ac, 0x0000 }, + { 0x9a00, 0x33af, 0x2000 }, + { 0x1a00, 0x33ae, 0x0000 }, + { 0x1a00, 0x33b0, 0x0000 }, + { 0x9a00, 0x33c1, 0x5000 }, + { 0x9a00, 0x33b9, 0x4000 }, + { 0x9a00, 0x33b5, 0x3000 }, + { 0x9a00, 0x33b3, 0x2000 }, + { 0x1a00, 0x33b2, 0x0000 }, + { 0x1a00, 0x33b4, 0x0000 }, + { 0x9a00, 0x33b7, 0x2000 }, + { 0x1a00, 0x33b6, 0x0000 }, + { 0x1a00, 0x33b8, 0x0000 }, + { 0x9a00, 0x33bd, 0x3000 }, + { 0x9a00, 0x33bb, 0x2000 }, + { 0x1a00, 0x33ba, 0x0000 }, + { 0x1a00, 0x33bc, 0x0000 }, + { 0x9a00, 0x33bf, 0x2000 }, + { 0x1a00, 0x33be, 0x0000 }, + { 0x1a00, 0x33c0, 0x0000 }, + { 0x9a00, 0x33c9, 0x4000 }, + { 0x9a00, 0x33c5, 0x3000 }, + { 0x9a00, 0x33c3, 0x2000 }, + { 0x1a00, 0x33c2, 0x0000 }, + { 0x1a00, 0x33c4, 0x0000 }, + { 0x9a00, 0x33c7, 0x2000 }, + { 0x1a00, 0x33c6, 0x0000 }, + { 0x1a00, 0x33c8, 0x0000 }, + { 0x9a00, 0x33cd, 0x3000 }, + { 0x9a00, 0x33cb, 0x2000 }, + { 0x1a00, 0x33ca, 0x0000 }, + { 0x1a00, 0x33cc, 0x0000 }, + { 0x9a00, 0x33cf, 0x2000 }, + { 0x1a00, 0x33ce, 0x0000 }, + { 0x1a00, 0x33d0, 0x0000 }, + { 0x9a00, 0x33f1, 0x6000 }, + { 0x9a00, 0x33e1, 0x5000 }, + { 0x9a00, 0x33d9, 0x4000 }, + { 0x9a00, 0x33d5, 0x3000 }, + { 0x9a00, 0x33d3, 0x2000 }, + { 0x1a00, 0x33d2, 0x0000 }, + { 0x1a00, 0x33d4, 0x0000 }, + { 0x9a00, 0x33d7, 0x2000 }, + { 0x1a00, 0x33d6, 0x0000 }, + { 0x1a00, 0x33d8, 0x0000 }, + { 0x9a00, 0x33dd, 0x3000 }, + { 0x9a00, 0x33db, 0x2000 }, + { 0x1a00, 0x33da, 0x0000 }, + { 0x1a00, 0x33dc, 0x0000 }, + { 0x9a00, 0x33df, 0x2000 }, + { 0x1a00, 0x33de, 0x0000 }, + { 0x1a00, 0x33e0, 0x0000 }, + { 0x9a00, 0x33e9, 0x4000 }, + { 0x9a00, 0x33e5, 0x3000 }, + { 0x9a00, 0x33e3, 0x2000 }, + { 0x1a00, 0x33e2, 0x0000 }, + { 0x1a00, 0x33e4, 0x0000 }, + { 0x9a00, 0x33e7, 0x2000 }, + { 0x1a00, 0x33e6, 0x0000 }, + { 0x1a00, 0x33e8, 0x0000 }, + { 0x9a00, 0x33ed, 0x3000 }, + { 0x9a00, 0x33eb, 0x2000 }, + { 0x1a00, 0x33ea, 0x0000 }, + { 0x1a00, 0x33ec, 0x0000 }, + { 0x9a00, 0x33ef, 0x2000 }, + { 0x1a00, 0x33ee, 0x0000 }, + { 0x1a00, 0x33f0, 0x0000 }, + { 0x8700, 0x4db5, 0x5000 }, + { 0x9a00, 0x33f9, 0x4000 }, + { 0x9a00, 0x33f5, 0x3000 }, + { 0x9a00, 0x33f3, 0x2000 }, + { 0x1a00, 0x33f2, 0x0000 }, + { 0x1a00, 0x33f4, 0x0000 }, + { 0x9a00, 0x33f7, 0x2000 }, + { 0x1a00, 0x33f6, 0x0000 }, + { 0x1a00, 0x33f8, 0x0000 }, + { 0x9a00, 0x33fd, 0x3000 }, + { 0x9a00, 0x33fb, 0x2000 }, + { 0x1a00, 0x33fa, 0x0000 }, + { 0x1a00, 0x33fc, 0x0000 }, + { 0x9a00, 0x33ff, 0x2000 }, + { 0x1a00, 0x33fe, 0x0000 }, + { 0x0700, 0x3400, 0x0000 }, + { 0x9a00, 0x4dc7, 0x4000 }, + { 0x9a00, 0x4dc3, 0x3000 }, + { 0x9a00, 0x4dc1, 0x2000 }, + { 0x1a00, 0x4dc0, 0x0000 }, + { 0x1a00, 0x4dc2, 0x0000 }, + { 0x9a00, 0x4dc5, 0x2000 }, + { 0x1a00, 0x4dc4, 0x0000 }, + { 0x1a00, 0x4dc6, 0x0000 }, + { 0x9a00, 0x4dcb, 0x3000 }, + { 0x9a00, 0x4dc9, 0x2000 }, + { 0x1a00, 0x4dc8, 0x0000 }, + { 0x1a00, 0x4dca, 0x0000 }, + { 0x9a00, 0x4dcd, 0x2000 }, + { 0x1a00, 0x4dcc, 0x0000 }, + { 0x1a00, 0x4dce, 0x0000 }, + { 0x8700, 0xa00d, 0x7000 }, + { 0x9a00, 0x4def, 0x6000 }, + { 0x9a00, 0x4ddf, 0x5000 }, + { 0x9a00, 0x4dd7, 0x4000 }, + { 0x9a00, 0x4dd3, 0x3000 }, + { 0x9a00, 0x4dd1, 0x2000 }, + { 0x1a00, 0x4dd0, 0x0000 }, + { 0x1a00, 0x4dd2, 0x0000 }, + { 0x9a00, 0x4dd5, 0x2000 }, + { 0x1a00, 0x4dd4, 0x0000 }, + { 0x1a00, 0x4dd6, 0x0000 }, + { 0x9a00, 0x4ddb, 0x3000 }, + { 0x9a00, 0x4dd9, 0x2000 }, + { 0x1a00, 0x4dd8, 0x0000 }, + { 0x1a00, 0x4dda, 0x0000 }, + { 0x9a00, 0x4ddd, 0x2000 }, + { 0x1a00, 0x4ddc, 0x0000 }, + { 0x1a00, 0x4dde, 0x0000 }, + { 0x9a00, 0x4de7, 0x4000 }, + { 0x9a00, 0x4de3, 0x3000 }, + { 0x9a00, 0x4de1, 0x2000 }, + { 0x1a00, 0x4de0, 0x0000 }, + { 0x1a00, 0x4de2, 0x0000 }, + { 0x9a00, 0x4de5, 0x2000 }, + { 0x1a00, 0x4de4, 0x0000 }, + { 0x1a00, 0x4de6, 0x0000 }, + { 0x9a00, 0x4deb, 0x3000 }, + { 0x9a00, 0x4de9, 0x2000 }, + { 0x1a00, 0x4de8, 0x0000 }, + { 0x1a00, 0x4dea, 0x0000 }, + { 0x9a00, 0x4ded, 0x2000 }, + { 0x1a00, 0x4dec, 0x0000 }, + { 0x1a00, 0x4dee, 0x0000 }, + { 0x9a00, 0x4dff, 0x5000 }, + { 0x9a00, 0x4df7, 0x4000 }, + { 0x9a00, 0x4df3, 0x3000 }, + { 0x9a00, 0x4df1, 0x2000 }, + { 0x1a00, 0x4df0, 0x0000 }, + { 0x1a00, 0x4df2, 0x0000 }, + { 0x9a00, 0x4df5, 0x2000 }, + { 0x1a00, 0x4df4, 0x0000 }, + { 0x1a00, 0x4df6, 0x0000 }, + { 0x9a00, 0x4dfb, 0x3000 }, + { 0x9a00, 0x4df9, 0x2000 }, + { 0x1a00, 0x4df8, 0x0000 }, + { 0x1a00, 0x4dfa, 0x0000 }, + { 0x9a00, 0x4dfd, 0x2000 }, + { 0x1a00, 0x4dfc, 0x0000 }, + { 0x1a00, 0x4dfe, 0x0000 }, + { 0x8700, 0xa005, 0x4000 }, + { 0x8700, 0xa001, 0x3000 }, + { 0x8700, 0x9fa5, 0x2000 }, + { 0x0700, 0x4e00, 0x0000 }, + { 0x0700, 0xa000, 0x0000 }, + { 0x8700, 0xa003, 0x2000 }, + { 0x0700, 0xa002, 0x0000 }, + { 0x0700, 0xa004, 0x0000 }, + { 0x8700, 0xa009, 0x3000 }, + { 0x8700, 0xa007, 0x2000 }, + { 0x0700, 0xa006, 0x0000 }, + { 0x0700, 0xa008, 0x0000 }, + { 0x8700, 0xa00b, 0x2000 }, + { 0x0700, 0xa00a, 0x0000 }, + { 0x0700, 0xa00c, 0x0000 }, + { 0x8700, 0xa02d, 0x6000 }, + { 0x8700, 0xa01d, 0x5000 }, + { 0x8700, 0xa015, 0x4000 }, + { 0x8700, 0xa011, 0x3000 }, + { 0x8700, 0xa00f, 0x2000 }, + { 0x0700, 0xa00e, 0x0000 }, + { 0x0700, 0xa010, 0x0000 }, + { 0x8700, 0xa013, 0x2000 }, + { 0x0700, 0xa012, 0x0000 }, + { 0x0700, 0xa014, 0x0000 }, + { 0x8700, 0xa019, 0x3000 }, + { 0x8700, 0xa017, 0x2000 }, + { 0x0700, 0xa016, 0x0000 }, + { 0x0700, 0xa018, 0x0000 }, + { 0x8700, 0xa01b, 0x2000 }, + { 0x0700, 0xa01a, 0x0000 }, + { 0x0700, 0xa01c, 0x0000 }, + { 0x8700, 0xa025, 0x4000 }, + { 0x8700, 0xa021, 0x3000 }, + { 0x8700, 0xa01f, 0x2000 }, + { 0x0700, 0xa01e, 0x0000 }, + { 0x0700, 0xa020, 0x0000 }, + { 0x8700, 0xa023, 0x2000 }, + { 0x0700, 0xa022, 0x0000 }, + { 0x0700, 0xa024, 0x0000 }, + { 0x8700, 0xa029, 0x3000 }, + { 0x8700, 0xa027, 0x2000 }, + { 0x0700, 0xa026, 0x0000 }, + { 0x0700, 0xa028, 0x0000 }, + { 0x8700, 0xa02b, 0x2000 }, + { 0x0700, 0xa02a, 0x0000 }, + { 0x0700, 0xa02c, 0x0000 }, + { 0x8700, 0xa03d, 0x5000 }, + { 0x8700, 0xa035, 0x4000 }, + { 0x8700, 0xa031, 0x3000 }, + { 0x8700, 0xa02f, 0x2000 }, + { 0x0700, 0xa02e, 0x0000 }, + { 0x0700, 0xa030, 0x0000 }, + { 0x8700, 0xa033, 0x2000 }, + { 0x0700, 0xa032, 0x0000 }, + { 0x0700, 0xa034, 0x0000 }, + { 0x8700, 0xa039, 0x3000 }, + { 0x8700, 0xa037, 0x2000 }, + { 0x0700, 0xa036, 0x0000 }, + { 0x0700, 0xa038, 0x0000 }, + { 0x8700, 0xa03b, 0x2000 }, + { 0x0700, 0xa03a, 0x0000 }, + { 0x0700, 0xa03c, 0x0000 }, + { 0x8700, 0xa045, 0x4000 }, + { 0x8700, 0xa041, 0x3000 }, + { 0x8700, 0xa03f, 0x2000 }, + { 0x0700, 0xa03e, 0x0000 }, + { 0x0700, 0xa040, 0x0000 }, + { 0x8700, 0xa043, 0x2000 }, + { 0x0700, 0xa042, 0x0000 }, + { 0x0700, 0xa044, 0x0000 }, + { 0x8700, 0xa049, 0x3000 }, + { 0x8700, 0xa047, 0x2000 }, + { 0x0700, 0xa046, 0x0000 }, + { 0x0700, 0xa048, 0x0000 }, + { 0x8700, 0xa04b, 0x2000 }, + { 0x0700, 0xa04a, 0x0000 }, + { 0x0700, 0xa04c, 0x0000 }, + { 0x8700, 0xa0cd, 0x8000 }, + { 0x8700, 0xa08d, 0x7000 }, + { 0x8700, 0xa06d, 0x6000 }, + { 0x8700, 0xa05d, 0x5000 }, + { 0x8700, 0xa055, 0x4000 }, + { 0x8700, 0xa051, 0x3000 }, + { 0x8700, 0xa04f, 0x2000 }, + { 0x0700, 0xa04e, 0x0000 }, + { 0x0700, 0xa050, 0x0000 }, + { 0x8700, 0xa053, 0x2000 }, + { 0x0700, 0xa052, 0x0000 }, + { 0x0700, 0xa054, 0x0000 }, + { 0x8700, 0xa059, 0x3000 }, + { 0x8700, 0xa057, 0x2000 }, + { 0x0700, 0xa056, 0x0000 }, + { 0x0700, 0xa058, 0x0000 }, + { 0x8700, 0xa05b, 0x2000 }, + { 0x0700, 0xa05a, 0x0000 }, + { 0x0700, 0xa05c, 0x0000 }, + { 0x8700, 0xa065, 0x4000 }, + { 0x8700, 0xa061, 0x3000 }, + { 0x8700, 0xa05f, 0x2000 }, + { 0x0700, 0xa05e, 0x0000 }, + { 0x0700, 0xa060, 0x0000 }, + { 0x8700, 0xa063, 0x2000 }, + { 0x0700, 0xa062, 0x0000 }, + { 0x0700, 0xa064, 0x0000 }, + { 0x8700, 0xa069, 0x3000 }, + { 0x8700, 0xa067, 0x2000 }, + { 0x0700, 0xa066, 0x0000 }, + { 0x0700, 0xa068, 0x0000 }, + { 0x8700, 0xa06b, 0x2000 }, + { 0x0700, 0xa06a, 0x0000 }, + { 0x0700, 0xa06c, 0x0000 }, + { 0x8700, 0xa07d, 0x5000 }, + { 0x8700, 0xa075, 0x4000 }, + { 0x8700, 0xa071, 0x3000 }, + { 0x8700, 0xa06f, 0x2000 }, + { 0x0700, 0xa06e, 0x0000 }, + { 0x0700, 0xa070, 0x0000 }, + { 0x8700, 0xa073, 0x2000 }, + { 0x0700, 0xa072, 0x0000 }, + { 0x0700, 0xa074, 0x0000 }, + { 0x8700, 0xa079, 0x3000 }, + { 0x8700, 0xa077, 0x2000 }, + { 0x0700, 0xa076, 0x0000 }, + { 0x0700, 0xa078, 0x0000 }, + { 0x8700, 0xa07b, 0x2000 }, + { 0x0700, 0xa07a, 0x0000 }, + { 0x0700, 0xa07c, 0x0000 }, + { 0x8700, 0xa085, 0x4000 }, + { 0x8700, 0xa081, 0x3000 }, + { 0x8700, 0xa07f, 0x2000 }, + { 0x0700, 0xa07e, 0x0000 }, + { 0x0700, 0xa080, 0x0000 }, + { 0x8700, 0xa083, 0x2000 }, + { 0x0700, 0xa082, 0x0000 }, + { 0x0700, 0xa084, 0x0000 }, + { 0x8700, 0xa089, 0x3000 }, + { 0x8700, 0xa087, 0x2000 }, + { 0x0700, 0xa086, 0x0000 }, + { 0x0700, 0xa088, 0x0000 }, + { 0x8700, 0xa08b, 0x2000 }, + { 0x0700, 0xa08a, 0x0000 }, + { 0x0700, 0xa08c, 0x0000 }, + { 0x8700, 0xa0ad, 0x6000 }, + { 0x8700, 0xa09d, 0x5000 }, + { 0x8700, 0xa095, 0x4000 }, + { 0x8700, 0xa091, 0x3000 }, + { 0x8700, 0xa08f, 0x2000 }, + { 0x0700, 0xa08e, 0x0000 }, + { 0x0700, 0xa090, 0x0000 }, + { 0x8700, 0xa093, 0x2000 }, + { 0x0700, 0xa092, 0x0000 }, + { 0x0700, 0xa094, 0x0000 }, + { 0x8700, 0xa099, 0x3000 }, + { 0x8700, 0xa097, 0x2000 }, + { 0x0700, 0xa096, 0x0000 }, + { 0x0700, 0xa098, 0x0000 }, + { 0x8700, 0xa09b, 0x2000 }, + { 0x0700, 0xa09a, 0x0000 }, + { 0x0700, 0xa09c, 0x0000 }, + { 0x8700, 0xa0a5, 0x4000 }, + { 0x8700, 0xa0a1, 0x3000 }, + { 0x8700, 0xa09f, 0x2000 }, + { 0x0700, 0xa09e, 0x0000 }, + { 0x0700, 0xa0a0, 0x0000 }, + { 0x8700, 0xa0a3, 0x2000 }, + { 0x0700, 0xa0a2, 0x0000 }, + { 0x0700, 0xa0a4, 0x0000 }, + { 0x8700, 0xa0a9, 0x3000 }, + { 0x8700, 0xa0a7, 0x2000 }, + { 0x0700, 0xa0a6, 0x0000 }, + { 0x0700, 0xa0a8, 0x0000 }, + { 0x8700, 0xa0ab, 0x2000 }, + { 0x0700, 0xa0aa, 0x0000 }, + { 0x0700, 0xa0ac, 0x0000 }, + { 0x8700, 0xa0bd, 0x5000 }, + { 0x8700, 0xa0b5, 0x4000 }, + { 0x8700, 0xa0b1, 0x3000 }, + { 0x8700, 0xa0af, 0x2000 }, + { 0x0700, 0xa0ae, 0x0000 }, + { 0x0700, 0xa0b0, 0x0000 }, + { 0x8700, 0xa0b3, 0x2000 }, + { 0x0700, 0xa0b2, 0x0000 }, + { 0x0700, 0xa0b4, 0x0000 }, + { 0x8700, 0xa0b9, 0x3000 }, + { 0x8700, 0xa0b7, 0x2000 }, + { 0x0700, 0xa0b6, 0x0000 }, + { 0x0700, 0xa0b8, 0x0000 }, + { 0x8700, 0xa0bb, 0x2000 }, + { 0x0700, 0xa0ba, 0x0000 }, + { 0x0700, 0xa0bc, 0x0000 }, + { 0x8700, 0xa0c5, 0x4000 }, + { 0x8700, 0xa0c1, 0x3000 }, + { 0x8700, 0xa0bf, 0x2000 }, + { 0x0700, 0xa0be, 0x0000 }, + { 0x0700, 0xa0c0, 0x0000 }, + { 0x8700, 0xa0c3, 0x2000 }, + { 0x0700, 0xa0c2, 0x0000 }, + { 0x0700, 0xa0c4, 0x0000 }, + { 0x8700, 0xa0c9, 0x3000 }, + { 0x8700, 0xa0c7, 0x2000 }, + { 0x0700, 0xa0c6, 0x0000 }, + { 0x0700, 0xa0c8, 0x0000 }, + { 0x8700, 0xa0cb, 0x2000 }, + { 0x0700, 0xa0ca, 0x0000 }, + { 0x0700, 0xa0cc, 0x0000 }, + { 0x8700, 0xa10d, 0x7000 }, + { 0x8700, 0xa0ed, 0x6000 }, + { 0x8700, 0xa0dd, 0x5000 }, + { 0x8700, 0xa0d5, 0x4000 }, + { 0x8700, 0xa0d1, 0x3000 }, + { 0x8700, 0xa0cf, 0x2000 }, + { 0x0700, 0xa0ce, 0x0000 }, + { 0x0700, 0xa0d0, 0x0000 }, + { 0x8700, 0xa0d3, 0x2000 }, + { 0x0700, 0xa0d2, 0x0000 }, + { 0x0700, 0xa0d4, 0x0000 }, + { 0x8700, 0xa0d9, 0x3000 }, + { 0x8700, 0xa0d7, 0x2000 }, + { 0x0700, 0xa0d6, 0x0000 }, + { 0x0700, 0xa0d8, 0x0000 }, + { 0x8700, 0xa0db, 0x2000 }, + { 0x0700, 0xa0da, 0x0000 }, + { 0x0700, 0xa0dc, 0x0000 }, + { 0x8700, 0xa0e5, 0x4000 }, + { 0x8700, 0xa0e1, 0x3000 }, + { 0x8700, 0xa0df, 0x2000 }, + { 0x0700, 0xa0de, 0x0000 }, + { 0x0700, 0xa0e0, 0x0000 }, + { 0x8700, 0xa0e3, 0x2000 }, + { 0x0700, 0xa0e2, 0x0000 }, + { 0x0700, 0xa0e4, 0x0000 }, + { 0x8700, 0xa0e9, 0x3000 }, + { 0x8700, 0xa0e7, 0x2000 }, + { 0x0700, 0xa0e6, 0x0000 }, + { 0x0700, 0xa0e8, 0x0000 }, + { 0x8700, 0xa0eb, 0x2000 }, + { 0x0700, 0xa0ea, 0x0000 }, + { 0x0700, 0xa0ec, 0x0000 }, + { 0x8700, 0xa0fd, 0x5000 }, + { 0x8700, 0xa0f5, 0x4000 }, + { 0x8700, 0xa0f1, 0x3000 }, + { 0x8700, 0xa0ef, 0x2000 }, + { 0x0700, 0xa0ee, 0x0000 }, + { 0x0700, 0xa0f0, 0x0000 }, + { 0x8700, 0xa0f3, 0x2000 }, + { 0x0700, 0xa0f2, 0x0000 }, + { 0x0700, 0xa0f4, 0x0000 }, + { 0x8700, 0xa0f9, 0x3000 }, + { 0x8700, 0xa0f7, 0x2000 }, + { 0x0700, 0xa0f6, 0x0000 }, + { 0x0700, 0xa0f8, 0x0000 }, + { 0x8700, 0xa0fb, 0x2000 }, + { 0x0700, 0xa0fa, 0x0000 }, + { 0x0700, 0xa0fc, 0x0000 }, + { 0x8700, 0xa105, 0x4000 }, + { 0x8700, 0xa101, 0x3000 }, + { 0x8700, 0xa0ff, 0x2000 }, + { 0x0700, 0xa0fe, 0x0000 }, + { 0x0700, 0xa100, 0x0000 }, + { 0x8700, 0xa103, 0x2000 }, + { 0x0700, 0xa102, 0x0000 }, + { 0x0700, 0xa104, 0x0000 }, + { 0x8700, 0xa109, 0x3000 }, + { 0x8700, 0xa107, 0x2000 }, + { 0x0700, 0xa106, 0x0000 }, + { 0x0700, 0xa108, 0x0000 }, + { 0x8700, 0xa10b, 0x2000 }, + { 0x0700, 0xa10a, 0x0000 }, + { 0x0700, 0xa10c, 0x0000 }, + { 0x8700, 0xa12d, 0x6000 }, + { 0x8700, 0xa11d, 0x5000 }, + { 0x8700, 0xa115, 0x4000 }, + { 0x8700, 0xa111, 0x3000 }, + { 0x8700, 0xa10f, 0x2000 }, + { 0x0700, 0xa10e, 0x0000 }, + { 0x0700, 0xa110, 0x0000 }, + { 0x8700, 0xa113, 0x2000 }, + { 0x0700, 0xa112, 0x0000 }, + { 0x0700, 0xa114, 0x0000 }, + { 0x8700, 0xa119, 0x3000 }, + { 0x8700, 0xa117, 0x2000 }, + { 0x0700, 0xa116, 0x0000 }, + { 0x0700, 0xa118, 0x0000 }, + { 0x8700, 0xa11b, 0x2000 }, + { 0x0700, 0xa11a, 0x0000 }, + { 0x0700, 0xa11c, 0x0000 }, + { 0x8700, 0xa125, 0x4000 }, + { 0x8700, 0xa121, 0x3000 }, + { 0x8700, 0xa11f, 0x2000 }, + { 0x0700, 0xa11e, 0x0000 }, + { 0x0700, 0xa120, 0x0000 }, + { 0x8700, 0xa123, 0x2000 }, + { 0x0700, 0xa122, 0x0000 }, + { 0x0700, 0xa124, 0x0000 }, + { 0x8700, 0xa129, 0x3000 }, + { 0x8700, 0xa127, 0x2000 }, + { 0x0700, 0xa126, 0x0000 }, + { 0x0700, 0xa128, 0x0000 }, + { 0x8700, 0xa12b, 0x2000 }, + { 0x0700, 0xa12a, 0x0000 }, + { 0x0700, 0xa12c, 0x0000 }, + { 0x8700, 0xa13d, 0x5000 }, + { 0x8700, 0xa135, 0x4000 }, + { 0x8700, 0xa131, 0x3000 }, + { 0x8700, 0xa12f, 0x2000 }, + { 0x0700, 0xa12e, 0x0000 }, + { 0x0700, 0xa130, 0x0000 }, + { 0x8700, 0xa133, 0x2000 }, + { 0x0700, 0xa132, 0x0000 }, + { 0x0700, 0xa134, 0x0000 }, + { 0x8700, 0xa139, 0x3000 }, + { 0x8700, 0xa137, 0x2000 }, + { 0x0700, 0xa136, 0x0000 }, + { 0x0700, 0xa138, 0x0000 }, + { 0x8700, 0xa13b, 0x2000 }, + { 0x0700, 0xa13a, 0x0000 }, + { 0x0700, 0xa13c, 0x0000 }, + { 0x8700, 0xa145, 0x4000 }, + { 0x8700, 0xa141, 0x3000 }, + { 0x8700, 0xa13f, 0x2000 }, + { 0x0700, 0xa13e, 0x0000 }, + { 0x0700, 0xa140, 0x0000 }, + { 0x8700, 0xa143, 0x2000 }, + { 0x0700, 0xa142, 0x0000 }, + { 0x0700, 0xa144, 0x0000 }, + { 0x8700, 0xa149, 0x3000 }, + { 0x8700, 0xa147, 0x2000 }, + { 0x0700, 0xa146, 0x0000 }, + { 0x0700, 0xa148, 0x0000 }, + { 0x8700, 0xa14b, 0x2000 }, + { 0x0700, 0xa14a, 0x0000 }, + { 0x0700, 0xa14c, 0x0000 }, + { 0x8700, 0xa24d, 0x9000 }, + { 0x8700, 0xa1cd, 0x8000 }, + { 0x8700, 0xa18d, 0x7000 }, + { 0x8700, 0xa16d, 0x6000 }, + { 0x8700, 0xa15d, 0x5000 }, + { 0x8700, 0xa155, 0x4000 }, + { 0x8700, 0xa151, 0x3000 }, + { 0x8700, 0xa14f, 0x2000 }, + { 0x0700, 0xa14e, 0x0000 }, + { 0x0700, 0xa150, 0x0000 }, + { 0x8700, 0xa153, 0x2000 }, + { 0x0700, 0xa152, 0x0000 }, + { 0x0700, 0xa154, 0x0000 }, + { 0x8700, 0xa159, 0x3000 }, + { 0x8700, 0xa157, 0x2000 }, + { 0x0700, 0xa156, 0x0000 }, + { 0x0700, 0xa158, 0x0000 }, + { 0x8700, 0xa15b, 0x2000 }, + { 0x0700, 0xa15a, 0x0000 }, + { 0x0700, 0xa15c, 0x0000 }, + { 0x8700, 0xa165, 0x4000 }, + { 0x8700, 0xa161, 0x3000 }, + { 0x8700, 0xa15f, 0x2000 }, + { 0x0700, 0xa15e, 0x0000 }, + { 0x0700, 0xa160, 0x0000 }, + { 0x8700, 0xa163, 0x2000 }, + { 0x0700, 0xa162, 0x0000 }, + { 0x0700, 0xa164, 0x0000 }, + { 0x8700, 0xa169, 0x3000 }, + { 0x8700, 0xa167, 0x2000 }, + { 0x0700, 0xa166, 0x0000 }, + { 0x0700, 0xa168, 0x0000 }, + { 0x8700, 0xa16b, 0x2000 }, + { 0x0700, 0xa16a, 0x0000 }, + { 0x0700, 0xa16c, 0x0000 }, + { 0x8700, 0xa17d, 0x5000 }, + { 0x8700, 0xa175, 0x4000 }, + { 0x8700, 0xa171, 0x3000 }, + { 0x8700, 0xa16f, 0x2000 }, + { 0x0700, 0xa16e, 0x0000 }, + { 0x0700, 0xa170, 0x0000 }, + { 0x8700, 0xa173, 0x2000 }, + { 0x0700, 0xa172, 0x0000 }, + { 0x0700, 0xa174, 0x0000 }, + { 0x8700, 0xa179, 0x3000 }, + { 0x8700, 0xa177, 0x2000 }, + { 0x0700, 0xa176, 0x0000 }, + { 0x0700, 0xa178, 0x0000 }, + { 0x8700, 0xa17b, 0x2000 }, + { 0x0700, 0xa17a, 0x0000 }, + { 0x0700, 0xa17c, 0x0000 }, + { 0x8700, 0xa185, 0x4000 }, + { 0x8700, 0xa181, 0x3000 }, + { 0x8700, 0xa17f, 0x2000 }, + { 0x0700, 0xa17e, 0x0000 }, + { 0x0700, 0xa180, 0x0000 }, + { 0x8700, 0xa183, 0x2000 }, + { 0x0700, 0xa182, 0x0000 }, + { 0x0700, 0xa184, 0x0000 }, + { 0x8700, 0xa189, 0x3000 }, + { 0x8700, 0xa187, 0x2000 }, + { 0x0700, 0xa186, 0x0000 }, + { 0x0700, 0xa188, 0x0000 }, + { 0x8700, 0xa18b, 0x2000 }, + { 0x0700, 0xa18a, 0x0000 }, + { 0x0700, 0xa18c, 0x0000 }, + { 0x8700, 0xa1ad, 0x6000 }, + { 0x8700, 0xa19d, 0x5000 }, + { 0x8700, 0xa195, 0x4000 }, + { 0x8700, 0xa191, 0x3000 }, + { 0x8700, 0xa18f, 0x2000 }, + { 0x0700, 0xa18e, 0x0000 }, + { 0x0700, 0xa190, 0x0000 }, + { 0x8700, 0xa193, 0x2000 }, + { 0x0700, 0xa192, 0x0000 }, + { 0x0700, 0xa194, 0x0000 }, + { 0x8700, 0xa199, 0x3000 }, + { 0x8700, 0xa197, 0x2000 }, + { 0x0700, 0xa196, 0x0000 }, + { 0x0700, 0xa198, 0x0000 }, + { 0x8700, 0xa19b, 0x2000 }, + { 0x0700, 0xa19a, 0x0000 }, + { 0x0700, 0xa19c, 0x0000 }, + { 0x8700, 0xa1a5, 0x4000 }, + { 0x8700, 0xa1a1, 0x3000 }, + { 0x8700, 0xa19f, 0x2000 }, + { 0x0700, 0xa19e, 0x0000 }, + { 0x0700, 0xa1a0, 0x0000 }, + { 0x8700, 0xa1a3, 0x2000 }, + { 0x0700, 0xa1a2, 0x0000 }, + { 0x0700, 0xa1a4, 0x0000 }, + { 0x8700, 0xa1a9, 0x3000 }, + { 0x8700, 0xa1a7, 0x2000 }, + { 0x0700, 0xa1a6, 0x0000 }, + { 0x0700, 0xa1a8, 0x0000 }, + { 0x8700, 0xa1ab, 0x2000 }, + { 0x0700, 0xa1aa, 0x0000 }, + { 0x0700, 0xa1ac, 0x0000 }, + { 0x8700, 0xa1bd, 0x5000 }, + { 0x8700, 0xa1b5, 0x4000 }, + { 0x8700, 0xa1b1, 0x3000 }, + { 0x8700, 0xa1af, 0x2000 }, + { 0x0700, 0xa1ae, 0x0000 }, + { 0x0700, 0xa1b0, 0x0000 }, + { 0x8700, 0xa1b3, 0x2000 }, + { 0x0700, 0xa1b2, 0x0000 }, + { 0x0700, 0xa1b4, 0x0000 }, + { 0x8700, 0xa1b9, 0x3000 }, + { 0x8700, 0xa1b7, 0x2000 }, + { 0x0700, 0xa1b6, 0x0000 }, + { 0x0700, 0xa1b8, 0x0000 }, + { 0x8700, 0xa1bb, 0x2000 }, + { 0x0700, 0xa1ba, 0x0000 }, + { 0x0700, 0xa1bc, 0x0000 }, + { 0x8700, 0xa1c5, 0x4000 }, + { 0x8700, 0xa1c1, 0x3000 }, + { 0x8700, 0xa1bf, 0x2000 }, + { 0x0700, 0xa1be, 0x0000 }, + { 0x0700, 0xa1c0, 0x0000 }, + { 0x8700, 0xa1c3, 0x2000 }, + { 0x0700, 0xa1c2, 0x0000 }, + { 0x0700, 0xa1c4, 0x0000 }, + { 0x8700, 0xa1c9, 0x3000 }, + { 0x8700, 0xa1c7, 0x2000 }, + { 0x0700, 0xa1c6, 0x0000 }, + { 0x0700, 0xa1c8, 0x0000 }, + { 0x8700, 0xa1cb, 0x2000 }, + { 0x0700, 0xa1ca, 0x0000 }, + { 0x0700, 0xa1cc, 0x0000 }, + { 0x8700, 0xa20d, 0x7000 }, + { 0x8700, 0xa1ed, 0x6000 }, + { 0x8700, 0xa1dd, 0x5000 }, + { 0x8700, 0xa1d5, 0x4000 }, + { 0x8700, 0xa1d1, 0x3000 }, + { 0x8700, 0xa1cf, 0x2000 }, + { 0x0700, 0xa1ce, 0x0000 }, + { 0x0700, 0xa1d0, 0x0000 }, + { 0x8700, 0xa1d3, 0x2000 }, + { 0x0700, 0xa1d2, 0x0000 }, + { 0x0700, 0xa1d4, 0x0000 }, + { 0x8700, 0xa1d9, 0x3000 }, + { 0x8700, 0xa1d7, 0x2000 }, + { 0x0700, 0xa1d6, 0x0000 }, + { 0x0700, 0xa1d8, 0x0000 }, + { 0x8700, 0xa1db, 0x2000 }, + { 0x0700, 0xa1da, 0x0000 }, + { 0x0700, 0xa1dc, 0x0000 }, + { 0x8700, 0xa1e5, 0x4000 }, + { 0x8700, 0xa1e1, 0x3000 }, + { 0x8700, 0xa1df, 0x2000 }, + { 0x0700, 0xa1de, 0x0000 }, + { 0x0700, 0xa1e0, 0x0000 }, + { 0x8700, 0xa1e3, 0x2000 }, + { 0x0700, 0xa1e2, 0x0000 }, + { 0x0700, 0xa1e4, 0x0000 }, + { 0x8700, 0xa1e9, 0x3000 }, + { 0x8700, 0xa1e7, 0x2000 }, + { 0x0700, 0xa1e6, 0x0000 }, + { 0x0700, 0xa1e8, 0x0000 }, + { 0x8700, 0xa1eb, 0x2000 }, + { 0x0700, 0xa1ea, 0x0000 }, + { 0x0700, 0xa1ec, 0x0000 }, + { 0x8700, 0xa1fd, 0x5000 }, + { 0x8700, 0xa1f5, 0x4000 }, + { 0x8700, 0xa1f1, 0x3000 }, + { 0x8700, 0xa1ef, 0x2000 }, + { 0x0700, 0xa1ee, 0x0000 }, + { 0x0700, 0xa1f0, 0x0000 }, + { 0x8700, 0xa1f3, 0x2000 }, + { 0x0700, 0xa1f2, 0x0000 }, + { 0x0700, 0xa1f4, 0x0000 }, + { 0x8700, 0xa1f9, 0x3000 }, + { 0x8700, 0xa1f7, 0x2000 }, + { 0x0700, 0xa1f6, 0x0000 }, + { 0x0700, 0xa1f8, 0x0000 }, + { 0x8700, 0xa1fb, 0x2000 }, + { 0x0700, 0xa1fa, 0x0000 }, + { 0x0700, 0xa1fc, 0x0000 }, + { 0x8700, 0xa205, 0x4000 }, + { 0x8700, 0xa201, 0x3000 }, + { 0x8700, 0xa1ff, 0x2000 }, + { 0x0700, 0xa1fe, 0x0000 }, + { 0x0700, 0xa200, 0x0000 }, + { 0x8700, 0xa203, 0x2000 }, + { 0x0700, 0xa202, 0x0000 }, + { 0x0700, 0xa204, 0x0000 }, + { 0x8700, 0xa209, 0x3000 }, + { 0x8700, 0xa207, 0x2000 }, + { 0x0700, 0xa206, 0x0000 }, + { 0x0700, 0xa208, 0x0000 }, + { 0x8700, 0xa20b, 0x2000 }, + { 0x0700, 0xa20a, 0x0000 }, + { 0x0700, 0xa20c, 0x0000 }, + { 0x8700, 0xa22d, 0x6000 }, + { 0x8700, 0xa21d, 0x5000 }, + { 0x8700, 0xa215, 0x4000 }, + { 0x8700, 0xa211, 0x3000 }, + { 0x8700, 0xa20f, 0x2000 }, + { 0x0700, 0xa20e, 0x0000 }, + { 0x0700, 0xa210, 0x0000 }, + { 0x8700, 0xa213, 0x2000 }, + { 0x0700, 0xa212, 0x0000 }, + { 0x0700, 0xa214, 0x0000 }, + { 0x8700, 0xa219, 0x3000 }, + { 0x8700, 0xa217, 0x2000 }, + { 0x0700, 0xa216, 0x0000 }, + { 0x0700, 0xa218, 0x0000 }, + { 0x8700, 0xa21b, 0x2000 }, + { 0x0700, 0xa21a, 0x0000 }, + { 0x0700, 0xa21c, 0x0000 }, + { 0x8700, 0xa225, 0x4000 }, + { 0x8700, 0xa221, 0x3000 }, + { 0x8700, 0xa21f, 0x2000 }, + { 0x0700, 0xa21e, 0x0000 }, + { 0x0700, 0xa220, 0x0000 }, + { 0x8700, 0xa223, 0x2000 }, + { 0x0700, 0xa222, 0x0000 }, + { 0x0700, 0xa224, 0x0000 }, + { 0x8700, 0xa229, 0x3000 }, + { 0x8700, 0xa227, 0x2000 }, + { 0x0700, 0xa226, 0x0000 }, + { 0x0700, 0xa228, 0x0000 }, + { 0x8700, 0xa22b, 0x2000 }, + { 0x0700, 0xa22a, 0x0000 }, + { 0x0700, 0xa22c, 0x0000 }, + { 0x8700, 0xa23d, 0x5000 }, + { 0x8700, 0xa235, 0x4000 }, + { 0x8700, 0xa231, 0x3000 }, + { 0x8700, 0xa22f, 0x2000 }, + { 0x0700, 0xa22e, 0x0000 }, + { 0x0700, 0xa230, 0x0000 }, + { 0x8700, 0xa233, 0x2000 }, + { 0x0700, 0xa232, 0x0000 }, + { 0x0700, 0xa234, 0x0000 }, + { 0x8700, 0xa239, 0x3000 }, + { 0x8700, 0xa237, 0x2000 }, + { 0x0700, 0xa236, 0x0000 }, + { 0x0700, 0xa238, 0x0000 }, + { 0x8700, 0xa23b, 0x2000 }, + { 0x0700, 0xa23a, 0x0000 }, + { 0x0700, 0xa23c, 0x0000 }, + { 0x8700, 0xa245, 0x4000 }, + { 0x8700, 0xa241, 0x3000 }, + { 0x8700, 0xa23f, 0x2000 }, + { 0x0700, 0xa23e, 0x0000 }, + { 0x0700, 0xa240, 0x0000 }, + { 0x8700, 0xa243, 0x2000 }, + { 0x0700, 0xa242, 0x0000 }, + { 0x0700, 0xa244, 0x0000 }, + { 0x8700, 0xa249, 0x3000 }, + { 0x8700, 0xa247, 0x2000 }, + { 0x0700, 0xa246, 0x0000 }, + { 0x0700, 0xa248, 0x0000 }, + { 0x8700, 0xa24b, 0x2000 }, + { 0x0700, 0xa24a, 0x0000 }, + { 0x0700, 0xa24c, 0x0000 }, + { 0x8700, 0xa2cd, 0x8000 }, + { 0x8700, 0xa28d, 0x7000 }, + { 0x8700, 0xa26d, 0x6000 }, + { 0x8700, 0xa25d, 0x5000 }, + { 0x8700, 0xa255, 0x4000 }, + { 0x8700, 0xa251, 0x3000 }, + { 0x8700, 0xa24f, 0x2000 }, + { 0x0700, 0xa24e, 0x0000 }, + { 0x0700, 0xa250, 0x0000 }, + { 0x8700, 0xa253, 0x2000 }, + { 0x0700, 0xa252, 0x0000 }, + { 0x0700, 0xa254, 0x0000 }, + { 0x8700, 0xa259, 0x3000 }, + { 0x8700, 0xa257, 0x2000 }, + { 0x0700, 0xa256, 0x0000 }, + { 0x0700, 0xa258, 0x0000 }, + { 0x8700, 0xa25b, 0x2000 }, + { 0x0700, 0xa25a, 0x0000 }, + { 0x0700, 0xa25c, 0x0000 }, + { 0x8700, 0xa265, 0x4000 }, + { 0x8700, 0xa261, 0x3000 }, + { 0x8700, 0xa25f, 0x2000 }, + { 0x0700, 0xa25e, 0x0000 }, + { 0x0700, 0xa260, 0x0000 }, + { 0x8700, 0xa263, 0x2000 }, + { 0x0700, 0xa262, 0x0000 }, + { 0x0700, 0xa264, 0x0000 }, + { 0x8700, 0xa269, 0x3000 }, + { 0x8700, 0xa267, 0x2000 }, + { 0x0700, 0xa266, 0x0000 }, + { 0x0700, 0xa268, 0x0000 }, + { 0x8700, 0xa26b, 0x2000 }, + { 0x0700, 0xa26a, 0x0000 }, + { 0x0700, 0xa26c, 0x0000 }, + { 0x8700, 0xa27d, 0x5000 }, + { 0x8700, 0xa275, 0x4000 }, + { 0x8700, 0xa271, 0x3000 }, + { 0x8700, 0xa26f, 0x2000 }, + { 0x0700, 0xa26e, 0x0000 }, + { 0x0700, 0xa270, 0x0000 }, + { 0x8700, 0xa273, 0x2000 }, + { 0x0700, 0xa272, 0x0000 }, + { 0x0700, 0xa274, 0x0000 }, + { 0x8700, 0xa279, 0x3000 }, + { 0x8700, 0xa277, 0x2000 }, + { 0x0700, 0xa276, 0x0000 }, + { 0x0700, 0xa278, 0x0000 }, + { 0x8700, 0xa27b, 0x2000 }, + { 0x0700, 0xa27a, 0x0000 }, + { 0x0700, 0xa27c, 0x0000 }, + { 0x8700, 0xa285, 0x4000 }, + { 0x8700, 0xa281, 0x3000 }, + { 0x8700, 0xa27f, 0x2000 }, + { 0x0700, 0xa27e, 0x0000 }, + { 0x0700, 0xa280, 0x0000 }, + { 0x8700, 0xa283, 0x2000 }, + { 0x0700, 0xa282, 0x0000 }, + { 0x0700, 0xa284, 0x0000 }, + { 0x8700, 0xa289, 0x3000 }, + { 0x8700, 0xa287, 0x2000 }, + { 0x0700, 0xa286, 0x0000 }, + { 0x0700, 0xa288, 0x0000 }, + { 0x8700, 0xa28b, 0x2000 }, + { 0x0700, 0xa28a, 0x0000 }, + { 0x0700, 0xa28c, 0x0000 }, + { 0x8700, 0xa2ad, 0x6000 }, + { 0x8700, 0xa29d, 0x5000 }, + { 0x8700, 0xa295, 0x4000 }, + { 0x8700, 0xa291, 0x3000 }, + { 0x8700, 0xa28f, 0x2000 }, + { 0x0700, 0xa28e, 0x0000 }, + { 0x0700, 0xa290, 0x0000 }, + { 0x8700, 0xa293, 0x2000 }, + { 0x0700, 0xa292, 0x0000 }, + { 0x0700, 0xa294, 0x0000 }, + { 0x8700, 0xa299, 0x3000 }, + { 0x8700, 0xa297, 0x2000 }, + { 0x0700, 0xa296, 0x0000 }, + { 0x0700, 0xa298, 0x0000 }, + { 0x8700, 0xa29b, 0x2000 }, + { 0x0700, 0xa29a, 0x0000 }, + { 0x0700, 0xa29c, 0x0000 }, + { 0x8700, 0xa2a5, 0x4000 }, + { 0x8700, 0xa2a1, 0x3000 }, + { 0x8700, 0xa29f, 0x2000 }, + { 0x0700, 0xa29e, 0x0000 }, + { 0x0700, 0xa2a0, 0x0000 }, + { 0x8700, 0xa2a3, 0x2000 }, + { 0x0700, 0xa2a2, 0x0000 }, + { 0x0700, 0xa2a4, 0x0000 }, + { 0x8700, 0xa2a9, 0x3000 }, + { 0x8700, 0xa2a7, 0x2000 }, + { 0x0700, 0xa2a6, 0x0000 }, + { 0x0700, 0xa2a8, 0x0000 }, + { 0x8700, 0xa2ab, 0x2000 }, + { 0x0700, 0xa2aa, 0x0000 }, + { 0x0700, 0xa2ac, 0x0000 }, + { 0x8700, 0xa2bd, 0x5000 }, + { 0x8700, 0xa2b5, 0x4000 }, + { 0x8700, 0xa2b1, 0x3000 }, + { 0x8700, 0xa2af, 0x2000 }, + { 0x0700, 0xa2ae, 0x0000 }, + { 0x0700, 0xa2b0, 0x0000 }, + { 0x8700, 0xa2b3, 0x2000 }, + { 0x0700, 0xa2b2, 0x0000 }, + { 0x0700, 0xa2b4, 0x0000 }, + { 0x8700, 0xa2b9, 0x3000 }, + { 0x8700, 0xa2b7, 0x2000 }, + { 0x0700, 0xa2b6, 0x0000 }, + { 0x0700, 0xa2b8, 0x0000 }, + { 0x8700, 0xa2bb, 0x2000 }, + { 0x0700, 0xa2ba, 0x0000 }, + { 0x0700, 0xa2bc, 0x0000 }, + { 0x8700, 0xa2c5, 0x4000 }, + { 0x8700, 0xa2c1, 0x3000 }, + { 0x8700, 0xa2bf, 0x2000 }, + { 0x0700, 0xa2be, 0x0000 }, + { 0x0700, 0xa2c0, 0x0000 }, + { 0x8700, 0xa2c3, 0x2000 }, + { 0x0700, 0xa2c2, 0x0000 }, + { 0x0700, 0xa2c4, 0x0000 }, + { 0x8700, 0xa2c9, 0x3000 }, + { 0x8700, 0xa2c7, 0x2000 }, + { 0x0700, 0xa2c6, 0x0000 }, + { 0x0700, 0xa2c8, 0x0000 }, + { 0x8700, 0xa2cb, 0x2000 }, + { 0x0700, 0xa2ca, 0x0000 }, + { 0x0700, 0xa2cc, 0x0000 }, + { 0x8700, 0xa30d, 0x7000 }, + { 0x8700, 0xa2ed, 0x6000 }, + { 0x8700, 0xa2dd, 0x5000 }, + { 0x8700, 0xa2d5, 0x4000 }, + { 0x8700, 0xa2d1, 0x3000 }, + { 0x8700, 0xa2cf, 0x2000 }, + { 0x0700, 0xa2ce, 0x0000 }, + { 0x0700, 0xa2d0, 0x0000 }, + { 0x8700, 0xa2d3, 0x2000 }, + { 0x0700, 0xa2d2, 0x0000 }, + { 0x0700, 0xa2d4, 0x0000 }, + { 0x8700, 0xa2d9, 0x3000 }, + { 0x8700, 0xa2d7, 0x2000 }, + { 0x0700, 0xa2d6, 0x0000 }, + { 0x0700, 0xa2d8, 0x0000 }, + { 0x8700, 0xa2db, 0x2000 }, + { 0x0700, 0xa2da, 0x0000 }, + { 0x0700, 0xa2dc, 0x0000 }, + { 0x8700, 0xa2e5, 0x4000 }, + { 0x8700, 0xa2e1, 0x3000 }, + { 0x8700, 0xa2df, 0x2000 }, + { 0x0700, 0xa2de, 0x0000 }, + { 0x0700, 0xa2e0, 0x0000 }, + { 0x8700, 0xa2e3, 0x2000 }, + { 0x0700, 0xa2e2, 0x0000 }, + { 0x0700, 0xa2e4, 0x0000 }, + { 0x8700, 0xa2e9, 0x3000 }, + { 0x8700, 0xa2e7, 0x2000 }, + { 0x0700, 0xa2e6, 0x0000 }, + { 0x0700, 0xa2e8, 0x0000 }, + { 0x8700, 0xa2eb, 0x2000 }, + { 0x0700, 0xa2ea, 0x0000 }, + { 0x0700, 0xa2ec, 0x0000 }, + { 0x8700, 0xa2fd, 0x5000 }, + { 0x8700, 0xa2f5, 0x4000 }, + { 0x8700, 0xa2f1, 0x3000 }, + { 0x8700, 0xa2ef, 0x2000 }, + { 0x0700, 0xa2ee, 0x0000 }, + { 0x0700, 0xa2f0, 0x0000 }, + { 0x8700, 0xa2f3, 0x2000 }, + { 0x0700, 0xa2f2, 0x0000 }, + { 0x0700, 0xa2f4, 0x0000 }, + { 0x8700, 0xa2f9, 0x3000 }, + { 0x8700, 0xa2f7, 0x2000 }, + { 0x0700, 0xa2f6, 0x0000 }, + { 0x0700, 0xa2f8, 0x0000 }, + { 0x8700, 0xa2fb, 0x2000 }, + { 0x0700, 0xa2fa, 0x0000 }, + { 0x0700, 0xa2fc, 0x0000 }, + { 0x8700, 0xa305, 0x4000 }, + { 0x8700, 0xa301, 0x3000 }, + { 0x8700, 0xa2ff, 0x2000 }, + { 0x0700, 0xa2fe, 0x0000 }, + { 0x0700, 0xa300, 0x0000 }, + { 0x8700, 0xa303, 0x2000 }, + { 0x0700, 0xa302, 0x0000 }, + { 0x0700, 0xa304, 0x0000 }, + { 0x8700, 0xa309, 0x3000 }, + { 0x8700, 0xa307, 0x2000 }, + { 0x0700, 0xa306, 0x0000 }, + { 0x0700, 0xa308, 0x0000 }, + { 0x8700, 0xa30b, 0x2000 }, + { 0x0700, 0xa30a, 0x0000 }, + { 0x0700, 0xa30c, 0x0000 }, + { 0x8700, 0xa32d, 0x6000 }, + { 0x8700, 0xa31d, 0x5000 }, + { 0x8700, 0xa315, 0x4000 }, + { 0x8700, 0xa311, 0x3000 }, + { 0x8700, 0xa30f, 0x2000 }, + { 0x0700, 0xa30e, 0x0000 }, + { 0x0700, 0xa310, 0x0000 }, + { 0x8700, 0xa313, 0x2000 }, + { 0x0700, 0xa312, 0x0000 }, + { 0x0700, 0xa314, 0x0000 }, + { 0x8700, 0xa319, 0x3000 }, + { 0x8700, 0xa317, 0x2000 }, + { 0x0700, 0xa316, 0x0000 }, + { 0x0700, 0xa318, 0x0000 }, + { 0x8700, 0xa31b, 0x2000 }, + { 0x0700, 0xa31a, 0x0000 }, + { 0x0700, 0xa31c, 0x0000 }, + { 0x8700, 0xa325, 0x4000 }, + { 0x8700, 0xa321, 0x3000 }, + { 0x8700, 0xa31f, 0x2000 }, + { 0x0700, 0xa31e, 0x0000 }, + { 0x0700, 0xa320, 0x0000 }, + { 0x8700, 0xa323, 0x2000 }, + { 0x0700, 0xa322, 0x0000 }, + { 0x0700, 0xa324, 0x0000 }, + { 0x8700, 0xa329, 0x3000 }, + { 0x8700, 0xa327, 0x2000 }, + { 0x0700, 0xa326, 0x0000 }, + { 0x0700, 0xa328, 0x0000 }, + { 0x8700, 0xa32b, 0x2000 }, + { 0x0700, 0xa32a, 0x0000 }, + { 0x0700, 0xa32c, 0x0000 }, + { 0x8700, 0xa33d, 0x5000 }, + { 0x8700, 0xa335, 0x4000 }, + { 0x8700, 0xa331, 0x3000 }, + { 0x8700, 0xa32f, 0x2000 }, + { 0x0700, 0xa32e, 0x0000 }, + { 0x0700, 0xa330, 0x0000 }, + { 0x8700, 0xa333, 0x2000 }, + { 0x0700, 0xa332, 0x0000 }, + { 0x0700, 0xa334, 0x0000 }, + { 0x8700, 0xa339, 0x3000 }, + { 0x8700, 0xa337, 0x2000 }, + { 0x0700, 0xa336, 0x0000 }, + { 0x0700, 0xa338, 0x0000 }, + { 0x8700, 0xa33b, 0x2000 }, + { 0x0700, 0xa33a, 0x0000 }, + { 0x0700, 0xa33c, 0x0000 }, + { 0x8700, 0xa345, 0x4000 }, + { 0x8700, 0xa341, 0x3000 }, + { 0x8700, 0xa33f, 0x2000 }, + { 0x0700, 0xa33e, 0x0000 }, + { 0x0700, 0xa340, 0x0000 }, + { 0x8700, 0xa343, 0x2000 }, + { 0x0700, 0xa342, 0x0000 }, + { 0x0700, 0xa344, 0x0000 }, + { 0x8700, 0xa349, 0x3000 }, + { 0x8700, 0xa347, 0x2000 }, + { 0x0700, 0xa346, 0x0000 }, + { 0x0700, 0xa348, 0x0000 }, + { 0x8700, 0xa34b, 0x2000 }, + { 0x0700, 0xa34a, 0x0000 }, + { 0x0700, 0xa34c, 0x0000 }, + { 0x8700, 0xfc4d, 0xb000 }, + { 0x8700, 0xf97f, 0xa000 }, + { 0x8700, 0xa44d, 0x9000 }, + { 0x8700, 0xa3cd, 0x8000 }, + { 0x8700, 0xa38d, 0x7000 }, + { 0x8700, 0xa36d, 0x6000 }, + { 0x8700, 0xa35d, 0x5000 }, + { 0x8700, 0xa355, 0x4000 }, + { 0x8700, 0xa351, 0x3000 }, + { 0x8700, 0xa34f, 0x2000 }, + { 0x0700, 0xa34e, 0x0000 }, + { 0x0700, 0xa350, 0x0000 }, + { 0x8700, 0xa353, 0x2000 }, + { 0x0700, 0xa352, 0x0000 }, + { 0x0700, 0xa354, 0x0000 }, + { 0x8700, 0xa359, 0x3000 }, + { 0x8700, 0xa357, 0x2000 }, + { 0x0700, 0xa356, 0x0000 }, + { 0x0700, 0xa358, 0x0000 }, + { 0x8700, 0xa35b, 0x2000 }, + { 0x0700, 0xa35a, 0x0000 }, + { 0x0700, 0xa35c, 0x0000 }, + { 0x8700, 0xa365, 0x4000 }, + { 0x8700, 0xa361, 0x3000 }, + { 0x8700, 0xa35f, 0x2000 }, + { 0x0700, 0xa35e, 0x0000 }, + { 0x0700, 0xa360, 0x0000 }, + { 0x8700, 0xa363, 0x2000 }, + { 0x0700, 0xa362, 0x0000 }, + { 0x0700, 0xa364, 0x0000 }, + { 0x8700, 0xa369, 0x3000 }, + { 0x8700, 0xa367, 0x2000 }, + { 0x0700, 0xa366, 0x0000 }, + { 0x0700, 0xa368, 0x0000 }, + { 0x8700, 0xa36b, 0x2000 }, + { 0x0700, 0xa36a, 0x0000 }, + { 0x0700, 0xa36c, 0x0000 }, + { 0x8700, 0xa37d, 0x5000 }, + { 0x8700, 0xa375, 0x4000 }, + { 0x8700, 0xa371, 0x3000 }, + { 0x8700, 0xa36f, 0x2000 }, + { 0x0700, 0xa36e, 0x0000 }, + { 0x0700, 0xa370, 0x0000 }, + { 0x8700, 0xa373, 0x2000 }, + { 0x0700, 0xa372, 0x0000 }, + { 0x0700, 0xa374, 0x0000 }, + { 0x8700, 0xa379, 0x3000 }, + { 0x8700, 0xa377, 0x2000 }, + { 0x0700, 0xa376, 0x0000 }, + { 0x0700, 0xa378, 0x0000 }, + { 0x8700, 0xa37b, 0x2000 }, + { 0x0700, 0xa37a, 0x0000 }, + { 0x0700, 0xa37c, 0x0000 }, + { 0x8700, 0xa385, 0x4000 }, + { 0x8700, 0xa381, 0x3000 }, + { 0x8700, 0xa37f, 0x2000 }, + { 0x0700, 0xa37e, 0x0000 }, + { 0x0700, 0xa380, 0x0000 }, + { 0x8700, 0xa383, 0x2000 }, + { 0x0700, 0xa382, 0x0000 }, + { 0x0700, 0xa384, 0x0000 }, + { 0x8700, 0xa389, 0x3000 }, + { 0x8700, 0xa387, 0x2000 }, + { 0x0700, 0xa386, 0x0000 }, + { 0x0700, 0xa388, 0x0000 }, + { 0x8700, 0xa38b, 0x2000 }, + { 0x0700, 0xa38a, 0x0000 }, + { 0x0700, 0xa38c, 0x0000 }, + { 0x8700, 0xa3ad, 0x6000 }, + { 0x8700, 0xa39d, 0x5000 }, + { 0x8700, 0xa395, 0x4000 }, + { 0x8700, 0xa391, 0x3000 }, + { 0x8700, 0xa38f, 0x2000 }, + { 0x0700, 0xa38e, 0x0000 }, + { 0x0700, 0xa390, 0x0000 }, + { 0x8700, 0xa393, 0x2000 }, + { 0x0700, 0xa392, 0x0000 }, + { 0x0700, 0xa394, 0x0000 }, + { 0x8700, 0xa399, 0x3000 }, + { 0x8700, 0xa397, 0x2000 }, + { 0x0700, 0xa396, 0x0000 }, + { 0x0700, 0xa398, 0x0000 }, + { 0x8700, 0xa39b, 0x2000 }, + { 0x0700, 0xa39a, 0x0000 }, + { 0x0700, 0xa39c, 0x0000 }, + { 0x8700, 0xa3a5, 0x4000 }, + { 0x8700, 0xa3a1, 0x3000 }, + { 0x8700, 0xa39f, 0x2000 }, + { 0x0700, 0xa39e, 0x0000 }, + { 0x0700, 0xa3a0, 0x0000 }, + { 0x8700, 0xa3a3, 0x2000 }, + { 0x0700, 0xa3a2, 0x0000 }, + { 0x0700, 0xa3a4, 0x0000 }, + { 0x8700, 0xa3a9, 0x3000 }, + { 0x8700, 0xa3a7, 0x2000 }, + { 0x0700, 0xa3a6, 0x0000 }, + { 0x0700, 0xa3a8, 0x0000 }, + { 0x8700, 0xa3ab, 0x2000 }, + { 0x0700, 0xa3aa, 0x0000 }, + { 0x0700, 0xa3ac, 0x0000 }, + { 0x8700, 0xa3bd, 0x5000 }, + { 0x8700, 0xa3b5, 0x4000 }, + { 0x8700, 0xa3b1, 0x3000 }, + { 0x8700, 0xa3af, 0x2000 }, + { 0x0700, 0xa3ae, 0x0000 }, + { 0x0700, 0xa3b0, 0x0000 }, + { 0x8700, 0xa3b3, 0x2000 }, + { 0x0700, 0xa3b2, 0x0000 }, + { 0x0700, 0xa3b4, 0x0000 }, + { 0x8700, 0xa3b9, 0x3000 }, + { 0x8700, 0xa3b7, 0x2000 }, + { 0x0700, 0xa3b6, 0x0000 }, + { 0x0700, 0xa3b8, 0x0000 }, + { 0x8700, 0xa3bb, 0x2000 }, + { 0x0700, 0xa3ba, 0x0000 }, + { 0x0700, 0xa3bc, 0x0000 }, + { 0x8700, 0xa3c5, 0x4000 }, + { 0x8700, 0xa3c1, 0x3000 }, + { 0x8700, 0xa3bf, 0x2000 }, + { 0x0700, 0xa3be, 0x0000 }, + { 0x0700, 0xa3c0, 0x0000 }, + { 0x8700, 0xa3c3, 0x2000 }, + { 0x0700, 0xa3c2, 0x0000 }, + { 0x0700, 0xa3c4, 0x0000 }, + { 0x8700, 0xa3c9, 0x3000 }, + { 0x8700, 0xa3c7, 0x2000 }, + { 0x0700, 0xa3c6, 0x0000 }, + { 0x0700, 0xa3c8, 0x0000 }, + { 0x8700, 0xa3cb, 0x2000 }, + { 0x0700, 0xa3ca, 0x0000 }, + { 0x0700, 0xa3cc, 0x0000 }, + { 0x8700, 0xa40d, 0x7000 }, + { 0x8700, 0xa3ed, 0x6000 }, + { 0x8700, 0xa3dd, 0x5000 }, + { 0x8700, 0xa3d5, 0x4000 }, + { 0x8700, 0xa3d1, 0x3000 }, + { 0x8700, 0xa3cf, 0x2000 }, + { 0x0700, 0xa3ce, 0x0000 }, + { 0x0700, 0xa3d0, 0x0000 }, + { 0x8700, 0xa3d3, 0x2000 }, + { 0x0700, 0xa3d2, 0x0000 }, + { 0x0700, 0xa3d4, 0x0000 }, + { 0x8700, 0xa3d9, 0x3000 }, + { 0x8700, 0xa3d7, 0x2000 }, + { 0x0700, 0xa3d6, 0x0000 }, + { 0x0700, 0xa3d8, 0x0000 }, + { 0x8700, 0xa3db, 0x2000 }, + { 0x0700, 0xa3da, 0x0000 }, + { 0x0700, 0xa3dc, 0x0000 }, + { 0x8700, 0xa3e5, 0x4000 }, + { 0x8700, 0xa3e1, 0x3000 }, + { 0x8700, 0xa3df, 0x2000 }, + { 0x0700, 0xa3de, 0x0000 }, + { 0x0700, 0xa3e0, 0x0000 }, + { 0x8700, 0xa3e3, 0x2000 }, + { 0x0700, 0xa3e2, 0x0000 }, + { 0x0700, 0xa3e4, 0x0000 }, + { 0x8700, 0xa3e9, 0x3000 }, + { 0x8700, 0xa3e7, 0x2000 }, + { 0x0700, 0xa3e6, 0x0000 }, + { 0x0700, 0xa3e8, 0x0000 }, + { 0x8700, 0xa3eb, 0x2000 }, + { 0x0700, 0xa3ea, 0x0000 }, + { 0x0700, 0xa3ec, 0x0000 }, + { 0x8700, 0xa3fd, 0x5000 }, + { 0x8700, 0xa3f5, 0x4000 }, + { 0x8700, 0xa3f1, 0x3000 }, + { 0x8700, 0xa3ef, 0x2000 }, + { 0x0700, 0xa3ee, 0x0000 }, + { 0x0700, 0xa3f0, 0x0000 }, + { 0x8700, 0xa3f3, 0x2000 }, + { 0x0700, 0xa3f2, 0x0000 }, + { 0x0700, 0xa3f4, 0x0000 }, + { 0x8700, 0xa3f9, 0x3000 }, + { 0x8700, 0xa3f7, 0x2000 }, + { 0x0700, 0xa3f6, 0x0000 }, + { 0x0700, 0xa3f8, 0x0000 }, + { 0x8700, 0xa3fb, 0x2000 }, + { 0x0700, 0xa3fa, 0x0000 }, + { 0x0700, 0xa3fc, 0x0000 }, + { 0x8700, 0xa405, 0x4000 }, + { 0x8700, 0xa401, 0x3000 }, + { 0x8700, 0xa3ff, 0x2000 }, + { 0x0700, 0xa3fe, 0x0000 }, + { 0x0700, 0xa400, 0x0000 }, + { 0x8700, 0xa403, 0x2000 }, + { 0x0700, 0xa402, 0x0000 }, + { 0x0700, 0xa404, 0x0000 }, + { 0x8700, 0xa409, 0x3000 }, + { 0x8700, 0xa407, 0x2000 }, + { 0x0700, 0xa406, 0x0000 }, + { 0x0700, 0xa408, 0x0000 }, + { 0x8700, 0xa40b, 0x2000 }, + { 0x0700, 0xa40a, 0x0000 }, + { 0x0700, 0xa40c, 0x0000 }, + { 0x8700, 0xa42d, 0x6000 }, + { 0x8700, 0xa41d, 0x5000 }, + { 0x8700, 0xa415, 0x4000 }, + { 0x8700, 0xa411, 0x3000 }, + { 0x8700, 0xa40f, 0x2000 }, + { 0x0700, 0xa40e, 0x0000 }, + { 0x0700, 0xa410, 0x0000 }, + { 0x8700, 0xa413, 0x2000 }, + { 0x0700, 0xa412, 0x0000 }, + { 0x0700, 0xa414, 0x0000 }, + { 0x8700, 0xa419, 0x3000 }, + { 0x8700, 0xa417, 0x2000 }, + { 0x0700, 0xa416, 0x0000 }, + { 0x0700, 0xa418, 0x0000 }, + { 0x8700, 0xa41b, 0x2000 }, + { 0x0700, 0xa41a, 0x0000 }, + { 0x0700, 0xa41c, 0x0000 }, + { 0x8700, 0xa425, 0x4000 }, + { 0x8700, 0xa421, 0x3000 }, + { 0x8700, 0xa41f, 0x2000 }, + { 0x0700, 0xa41e, 0x0000 }, + { 0x0700, 0xa420, 0x0000 }, + { 0x8700, 0xa423, 0x2000 }, + { 0x0700, 0xa422, 0x0000 }, + { 0x0700, 0xa424, 0x0000 }, + { 0x8700, 0xa429, 0x3000 }, + { 0x8700, 0xa427, 0x2000 }, + { 0x0700, 0xa426, 0x0000 }, + { 0x0700, 0xa428, 0x0000 }, + { 0x8700, 0xa42b, 0x2000 }, + { 0x0700, 0xa42a, 0x0000 }, + { 0x0700, 0xa42c, 0x0000 }, + { 0x8700, 0xa43d, 0x5000 }, + { 0x8700, 0xa435, 0x4000 }, + { 0x8700, 0xa431, 0x3000 }, + { 0x8700, 0xa42f, 0x2000 }, + { 0x0700, 0xa42e, 0x0000 }, + { 0x0700, 0xa430, 0x0000 }, + { 0x8700, 0xa433, 0x2000 }, + { 0x0700, 0xa432, 0x0000 }, + { 0x0700, 0xa434, 0x0000 }, + { 0x8700, 0xa439, 0x3000 }, + { 0x8700, 0xa437, 0x2000 }, + { 0x0700, 0xa436, 0x0000 }, + { 0x0700, 0xa438, 0x0000 }, + { 0x8700, 0xa43b, 0x2000 }, + { 0x0700, 0xa43a, 0x0000 }, + { 0x0700, 0xa43c, 0x0000 }, + { 0x8700, 0xa445, 0x4000 }, + { 0x8700, 0xa441, 0x3000 }, + { 0x8700, 0xa43f, 0x2000 }, + { 0x0700, 0xa43e, 0x0000 }, + { 0x0700, 0xa440, 0x0000 }, + { 0x8700, 0xa443, 0x2000 }, + { 0x0700, 0xa442, 0x0000 }, + { 0x0700, 0xa444, 0x0000 }, + { 0x8700, 0xa449, 0x3000 }, + { 0x8700, 0xa447, 0x2000 }, + { 0x0700, 0xa446, 0x0000 }, + { 0x0700, 0xa448, 0x0000 }, + { 0x8700, 0xa44b, 0x2000 }, + { 0x0700, 0xa44a, 0x0000 }, + { 0x0700, 0xa44c, 0x0000 }, + { 0x8300, 0xf8ff, 0x8000 }, + { 0x9a00, 0xa490, 0x7000 }, + { 0x8700, 0xa46d, 0x6000 }, + { 0x8700, 0xa45d, 0x5000 }, + { 0x8700, 0xa455, 0x4000 }, + { 0x8700, 0xa451, 0x3000 }, + { 0x8700, 0xa44f, 0x2000 }, + { 0x0700, 0xa44e, 0x0000 }, + { 0x0700, 0xa450, 0x0000 }, + { 0x8700, 0xa453, 0x2000 }, + { 0x0700, 0xa452, 0x0000 }, + { 0x0700, 0xa454, 0x0000 }, + { 0x8700, 0xa459, 0x3000 }, + { 0x8700, 0xa457, 0x2000 }, + { 0x0700, 0xa456, 0x0000 }, + { 0x0700, 0xa458, 0x0000 }, + { 0x8700, 0xa45b, 0x2000 }, + { 0x0700, 0xa45a, 0x0000 }, + { 0x0700, 0xa45c, 0x0000 }, + { 0x8700, 0xa465, 0x4000 }, + { 0x8700, 0xa461, 0x3000 }, + { 0x8700, 0xa45f, 0x2000 }, + { 0x0700, 0xa45e, 0x0000 }, + { 0x0700, 0xa460, 0x0000 }, + { 0x8700, 0xa463, 0x2000 }, + { 0x0700, 0xa462, 0x0000 }, + { 0x0700, 0xa464, 0x0000 }, + { 0x8700, 0xa469, 0x3000 }, + { 0x8700, 0xa467, 0x2000 }, + { 0x0700, 0xa466, 0x0000 }, + { 0x0700, 0xa468, 0x0000 }, + { 0x8700, 0xa46b, 0x2000 }, + { 0x0700, 0xa46a, 0x0000 }, + { 0x0700, 0xa46c, 0x0000 }, + { 0x8700, 0xa47d, 0x5000 }, + { 0x8700, 0xa475, 0x4000 }, + { 0x8700, 0xa471, 0x3000 }, + { 0x8700, 0xa46f, 0x2000 }, + { 0x0700, 0xa46e, 0x0000 }, + { 0x0700, 0xa470, 0x0000 }, + { 0x8700, 0xa473, 0x2000 }, + { 0x0700, 0xa472, 0x0000 }, + { 0x0700, 0xa474, 0x0000 }, + { 0x8700, 0xa479, 0x3000 }, + { 0x8700, 0xa477, 0x2000 }, + { 0x0700, 0xa476, 0x0000 }, + { 0x0700, 0xa478, 0x0000 }, + { 0x8700, 0xa47b, 0x2000 }, + { 0x0700, 0xa47a, 0x0000 }, + { 0x0700, 0xa47c, 0x0000 }, + { 0x8700, 0xa485, 0x4000 }, + { 0x8700, 0xa481, 0x3000 }, + { 0x8700, 0xa47f, 0x2000 }, + { 0x0700, 0xa47e, 0x0000 }, + { 0x0700, 0xa480, 0x0000 }, + { 0x8700, 0xa483, 0x2000 }, + { 0x0700, 0xa482, 0x0000 }, + { 0x0700, 0xa484, 0x0000 }, + { 0x8700, 0xa489, 0x3000 }, + { 0x8700, 0xa487, 0x2000 }, + { 0x0700, 0xa486, 0x0000 }, + { 0x0700, 0xa488, 0x0000 }, + { 0x8700, 0xa48b, 0x2000 }, + { 0x0700, 0xa48a, 0x0000 }, + { 0x0700, 0xa48c, 0x0000 }, + { 0x9a00, 0xa4b0, 0x6000 }, + { 0x9a00, 0xa4a0, 0x5000 }, + { 0x9a00, 0xa498, 0x4000 }, + { 0x9a00, 0xa494, 0x3000 }, + { 0x9a00, 0xa492, 0x2000 }, + { 0x1a00, 0xa491, 0x0000 }, + { 0x1a00, 0xa493, 0x0000 }, + { 0x9a00, 0xa496, 0x2000 }, + { 0x1a00, 0xa495, 0x0000 }, + { 0x1a00, 0xa497, 0x0000 }, + { 0x9a00, 0xa49c, 0x3000 }, + { 0x9a00, 0xa49a, 0x2000 }, + { 0x1a00, 0xa499, 0x0000 }, + { 0x1a00, 0xa49b, 0x0000 }, + { 0x9a00, 0xa49e, 0x2000 }, + { 0x1a00, 0xa49d, 0x0000 }, + { 0x1a00, 0xa49f, 0x0000 }, + { 0x9a00, 0xa4a8, 0x4000 }, + { 0x9a00, 0xa4a4, 0x3000 }, + { 0x9a00, 0xa4a2, 0x2000 }, + { 0x1a00, 0xa4a1, 0x0000 }, + { 0x1a00, 0xa4a3, 0x0000 }, + { 0x9a00, 0xa4a6, 0x2000 }, + { 0x1a00, 0xa4a5, 0x0000 }, + { 0x1a00, 0xa4a7, 0x0000 }, + { 0x9a00, 0xa4ac, 0x3000 }, + { 0x9a00, 0xa4aa, 0x2000 }, + { 0x1a00, 0xa4a9, 0x0000 }, + { 0x1a00, 0xa4ab, 0x0000 }, + { 0x9a00, 0xa4ae, 0x2000 }, + { 0x1a00, 0xa4ad, 0x0000 }, + { 0x1a00, 0xa4af, 0x0000 }, + { 0x9a00, 0xa4c0, 0x5000 }, + { 0x9a00, 0xa4b8, 0x4000 }, + { 0x9a00, 0xa4b4, 0x3000 }, + { 0x9a00, 0xa4b2, 0x2000 }, + { 0x1a00, 0xa4b1, 0x0000 }, + { 0x1a00, 0xa4b3, 0x0000 }, + { 0x9a00, 0xa4b6, 0x2000 }, + { 0x1a00, 0xa4b5, 0x0000 }, + { 0x1a00, 0xa4b7, 0x0000 }, + { 0x9a00, 0xa4bc, 0x3000 }, + { 0x9a00, 0xa4ba, 0x2000 }, + { 0x1a00, 0xa4b9, 0x0000 }, + { 0x1a00, 0xa4bb, 0x0000 }, + { 0x9a00, 0xa4be, 0x2000 }, + { 0x1a00, 0xa4bd, 0x0000 }, + { 0x1a00, 0xa4bf, 0x0000 }, + { 0x8700, 0xd7a3, 0x4000 }, + { 0x9a00, 0xa4c4, 0x3000 }, + { 0x9a00, 0xa4c2, 0x2000 }, + { 0x1a00, 0xa4c1, 0x0000 }, + { 0x1a00, 0xa4c3, 0x0000 }, + { 0x9a00, 0xa4c6, 0x2000 }, + { 0x1a00, 0xa4c5, 0x0000 }, + { 0x0700, 0xac00, 0x0000 }, + { 0x8400, 0xdbff, 0x3000 }, + { 0x8400, 0xdb7f, 0x2000 }, + { 0x0400, 0xd800, 0x0000 }, + { 0x0400, 0xdb80, 0x0000 }, + { 0x8400, 0xdfff, 0x2000 }, + { 0x0400, 0xdc00, 0x0000 }, + { 0x0300, 0xe000, 0x0000 }, + { 0x8700, 0xf93f, 0x7000 }, + { 0x8700, 0xf91f, 0x6000 }, + { 0x8700, 0xf90f, 0x5000 }, + { 0x8700, 0xf907, 0x4000 }, + { 0x8700, 0xf903, 0x3000 }, + { 0x8700, 0xf901, 0x2000 }, + { 0x0700, 0xf900, 0x0000 }, + { 0x0700, 0xf902, 0x0000 }, + { 0x8700, 0xf905, 0x2000 }, + { 0x0700, 0xf904, 0x0000 }, + { 0x0700, 0xf906, 0x0000 }, + { 0x8700, 0xf90b, 0x3000 }, + { 0x8700, 0xf909, 0x2000 }, + { 0x0700, 0xf908, 0x0000 }, + { 0x0700, 0xf90a, 0x0000 }, + { 0x8700, 0xf90d, 0x2000 }, + { 0x0700, 0xf90c, 0x0000 }, + { 0x0700, 0xf90e, 0x0000 }, + { 0x8700, 0xf917, 0x4000 }, + { 0x8700, 0xf913, 0x3000 }, + { 0x8700, 0xf911, 0x2000 }, + { 0x0700, 0xf910, 0x0000 }, + { 0x0700, 0xf912, 0x0000 }, + { 0x8700, 0xf915, 0x2000 }, + { 0x0700, 0xf914, 0x0000 }, + { 0x0700, 0xf916, 0x0000 }, + { 0x8700, 0xf91b, 0x3000 }, + { 0x8700, 0xf919, 0x2000 }, + { 0x0700, 0xf918, 0x0000 }, + { 0x0700, 0xf91a, 0x0000 }, + { 0x8700, 0xf91d, 0x2000 }, + { 0x0700, 0xf91c, 0x0000 }, + { 0x0700, 0xf91e, 0x0000 }, + { 0x8700, 0xf92f, 0x5000 }, + { 0x8700, 0xf927, 0x4000 }, + { 0x8700, 0xf923, 0x3000 }, + { 0x8700, 0xf921, 0x2000 }, + { 0x0700, 0xf920, 0x0000 }, + { 0x0700, 0xf922, 0x0000 }, + { 0x8700, 0xf925, 0x2000 }, + { 0x0700, 0xf924, 0x0000 }, + { 0x0700, 0xf926, 0x0000 }, + { 0x8700, 0xf92b, 0x3000 }, + { 0x8700, 0xf929, 0x2000 }, + { 0x0700, 0xf928, 0x0000 }, + { 0x0700, 0xf92a, 0x0000 }, + { 0x8700, 0xf92d, 0x2000 }, + { 0x0700, 0xf92c, 0x0000 }, + { 0x0700, 0xf92e, 0x0000 }, + { 0x8700, 0xf937, 0x4000 }, + { 0x8700, 0xf933, 0x3000 }, + { 0x8700, 0xf931, 0x2000 }, + { 0x0700, 0xf930, 0x0000 }, + { 0x0700, 0xf932, 0x0000 }, + { 0x8700, 0xf935, 0x2000 }, + { 0x0700, 0xf934, 0x0000 }, + { 0x0700, 0xf936, 0x0000 }, + { 0x8700, 0xf93b, 0x3000 }, + { 0x8700, 0xf939, 0x2000 }, + { 0x0700, 0xf938, 0x0000 }, + { 0x0700, 0xf93a, 0x0000 }, + { 0x8700, 0xf93d, 0x2000 }, + { 0x0700, 0xf93c, 0x0000 }, + { 0x0700, 0xf93e, 0x0000 }, + { 0x8700, 0xf95f, 0x6000 }, + { 0x8700, 0xf94f, 0x5000 }, + { 0x8700, 0xf947, 0x4000 }, + { 0x8700, 0xf943, 0x3000 }, + { 0x8700, 0xf941, 0x2000 }, + { 0x0700, 0xf940, 0x0000 }, + { 0x0700, 0xf942, 0x0000 }, + { 0x8700, 0xf945, 0x2000 }, + { 0x0700, 0xf944, 0x0000 }, + { 0x0700, 0xf946, 0x0000 }, + { 0x8700, 0xf94b, 0x3000 }, + { 0x8700, 0xf949, 0x2000 }, + { 0x0700, 0xf948, 0x0000 }, + { 0x0700, 0xf94a, 0x0000 }, + { 0x8700, 0xf94d, 0x2000 }, + { 0x0700, 0xf94c, 0x0000 }, + { 0x0700, 0xf94e, 0x0000 }, + { 0x8700, 0xf957, 0x4000 }, + { 0x8700, 0xf953, 0x3000 }, + { 0x8700, 0xf951, 0x2000 }, + { 0x0700, 0xf950, 0x0000 }, + { 0x0700, 0xf952, 0x0000 }, + { 0x8700, 0xf955, 0x2000 }, + { 0x0700, 0xf954, 0x0000 }, + { 0x0700, 0xf956, 0x0000 }, + { 0x8700, 0xf95b, 0x3000 }, + { 0x8700, 0xf959, 0x2000 }, + { 0x0700, 0xf958, 0x0000 }, + { 0x0700, 0xf95a, 0x0000 }, + { 0x8700, 0xf95d, 0x2000 }, + { 0x0700, 0xf95c, 0x0000 }, + { 0x0700, 0xf95e, 0x0000 }, + { 0x8700, 0xf96f, 0x5000 }, + { 0x8700, 0xf967, 0x4000 }, + { 0x8700, 0xf963, 0x3000 }, + { 0x8700, 0xf961, 0x2000 }, + { 0x0700, 0xf960, 0x0000 }, + { 0x0700, 0xf962, 0x0000 }, + { 0x8700, 0xf965, 0x2000 }, + { 0x0700, 0xf964, 0x0000 }, + { 0x0700, 0xf966, 0x0000 }, + { 0x8700, 0xf96b, 0x3000 }, + { 0x8700, 0xf969, 0x2000 }, + { 0x0700, 0xf968, 0x0000 }, + { 0x0700, 0xf96a, 0x0000 }, + { 0x8700, 0xf96d, 0x2000 }, + { 0x0700, 0xf96c, 0x0000 }, + { 0x0700, 0xf96e, 0x0000 }, + { 0x8700, 0xf977, 0x4000 }, + { 0x8700, 0xf973, 0x3000 }, + { 0x8700, 0xf971, 0x2000 }, + { 0x0700, 0xf970, 0x0000 }, + { 0x0700, 0xf972, 0x0000 }, + { 0x8700, 0xf975, 0x2000 }, + { 0x0700, 0xf974, 0x0000 }, + { 0x0700, 0xf976, 0x0000 }, + { 0x8700, 0xf97b, 0x3000 }, + { 0x8700, 0xf979, 0x2000 }, + { 0x0700, 0xf978, 0x0000 }, + { 0x0700, 0xf97a, 0x0000 }, + { 0x8700, 0xf97d, 0x2000 }, + { 0x0700, 0xf97c, 0x0000 }, + { 0x0700, 0xf97e, 0x0000 }, + { 0x8700, 0xfb27, 0x9000 }, + { 0x8700, 0xf9ff, 0x8000 }, + { 0x8700, 0xf9bf, 0x7000 }, + { 0x8700, 0xf99f, 0x6000 }, + { 0x8700, 0xf98f, 0x5000 }, + { 0x8700, 0xf987, 0x4000 }, + { 0x8700, 0xf983, 0x3000 }, + { 0x8700, 0xf981, 0x2000 }, + { 0x0700, 0xf980, 0x0000 }, + { 0x0700, 0xf982, 0x0000 }, + { 0x8700, 0xf985, 0x2000 }, + { 0x0700, 0xf984, 0x0000 }, + { 0x0700, 0xf986, 0x0000 }, + { 0x8700, 0xf98b, 0x3000 }, + { 0x8700, 0xf989, 0x2000 }, + { 0x0700, 0xf988, 0x0000 }, + { 0x0700, 0xf98a, 0x0000 }, + { 0x8700, 0xf98d, 0x2000 }, + { 0x0700, 0xf98c, 0x0000 }, + { 0x0700, 0xf98e, 0x0000 }, + { 0x8700, 0xf997, 0x4000 }, + { 0x8700, 0xf993, 0x3000 }, + { 0x8700, 0xf991, 0x2000 }, + { 0x0700, 0xf990, 0x0000 }, + { 0x0700, 0xf992, 0x0000 }, + { 0x8700, 0xf995, 0x2000 }, + { 0x0700, 0xf994, 0x0000 }, + { 0x0700, 0xf996, 0x0000 }, + { 0x8700, 0xf99b, 0x3000 }, + { 0x8700, 0xf999, 0x2000 }, + { 0x0700, 0xf998, 0x0000 }, + { 0x0700, 0xf99a, 0x0000 }, + { 0x8700, 0xf99d, 0x2000 }, + { 0x0700, 0xf99c, 0x0000 }, + { 0x0700, 0xf99e, 0x0000 }, + { 0x8700, 0xf9af, 0x5000 }, + { 0x8700, 0xf9a7, 0x4000 }, + { 0x8700, 0xf9a3, 0x3000 }, + { 0x8700, 0xf9a1, 0x2000 }, + { 0x0700, 0xf9a0, 0x0000 }, + { 0x0700, 0xf9a2, 0x0000 }, + { 0x8700, 0xf9a5, 0x2000 }, + { 0x0700, 0xf9a4, 0x0000 }, + { 0x0700, 0xf9a6, 0x0000 }, + { 0x8700, 0xf9ab, 0x3000 }, + { 0x8700, 0xf9a9, 0x2000 }, + { 0x0700, 0xf9a8, 0x0000 }, + { 0x0700, 0xf9aa, 0x0000 }, + { 0x8700, 0xf9ad, 0x2000 }, + { 0x0700, 0xf9ac, 0x0000 }, + { 0x0700, 0xf9ae, 0x0000 }, + { 0x8700, 0xf9b7, 0x4000 }, + { 0x8700, 0xf9b3, 0x3000 }, + { 0x8700, 0xf9b1, 0x2000 }, + { 0x0700, 0xf9b0, 0x0000 }, + { 0x0700, 0xf9b2, 0x0000 }, + { 0x8700, 0xf9b5, 0x2000 }, + { 0x0700, 0xf9b4, 0x0000 }, + { 0x0700, 0xf9b6, 0x0000 }, + { 0x8700, 0xf9bb, 0x3000 }, + { 0x8700, 0xf9b9, 0x2000 }, + { 0x0700, 0xf9b8, 0x0000 }, + { 0x0700, 0xf9ba, 0x0000 }, + { 0x8700, 0xf9bd, 0x2000 }, + { 0x0700, 0xf9bc, 0x0000 }, + { 0x0700, 0xf9be, 0x0000 }, + { 0x8700, 0xf9df, 0x6000 }, + { 0x8700, 0xf9cf, 0x5000 }, + { 0x8700, 0xf9c7, 0x4000 }, + { 0x8700, 0xf9c3, 0x3000 }, + { 0x8700, 0xf9c1, 0x2000 }, + { 0x0700, 0xf9c0, 0x0000 }, + { 0x0700, 0xf9c2, 0x0000 }, + { 0x8700, 0xf9c5, 0x2000 }, + { 0x0700, 0xf9c4, 0x0000 }, + { 0x0700, 0xf9c6, 0x0000 }, + { 0x8700, 0xf9cb, 0x3000 }, + { 0x8700, 0xf9c9, 0x2000 }, + { 0x0700, 0xf9c8, 0x0000 }, + { 0x0700, 0xf9ca, 0x0000 }, + { 0x8700, 0xf9cd, 0x2000 }, + { 0x0700, 0xf9cc, 0x0000 }, + { 0x0700, 0xf9ce, 0x0000 }, + { 0x8700, 0xf9d7, 0x4000 }, + { 0x8700, 0xf9d3, 0x3000 }, + { 0x8700, 0xf9d1, 0x2000 }, + { 0x0700, 0xf9d0, 0x0000 }, + { 0x0700, 0xf9d2, 0x0000 }, + { 0x8700, 0xf9d5, 0x2000 }, + { 0x0700, 0xf9d4, 0x0000 }, + { 0x0700, 0xf9d6, 0x0000 }, + { 0x8700, 0xf9db, 0x3000 }, + { 0x8700, 0xf9d9, 0x2000 }, + { 0x0700, 0xf9d8, 0x0000 }, + { 0x0700, 0xf9da, 0x0000 }, + { 0x8700, 0xf9dd, 0x2000 }, + { 0x0700, 0xf9dc, 0x0000 }, + { 0x0700, 0xf9de, 0x0000 }, + { 0x8700, 0xf9ef, 0x5000 }, + { 0x8700, 0xf9e7, 0x4000 }, + { 0x8700, 0xf9e3, 0x3000 }, + { 0x8700, 0xf9e1, 0x2000 }, + { 0x0700, 0xf9e0, 0x0000 }, + { 0x0700, 0xf9e2, 0x0000 }, + { 0x8700, 0xf9e5, 0x2000 }, + { 0x0700, 0xf9e4, 0x0000 }, + { 0x0700, 0xf9e6, 0x0000 }, + { 0x8700, 0xf9eb, 0x3000 }, + { 0x8700, 0xf9e9, 0x2000 }, + { 0x0700, 0xf9e8, 0x0000 }, + { 0x0700, 0xf9ea, 0x0000 }, + { 0x8700, 0xf9ed, 0x2000 }, + { 0x0700, 0xf9ec, 0x0000 }, + { 0x0700, 0xf9ee, 0x0000 }, + { 0x8700, 0xf9f7, 0x4000 }, + { 0x8700, 0xf9f3, 0x3000 }, + { 0x8700, 0xf9f1, 0x2000 }, + { 0x0700, 0xf9f0, 0x0000 }, + { 0x0700, 0xf9f2, 0x0000 }, + { 0x8700, 0xf9f5, 0x2000 }, + { 0x0700, 0xf9f4, 0x0000 }, + { 0x0700, 0xf9f6, 0x0000 }, + { 0x8700, 0xf9fb, 0x3000 }, + { 0x8700, 0xf9f9, 0x2000 }, + { 0x0700, 0xf9f8, 0x0000 }, + { 0x0700, 0xf9fa, 0x0000 }, + { 0x8700, 0xf9fd, 0x2000 }, + { 0x0700, 0xf9fc, 0x0000 }, + { 0x0700, 0xf9fe, 0x0000 }, + { 0x8700, 0xfa41, 0x7000 }, + { 0x8700, 0xfa1f, 0x6000 }, + { 0x8700, 0xfa0f, 0x5000 }, + { 0x8700, 0xfa07, 0x4000 }, + { 0x8700, 0xfa03, 0x3000 }, + { 0x8700, 0xfa01, 0x2000 }, + { 0x0700, 0xfa00, 0x0000 }, + { 0x0700, 0xfa02, 0x0000 }, + { 0x8700, 0xfa05, 0x2000 }, + { 0x0700, 0xfa04, 0x0000 }, + { 0x0700, 0xfa06, 0x0000 }, + { 0x8700, 0xfa0b, 0x3000 }, + { 0x8700, 0xfa09, 0x2000 }, + { 0x0700, 0xfa08, 0x0000 }, + { 0x0700, 0xfa0a, 0x0000 }, + { 0x8700, 0xfa0d, 0x2000 }, + { 0x0700, 0xfa0c, 0x0000 }, + { 0x0700, 0xfa0e, 0x0000 }, + { 0x8700, 0xfa17, 0x4000 }, + { 0x8700, 0xfa13, 0x3000 }, + { 0x8700, 0xfa11, 0x2000 }, + { 0x0700, 0xfa10, 0x0000 }, + { 0x0700, 0xfa12, 0x0000 }, + { 0x8700, 0xfa15, 0x2000 }, + { 0x0700, 0xfa14, 0x0000 }, + { 0x0700, 0xfa16, 0x0000 }, + { 0x8700, 0xfa1b, 0x3000 }, + { 0x8700, 0xfa19, 0x2000 }, + { 0x0700, 0xfa18, 0x0000 }, + { 0x0700, 0xfa1a, 0x0000 }, + { 0x8700, 0xfa1d, 0x2000 }, + { 0x0700, 0xfa1c, 0x0000 }, + { 0x0700, 0xfa1e, 0x0000 }, + { 0x8700, 0xfa31, 0x5000 }, + { 0x8700, 0xfa27, 0x4000 }, + { 0x8700, 0xfa23, 0x3000 }, + { 0x8700, 0xfa21, 0x2000 }, + { 0x0700, 0xfa20, 0x0000 }, + { 0x0700, 0xfa22, 0x0000 }, + { 0x8700, 0xfa25, 0x2000 }, + { 0x0700, 0xfa24, 0x0000 }, + { 0x0700, 0xfa26, 0x0000 }, + { 0x8700, 0xfa2b, 0x3000 }, + { 0x8700, 0xfa29, 0x2000 }, + { 0x0700, 0xfa28, 0x0000 }, + { 0x0700, 0xfa2a, 0x0000 }, + { 0x8700, 0xfa2d, 0x2000 }, + { 0x0700, 0xfa2c, 0x0000 }, + { 0x0700, 0xfa30, 0x0000 }, + { 0x8700, 0xfa39, 0x4000 }, + { 0x8700, 0xfa35, 0x3000 }, + { 0x8700, 0xfa33, 0x2000 }, + { 0x0700, 0xfa32, 0x0000 }, + { 0x0700, 0xfa34, 0x0000 }, + { 0x8700, 0xfa37, 0x2000 }, + { 0x0700, 0xfa36, 0x0000 }, + { 0x0700, 0xfa38, 0x0000 }, + { 0x8700, 0xfa3d, 0x3000 }, + { 0x8700, 0xfa3b, 0x2000 }, + { 0x0700, 0xfa3a, 0x0000 }, + { 0x0700, 0xfa3c, 0x0000 }, + { 0x8700, 0xfa3f, 0x2000 }, + { 0x0700, 0xfa3e, 0x0000 }, + { 0x0700, 0xfa40, 0x0000 }, + { 0x8700, 0xfa61, 0x6000 }, + { 0x8700, 0xfa51, 0x5000 }, + { 0x8700, 0xfa49, 0x4000 }, + { 0x8700, 0xfa45, 0x3000 }, + { 0x8700, 0xfa43, 0x2000 }, + { 0x0700, 0xfa42, 0x0000 }, + { 0x0700, 0xfa44, 0x0000 }, + { 0x8700, 0xfa47, 0x2000 }, + { 0x0700, 0xfa46, 0x0000 }, + { 0x0700, 0xfa48, 0x0000 }, + { 0x8700, 0xfa4d, 0x3000 }, + { 0x8700, 0xfa4b, 0x2000 }, + { 0x0700, 0xfa4a, 0x0000 }, + { 0x0700, 0xfa4c, 0x0000 }, + { 0x8700, 0xfa4f, 0x2000 }, + { 0x0700, 0xfa4e, 0x0000 }, + { 0x0700, 0xfa50, 0x0000 }, + { 0x8700, 0xfa59, 0x4000 }, + { 0x8700, 0xfa55, 0x3000 }, + { 0x8700, 0xfa53, 0x2000 }, + { 0x0700, 0xfa52, 0x0000 }, + { 0x0700, 0xfa54, 0x0000 }, + { 0x8700, 0xfa57, 0x2000 }, + { 0x0700, 0xfa56, 0x0000 }, + { 0x0700, 0xfa58, 0x0000 }, + { 0x8700, 0xfa5d, 0x3000 }, + { 0x8700, 0xfa5b, 0x2000 }, + { 0x0700, 0xfa5a, 0x0000 }, + { 0x0700, 0xfa5c, 0x0000 }, + { 0x8700, 0xfa5f, 0x2000 }, + { 0x0700, 0xfa5e, 0x0000 }, + { 0x0700, 0xfa60, 0x0000 }, + { 0x8500, 0xfb06, 0x5000 }, + { 0x8700, 0xfa69, 0x4000 }, + { 0x8700, 0xfa65, 0x3000 }, + { 0x8700, 0xfa63, 0x2000 }, + { 0x0700, 0xfa62, 0x0000 }, + { 0x0700, 0xfa64, 0x0000 }, + { 0x8700, 0xfa67, 0x2000 }, + { 0x0700, 0xfa66, 0x0000 }, + { 0x0700, 0xfa68, 0x0000 }, + { 0x8500, 0xfb02, 0x3000 }, + { 0x8500, 0xfb00, 0x2000 }, + { 0x0700, 0xfa6a, 0x0000 }, + { 0x0500, 0xfb01, 0x0000 }, + { 0x8500, 0xfb04, 0x2000 }, + { 0x0500, 0xfb03, 0x0000 }, + { 0x0500, 0xfb05, 0x0000 }, + { 0x8700, 0xfb1f, 0x4000 }, + { 0x8500, 0xfb16, 0x3000 }, + { 0x8500, 0xfb14, 0x2000 }, + { 0x0500, 0xfb13, 0x0000 }, + { 0x0500, 0xfb15, 0x0000 }, + { 0x8700, 0xfb1d, 0x2000 }, + { 0x0500, 0xfb17, 0x0000 }, + { 0x0c00, 0xfb1e, 0x0000 }, + { 0x8700, 0xfb23, 0x3000 }, + { 0x8700, 0xfb21, 0x2000 }, + { 0x0700, 0xfb20, 0x0000 }, + { 0x0700, 0xfb22, 0x0000 }, + { 0x8700, 0xfb25, 0x2000 }, + { 0x0700, 0xfb24, 0x0000 }, + { 0x0700, 0xfb26, 0x0000 }, + { 0x8700, 0xfbac, 0x8000 }, + { 0x8700, 0xfb6c, 0x7000 }, + { 0x8700, 0xfb4c, 0x6000 }, + { 0x8700, 0xfb38, 0x5000 }, + { 0x8700, 0xfb2f, 0x4000 }, + { 0x8700, 0xfb2b, 0x3000 }, + { 0x9900, 0xfb29, 0x2000 }, + { 0x0700, 0xfb28, 0x0000 }, + { 0x0700, 0xfb2a, 0x0000 }, + { 0x8700, 0xfb2d, 0x2000 }, + { 0x0700, 0xfb2c, 0x0000 }, + { 0x0700, 0xfb2e, 0x0000 }, + { 0x8700, 0xfb33, 0x3000 }, + { 0x8700, 0xfb31, 0x2000 }, + { 0x0700, 0xfb30, 0x0000 }, + { 0x0700, 0xfb32, 0x0000 }, + { 0x8700, 0xfb35, 0x2000 }, + { 0x0700, 0xfb34, 0x0000 }, + { 0x0700, 0xfb36, 0x0000 }, + { 0x8700, 0xfb43, 0x4000 }, + { 0x8700, 0xfb3c, 0x3000 }, + { 0x8700, 0xfb3a, 0x2000 }, + { 0x0700, 0xfb39, 0x0000 }, + { 0x0700, 0xfb3b, 0x0000 }, + { 0x8700, 0xfb40, 0x2000 }, + { 0x0700, 0xfb3e, 0x0000 }, + { 0x0700, 0xfb41, 0x0000 }, + { 0x8700, 0xfb48, 0x3000 }, + { 0x8700, 0xfb46, 0x2000 }, + { 0x0700, 0xfb44, 0x0000 }, + { 0x0700, 0xfb47, 0x0000 }, + { 0x8700, 0xfb4a, 0x2000 }, + { 0x0700, 0xfb49, 0x0000 }, + { 0x0700, 0xfb4b, 0x0000 }, + { 0x8700, 0xfb5c, 0x5000 }, + { 0x8700, 0xfb54, 0x4000 }, + { 0x8700, 0xfb50, 0x3000 }, + { 0x8700, 0xfb4e, 0x2000 }, + { 0x0700, 0xfb4d, 0x0000 }, + { 0x0700, 0xfb4f, 0x0000 }, + { 0x8700, 0xfb52, 0x2000 }, + { 0x0700, 0xfb51, 0x0000 }, + { 0x0700, 0xfb53, 0x0000 }, + { 0x8700, 0xfb58, 0x3000 }, + { 0x8700, 0xfb56, 0x2000 }, + { 0x0700, 0xfb55, 0x0000 }, + { 0x0700, 0xfb57, 0x0000 }, + { 0x8700, 0xfb5a, 0x2000 }, + { 0x0700, 0xfb59, 0x0000 }, + { 0x0700, 0xfb5b, 0x0000 }, + { 0x8700, 0xfb64, 0x4000 }, + { 0x8700, 0xfb60, 0x3000 }, + { 0x8700, 0xfb5e, 0x2000 }, + { 0x0700, 0xfb5d, 0x0000 }, + { 0x0700, 0xfb5f, 0x0000 }, + { 0x8700, 0xfb62, 0x2000 }, + { 0x0700, 0xfb61, 0x0000 }, + { 0x0700, 0xfb63, 0x0000 }, + { 0x8700, 0xfb68, 0x3000 }, + { 0x8700, 0xfb66, 0x2000 }, + { 0x0700, 0xfb65, 0x0000 }, + { 0x0700, 0xfb67, 0x0000 }, + { 0x8700, 0xfb6a, 0x2000 }, + { 0x0700, 0xfb69, 0x0000 }, + { 0x0700, 0xfb6b, 0x0000 }, + { 0x8700, 0xfb8c, 0x6000 }, + { 0x8700, 0xfb7c, 0x5000 }, + { 0x8700, 0xfb74, 0x4000 }, + { 0x8700, 0xfb70, 0x3000 }, + { 0x8700, 0xfb6e, 0x2000 }, + { 0x0700, 0xfb6d, 0x0000 }, + { 0x0700, 0xfb6f, 0x0000 }, + { 0x8700, 0xfb72, 0x2000 }, + { 0x0700, 0xfb71, 0x0000 }, + { 0x0700, 0xfb73, 0x0000 }, + { 0x8700, 0xfb78, 0x3000 }, + { 0x8700, 0xfb76, 0x2000 }, + { 0x0700, 0xfb75, 0x0000 }, + { 0x0700, 0xfb77, 0x0000 }, + { 0x8700, 0xfb7a, 0x2000 }, + { 0x0700, 0xfb79, 0x0000 }, + { 0x0700, 0xfb7b, 0x0000 }, + { 0x8700, 0xfb84, 0x4000 }, + { 0x8700, 0xfb80, 0x3000 }, + { 0x8700, 0xfb7e, 0x2000 }, + { 0x0700, 0xfb7d, 0x0000 }, + { 0x0700, 0xfb7f, 0x0000 }, + { 0x8700, 0xfb82, 0x2000 }, + { 0x0700, 0xfb81, 0x0000 }, + { 0x0700, 0xfb83, 0x0000 }, + { 0x8700, 0xfb88, 0x3000 }, + { 0x8700, 0xfb86, 0x2000 }, + { 0x0700, 0xfb85, 0x0000 }, + { 0x0700, 0xfb87, 0x0000 }, + { 0x8700, 0xfb8a, 0x2000 }, + { 0x0700, 0xfb89, 0x0000 }, + { 0x0700, 0xfb8b, 0x0000 }, + { 0x8700, 0xfb9c, 0x5000 }, + { 0x8700, 0xfb94, 0x4000 }, + { 0x8700, 0xfb90, 0x3000 }, + { 0x8700, 0xfb8e, 0x2000 }, + { 0x0700, 0xfb8d, 0x0000 }, + { 0x0700, 0xfb8f, 0x0000 }, + { 0x8700, 0xfb92, 0x2000 }, + { 0x0700, 0xfb91, 0x0000 }, + { 0x0700, 0xfb93, 0x0000 }, + { 0x8700, 0xfb98, 0x3000 }, + { 0x8700, 0xfb96, 0x2000 }, + { 0x0700, 0xfb95, 0x0000 }, + { 0x0700, 0xfb97, 0x0000 }, + { 0x8700, 0xfb9a, 0x2000 }, + { 0x0700, 0xfb99, 0x0000 }, + { 0x0700, 0xfb9b, 0x0000 }, + { 0x8700, 0xfba4, 0x4000 }, + { 0x8700, 0xfba0, 0x3000 }, + { 0x8700, 0xfb9e, 0x2000 }, + { 0x0700, 0xfb9d, 0x0000 }, + { 0x0700, 0xfb9f, 0x0000 }, + { 0x8700, 0xfba2, 0x2000 }, + { 0x0700, 0xfba1, 0x0000 }, + { 0x0700, 0xfba3, 0x0000 }, + { 0x8700, 0xfba8, 0x3000 }, + { 0x8700, 0xfba6, 0x2000 }, + { 0x0700, 0xfba5, 0x0000 }, + { 0x0700, 0xfba7, 0x0000 }, + { 0x8700, 0xfbaa, 0x2000 }, + { 0x0700, 0xfba9, 0x0000 }, + { 0x0700, 0xfbab, 0x0000 }, + { 0x8700, 0xfc0d, 0x7000 }, + { 0x8700, 0xfbed, 0x6000 }, + { 0x8700, 0xfbdd, 0x5000 }, + { 0x8700, 0xfbd5, 0x4000 }, + { 0x8700, 0xfbb0, 0x3000 }, + { 0x8700, 0xfbae, 0x2000 }, + { 0x0700, 0xfbad, 0x0000 }, + { 0x0700, 0xfbaf, 0x0000 }, + { 0x8700, 0xfbd3, 0x2000 }, + { 0x0700, 0xfbb1, 0x0000 }, + { 0x0700, 0xfbd4, 0x0000 }, + { 0x8700, 0xfbd9, 0x3000 }, + { 0x8700, 0xfbd7, 0x2000 }, + { 0x0700, 0xfbd6, 0x0000 }, + { 0x0700, 0xfbd8, 0x0000 }, + { 0x8700, 0xfbdb, 0x2000 }, + { 0x0700, 0xfbda, 0x0000 }, + { 0x0700, 0xfbdc, 0x0000 }, + { 0x8700, 0xfbe5, 0x4000 }, + { 0x8700, 0xfbe1, 0x3000 }, + { 0x8700, 0xfbdf, 0x2000 }, + { 0x0700, 0xfbde, 0x0000 }, + { 0x0700, 0xfbe0, 0x0000 }, + { 0x8700, 0xfbe3, 0x2000 }, + { 0x0700, 0xfbe2, 0x0000 }, + { 0x0700, 0xfbe4, 0x0000 }, + { 0x8700, 0xfbe9, 0x3000 }, + { 0x8700, 0xfbe7, 0x2000 }, + { 0x0700, 0xfbe6, 0x0000 }, + { 0x0700, 0xfbe8, 0x0000 }, + { 0x8700, 0xfbeb, 0x2000 }, + { 0x0700, 0xfbea, 0x0000 }, + { 0x0700, 0xfbec, 0x0000 }, + { 0x8700, 0xfbfd, 0x5000 }, + { 0x8700, 0xfbf5, 0x4000 }, + { 0x8700, 0xfbf1, 0x3000 }, + { 0x8700, 0xfbef, 0x2000 }, + { 0x0700, 0xfbee, 0x0000 }, + { 0x0700, 0xfbf0, 0x0000 }, + { 0x8700, 0xfbf3, 0x2000 }, + { 0x0700, 0xfbf2, 0x0000 }, + { 0x0700, 0xfbf4, 0x0000 }, + { 0x8700, 0xfbf9, 0x3000 }, + { 0x8700, 0xfbf7, 0x2000 }, + { 0x0700, 0xfbf6, 0x0000 }, + { 0x0700, 0xfbf8, 0x0000 }, + { 0x8700, 0xfbfb, 0x2000 }, + { 0x0700, 0xfbfa, 0x0000 }, + { 0x0700, 0xfbfc, 0x0000 }, + { 0x8700, 0xfc05, 0x4000 }, + { 0x8700, 0xfc01, 0x3000 }, + { 0x8700, 0xfbff, 0x2000 }, + { 0x0700, 0xfbfe, 0x0000 }, + { 0x0700, 0xfc00, 0x0000 }, + { 0x8700, 0xfc03, 0x2000 }, + { 0x0700, 0xfc02, 0x0000 }, + { 0x0700, 0xfc04, 0x0000 }, + { 0x8700, 0xfc09, 0x3000 }, + { 0x8700, 0xfc07, 0x2000 }, + { 0x0700, 0xfc06, 0x0000 }, + { 0x0700, 0xfc08, 0x0000 }, + { 0x8700, 0xfc0b, 0x2000 }, + { 0x0700, 0xfc0a, 0x0000 }, + { 0x0700, 0xfc0c, 0x0000 }, + { 0x8700, 0xfc2d, 0x6000 }, + { 0x8700, 0xfc1d, 0x5000 }, + { 0x8700, 0xfc15, 0x4000 }, + { 0x8700, 0xfc11, 0x3000 }, + { 0x8700, 0xfc0f, 0x2000 }, + { 0x0700, 0xfc0e, 0x0000 }, + { 0x0700, 0xfc10, 0x0000 }, + { 0x8700, 0xfc13, 0x2000 }, + { 0x0700, 0xfc12, 0x0000 }, + { 0x0700, 0xfc14, 0x0000 }, + { 0x8700, 0xfc19, 0x3000 }, + { 0x8700, 0xfc17, 0x2000 }, + { 0x0700, 0xfc16, 0x0000 }, + { 0x0700, 0xfc18, 0x0000 }, + { 0x8700, 0xfc1b, 0x2000 }, + { 0x0700, 0xfc1a, 0x0000 }, + { 0x0700, 0xfc1c, 0x0000 }, + { 0x8700, 0xfc25, 0x4000 }, + { 0x8700, 0xfc21, 0x3000 }, + { 0x8700, 0xfc1f, 0x2000 }, + { 0x0700, 0xfc1e, 0x0000 }, + { 0x0700, 0xfc20, 0x0000 }, + { 0x8700, 0xfc23, 0x2000 }, + { 0x0700, 0xfc22, 0x0000 }, + { 0x0700, 0xfc24, 0x0000 }, + { 0x8700, 0xfc29, 0x3000 }, + { 0x8700, 0xfc27, 0x2000 }, + { 0x0700, 0xfc26, 0x0000 }, + { 0x0700, 0xfc28, 0x0000 }, + { 0x8700, 0xfc2b, 0x2000 }, + { 0x0700, 0xfc2a, 0x0000 }, + { 0x0700, 0xfc2c, 0x0000 }, + { 0x8700, 0xfc3d, 0x5000 }, + { 0x8700, 0xfc35, 0x4000 }, + { 0x8700, 0xfc31, 0x3000 }, + { 0x8700, 0xfc2f, 0x2000 }, + { 0x0700, 0xfc2e, 0x0000 }, + { 0x0700, 0xfc30, 0x0000 }, + { 0x8700, 0xfc33, 0x2000 }, + { 0x0700, 0xfc32, 0x0000 }, + { 0x0700, 0xfc34, 0x0000 }, + { 0x8700, 0xfc39, 0x3000 }, + { 0x8700, 0xfc37, 0x2000 }, + { 0x0700, 0xfc36, 0x0000 }, + { 0x0700, 0xfc38, 0x0000 }, + { 0x8700, 0xfc3b, 0x2000 }, + { 0x0700, 0xfc3a, 0x0000 }, + { 0x0700, 0xfc3c, 0x0000 }, + { 0x8700, 0xfc45, 0x4000 }, + { 0x8700, 0xfc41, 0x3000 }, + { 0x8700, 0xfc3f, 0x2000 }, + { 0x0700, 0xfc3e, 0x0000 }, + { 0x0700, 0xfc40, 0x0000 }, + { 0x8700, 0xfc43, 0x2000 }, + { 0x0700, 0xfc42, 0x0000 }, + { 0x0700, 0xfc44, 0x0000 }, + { 0x8700, 0xfc49, 0x3000 }, + { 0x8700, 0xfc47, 0x2000 }, + { 0x0700, 0xfc46, 0x0000 }, + { 0x0700, 0xfc48, 0x0000 }, + { 0x8700, 0xfc4b, 0x2000 }, + { 0x0700, 0xfc4a, 0x0000 }, + { 0x0700, 0xfc4c, 0x0000 }, + { 0x8700, 0xfeac, 0xa000 }, + { 0x8700, 0xfd5d, 0x9000 }, + { 0x8700, 0xfccd, 0x8000 }, + { 0x8700, 0xfc8d, 0x7000 }, + { 0x8700, 0xfc6d, 0x6000 }, + { 0x8700, 0xfc5d, 0x5000 }, + { 0x8700, 0xfc55, 0x4000 }, + { 0x8700, 0xfc51, 0x3000 }, + { 0x8700, 0xfc4f, 0x2000 }, + { 0x0700, 0xfc4e, 0x0000 }, + { 0x0700, 0xfc50, 0x0000 }, + { 0x8700, 0xfc53, 0x2000 }, + { 0x0700, 0xfc52, 0x0000 }, + { 0x0700, 0xfc54, 0x0000 }, + { 0x8700, 0xfc59, 0x3000 }, + { 0x8700, 0xfc57, 0x2000 }, + { 0x0700, 0xfc56, 0x0000 }, + { 0x0700, 0xfc58, 0x0000 }, + { 0x8700, 0xfc5b, 0x2000 }, + { 0x0700, 0xfc5a, 0x0000 }, + { 0x0700, 0xfc5c, 0x0000 }, + { 0x8700, 0xfc65, 0x4000 }, + { 0x8700, 0xfc61, 0x3000 }, + { 0x8700, 0xfc5f, 0x2000 }, + { 0x0700, 0xfc5e, 0x0000 }, + { 0x0700, 0xfc60, 0x0000 }, + { 0x8700, 0xfc63, 0x2000 }, + { 0x0700, 0xfc62, 0x0000 }, + { 0x0700, 0xfc64, 0x0000 }, + { 0x8700, 0xfc69, 0x3000 }, + { 0x8700, 0xfc67, 0x2000 }, + { 0x0700, 0xfc66, 0x0000 }, + { 0x0700, 0xfc68, 0x0000 }, + { 0x8700, 0xfc6b, 0x2000 }, + { 0x0700, 0xfc6a, 0x0000 }, + { 0x0700, 0xfc6c, 0x0000 }, + { 0x8700, 0xfc7d, 0x5000 }, + { 0x8700, 0xfc75, 0x4000 }, + { 0x8700, 0xfc71, 0x3000 }, + { 0x8700, 0xfc6f, 0x2000 }, + { 0x0700, 0xfc6e, 0x0000 }, + { 0x0700, 0xfc70, 0x0000 }, + { 0x8700, 0xfc73, 0x2000 }, + { 0x0700, 0xfc72, 0x0000 }, + { 0x0700, 0xfc74, 0x0000 }, + { 0x8700, 0xfc79, 0x3000 }, + { 0x8700, 0xfc77, 0x2000 }, + { 0x0700, 0xfc76, 0x0000 }, + { 0x0700, 0xfc78, 0x0000 }, + { 0x8700, 0xfc7b, 0x2000 }, + { 0x0700, 0xfc7a, 0x0000 }, + { 0x0700, 0xfc7c, 0x0000 }, + { 0x8700, 0xfc85, 0x4000 }, + { 0x8700, 0xfc81, 0x3000 }, + { 0x8700, 0xfc7f, 0x2000 }, + { 0x0700, 0xfc7e, 0x0000 }, + { 0x0700, 0xfc80, 0x0000 }, + { 0x8700, 0xfc83, 0x2000 }, + { 0x0700, 0xfc82, 0x0000 }, + { 0x0700, 0xfc84, 0x0000 }, + { 0x8700, 0xfc89, 0x3000 }, + { 0x8700, 0xfc87, 0x2000 }, + { 0x0700, 0xfc86, 0x0000 }, + { 0x0700, 0xfc88, 0x0000 }, + { 0x8700, 0xfc8b, 0x2000 }, + { 0x0700, 0xfc8a, 0x0000 }, + { 0x0700, 0xfc8c, 0x0000 }, + { 0x8700, 0xfcad, 0x6000 }, + { 0x8700, 0xfc9d, 0x5000 }, + { 0x8700, 0xfc95, 0x4000 }, + { 0x8700, 0xfc91, 0x3000 }, + { 0x8700, 0xfc8f, 0x2000 }, + { 0x0700, 0xfc8e, 0x0000 }, + { 0x0700, 0xfc90, 0x0000 }, + { 0x8700, 0xfc93, 0x2000 }, + { 0x0700, 0xfc92, 0x0000 }, + { 0x0700, 0xfc94, 0x0000 }, + { 0x8700, 0xfc99, 0x3000 }, + { 0x8700, 0xfc97, 0x2000 }, + { 0x0700, 0xfc96, 0x0000 }, + { 0x0700, 0xfc98, 0x0000 }, + { 0x8700, 0xfc9b, 0x2000 }, + { 0x0700, 0xfc9a, 0x0000 }, + { 0x0700, 0xfc9c, 0x0000 }, + { 0x8700, 0xfca5, 0x4000 }, + { 0x8700, 0xfca1, 0x3000 }, + { 0x8700, 0xfc9f, 0x2000 }, + { 0x0700, 0xfc9e, 0x0000 }, + { 0x0700, 0xfca0, 0x0000 }, + { 0x8700, 0xfca3, 0x2000 }, + { 0x0700, 0xfca2, 0x0000 }, + { 0x0700, 0xfca4, 0x0000 }, + { 0x8700, 0xfca9, 0x3000 }, + { 0x8700, 0xfca7, 0x2000 }, + { 0x0700, 0xfca6, 0x0000 }, + { 0x0700, 0xfca8, 0x0000 }, + { 0x8700, 0xfcab, 0x2000 }, + { 0x0700, 0xfcaa, 0x0000 }, + { 0x0700, 0xfcac, 0x0000 }, + { 0x8700, 0xfcbd, 0x5000 }, + { 0x8700, 0xfcb5, 0x4000 }, + { 0x8700, 0xfcb1, 0x3000 }, + { 0x8700, 0xfcaf, 0x2000 }, + { 0x0700, 0xfcae, 0x0000 }, + { 0x0700, 0xfcb0, 0x0000 }, + { 0x8700, 0xfcb3, 0x2000 }, + { 0x0700, 0xfcb2, 0x0000 }, + { 0x0700, 0xfcb4, 0x0000 }, + { 0x8700, 0xfcb9, 0x3000 }, + { 0x8700, 0xfcb7, 0x2000 }, + { 0x0700, 0xfcb6, 0x0000 }, + { 0x0700, 0xfcb8, 0x0000 }, + { 0x8700, 0xfcbb, 0x2000 }, + { 0x0700, 0xfcba, 0x0000 }, + { 0x0700, 0xfcbc, 0x0000 }, + { 0x8700, 0xfcc5, 0x4000 }, + { 0x8700, 0xfcc1, 0x3000 }, + { 0x8700, 0xfcbf, 0x2000 }, + { 0x0700, 0xfcbe, 0x0000 }, + { 0x0700, 0xfcc0, 0x0000 }, + { 0x8700, 0xfcc3, 0x2000 }, + { 0x0700, 0xfcc2, 0x0000 }, + { 0x0700, 0xfcc4, 0x0000 }, + { 0x8700, 0xfcc9, 0x3000 }, + { 0x8700, 0xfcc7, 0x2000 }, + { 0x0700, 0xfcc6, 0x0000 }, + { 0x0700, 0xfcc8, 0x0000 }, + { 0x8700, 0xfccb, 0x2000 }, + { 0x0700, 0xfcca, 0x0000 }, + { 0x0700, 0xfccc, 0x0000 }, + { 0x8700, 0xfd0d, 0x7000 }, + { 0x8700, 0xfced, 0x6000 }, + { 0x8700, 0xfcdd, 0x5000 }, + { 0x8700, 0xfcd5, 0x4000 }, + { 0x8700, 0xfcd1, 0x3000 }, + { 0x8700, 0xfccf, 0x2000 }, + { 0x0700, 0xfcce, 0x0000 }, + { 0x0700, 0xfcd0, 0x0000 }, + { 0x8700, 0xfcd3, 0x2000 }, + { 0x0700, 0xfcd2, 0x0000 }, + { 0x0700, 0xfcd4, 0x0000 }, + { 0x8700, 0xfcd9, 0x3000 }, + { 0x8700, 0xfcd7, 0x2000 }, + { 0x0700, 0xfcd6, 0x0000 }, + { 0x0700, 0xfcd8, 0x0000 }, + { 0x8700, 0xfcdb, 0x2000 }, + { 0x0700, 0xfcda, 0x0000 }, + { 0x0700, 0xfcdc, 0x0000 }, + { 0x8700, 0xfce5, 0x4000 }, + { 0x8700, 0xfce1, 0x3000 }, + { 0x8700, 0xfcdf, 0x2000 }, + { 0x0700, 0xfcde, 0x0000 }, + { 0x0700, 0xfce0, 0x0000 }, + { 0x8700, 0xfce3, 0x2000 }, + { 0x0700, 0xfce2, 0x0000 }, + { 0x0700, 0xfce4, 0x0000 }, + { 0x8700, 0xfce9, 0x3000 }, + { 0x8700, 0xfce7, 0x2000 }, + { 0x0700, 0xfce6, 0x0000 }, + { 0x0700, 0xfce8, 0x0000 }, + { 0x8700, 0xfceb, 0x2000 }, + { 0x0700, 0xfcea, 0x0000 }, + { 0x0700, 0xfcec, 0x0000 }, + { 0x8700, 0xfcfd, 0x5000 }, + { 0x8700, 0xfcf5, 0x4000 }, + { 0x8700, 0xfcf1, 0x3000 }, + { 0x8700, 0xfcef, 0x2000 }, + { 0x0700, 0xfcee, 0x0000 }, + { 0x0700, 0xfcf0, 0x0000 }, + { 0x8700, 0xfcf3, 0x2000 }, + { 0x0700, 0xfcf2, 0x0000 }, + { 0x0700, 0xfcf4, 0x0000 }, + { 0x8700, 0xfcf9, 0x3000 }, + { 0x8700, 0xfcf7, 0x2000 }, + { 0x0700, 0xfcf6, 0x0000 }, + { 0x0700, 0xfcf8, 0x0000 }, + { 0x8700, 0xfcfb, 0x2000 }, + { 0x0700, 0xfcfa, 0x0000 }, + { 0x0700, 0xfcfc, 0x0000 }, + { 0x8700, 0xfd05, 0x4000 }, + { 0x8700, 0xfd01, 0x3000 }, + { 0x8700, 0xfcff, 0x2000 }, + { 0x0700, 0xfcfe, 0x0000 }, + { 0x0700, 0xfd00, 0x0000 }, + { 0x8700, 0xfd03, 0x2000 }, + { 0x0700, 0xfd02, 0x0000 }, + { 0x0700, 0xfd04, 0x0000 }, + { 0x8700, 0xfd09, 0x3000 }, + { 0x8700, 0xfd07, 0x2000 }, + { 0x0700, 0xfd06, 0x0000 }, + { 0x0700, 0xfd08, 0x0000 }, + { 0x8700, 0xfd0b, 0x2000 }, + { 0x0700, 0xfd0a, 0x0000 }, + { 0x0700, 0xfd0c, 0x0000 }, + { 0x8700, 0xfd2d, 0x6000 }, + { 0x8700, 0xfd1d, 0x5000 }, + { 0x8700, 0xfd15, 0x4000 }, + { 0x8700, 0xfd11, 0x3000 }, + { 0x8700, 0xfd0f, 0x2000 }, + { 0x0700, 0xfd0e, 0x0000 }, + { 0x0700, 0xfd10, 0x0000 }, + { 0x8700, 0xfd13, 0x2000 }, + { 0x0700, 0xfd12, 0x0000 }, + { 0x0700, 0xfd14, 0x0000 }, + { 0x8700, 0xfd19, 0x3000 }, + { 0x8700, 0xfd17, 0x2000 }, + { 0x0700, 0xfd16, 0x0000 }, + { 0x0700, 0xfd18, 0x0000 }, + { 0x8700, 0xfd1b, 0x2000 }, + { 0x0700, 0xfd1a, 0x0000 }, + { 0x0700, 0xfd1c, 0x0000 }, + { 0x8700, 0xfd25, 0x4000 }, + { 0x8700, 0xfd21, 0x3000 }, + { 0x8700, 0xfd1f, 0x2000 }, + { 0x0700, 0xfd1e, 0x0000 }, + { 0x0700, 0xfd20, 0x0000 }, + { 0x8700, 0xfd23, 0x2000 }, + { 0x0700, 0xfd22, 0x0000 }, + { 0x0700, 0xfd24, 0x0000 }, + { 0x8700, 0xfd29, 0x3000 }, + { 0x8700, 0xfd27, 0x2000 }, + { 0x0700, 0xfd26, 0x0000 }, + { 0x0700, 0xfd28, 0x0000 }, + { 0x8700, 0xfd2b, 0x2000 }, + { 0x0700, 0xfd2a, 0x0000 }, + { 0x0700, 0xfd2c, 0x0000 }, + { 0x8700, 0xfd3d, 0x5000 }, + { 0x8700, 0xfd35, 0x4000 }, + { 0x8700, 0xfd31, 0x3000 }, + { 0x8700, 0xfd2f, 0x2000 }, + { 0x0700, 0xfd2e, 0x0000 }, + { 0x0700, 0xfd30, 0x0000 }, + { 0x8700, 0xfd33, 0x2000 }, + { 0x0700, 0xfd32, 0x0000 }, + { 0x0700, 0xfd34, 0x0000 }, + { 0x8700, 0xfd39, 0x3000 }, + { 0x8700, 0xfd37, 0x2000 }, + { 0x0700, 0xfd36, 0x0000 }, + { 0x0700, 0xfd38, 0x0000 }, + { 0x8700, 0xfd3b, 0x2000 }, + { 0x0700, 0xfd3a, 0x0000 }, + { 0x0700, 0xfd3c, 0x0000 }, + { 0x8700, 0xfd55, 0x4000 }, + { 0x8700, 0xfd51, 0x3000 }, + { 0x9200, 0xfd3f, 0x2000 }, + { 0x1600, 0xfd3e, 0x0000 }, + { 0x0700, 0xfd50, 0x0000 }, + { 0x8700, 0xfd53, 0x2000 }, + { 0x0700, 0xfd52, 0x0000 }, + { 0x0700, 0xfd54, 0x0000 }, + { 0x8700, 0xfd59, 0x3000 }, + { 0x8700, 0xfd57, 0x2000 }, + { 0x0700, 0xfd56, 0x0000 }, + { 0x0700, 0xfd58, 0x0000 }, + { 0x8700, 0xfd5b, 0x2000 }, + { 0x0700, 0xfd5a, 0x0000 }, + { 0x0700, 0xfd5c, 0x0000 }, + { 0x8c00, 0xfe09, 0x8000 }, + { 0x8700, 0xfd9f, 0x7000 }, + { 0x8700, 0xfd7d, 0x6000 }, + { 0x8700, 0xfd6d, 0x5000 }, + { 0x8700, 0xfd65, 0x4000 }, + { 0x8700, 0xfd61, 0x3000 }, + { 0x8700, 0xfd5f, 0x2000 }, + { 0x0700, 0xfd5e, 0x0000 }, + { 0x0700, 0xfd60, 0x0000 }, + { 0x8700, 0xfd63, 0x2000 }, + { 0x0700, 0xfd62, 0x0000 }, + { 0x0700, 0xfd64, 0x0000 }, + { 0x8700, 0xfd69, 0x3000 }, + { 0x8700, 0xfd67, 0x2000 }, + { 0x0700, 0xfd66, 0x0000 }, + { 0x0700, 0xfd68, 0x0000 }, + { 0x8700, 0xfd6b, 0x2000 }, + { 0x0700, 0xfd6a, 0x0000 }, + { 0x0700, 0xfd6c, 0x0000 }, + { 0x8700, 0xfd75, 0x4000 }, + { 0x8700, 0xfd71, 0x3000 }, + { 0x8700, 0xfd6f, 0x2000 }, + { 0x0700, 0xfd6e, 0x0000 }, + { 0x0700, 0xfd70, 0x0000 }, + { 0x8700, 0xfd73, 0x2000 }, + { 0x0700, 0xfd72, 0x0000 }, + { 0x0700, 0xfd74, 0x0000 }, + { 0x8700, 0xfd79, 0x3000 }, + { 0x8700, 0xfd77, 0x2000 }, + { 0x0700, 0xfd76, 0x0000 }, + { 0x0700, 0xfd78, 0x0000 }, + { 0x8700, 0xfd7b, 0x2000 }, + { 0x0700, 0xfd7a, 0x0000 }, + { 0x0700, 0xfd7c, 0x0000 }, + { 0x8700, 0xfd8d, 0x5000 }, + { 0x8700, 0xfd85, 0x4000 }, + { 0x8700, 0xfd81, 0x3000 }, + { 0x8700, 0xfd7f, 0x2000 }, + { 0x0700, 0xfd7e, 0x0000 }, + { 0x0700, 0xfd80, 0x0000 }, + { 0x8700, 0xfd83, 0x2000 }, + { 0x0700, 0xfd82, 0x0000 }, + { 0x0700, 0xfd84, 0x0000 }, + { 0x8700, 0xfd89, 0x3000 }, + { 0x8700, 0xfd87, 0x2000 }, + { 0x0700, 0xfd86, 0x0000 }, + { 0x0700, 0xfd88, 0x0000 }, + { 0x8700, 0xfd8b, 0x2000 }, + { 0x0700, 0xfd8a, 0x0000 }, + { 0x0700, 0xfd8c, 0x0000 }, + { 0x8700, 0xfd97, 0x4000 }, + { 0x8700, 0xfd93, 0x3000 }, + { 0x8700, 0xfd8f, 0x2000 }, + { 0x0700, 0xfd8e, 0x0000 }, + { 0x0700, 0xfd92, 0x0000 }, + { 0x8700, 0xfd95, 0x2000 }, + { 0x0700, 0xfd94, 0x0000 }, + { 0x0700, 0xfd96, 0x0000 }, + { 0x8700, 0xfd9b, 0x3000 }, + { 0x8700, 0xfd99, 0x2000 }, + { 0x0700, 0xfd98, 0x0000 }, + { 0x0700, 0xfd9a, 0x0000 }, + { 0x8700, 0xfd9d, 0x2000 }, + { 0x0700, 0xfd9c, 0x0000 }, + { 0x0700, 0xfd9e, 0x0000 }, + { 0x8700, 0xfdbf, 0x6000 }, + { 0x8700, 0xfdaf, 0x5000 }, + { 0x8700, 0xfda7, 0x4000 }, + { 0x8700, 0xfda3, 0x3000 }, + { 0x8700, 0xfda1, 0x2000 }, + { 0x0700, 0xfda0, 0x0000 }, + { 0x0700, 0xfda2, 0x0000 }, + { 0x8700, 0xfda5, 0x2000 }, + { 0x0700, 0xfda4, 0x0000 }, + { 0x0700, 0xfda6, 0x0000 }, + { 0x8700, 0xfdab, 0x3000 }, + { 0x8700, 0xfda9, 0x2000 }, + { 0x0700, 0xfda8, 0x0000 }, + { 0x0700, 0xfdaa, 0x0000 }, + { 0x8700, 0xfdad, 0x2000 }, + { 0x0700, 0xfdac, 0x0000 }, + { 0x0700, 0xfdae, 0x0000 }, + { 0x8700, 0xfdb7, 0x4000 }, + { 0x8700, 0xfdb3, 0x3000 }, + { 0x8700, 0xfdb1, 0x2000 }, + { 0x0700, 0xfdb0, 0x0000 }, + { 0x0700, 0xfdb2, 0x0000 }, + { 0x8700, 0xfdb5, 0x2000 }, + { 0x0700, 0xfdb4, 0x0000 }, + { 0x0700, 0xfdb6, 0x0000 }, + { 0x8700, 0xfdbb, 0x3000 }, + { 0x8700, 0xfdb9, 0x2000 }, + { 0x0700, 0xfdb8, 0x0000 }, + { 0x0700, 0xfdba, 0x0000 }, + { 0x8700, 0xfdbd, 0x2000 }, + { 0x0700, 0xfdbc, 0x0000 }, + { 0x0700, 0xfdbe, 0x0000 }, + { 0x8700, 0xfdf7, 0x5000 }, + { 0x8700, 0xfdc7, 0x4000 }, + { 0x8700, 0xfdc3, 0x3000 }, + { 0x8700, 0xfdc1, 0x2000 }, + { 0x0700, 0xfdc0, 0x0000 }, + { 0x0700, 0xfdc2, 0x0000 }, + { 0x8700, 0xfdc5, 0x2000 }, + { 0x0700, 0xfdc4, 0x0000 }, + { 0x0700, 0xfdc6, 0x0000 }, + { 0x8700, 0xfdf3, 0x3000 }, + { 0x8700, 0xfdf1, 0x2000 }, + { 0x0700, 0xfdf0, 0x0000 }, + { 0x0700, 0xfdf2, 0x0000 }, + { 0x8700, 0xfdf5, 0x2000 }, + { 0x0700, 0xfdf4, 0x0000 }, + { 0x0700, 0xfdf6, 0x0000 }, + { 0x8c00, 0xfe01, 0x4000 }, + { 0x8700, 0xfdfb, 0x3000 }, + { 0x8700, 0xfdf9, 0x2000 }, + { 0x0700, 0xfdf8, 0x0000 }, + { 0x0700, 0xfdfa, 0x0000 }, + { 0x9a00, 0xfdfd, 0x2000 }, + { 0x1700, 0xfdfc, 0x0000 }, + { 0x0c00, 0xfe00, 0x0000 }, + { 0x8c00, 0xfe05, 0x3000 }, + { 0x8c00, 0xfe03, 0x2000 }, + { 0x0c00, 0xfe02, 0x0000 }, + { 0x0c00, 0xfe04, 0x0000 }, + { 0x8c00, 0xfe07, 0x2000 }, + { 0x0c00, 0xfe06, 0x0000 }, + { 0x0c00, 0xfe08, 0x0000 }, + { 0x9900, 0xfe66, 0x7000 }, + { 0x9500, 0xfe45, 0x6000 }, + { 0x9600, 0xfe35, 0x5000 }, + { 0x8c00, 0xfe21, 0x4000 }, + { 0x8c00, 0xfe0d, 0x3000 }, + { 0x8c00, 0xfe0b, 0x2000 }, + { 0x0c00, 0xfe0a, 0x0000 }, + { 0x0c00, 0xfe0c, 0x0000 }, + { 0x8c00, 0xfe0f, 0x2000 }, + { 0x0c00, 0xfe0e, 0x0000 }, + { 0x0c00, 0xfe20, 0x0000 }, + { 0x9100, 0xfe31, 0x3000 }, + { 0x8c00, 0xfe23, 0x2000 }, + { 0x0c00, 0xfe22, 0x0000 }, + { 0x1500, 0xfe30, 0x0000 }, + { 0x9000, 0xfe33, 0x2000 }, + { 0x1100, 0xfe32, 0x0000 }, + { 0x1000, 0xfe34, 0x0000 }, + { 0x9600, 0xfe3d, 0x4000 }, + { 0x9600, 0xfe39, 0x3000 }, + { 0x9600, 0xfe37, 0x2000 }, + { 0x1200, 0xfe36, 0x0000 }, + { 0x1200, 0xfe38, 0x0000 }, + { 0x9600, 0xfe3b, 0x2000 }, + { 0x1200, 0xfe3a, 0x0000 }, + { 0x1200, 0xfe3c, 0x0000 }, + { 0x9600, 0xfe41, 0x3000 }, + { 0x9600, 0xfe3f, 0x2000 }, + { 0x1200, 0xfe3e, 0x0000 }, + { 0x1200, 0xfe40, 0x0000 }, + { 0x9600, 0xfe43, 0x2000 }, + { 0x1200, 0xfe42, 0x0000 }, + { 0x1200, 0xfe44, 0x0000 }, + { 0x9500, 0xfe56, 0x5000 }, + { 0x9000, 0xfe4d, 0x4000 }, + { 0x9500, 0xfe49, 0x3000 }, + { 0x9600, 0xfe47, 0x2000 }, + { 0x1500, 0xfe46, 0x0000 }, + { 0x1200, 0xfe48, 0x0000 }, + { 0x9500, 0xfe4b, 0x2000 }, + { 0x1500, 0xfe4a, 0x0000 }, + { 0x1500, 0xfe4c, 0x0000 }, + { 0x9500, 0xfe51, 0x3000 }, + { 0x9000, 0xfe4f, 0x2000 }, + { 0x1000, 0xfe4e, 0x0000 }, + { 0x1500, 0xfe50, 0x0000 }, + { 0x9500, 0xfe54, 0x2000 }, + { 0x1500, 0xfe52, 0x0000 }, + { 0x1500, 0xfe55, 0x0000 }, + { 0x9200, 0xfe5e, 0x4000 }, + { 0x9200, 0xfe5a, 0x3000 }, + { 0x9100, 0xfe58, 0x2000 }, + { 0x1500, 0xfe57, 0x0000 }, + { 0x1600, 0xfe59, 0x0000 }, + { 0x9200, 0xfe5c, 0x2000 }, + { 0x1600, 0xfe5b, 0x0000 }, + { 0x1600, 0xfe5d, 0x0000 }, + { 0x9900, 0xfe62, 0x3000 }, + { 0x9500, 0xfe60, 0x2000 }, + { 0x1500, 0xfe5f, 0x0000 }, + { 0x1500, 0xfe61, 0x0000 }, + { 0x9900, 0xfe64, 0x2000 }, + { 0x1100, 0xfe63, 0x0000 }, + { 0x1900, 0xfe65, 0x0000 }, + { 0x8700, 0xfe8c, 0x6000 }, + { 0x8700, 0xfe7c, 0x5000 }, + { 0x8700, 0xfe73, 0x4000 }, + { 0x9500, 0xfe6b, 0x3000 }, + { 0x9700, 0xfe69, 0x2000 }, + { 0x1500, 0xfe68, 0x0000 }, + { 0x1500, 0xfe6a, 0x0000 }, + { 0x8700, 0xfe71, 0x2000 }, + { 0x0700, 0xfe70, 0x0000 }, + { 0x0700, 0xfe72, 0x0000 }, + { 0x8700, 0xfe78, 0x3000 }, + { 0x8700, 0xfe76, 0x2000 }, + { 0x0700, 0xfe74, 0x0000 }, + { 0x0700, 0xfe77, 0x0000 }, + { 0x8700, 0xfe7a, 0x2000 }, + { 0x0700, 0xfe79, 0x0000 }, + { 0x0700, 0xfe7b, 0x0000 }, + { 0x8700, 0xfe84, 0x4000 }, + { 0x8700, 0xfe80, 0x3000 }, + { 0x8700, 0xfe7e, 0x2000 }, + { 0x0700, 0xfe7d, 0x0000 }, + { 0x0700, 0xfe7f, 0x0000 }, + { 0x8700, 0xfe82, 0x2000 }, + { 0x0700, 0xfe81, 0x0000 }, + { 0x0700, 0xfe83, 0x0000 }, + { 0x8700, 0xfe88, 0x3000 }, + { 0x8700, 0xfe86, 0x2000 }, + { 0x0700, 0xfe85, 0x0000 }, + { 0x0700, 0xfe87, 0x0000 }, + { 0x8700, 0xfe8a, 0x2000 }, + { 0x0700, 0xfe89, 0x0000 }, + { 0x0700, 0xfe8b, 0x0000 }, + { 0x8700, 0xfe9c, 0x5000 }, + { 0x8700, 0xfe94, 0x4000 }, + { 0x8700, 0xfe90, 0x3000 }, + { 0x8700, 0xfe8e, 0x2000 }, + { 0x0700, 0xfe8d, 0x0000 }, + { 0x0700, 0xfe8f, 0x0000 }, + { 0x8700, 0xfe92, 0x2000 }, + { 0x0700, 0xfe91, 0x0000 }, + { 0x0700, 0xfe93, 0x0000 }, + { 0x8700, 0xfe98, 0x3000 }, + { 0x8700, 0xfe96, 0x2000 }, + { 0x0700, 0xfe95, 0x0000 }, + { 0x0700, 0xfe97, 0x0000 }, + { 0x8700, 0xfe9a, 0x2000 }, + { 0x0700, 0xfe99, 0x0000 }, + { 0x0700, 0xfe9b, 0x0000 }, + { 0x8700, 0xfea4, 0x4000 }, + { 0x8700, 0xfea0, 0x3000 }, + { 0x8700, 0xfe9e, 0x2000 }, + { 0x0700, 0xfe9d, 0x0000 }, + { 0x0700, 0xfe9f, 0x0000 }, + { 0x8700, 0xfea2, 0x2000 }, + { 0x0700, 0xfea1, 0x0000 }, + { 0x0700, 0xfea3, 0x0000 }, + { 0x8700, 0xfea8, 0x3000 }, + { 0x8700, 0xfea6, 0x2000 }, + { 0x0700, 0xfea5, 0x0000 }, + { 0x0700, 0xfea7, 0x0000 }, + { 0x8700, 0xfeaa, 0x2000 }, + { 0x0700, 0xfea9, 0x0000 }, + { 0x0700, 0xfeab, 0x0000 }, + { 0x8700, 0xffaf, 0x9000 }, + { 0x8900, 0xff2f, 0x8020 }, + { 0x8700, 0xfeec, 0x7000 }, + { 0x8700, 0xfecc, 0x6000 }, + { 0x8700, 0xfebc, 0x5000 }, + { 0x8700, 0xfeb4, 0x4000 }, + { 0x8700, 0xfeb0, 0x3000 }, + { 0x8700, 0xfeae, 0x2000 }, + { 0x0700, 0xfead, 0x0000 }, + { 0x0700, 0xfeaf, 0x0000 }, + { 0x8700, 0xfeb2, 0x2000 }, + { 0x0700, 0xfeb1, 0x0000 }, + { 0x0700, 0xfeb3, 0x0000 }, + { 0x8700, 0xfeb8, 0x3000 }, + { 0x8700, 0xfeb6, 0x2000 }, + { 0x0700, 0xfeb5, 0x0000 }, + { 0x0700, 0xfeb7, 0x0000 }, + { 0x8700, 0xfeba, 0x2000 }, + { 0x0700, 0xfeb9, 0x0000 }, + { 0x0700, 0xfebb, 0x0000 }, + { 0x8700, 0xfec4, 0x4000 }, + { 0x8700, 0xfec0, 0x3000 }, + { 0x8700, 0xfebe, 0x2000 }, + { 0x0700, 0xfebd, 0x0000 }, + { 0x0700, 0xfebf, 0x0000 }, + { 0x8700, 0xfec2, 0x2000 }, + { 0x0700, 0xfec1, 0x0000 }, + { 0x0700, 0xfec3, 0x0000 }, + { 0x8700, 0xfec8, 0x3000 }, + { 0x8700, 0xfec6, 0x2000 }, + { 0x0700, 0xfec5, 0x0000 }, + { 0x0700, 0xfec7, 0x0000 }, + { 0x8700, 0xfeca, 0x2000 }, + { 0x0700, 0xfec9, 0x0000 }, + { 0x0700, 0xfecb, 0x0000 }, + { 0x8700, 0xfedc, 0x5000 }, + { 0x8700, 0xfed4, 0x4000 }, + { 0x8700, 0xfed0, 0x3000 }, + { 0x8700, 0xfece, 0x2000 }, + { 0x0700, 0xfecd, 0x0000 }, + { 0x0700, 0xfecf, 0x0000 }, + { 0x8700, 0xfed2, 0x2000 }, + { 0x0700, 0xfed1, 0x0000 }, + { 0x0700, 0xfed3, 0x0000 }, + { 0x8700, 0xfed8, 0x3000 }, + { 0x8700, 0xfed6, 0x2000 }, + { 0x0700, 0xfed5, 0x0000 }, + { 0x0700, 0xfed7, 0x0000 }, + { 0x8700, 0xfeda, 0x2000 }, + { 0x0700, 0xfed9, 0x0000 }, + { 0x0700, 0xfedb, 0x0000 }, + { 0x8700, 0xfee4, 0x4000 }, + { 0x8700, 0xfee0, 0x3000 }, + { 0x8700, 0xfede, 0x2000 }, + { 0x0700, 0xfedd, 0x0000 }, + { 0x0700, 0xfedf, 0x0000 }, + { 0x8700, 0xfee2, 0x2000 }, + { 0x0700, 0xfee1, 0x0000 }, + { 0x0700, 0xfee3, 0x0000 }, + { 0x8700, 0xfee8, 0x3000 }, + { 0x8700, 0xfee6, 0x2000 }, + { 0x0700, 0xfee5, 0x0000 }, + { 0x0700, 0xfee7, 0x0000 }, + { 0x8700, 0xfeea, 0x2000 }, + { 0x0700, 0xfee9, 0x0000 }, + { 0x0700, 0xfeeb, 0x0000 }, + { 0x9500, 0xff0f, 0x6000 }, + { 0x8700, 0xfefc, 0x5000 }, + { 0x8700, 0xfef4, 0x4000 }, + { 0x8700, 0xfef0, 0x3000 }, + { 0x8700, 0xfeee, 0x2000 }, + { 0x0700, 0xfeed, 0x0000 }, + { 0x0700, 0xfeef, 0x0000 }, + { 0x8700, 0xfef2, 0x2000 }, + { 0x0700, 0xfef1, 0x0000 }, + { 0x0700, 0xfef3, 0x0000 }, + { 0x8700, 0xfef8, 0x3000 }, + { 0x8700, 0xfef6, 0x2000 }, + { 0x0700, 0xfef5, 0x0000 }, + { 0x0700, 0xfef7, 0x0000 }, + { 0x8700, 0xfefa, 0x2000 }, + { 0x0700, 0xfef9, 0x0000 }, + { 0x0700, 0xfefb, 0x0000 }, + { 0x9500, 0xff07, 0x4000 }, + { 0x9500, 0xff03, 0x3000 }, + { 0x9500, 0xff01, 0x2000 }, + { 0x0100, 0xfeff, 0x0000 }, + { 0x1500, 0xff02, 0x0000 }, + { 0x9500, 0xff05, 0x2000 }, + { 0x1700, 0xff04, 0x0000 }, + { 0x1500, 0xff06, 0x0000 }, + { 0x9900, 0xff0b, 0x3000 }, + { 0x9200, 0xff09, 0x2000 }, + { 0x1600, 0xff08, 0x0000 }, + { 0x1500, 0xff0a, 0x0000 }, + { 0x9100, 0xff0d, 0x2000 }, + { 0x1500, 0xff0c, 0x0000 }, + { 0x1500, 0xff0e, 0x0000 }, + { 0x9500, 0xff1f, 0x5000 }, + { 0x8d00, 0xff17, 0x4000 }, + { 0x8d00, 0xff13, 0x3000 }, + { 0x8d00, 0xff11, 0x2000 }, + { 0x0d00, 0xff10, 0x0000 }, + { 0x0d00, 0xff12, 0x0000 }, + { 0x8d00, 0xff15, 0x2000 }, + { 0x0d00, 0xff14, 0x0000 }, + { 0x0d00, 0xff16, 0x0000 }, + { 0x9500, 0xff1b, 0x3000 }, + { 0x8d00, 0xff19, 0x2000 }, + { 0x0d00, 0xff18, 0x0000 }, + { 0x1500, 0xff1a, 0x0000 }, + { 0x9900, 0xff1d, 0x2000 }, + { 0x1900, 0xff1c, 0x0000 }, + { 0x1900, 0xff1e, 0x0000 }, + { 0x8900, 0xff27, 0x4020 }, + { 0x8900, 0xff23, 0x3020 }, + { 0x8900, 0xff21, 0x2020 }, + { 0x1500, 0xff20, 0x0000 }, + { 0x0900, 0xff22, 0x0020 }, + { 0x8900, 0xff25, 0x2020 }, + { 0x0900, 0xff24, 0x0020 }, + { 0x0900, 0xff26, 0x0020 }, + { 0x8900, 0xff2b, 0x3020 }, + { 0x8900, 0xff29, 0x2020 }, + { 0x0900, 0xff28, 0x0020 }, + { 0x0900, 0xff2a, 0x0020 }, + { 0x8900, 0xff2d, 0x2020 }, + { 0x0900, 0xff2c, 0x0020 }, + { 0x0900, 0xff2e, 0x0020 }, + { 0x8700, 0xff6f, 0x7000 }, + { 0x8500, 0xff4f, 0x6fe0 }, + { 0x9000, 0xff3f, 0x5000 }, + { 0x8900, 0xff37, 0x4020 }, + { 0x8900, 0xff33, 0x3020 }, + { 0x8900, 0xff31, 0x2020 }, + { 0x0900, 0xff30, 0x0020 }, + { 0x0900, 0xff32, 0x0020 }, + { 0x8900, 0xff35, 0x2020 }, + { 0x0900, 0xff34, 0x0020 }, + { 0x0900, 0xff36, 0x0020 }, + { 0x9600, 0xff3b, 0x3000 }, + { 0x8900, 0xff39, 0x2020 }, + { 0x0900, 0xff38, 0x0020 }, + { 0x0900, 0xff3a, 0x0020 }, + { 0x9200, 0xff3d, 0x2000 }, + { 0x1500, 0xff3c, 0x0000 }, + { 0x1800, 0xff3e, 0x0000 }, + { 0x8500, 0xff47, 0x4fe0 }, + { 0x8500, 0xff43, 0x3fe0 }, + { 0x8500, 0xff41, 0x2fe0 }, + { 0x1800, 0xff40, 0x0000 }, + { 0x0500, 0xff42, 0x0fe0 }, + { 0x8500, 0xff45, 0x2fe0 }, + { 0x0500, 0xff44, 0x0fe0 }, + { 0x0500, 0xff46, 0x0fe0 }, + { 0x8500, 0xff4b, 0x3fe0 }, + { 0x8500, 0xff49, 0x2fe0 }, + { 0x0500, 0xff48, 0x0fe0 }, + { 0x0500, 0xff4a, 0x0fe0 }, + { 0x8500, 0xff4d, 0x2fe0 }, + { 0x0500, 0xff4c, 0x0fe0 }, + { 0x0500, 0xff4e, 0x0fe0 }, + { 0x9600, 0xff5f, 0x5000 }, + { 0x8500, 0xff57, 0x4fe0 }, + { 0x8500, 0xff53, 0x3fe0 }, + { 0x8500, 0xff51, 0x2fe0 }, + { 0x0500, 0xff50, 0x0fe0 }, + { 0x0500, 0xff52, 0x0fe0 }, + { 0x8500, 0xff55, 0x2fe0 }, + { 0x0500, 0xff54, 0x0fe0 }, + { 0x0500, 0xff56, 0x0fe0 }, + { 0x9600, 0xff5b, 0x3000 }, + { 0x8500, 0xff59, 0x2fe0 }, + { 0x0500, 0xff58, 0x0fe0 }, + { 0x0500, 0xff5a, 0x0fe0 }, + { 0x9200, 0xff5d, 0x2000 }, + { 0x1900, 0xff5c, 0x0000 }, + { 0x1900, 0xff5e, 0x0000 }, + { 0x8700, 0xff67, 0x4000 }, + { 0x9200, 0xff63, 0x3000 }, + { 0x9500, 0xff61, 0x2000 }, + { 0x1200, 0xff60, 0x0000 }, + { 0x1600, 0xff62, 0x0000 }, + { 0x9000, 0xff65, 0x2000 }, + { 0x1500, 0xff64, 0x0000 }, + { 0x0700, 0xff66, 0x0000 }, + { 0x8700, 0xff6b, 0x3000 }, + { 0x8700, 0xff69, 0x2000 }, + { 0x0700, 0xff68, 0x0000 }, + { 0x0700, 0xff6a, 0x0000 }, + { 0x8700, 0xff6d, 0x2000 }, + { 0x0700, 0xff6c, 0x0000 }, + { 0x0700, 0xff6e, 0x0000 }, + { 0x8700, 0xff8f, 0x6000 }, + { 0x8700, 0xff7f, 0x5000 }, + { 0x8700, 0xff77, 0x4000 }, + { 0x8700, 0xff73, 0x3000 }, + { 0x8700, 0xff71, 0x2000 }, + { 0x0600, 0xff70, 0x0000 }, + { 0x0700, 0xff72, 0x0000 }, + { 0x8700, 0xff75, 0x2000 }, + { 0x0700, 0xff74, 0x0000 }, + { 0x0700, 0xff76, 0x0000 }, + { 0x8700, 0xff7b, 0x3000 }, + { 0x8700, 0xff79, 0x2000 }, + { 0x0700, 0xff78, 0x0000 }, + { 0x0700, 0xff7a, 0x0000 }, + { 0x8700, 0xff7d, 0x2000 }, + { 0x0700, 0xff7c, 0x0000 }, + { 0x0700, 0xff7e, 0x0000 }, + { 0x8700, 0xff87, 0x4000 }, + { 0x8700, 0xff83, 0x3000 }, + { 0x8700, 0xff81, 0x2000 }, + { 0x0700, 0xff80, 0x0000 }, + { 0x0700, 0xff82, 0x0000 }, + { 0x8700, 0xff85, 0x2000 }, + { 0x0700, 0xff84, 0x0000 }, + { 0x0700, 0xff86, 0x0000 }, + { 0x8700, 0xff8b, 0x3000 }, + { 0x8700, 0xff89, 0x2000 }, + { 0x0700, 0xff88, 0x0000 }, + { 0x0700, 0xff8a, 0x0000 }, + { 0x8700, 0xff8d, 0x2000 }, + { 0x0700, 0xff8c, 0x0000 }, + { 0x0700, 0xff8e, 0x0000 }, + { 0x8600, 0xff9f, 0x5000 }, + { 0x8700, 0xff97, 0x4000 }, + { 0x8700, 0xff93, 0x3000 }, + { 0x8700, 0xff91, 0x2000 }, + { 0x0700, 0xff90, 0x0000 }, + { 0x0700, 0xff92, 0x0000 }, + { 0x8700, 0xff95, 0x2000 }, + { 0x0700, 0xff94, 0x0000 }, + { 0x0700, 0xff96, 0x0000 }, + { 0x8700, 0xff9b, 0x3000 }, + { 0x8700, 0xff99, 0x2000 }, + { 0x0700, 0xff98, 0x0000 }, + { 0x0700, 0xff9a, 0x0000 }, + { 0x8700, 0xff9d, 0x2000 }, + { 0x0700, 0xff9c, 0x0000 }, + { 0x0600, 0xff9e, 0x0000 }, + { 0x8700, 0xffa7, 0x4000 }, + { 0x8700, 0xffa3, 0x3000 }, + { 0x8700, 0xffa1, 0x2000 }, + { 0x0700, 0xffa0, 0x0000 }, + { 0x0700, 0xffa2, 0x0000 }, + { 0x8700, 0xffa5, 0x2000 }, + { 0x0700, 0xffa4, 0x0000 }, + { 0x0700, 0xffa6, 0x0000 }, + { 0x8700, 0xffab, 0x3000 }, + { 0x8700, 0xffa9, 0x2000 }, + { 0x0700, 0xffa8, 0x0000 }, + { 0x0700, 0xffaa, 0x0000 }, + { 0x8700, 0xffad, 0x2000 }, + { 0x0700, 0xffac, 0x0000 }, + { 0x0700, 0xffae, 0x0000 }, + { 0x8701, 0x004c, 0x8000 }, + { 0x8701, 0x0008, 0x7000 }, + { 0x8700, 0xffd6, 0x6000 }, + { 0x8700, 0xffc2, 0x5000 }, + { 0x8700, 0xffb7, 0x4000 }, + { 0x8700, 0xffb3, 0x3000 }, + { 0x8700, 0xffb1, 0x2000 }, + { 0x0700, 0xffb0, 0x0000 }, + { 0x0700, 0xffb2, 0x0000 }, + { 0x8700, 0xffb5, 0x2000 }, + { 0x0700, 0xffb4, 0x0000 }, + { 0x0700, 0xffb6, 0x0000 }, + { 0x8700, 0xffbb, 0x3000 }, + { 0x8700, 0xffb9, 0x2000 }, + { 0x0700, 0xffb8, 0x0000 }, + { 0x0700, 0xffba, 0x0000 }, + { 0x8700, 0xffbd, 0x2000 }, + { 0x0700, 0xffbc, 0x0000 }, + { 0x0700, 0xffbe, 0x0000 }, + { 0x8700, 0xffcc, 0x4000 }, + { 0x8700, 0xffc6, 0x3000 }, + { 0x8700, 0xffc4, 0x2000 }, + { 0x0700, 0xffc3, 0x0000 }, + { 0x0700, 0xffc5, 0x0000 }, + { 0x8700, 0xffca, 0x2000 }, + { 0x0700, 0xffc7, 0x0000 }, + { 0x0700, 0xffcb, 0x0000 }, + { 0x8700, 0xffd2, 0x3000 }, + { 0x8700, 0xffce, 0x2000 }, + { 0x0700, 0xffcd, 0x0000 }, + { 0x0700, 0xffcf, 0x0000 }, + { 0x8700, 0xffd4, 0x2000 }, + { 0x0700, 0xffd3, 0x0000 }, + { 0x0700, 0xffd5, 0x0000 }, + { 0x9900, 0xffec, 0x5000 }, + { 0x9800, 0xffe3, 0x4000 }, + { 0x8700, 0xffdc, 0x3000 }, + { 0x8700, 0xffda, 0x2000 }, + { 0x0700, 0xffd7, 0x0000 }, + { 0x0700, 0xffdb, 0x0000 }, + { 0x9700, 0xffe1, 0x2000 }, + { 0x1700, 0xffe0, 0x0000 }, + { 0x1900, 0xffe2, 0x0000 }, + { 0x9a00, 0xffe8, 0x3000 }, + { 0x9700, 0xffe5, 0x2000 }, + { 0x1a00, 0xffe4, 0x0000 }, + { 0x1700, 0xffe6, 0x0000 }, + { 0x9900, 0xffea, 0x2000 }, + { 0x1900, 0xffe9, 0x0000 }, + { 0x1900, 0xffeb, 0x0000 }, + { 0x8701, 0x0000, 0x4000 }, + { 0x8100, 0xfffa, 0x3000 }, + { 0x9a00, 0xffee, 0x2000 }, + { 0x1a00, 0xffed, 0x0000 }, + { 0x0100, 0xfff9, 0x0000 }, + { 0x9a00, 0xfffc, 0x2000 }, + { 0x0100, 0xfffb, 0x0000 }, + { 0x1a00, 0xfffd, 0x0000 }, + { 0x8701, 0x0004, 0x3000 }, + { 0x8701, 0x0002, 0x2000 }, + { 0x0701, 0x0001, 0x0000 }, + { 0x0701, 0x0003, 0x0000 }, + { 0x8701, 0x0006, 0x2000 }, + { 0x0701, 0x0005, 0x0000 }, + { 0x0701, 0x0007, 0x0000 }, + { 0x8701, 0x002a, 0x6000 }, + { 0x8701, 0x0019, 0x5000 }, + { 0x8701, 0x0011, 0x4000 }, + { 0x8701, 0x000d, 0x3000 }, + { 0x8701, 0x000a, 0x2000 }, + { 0x0701, 0x0009, 0x0000 }, + { 0x0701, 0x000b, 0x0000 }, + { 0x8701, 0x000f, 0x2000 }, + { 0x0701, 0x000e, 0x0000 }, + { 0x0701, 0x0010, 0x0000 }, + { 0x8701, 0x0015, 0x3000 }, + { 0x8701, 0x0013, 0x2000 }, + { 0x0701, 0x0012, 0x0000 }, + { 0x0701, 0x0014, 0x0000 }, + { 0x8701, 0x0017, 0x2000 }, + { 0x0701, 0x0016, 0x0000 }, + { 0x0701, 0x0018, 0x0000 }, + { 0x8701, 0x0021, 0x4000 }, + { 0x8701, 0x001d, 0x3000 }, + { 0x8701, 0x001b, 0x2000 }, + { 0x0701, 0x001a, 0x0000 }, + { 0x0701, 0x001c, 0x0000 }, + { 0x8701, 0x001f, 0x2000 }, + { 0x0701, 0x001e, 0x0000 }, + { 0x0701, 0x0020, 0x0000 }, + { 0x8701, 0x0025, 0x3000 }, + { 0x8701, 0x0023, 0x2000 }, + { 0x0701, 0x0022, 0x0000 }, + { 0x0701, 0x0024, 0x0000 }, + { 0x8701, 0x0028, 0x2000 }, + { 0x0701, 0x0026, 0x0000 }, + { 0x0701, 0x0029, 0x0000 }, + { 0x8701, 0x003a, 0x5000 }, + { 0x8701, 0x0032, 0x4000 }, + { 0x8701, 0x002e, 0x3000 }, + { 0x8701, 0x002c, 0x2000 }, + { 0x0701, 0x002b, 0x0000 }, + { 0x0701, 0x002d, 0x0000 }, + { 0x8701, 0x0030, 0x2000 }, + { 0x0701, 0x002f, 0x0000 }, + { 0x0701, 0x0031, 0x0000 }, + { 0x8701, 0x0036, 0x3000 }, + { 0x8701, 0x0034, 0x2000 }, + { 0x0701, 0x0033, 0x0000 }, + { 0x0701, 0x0035, 0x0000 }, + { 0x8701, 0x0038, 0x2000 }, + { 0x0701, 0x0037, 0x0000 }, + { 0x0701, 0x0039, 0x0000 }, + { 0x8701, 0x0044, 0x4000 }, + { 0x8701, 0x0040, 0x3000 }, + { 0x8701, 0x003d, 0x2000 }, + { 0x0701, 0x003c, 0x0000 }, + { 0x0701, 0x003f, 0x0000 }, + { 0x8701, 0x0042, 0x2000 }, + { 0x0701, 0x0041, 0x0000 }, + { 0x0701, 0x0043, 0x0000 }, + { 0x8701, 0x0048, 0x3000 }, + { 0x8701, 0x0046, 0x2000 }, + { 0x0701, 0x0045, 0x0000 }, + { 0x0701, 0x0047, 0x0000 }, + { 0x8701, 0x004a, 0x2000 }, + { 0x0701, 0x0049, 0x0000 }, + { 0x0701, 0x004b, 0x0000 }, + { 0x8701, 0x00b0, 0x7000 }, + { 0x8701, 0x0090, 0x6000 }, + { 0x8701, 0x0080, 0x5000 }, + { 0x8701, 0x0056, 0x4000 }, + { 0x8701, 0x0052, 0x3000 }, + { 0x8701, 0x0050, 0x2000 }, + { 0x0701, 0x004d, 0x0000 }, + { 0x0701, 0x0051, 0x0000 }, + { 0x8701, 0x0054, 0x2000 }, + { 0x0701, 0x0053, 0x0000 }, + { 0x0701, 0x0055, 0x0000 }, + { 0x8701, 0x005a, 0x3000 }, + { 0x8701, 0x0058, 0x2000 }, + { 0x0701, 0x0057, 0x0000 }, + { 0x0701, 0x0059, 0x0000 }, + { 0x8701, 0x005c, 0x2000 }, + { 0x0701, 0x005b, 0x0000 }, + { 0x0701, 0x005d, 0x0000 }, + { 0x8701, 0x0088, 0x4000 }, + { 0x8701, 0x0084, 0x3000 }, + { 0x8701, 0x0082, 0x2000 }, + { 0x0701, 0x0081, 0x0000 }, + { 0x0701, 0x0083, 0x0000 }, + { 0x8701, 0x0086, 0x2000 }, + { 0x0701, 0x0085, 0x0000 }, + { 0x0701, 0x0087, 0x0000 }, + { 0x8701, 0x008c, 0x3000 }, + { 0x8701, 0x008a, 0x2000 }, + { 0x0701, 0x0089, 0x0000 }, + { 0x0701, 0x008b, 0x0000 }, + { 0x8701, 0x008e, 0x2000 }, + { 0x0701, 0x008d, 0x0000 }, + { 0x0701, 0x008f, 0x0000 }, + { 0x8701, 0x00a0, 0x5000 }, + { 0x8701, 0x0098, 0x4000 }, + { 0x8701, 0x0094, 0x3000 }, + { 0x8701, 0x0092, 0x2000 }, + { 0x0701, 0x0091, 0x0000 }, + { 0x0701, 0x0093, 0x0000 }, + { 0x8701, 0x0096, 0x2000 }, + { 0x0701, 0x0095, 0x0000 }, + { 0x0701, 0x0097, 0x0000 }, + { 0x8701, 0x009c, 0x3000 }, + { 0x8701, 0x009a, 0x2000 }, + { 0x0701, 0x0099, 0x0000 }, + { 0x0701, 0x009b, 0x0000 }, + { 0x8701, 0x009e, 0x2000 }, + { 0x0701, 0x009d, 0x0000 }, + { 0x0701, 0x009f, 0x0000 }, + { 0x8701, 0x00a8, 0x4000 }, + { 0x8701, 0x00a4, 0x3000 }, + { 0x8701, 0x00a2, 0x2000 }, + { 0x0701, 0x00a1, 0x0000 }, + { 0x0701, 0x00a3, 0x0000 }, + { 0x8701, 0x00a6, 0x2000 }, + { 0x0701, 0x00a5, 0x0000 }, + { 0x0701, 0x00a7, 0x0000 }, + { 0x8701, 0x00ac, 0x3000 }, + { 0x8701, 0x00aa, 0x2000 }, + { 0x0701, 0x00a9, 0x0000 }, + { 0x0701, 0x00ab, 0x0000 }, + { 0x8701, 0x00ae, 0x2000 }, + { 0x0701, 0x00ad, 0x0000 }, + { 0x0701, 0x00af, 0x0000 }, + { 0x8701, 0x00d0, 0x6000 }, + { 0x8701, 0x00c0, 0x5000 }, + { 0x8701, 0x00b8, 0x4000 }, + { 0x8701, 0x00b4, 0x3000 }, + { 0x8701, 0x00b2, 0x2000 }, + { 0x0701, 0x00b1, 0x0000 }, + { 0x0701, 0x00b3, 0x0000 }, + { 0x8701, 0x00b6, 0x2000 }, + { 0x0701, 0x00b5, 0x0000 }, + { 0x0701, 0x00b7, 0x0000 }, + { 0x8701, 0x00bc, 0x3000 }, + { 0x8701, 0x00ba, 0x2000 }, + { 0x0701, 0x00b9, 0x0000 }, + { 0x0701, 0x00bb, 0x0000 }, + { 0x8701, 0x00be, 0x2000 }, + { 0x0701, 0x00bd, 0x0000 }, + { 0x0701, 0x00bf, 0x0000 }, + { 0x8701, 0x00c8, 0x4000 }, + { 0x8701, 0x00c4, 0x3000 }, + { 0x8701, 0x00c2, 0x2000 }, + { 0x0701, 0x00c1, 0x0000 }, + { 0x0701, 0x00c3, 0x0000 }, + { 0x8701, 0x00c6, 0x2000 }, + { 0x0701, 0x00c5, 0x0000 }, + { 0x0701, 0x00c7, 0x0000 }, + { 0x8701, 0x00cc, 0x3000 }, + { 0x8701, 0x00ca, 0x2000 }, + { 0x0701, 0x00c9, 0x0000 }, + { 0x0701, 0x00cb, 0x0000 }, + { 0x8701, 0x00ce, 0x2000 }, + { 0x0701, 0x00cd, 0x0000 }, + { 0x0701, 0x00cf, 0x0000 }, + { 0x8701, 0x00e0, 0x5000 }, + { 0x8701, 0x00d8, 0x4000 }, + { 0x8701, 0x00d4, 0x3000 }, + { 0x8701, 0x00d2, 0x2000 }, + { 0x0701, 0x00d1, 0x0000 }, + { 0x0701, 0x00d3, 0x0000 }, + { 0x8701, 0x00d6, 0x2000 }, + { 0x0701, 0x00d5, 0x0000 }, + { 0x0701, 0x00d7, 0x0000 }, + { 0x8701, 0x00dc, 0x3000 }, + { 0x8701, 0x00da, 0x2000 }, + { 0x0701, 0x00d9, 0x0000 }, + { 0x0701, 0x00db, 0x0000 }, + { 0x8701, 0x00de, 0x2000 }, + { 0x0701, 0x00dd, 0x0000 }, + { 0x0701, 0x00df, 0x0000 }, + { 0x8701, 0x00e8, 0x4000 }, + { 0x8701, 0x00e4, 0x3000 }, + { 0x8701, 0x00e2, 0x2000 }, + { 0x0701, 0x00e1, 0x0000 }, + { 0x0701, 0x00e3, 0x0000 }, + { 0x8701, 0x00e6, 0x2000 }, + { 0x0701, 0x00e5, 0x0000 }, + { 0x0701, 0x00e7, 0x0000 }, + { 0x8701, 0x00ec, 0x3000 }, + { 0x8701, 0x00ea, 0x2000 }, + { 0x0701, 0x00e9, 0x0000 }, + { 0x0701, 0x00eb, 0x0000 }, + { 0x8701, 0x00ee, 0x2000 }, + { 0x0701, 0x00ed, 0x0000 }, + { 0x0701, 0x00ef, 0x0000 }, + { 0x8501, 0xd459, 0xb000 }, + { 0x9a01, 0xd080, 0xa000 }, + { 0x8701, 0x045f, 0x9000 }, + { 0x8701, 0x0349, 0x8000 }, + { 0x9a01, 0x013c, 0x7000 }, + { 0x8f01, 0x0119, 0x6000 }, + { 0x8f01, 0x0109, 0x5000 }, + { 0x8701, 0x00f8, 0x4000 }, + { 0x8701, 0x00f4, 0x3000 }, + { 0x8701, 0x00f2, 0x2000 }, + { 0x0701, 0x00f1, 0x0000 }, + { 0x0701, 0x00f3, 0x0000 }, + { 0x8701, 0x00f6, 0x2000 }, + { 0x0701, 0x00f5, 0x0000 }, + { 0x0701, 0x00f7, 0x0000 }, + { 0x9501, 0x0101, 0x3000 }, + { 0x8701, 0x00fa, 0x2000 }, + { 0x0701, 0x00f9, 0x0000 }, + { 0x1501, 0x0100, 0x0000 }, + { 0x8f01, 0x0107, 0x2000 }, + { 0x1a01, 0x0102, 0x0000 }, + { 0x0f01, 0x0108, 0x0000 }, + { 0x8f01, 0x0111, 0x4000 }, + { 0x8f01, 0x010d, 0x3000 }, + { 0x8f01, 0x010b, 0x2000 }, + { 0x0f01, 0x010a, 0x0000 }, + { 0x0f01, 0x010c, 0x0000 }, + { 0x8f01, 0x010f, 0x2000 }, + { 0x0f01, 0x010e, 0x0000 }, + { 0x0f01, 0x0110, 0x0000 }, + { 0x8f01, 0x0115, 0x3000 }, + { 0x8f01, 0x0113, 0x2000 }, + { 0x0f01, 0x0112, 0x0000 }, + { 0x0f01, 0x0114, 0x0000 }, + { 0x8f01, 0x0117, 0x2000 }, + { 0x0f01, 0x0116, 0x0000 }, + { 0x0f01, 0x0118, 0x0000 }, + { 0x8f01, 0x0129, 0x5000 }, + { 0x8f01, 0x0121, 0x4000 }, + { 0x8f01, 0x011d, 0x3000 }, + { 0x8f01, 0x011b, 0x2000 }, + { 0x0f01, 0x011a, 0x0000 }, + { 0x0f01, 0x011c, 0x0000 }, + { 0x8f01, 0x011f, 0x2000 }, + { 0x0f01, 0x011e, 0x0000 }, + { 0x0f01, 0x0120, 0x0000 }, + { 0x8f01, 0x0125, 0x3000 }, + { 0x8f01, 0x0123, 0x2000 }, + { 0x0f01, 0x0122, 0x0000 }, + { 0x0f01, 0x0124, 0x0000 }, + { 0x8f01, 0x0127, 0x2000 }, + { 0x0f01, 0x0126, 0x0000 }, + { 0x0f01, 0x0128, 0x0000 }, + { 0x8f01, 0x0131, 0x4000 }, + { 0x8f01, 0x012d, 0x3000 }, + { 0x8f01, 0x012b, 0x2000 }, + { 0x0f01, 0x012a, 0x0000 }, + { 0x0f01, 0x012c, 0x0000 }, + { 0x8f01, 0x012f, 0x2000 }, + { 0x0f01, 0x012e, 0x0000 }, + { 0x0f01, 0x0130, 0x0000 }, + { 0x9a01, 0x0138, 0x3000 }, + { 0x8f01, 0x0133, 0x2000 }, + { 0x0f01, 0x0132, 0x0000 }, + { 0x1a01, 0x0137, 0x0000 }, + { 0x9a01, 0x013a, 0x2000 }, + { 0x1a01, 0x0139, 0x0000 }, + { 0x1a01, 0x013b, 0x0000 }, + { 0x8701, 0x031c, 0x6000 }, + { 0x8701, 0x030c, 0x5000 }, + { 0x8701, 0x0304, 0x4000 }, + { 0x8701, 0x0300, 0x3000 }, + { 0x9a01, 0x013e, 0x2000 }, + { 0x1a01, 0x013d, 0x0000 }, + { 0x1a01, 0x013f, 0x0000 }, + { 0x8701, 0x0302, 0x2000 }, + { 0x0701, 0x0301, 0x0000 }, + { 0x0701, 0x0303, 0x0000 }, + { 0x8701, 0x0308, 0x3000 }, + { 0x8701, 0x0306, 0x2000 }, + { 0x0701, 0x0305, 0x0000 }, + { 0x0701, 0x0307, 0x0000 }, + { 0x8701, 0x030a, 0x2000 }, + { 0x0701, 0x0309, 0x0000 }, + { 0x0701, 0x030b, 0x0000 }, + { 0x8701, 0x0314, 0x4000 }, + { 0x8701, 0x0310, 0x3000 }, + { 0x8701, 0x030e, 0x2000 }, + { 0x0701, 0x030d, 0x0000 }, + { 0x0701, 0x030f, 0x0000 }, + { 0x8701, 0x0312, 0x2000 }, + { 0x0701, 0x0311, 0x0000 }, + { 0x0701, 0x0313, 0x0000 }, + { 0x8701, 0x0318, 0x3000 }, + { 0x8701, 0x0316, 0x2000 }, + { 0x0701, 0x0315, 0x0000 }, + { 0x0701, 0x0317, 0x0000 }, + { 0x8701, 0x031a, 0x2000 }, + { 0x0701, 0x0319, 0x0000 }, + { 0x0701, 0x031b, 0x0000 }, + { 0x8701, 0x0339, 0x5000 }, + { 0x8701, 0x0331, 0x4000 }, + { 0x8f01, 0x0321, 0x3000 }, + { 0x8701, 0x031e, 0x2000 }, + { 0x0701, 0x031d, 0x0000 }, + { 0x0f01, 0x0320, 0x0000 }, + { 0x8f01, 0x0323, 0x2000 }, + { 0x0f01, 0x0322, 0x0000 }, + { 0x0701, 0x0330, 0x0000 }, + { 0x8701, 0x0335, 0x3000 }, + { 0x8701, 0x0333, 0x2000 }, + { 0x0701, 0x0332, 0x0000 }, + { 0x0701, 0x0334, 0x0000 }, + { 0x8701, 0x0337, 0x2000 }, + { 0x0701, 0x0336, 0x0000 }, + { 0x0701, 0x0338, 0x0000 }, + { 0x8701, 0x0341, 0x4000 }, + { 0x8701, 0x033d, 0x3000 }, + { 0x8701, 0x033b, 0x2000 }, + { 0x0701, 0x033a, 0x0000 }, + { 0x0701, 0x033c, 0x0000 }, + { 0x8701, 0x033f, 0x2000 }, + { 0x0701, 0x033e, 0x0000 }, + { 0x0701, 0x0340, 0x0000 }, + { 0x8701, 0x0345, 0x3000 }, + { 0x8701, 0x0343, 0x2000 }, + { 0x0701, 0x0342, 0x0000 }, + { 0x0701, 0x0344, 0x0000 }, + { 0x8701, 0x0347, 0x2000 }, + { 0x0701, 0x0346, 0x0000 }, + { 0x0701, 0x0348, 0x0000 }, + { 0x8901, 0x041f, 0x7028 }, + { 0x9501, 0x039f, 0x6000 }, + { 0x8701, 0x038e, 0x5000 }, + { 0x8701, 0x0386, 0x4000 }, + { 0x8701, 0x0382, 0x3000 }, + { 0x8701, 0x0380, 0x2000 }, + { 0x0e01, 0x034a, 0x0000 }, + { 0x0701, 0x0381, 0x0000 }, + { 0x8701, 0x0384, 0x2000 }, + { 0x0701, 0x0383, 0x0000 }, + { 0x0701, 0x0385, 0x0000 }, + { 0x8701, 0x038a, 0x3000 }, + { 0x8701, 0x0388, 0x2000 }, + { 0x0701, 0x0387, 0x0000 }, + { 0x0701, 0x0389, 0x0000 }, + { 0x8701, 0x038c, 0x2000 }, + { 0x0701, 0x038b, 0x0000 }, + { 0x0701, 0x038d, 0x0000 }, + { 0x8701, 0x0396, 0x4000 }, + { 0x8701, 0x0392, 0x3000 }, + { 0x8701, 0x0390, 0x2000 }, + { 0x0701, 0x038f, 0x0000 }, + { 0x0701, 0x0391, 0x0000 }, + { 0x8701, 0x0394, 0x2000 }, + { 0x0701, 0x0393, 0x0000 }, + { 0x0701, 0x0395, 0x0000 }, + { 0x8701, 0x039a, 0x3000 }, + { 0x8701, 0x0398, 0x2000 }, + { 0x0701, 0x0397, 0x0000 }, + { 0x0701, 0x0399, 0x0000 }, + { 0x8701, 0x039c, 0x2000 }, + { 0x0701, 0x039b, 0x0000 }, + { 0x0701, 0x039d, 0x0000 }, + { 0x8901, 0x040f, 0x5028 }, + { 0x8901, 0x0407, 0x4028 }, + { 0x8901, 0x0403, 0x3028 }, + { 0x8901, 0x0401, 0x2028 }, + { 0x0901, 0x0400, 0x0028 }, + { 0x0901, 0x0402, 0x0028 }, + { 0x8901, 0x0405, 0x2028 }, + { 0x0901, 0x0404, 0x0028 }, + { 0x0901, 0x0406, 0x0028 }, + { 0x8901, 0x040b, 0x3028 }, + { 0x8901, 0x0409, 0x2028 }, + { 0x0901, 0x0408, 0x0028 }, + { 0x0901, 0x040a, 0x0028 }, + { 0x8901, 0x040d, 0x2028 }, + { 0x0901, 0x040c, 0x0028 }, + { 0x0901, 0x040e, 0x0028 }, + { 0x8901, 0x0417, 0x4028 }, + { 0x8901, 0x0413, 0x3028 }, + { 0x8901, 0x0411, 0x2028 }, + { 0x0901, 0x0410, 0x0028 }, + { 0x0901, 0x0412, 0x0028 }, + { 0x8901, 0x0415, 0x2028 }, + { 0x0901, 0x0414, 0x0028 }, + { 0x0901, 0x0416, 0x0028 }, + { 0x8901, 0x041b, 0x3028 }, + { 0x8901, 0x0419, 0x2028 }, + { 0x0901, 0x0418, 0x0028 }, + { 0x0901, 0x041a, 0x0028 }, + { 0x8901, 0x041d, 0x2028 }, + { 0x0901, 0x041c, 0x0028 }, + { 0x0901, 0x041e, 0x0028 }, + { 0x8501, 0x043f, 0x6fd8 }, + { 0x8501, 0x042f, 0x5fd8 }, + { 0x8901, 0x0427, 0x4028 }, + { 0x8901, 0x0423, 0x3028 }, + { 0x8901, 0x0421, 0x2028 }, + { 0x0901, 0x0420, 0x0028 }, + { 0x0901, 0x0422, 0x0028 }, + { 0x8901, 0x0425, 0x2028 }, + { 0x0901, 0x0424, 0x0028 }, + { 0x0901, 0x0426, 0x0028 }, + { 0x8501, 0x042b, 0x3fd8 }, + { 0x8501, 0x0429, 0x2fd8 }, + { 0x0501, 0x0428, 0x0fd8 }, + { 0x0501, 0x042a, 0x0fd8 }, + { 0x8501, 0x042d, 0x2fd8 }, + { 0x0501, 0x042c, 0x0fd8 }, + { 0x0501, 0x042e, 0x0fd8 }, + { 0x8501, 0x0437, 0x4fd8 }, + { 0x8501, 0x0433, 0x3fd8 }, + { 0x8501, 0x0431, 0x2fd8 }, + { 0x0501, 0x0430, 0x0fd8 }, + { 0x0501, 0x0432, 0x0fd8 }, + { 0x8501, 0x0435, 0x2fd8 }, + { 0x0501, 0x0434, 0x0fd8 }, + { 0x0501, 0x0436, 0x0fd8 }, + { 0x8501, 0x043b, 0x3fd8 }, + { 0x8501, 0x0439, 0x2fd8 }, + { 0x0501, 0x0438, 0x0fd8 }, + { 0x0501, 0x043a, 0x0fd8 }, + { 0x8501, 0x043d, 0x2fd8 }, + { 0x0501, 0x043c, 0x0fd8 }, + { 0x0501, 0x043e, 0x0fd8 }, + { 0x8501, 0x044f, 0x5fd8 }, + { 0x8501, 0x0447, 0x4fd8 }, + { 0x8501, 0x0443, 0x3fd8 }, + { 0x8501, 0x0441, 0x2fd8 }, + { 0x0501, 0x0440, 0x0fd8 }, + { 0x0501, 0x0442, 0x0fd8 }, + { 0x8501, 0x0445, 0x2fd8 }, + { 0x0501, 0x0444, 0x0fd8 }, + { 0x0501, 0x0446, 0x0fd8 }, + { 0x8501, 0x044b, 0x3fd8 }, + { 0x8501, 0x0449, 0x2fd8 }, + { 0x0501, 0x0448, 0x0fd8 }, + { 0x0501, 0x044a, 0x0fd8 }, + { 0x8501, 0x044d, 0x2fd8 }, + { 0x0501, 0x044c, 0x0fd8 }, + { 0x0501, 0x044e, 0x0fd8 }, + { 0x8701, 0x0457, 0x4000 }, + { 0x8701, 0x0453, 0x3000 }, + { 0x8701, 0x0451, 0x2000 }, + { 0x0701, 0x0450, 0x0000 }, + { 0x0701, 0x0452, 0x0000 }, + { 0x8701, 0x0455, 0x2000 }, + { 0x0701, 0x0454, 0x0000 }, + { 0x0701, 0x0456, 0x0000 }, + { 0x8701, 0x045b, 0x3000 }, + { 0x8701, 0x0459, 0x2000 }, + { 0x0701, 0x0458, 0x0000 }, + { 0x0701, 0x045a, 0x0000 }, + { 0x8701, 0x045d, 0x2000 }, + { 0x0701, 0x045c, 0x0000 }, + { 0x0701, 0x045e, 0x0000 }, + { 0x9a01, 0xd000, 0x8000 }, + { 0x8d01, 0x04a1, 0x7000 }, + { 0x8701, 0x047f, 0x6000 }, + { 0x8701, 0x046f, 0x5000 }, + { 0x8701, 0x0467, 0x4000 }, + { 0x8701, 0x0463, 0x3000 }, + { 0x8701, 0x0461, 0x2000 }, + { 0x0701, 0x0460, 0x0000 }, + { 0x0701, 0x0462, 0x0000 }, + { 0x8701, 0x0465, 0x2000 }, + { 0x0701, 0x0464, 0x0000 }, + { 0x0701, 0x0466, 0x0000 }, + { 0x8701, 0x046b, 0x3000 }, + { 0x8701, 0x0469, 0x2000 }, + { 0x0701, 0x0468, 0x0000 }, + { 0x0701, 0x046a, 0x0000 }, + { 0x8701, 0x046d, 0x2000 }, + { 0x0701, 0x046c, 0x0000 }, + { 0x0701, 0x046e, 0x0000 }, + { 0x8701, 0x0477, 0x4000 }, + { 0x8701, 0x0473, 0x3000 }, + { 0x8701, 0x0471, 0x2000 }, + { 0x0701, 0x0470, 0x0000 }, + { 0x0701, 0x0472, 0x0000 }, + { 0x8701, 0x0475, 0x2000 }, + { 0x0701, 0x0474, 0x0000 }, + { 0x0701, 0x0476, 0x0000 }, + { 0x8701, 0x047b, 0x3000 }, + { 0x8701, 0x0479, 0x2000 }, + { 0x0701, 0x0478, 0x0000 }, + { 0x0701, 0x047a, 0x0000 }, + { 0x8701, 0x047d, 0x2000 }, + { 0x0701, 0x047c, 0x0000 }, + { 0x0701, 0x047e, 0x0000 }, + { 0x8701, 0x048f, 0x5000 }, + { 0x8701, 0x0487, 0x4000 }, + { 0x8701, 0x0483, 0x3000 }, + { 0x8701, 0x0481, 0x2000 }, + { 0x0701, 0x0480, 0x0000 }, + { 0x0701, 0x0482, 0x0000 }, + { 0x8701, 0x0485, 0x2000 }, + { 0x0701, 0x0484, 0x0000 }, + { 0x0701, 0x0486, 0x0000 }, + { 0x8701, 0x048b, 0x3000 }, + { 0x8701, 0x0489, 0x2000 }, + { 0x0701, 0x0488, 0x0000 }, + { 0x0701, 0x048a, 0x0000 }, + { 0x8701, 0x048d, 0x2000 }, + { 0x0701, 0x048c, 0x0000 }, + { 0x0701, 0x048e, 0x0000 }, + { 0x8701, 0x0497, 0x4000 }, + { 0x8701, 0x0493, 0x3000 }, + { 0x8701, 0x0491, 0x2000 }, + { 0x0701, 0x0490, 0x0000 }, + { 0x0701, 0x0492, 0x0000 }, + { 0x8701, 0x0495, 0x2000 }, + { 0x0701, 0x0494, 0x0000 }, + { 0x0701, 0x0496, 0x0000 }, + { 0x8701, 0x049b, 0x3000 }, + { 0x8701, 0x0499, 0x2000 }, + { 0x0701, 0x0498, 0x0000 }, + { 0x0701, 0x049a, 0x0000 }, + { 0x8701, 0x049d, 0x2000 }, + { 0x0701, 0x049c, 0x0000 }, + { 0x0d01, 0x04a0, 0x0000 }, + { 0x8701, 0x081a, 0x6000 }, + { 0x8701, 0x080a, 0x5000 }, + { 0x8d01, 0x04a9, 0x4000 }, + { 0x8d01, 0x04a5, 0x3000 }, + { 0x8d01, 0x04a3, 0x2000 }, + { 0x0d01, 0x04a2, 0x0000 }, + { 0x0d01, 0x04a4, 0x0000 }, + { 0x8d01, 0x04a7, 0x2000 }, + { 0x0d01, 0x04a6, 0x0000 }, + { 0x0d01, 0x04a8, 0x0000 }, + { 0x8701, 0x0803, 0x3000 }, + { 0x8701, 0x0801, 0x2000 }, + { 0x0701, 0x0800, 0x0000 }, + { 0x0701, 0x0802, 0x0000 }, + { 0x8701, 0x0805, 0x2000 }, + { 0x0701, 0x0804, 0x0000 }, + { 0x0701, 0x0808, 0x0000 }, + { 0x8701, 0x0812, 0x4000 }, + { 0x8701, 0x080e, 0x3000 }, + { 0x8701, 0x080c, 0x2000 }, + { 0x0701, 0x080b, 0x0000 }, + { 0x0701, 0x080d, 0x0000 }, + { 0x8701, 0x0810, 0x2000 }, + { 0x0701, 0x080f, 0x0000 }, + { 0x0701, 0x0811, 0x0000 }, + { 0x8701, 0x0816, 0x3000 }, + { 0x8701, 0x0814, 0x2000 }, + { 0x0701, 0x0813, 0x0000 }, + { 0x0701, 0x0815, 0x0000 }, + { 0x8701, 0x0818, 0x2000 }, + { 0x0701, 0x0817, 0x0000 }, + { 0x0701, 0x0819, 0x0000 }, + { 0x8701, 0x082a, 0x5000 }, + { 0x8701, 0x0822, 0x4000 }, + { 0x8701, 0x081e, 0x3000 }, + { 0x8701, 0x081c, 0x2000 }, + { 0x0701, 0x081b, 0x0000 }, + { 0x0701, 0x081d, 0x0000 }, + { 0x8701, 0x0820, 0x2000 }, + { 0x0701, 0x081f, 0x0000 }, + { 0x0701, 0x0821, 0x0000 }, + { 0x8701, 0x0826, 0x3000 }, + { 0x8701, 0x0824, 0x2000 }, + { 0x0701, 0x0823, 0x0000 }, + { 0x0701, 0x0825, 0x0000 }, + { 0x8701, 0x0828, 0x2000 }, + { 0x0701, 0x0827, 0x0000 }, + { 0x0701, 0x0829, 0x0000 }, + { 0x8701, 0x0832, 0x4000 }, + { 0x8701, 0x082e, 0x3000 }, + { 0x8701, 0x082c, 0x2000 }, + { 0x0701, 0x082b, 0x0000 }, + { 0x0701, 0x082d, 0x0000 }, + { 0x8701, 0x0830, 0x2000 }, + { 0x0701, 0x082f, 0x0000 }, + { 0x0701, 0x0831, 0x0000 }, + { 0x8701, 0x0837, 0x3000 }, + { 0x8701, 0x0834, 0x2000 }, + { 0x0701, 0x0833, 0x0000 }, + { 0x0701, 0x0835, 0x0000 }, + { 0x8701, 0x083c, 0x2000 }, + { 0x0701, 0x0838, 0x0000 }, + { 0x0701, 0x083f, 0x0000 }, + { 0x9a01, 0xd040, 0x7000 }, + { 0x9a01, 0xd020, 0x6000 }, + { 0x9a01, 0xd010, 0x5000 }, + { 0x9a01, 0xd008, 0x4000 }, + { 0x9a01, 0xd004, 0x3000 }, + { 0x9a01, 0xd002, 0x2000 }, + { 0x1a01, 0xd001, 0x0000 }, + { 0x1a01, 0xd003, 0x0000 }, + { 0x9a01, 0xd006, 0x2000 }, + { 0x1a01, 0xd005, 0x0000 }, + { 0x1a01, 0xd007, 0x0000 }, + { 0x9a01, 0xd00c, 0x3000 }, + { 0x9a01, 0xd00a, 0x2000 }, + { 0x1a01, 0xd009, 0x0000 }, + { 0x1a01, 0xd00b, 0x0000 }, + { 0x9a01, 0xd00e, 0x2000 }, + { 0x1a01, 0xd00d, 0x0000 }, + { 0x1a01, 0xd00f, 0x0000 }, + { 0x9a01, 0xd018, 0x4000 }, + { 0x9a01, 0xd014, 0x3000 }, + { 0x9a01, 0xd012, 0x2000 }, + { 0x1a01, 0xd011, 0x0000 }, + { 0x1a01, 0xd013, 0x0000 }, + { 0x9a01, 0xd016, 0x2000 }, + { 0x1a01, 0xd015, 0x0000 }, + { 0x1a01, 0xd017, 0x0000 }, + { 0x9a01, 0xd01c, 0x3000 }, + { 0x9a01, 0xd01a, 0x2000 }, + { 0x1a01, 0xd019, 0x0000 }, + { 0x1a01, 0xd01b, 0x0000 }, + { 0x9a01, 0xd01e, 0x2000 }, + { 0x1a01, 0xd01d, 0x0000 }, + { 0x1a01, 0xd01f, 0x0000 }, + { 0x9a01, 0xd030, 0x5000 }, + { 0x9a01, 0xd028, 0x4000 }, + { 0x9a01, 0xd024, 0x3000 }, + { 0x9a01, 0xd022, 0x2000 }, + { 0x1a01, 0xd021, 0x0000 }, + { 0x1a01, 0xd023, 0x0000 }, + { 0x9a01, 0xd026, 0x2000 }, + { 0x1a01, 0xd025, 0x0000 }, + { 0x1a01, 0xd027, 0x0000 }, + { 0x9a01, 0xd02c, 0x3000 }, + { 0x9a01, 0xd02a, 0x2000 }, + { 0x1a01, 0xd029, 0x0000 }, + { 0x1a01, 0xd02b, 0x0000 }, + { 0x9a01, 0xd02e, 0x2000 }, + { 0x1a01, 0xd02d, 0x0000 }, + { 0x1a01, 0xd02f, 0x0000 }, + { 0x9a01, 0xd038, 0x4000 }, + { 0x9a01, 0xd034, 0x3000 }, + { 0x9a01, 0xd032, 0x2000 }, + { 0x1a01, 0xd031, 0x0000 }, + { 0x1a01, 0xd033, 0x0000 }, + { 0x9a01, 0xd036, 0x2000 }, + { 0x1a01, 0xd035, 0x0000 }, + { 0x1a01, 0xd037, 0x0000 }, + { 0x9a01, 0xd03c, 0x3000 }, + { 0x9a01, 0xd03a, 0x2000 }, + { 0x1a01, 0xd039, 0x0000 }, + { 0x1a01, 0xd03b, 0x0000 }, + { 0x9a01, 0xd03e, 0x2000 }, + { 0x1a01, 0xd03d, 0x0000 }, + { 0x1a01, 0xd03f, 0x0000 }, + { 0x9a01, 0xd060, 0x6000 }, + { 0x9a01, 0xd050, 0x5000 }, + { 0x9a01, 0xd048, 0x4000 }, + { 0x9a01, 0xd044, 0x3000 }, + { 0x9a01, 0xd042, 0x2000 }, + { 0x1a01, 0xd041, 0x0000 }, + { 0x1a01, 0xd043, 0x0000 }, + { 0x9a01, 0xd046, 0x2000 }, + { 0x1a01, 0xd045, 0x0000 }, + { 0x1a01, 0xd047, 0x0000 }, + { 0x9a01, 0xd04c, 0x3000 }, + { 0x9a01, 0xd04a, 0x2000 }, + { 0x1a01, 0xd049, 0x0000 }, + { 0x1a01, 0xd04b, 0x0000 }, + { 0x9a01, 0xd04e, 0x2000 }, + { 0x1a01, 0xd04d, 0x0000 }, + { 0x1a01, 0xd04f, 0x0000 }, + { 0x9a01, 0xd058, 0x4000 }, + { 0x9a01, 0xd054, 0x3000 }, + { 0x9a01, 0xd052, 0x2000 }, + { 0x1a01, 0xd051, 0x0000 }, + { 0x1a01, 0xd053, 0x0000 }, + { 0x9a01, 0xd056, 0x2000 }, + { 0x1a01, 0xd055, 0x0000 }, + { 0x1a01, 0xd057, 0x0000 }, + { 0x9a01, 0xd05c, 0x3000 }, + { 0x9a01, 0xd05a, 0x2000 }, + { 0x1a01, 0xd059, 0x0000 }, + { 0x1a01, 0xd05b, 0x0000 }, + { 0x9a01, 0xd05e, 0x2000 }, + { 0x1a01, 0xd05d, 0x0000 }, + { 0x1a01, 0xd05f, 0x0000 }, + { 0x9a01, 0xd070, 0x5000 }, + { 0x9a01, 0xd068, 0x4000 }, + { 0x9a01, 0xd064, 0x3000 }, + { 0x9a01, 0xd062, 0x2000 }, + { 0x1a01, 0xd061, 0x0000 }, + { 0x1a01, 0xd063, 0x0000 }, + { 0x9a01, 0xd066, 0x2000 }, + { 0x1a01, 0xd065, 0x0000 }, + { 0x1a01, 0xd067, 0x0000 }, + { 0x9a01, 0xd06c, 0x3000 }, + { 0x9a01, 0xd06a, 0x2000 }, + { 0x1a01, 0xd069, 0x0000 }, + { 0x1a01, 0xd06b, 0x0000 }, + { 0x9a01, 0xd06e, 0x2000 }, + { 0x1a01, 0xd06d, 0x0000 }, + { 0x1a01, 0xd06f, 0x0000 }, + { 0x9a01, 0xd078, 0x4000 }, + { 0x9a01, 0xd074, 0x3000 }, + { 0x9a01, 0xd072, 0x2000 }, + { 0x1a01, 0xd071, 0x0000 }, + { 0x1a01, 0xd073, 0x0000 }, + { 0x9a01, 0xd076, 0x2000 }, + { 0x1a01, 0xd075, 0x0000 }, + { 0x1a01, 0xd077, 0x0000 }, + { 0x9a01, 0xd07c, 0x3000 }, + { 0x9a01, 0xd07a, 0x2000 }, + { 0x1a01, 0xd079, 0x0000 }, + { 0x1a01, 0xd07b, 0x0000 }, + { 0x9a01, 0xd07e, 0x2000 }, + { 0x1a01, 0xd07d, 0x0000 }, + { 0x1a01, 0xd07f, 0x0000 }, + { 0x9a01, 0xd18d, 0x9000 }, + { 0x9a01, 0xd10a, 0x8000 }, + { 0x9a01, 0xd0c0, 0x7000 }, + { 0x9a01, 0xd0a0, 0x6000 }, + { 0x9a01, 0xd090, 0x5000 }, + { 0x9a01, 0xd088, 0x4000 }, + { 0x9a01, 0xd084, 0x3000 }, + { 0x9a01, 0xd082, 0x2000 }, + { 0x1a01, 0xd081, 0x0000 }, + { 0x1a01, 0xd083, 0x0000 }, + { 0x9a01, 0xd086, 0x2000 }, + { 0x1a01, 0xd085, 0x0000 }, + { 0x1a01, 0xd087, 0x0000 }, + { 0x9a01, 0xd08c, 0x3000 }, + { 0x9a01, 0xd08a, 0x2000 }, + { 0x1a01, 0xd089, 0x0000 }, + { 0x1a01, 0xd08b, 0x0000 }, + { 0x9a01, 0xd08e, 0x2000 }, + { 0x1a01, 0xd08d, 0x0000 }, + { 0x1a01, 0xd08f, 0x0000 }, + { 0x9a01, 0xd098, 0x4000 }, + { 0x9a01, 0xd094, 0x3000 }, + { 0x9a01, 0xd092, 0x2000 }, + { 0x1a01, 0xd091, 0x0000 }, + { 0x1a01, 0xd093, 0x0000 }, + { 0x9a01, 0xd096, 0x2000 }, + { 0x1a01, 0xd095, 0x0000 }, + { 0x1a01, 0xd097, 0x0000 }, + { 0x9a01, 0xd09c, 0x3000 }, + { 0x9a01, 0xd09a, 0x2000 }, + { 0x1a01, 0xd099, 0x0000 }, + { 0x1a01, 0xd09b, 0x0000 }, + { 0x9a01, 0xd09e, 0x2000 }, + { 0x1a01, 0xd09d, 0x0000 }, + { 0x1a01, 0xd09f, 0x0000 }, + { 0x9a01, 0xd0b0, 0x5000 }, + { 0x9a01, 0xd0a8, 0x4000 }, + { 0x9a01, 0xd0a4, 0x3000 }, + { 0x9a01, 0xd0a2, 0x2000 }, + { 0x1a01, 0xd0a1, 0x0000 }, + { 0x1a01, 0xd0a3, 0x0000 }, + { 0x9a01, 0xd0a6, 0x2000 }, + { 0x1a01, 0xd0a5, 0x0000 }, + { 0x1a01, 0xd0a7, 0x0000 }, + { 0x9a01, 0xd0ac, 0x3000 }, + { 0x9a01, 0xd0aa, 0x2000 }, + { 0x1a01, 0xd0a9, 0x0000 }, + { 0x1a01, 0xd0ab, 0x0000 }, + { 0x9a01, 0xd0ae, 0x2000 }, + { 0x1a01, 0xd0ad, 0x0000 }, + { 0x1a01, 0xd0af, 0x0000 }, + { 0x9a01, 0xd0b8, 0x4000 }, + { 0x9a01, 0xd0b4, 0x3000 }, + { 0x9a01, 0xd0b2, 0x2000 }, + { 0x1a01, 0xd0b1, 0x0000 }, + { 0x1a01, 0xd0b3, 0x0000 }, + { 0x9a01, 0xd0b6, 0x2000 }, + { 0x1a01, 0xd0b5, 0x0000 }, + { 0x1a01, 0xd0b7, 0x0000 }, + { 0x9a01, 0xd0bc, 0x3000 }, + { 0x9a01, 0xd0ba, 0x2000 }, + { 0x1a01, 0xd0b9, 0x0000 }, + { 0x1a01, 0xd0bb, 0x0000 }, + { 0x9a01, 0xd0be, 0x2000 }, + { 0x1a01, 0xd0bd, 0x0000 }, + { 0x1a01, 0xd0bf, 0x0000 }, + { 0x9a01, 0xd0e0, 0x6000 }, + { 0x9a01, 0xd0d0, 0x5000 }, + { 0x9a01, 0xd0c8, 0x4000 }, + { 0x9a01, 0xd0c4, 0x3000 }, + { 0x9a01, 0xd0c2, 0x2000 }, + { 0x1a01, 0xd0c1, 0x0000 }, + { 0x1a01, 0xd0c3, 0x0000 }, + { 0x9a01, 0xd0c6, 0x2000 }, + { 0x1a01, 0xd0c5, 0x0000 }, + { 0x1a01, 0xd0c7, 0x0000 }, + { 0x9a01, 0xd0cc, 0x3000 }, + { 0x9a01, 0xd0ca, 0x2000 }, + { 0x1a01, 0xd0c9, 0x0000 }, + { 0x1a01, 0xd0cb, 0x0000 }, + { 0x9a01, 0xd0ce, 0x2000 }, + { 0x1a01, 0xd0cd, 0x0000 }, + { 0x1a01, 0xd0cf, 0x0000 }, + { 0x9a01, 0xd0d8, 0x4000 }, + { 0x9a01, 0xd0d4, 0x3000 }, + { 0x9a01, 0xd0d2, 0x2000 }, + { 0x1a01, 0xd0d1, 0x0000 }, + { 0x1a01, 0xd0d3, 0x0000 }, + { 0x9a01, 0xd0d6, 0x2000 }, + { 0x1a01, 0xd0d5, 0x0000 }, + { 0x1a01, 0xd0d7, 0x0000 }, + { 0x9a01, 0xd0dc, 0x3000 }, + { 0x9a01, 0xd0da, 0x2000 }, + { 0x1a01, 0xd0d9, 0x0000 }, + { 0x1a01, 0xd0db, 0x0000 }, + { 0x9a01, 0xd0de, 0x2000 }, + { 0x1a01, 0xd0dd, 0x0000 }, + { 0x1a01, 0xd0df, 0x0000 }, + { 0x9a01, 0xd0f0, 0x5000 }, + { 0x9a01, 0xd0e8, 0x4000 }, + { 0x9a01, 0xd0e4, 0x3000 }, + { 0x9a01, 0xd0e2, 0x2000 }, + { 0x1a01, 0xd0e1, 0x0000 }, + { 0x1a01, 0xd0e3, 0x0000 }, + { 0x9a01, 0xd0e6, 0x2000 }, + { 0x1a01, 0xd0e5, 0x0000 }, + { 0x1a01, 0xd0e7, 0x0000 }, + { 0x9a01, 0xd0ec, 0x3000 }, + { 0x9a01, 0xd0ea, 0x2000 }, + { 0x1a01, 0xd0e9, 0x0000 }, + { 0x1a01, 0xd0eb, 0x0000 }, + { 0x9a01, 0xd0ee, 0x2000 }, + { 0x1a01, 0xd0ed, 0x0000 }, + { 0x1a01, 0xd0ef, 0x0000 }, + { 0x9a01, 0xd102, 0x4000 }, + { 0x9a01, 0xd0f4, 0x3000 }, + { 0x9a01, 0xd0f2, 0x2000 }, + { 0x1a01, 0xd0f1, 0x0000 }, + { 0x1a01, 0xd0f3, 0x0000 }, + { 0x9a01, 0xd100, 0x2000 }, + { 0x1a01, 0xd0f5, 0x0000 }, + { 0x1a01, 0xd101, 0x0000 }, + { 0x9a01, 0xd106, 0x3000 }, + { 0x9a01, 0xd104, 0x2000 }, + { 0x1a01, 0xd103, 0x0000 }, + { 0x1a01, 0xd105, 0x0000 }, + { 0x9a01, 0xd108, 0x2000 }, + { 0x1a01, 0xd107, 0x0000 }, + { 0x1a01, 0xd109, 0x0000 }, + { 0x9a01, 0xd14d, 0x7000 }, + { 0x9a01, 0xd12d, 0x6000 }, + { 0x9a01, 0xd11a, 0x5000 }, + { 0x9a01, 0xd112, 0x4000 }, + { 0x9a01, 0xd10e, 0x3000 }, + { 0x9a01, 0xd10c, 0x2000 }, + { 0x1a01, 0xd10b, 0x0000 }, + { 0x1a01, 0xd10d, 0x0000 }, + { 0x9a01, 0xd110, 0x2000 }, + { 0x1a01, 0xd10f, 0x0000 }, + { 0x1a01, 0xd111, 0x0000 }, + { 0x9a01, 0xd116, 0x3000 }, + { 0x9a01, 0xd114, 0x2000 }, + { 0x1a01, 0xd113, 0x0000 }, + { 0x1a01, 0xd115, 0x0000 }, + { 0x9a01, 0xd118, 0x2000 }, + { 0x1a01, 0xd117, 0x0000 }, + { 0x1a01, 0xd119, 0x0000 }, + { 0x9a01, 0xd122, 0x4000 }, + { 0x9a01, 0xd11e, 0x3000 }, + { 0x9a01, 0xd11c, 0x2000 }, + { 0x1a01, 0xd11b, 0x0000 }, + { 0x1a01, 0xd11d, 0x0000 }, + { 0x9a01, 0xd120, 0x2000 }, + { 0x1a01, 0xd11f, 0x0000 }, + { 0x1a01, 0xd121, 0x0000 }, + { 0x9a01, 0xd126, 0x3000 }, + { 0x9a01, 0xd124, 0x2000 }, + { 0x1a01, 0xd123, 0x0000 }, + { 0x1a01, 0xd125, 0x0000 }, + { 0x9a01, 0xd12b, 0x2000 }, + { 0x1a01, 0xd12a, 0x0000 }, + { 0x1a01, 0xd12c, 0x0000 }, + { 0x9a01, 0xd13d, 0x5000 }, + { 0x9a01, 0xd135, 0x4000 }, + { 0x9a01, 0xd131, 0x3000 }, + { 0x9a01, 0xd12f, 0x2000 }, + { 0x1a01, 0xd12e, 0x0000 }, + { 0x1a01, 0xd130, 0x0000 }, + { 0x9a01, 0xd133, 0x2000 }, + { 0x1a01, 0xd132, 0x0000 }, + { 0x1a01, 0xd134, 0x0000 }, + { 0x9a01, 0xd139, 0x3000 }, + { 0x9a01, 0xd137, 0x2000 }, + { 0x1a01, 0xd136, 0x0000 }, + { 0x1a01, 0xd138, 0x0000 }, + { 0x9a01, 0xd13b, 0x2000 }, + { 0x1a01, 0xd13a, 0x0000 }, + { 0x1a01, 0xd13c, 0x0000 }, + { 0x9a01, 0xd145, 0x4000 }, + { 0x9a01, 0xd141, 0x3000 }, + { 0x9a01, 0xd13f, 0x2000 }, + { 0x1a01, 0xd13e, 0x0000 }, + { 0x1a01, 0xd140, 0x0000 }, + { 0x9a01, 0xd143, 0x2000 }, + { 0x1a01, 0xd142, 0x0000 }, + { 0x1a01, 0xd144, 0x0000 }, + { 0x9a01, 0xd149, 0x3000 }, + { 0x9a01, 0xd147, 0x2000 }, + { 0x1a01, 0xd146, 0x0000 }, + { 0x1a01, 0xd148, 0x0000 }, + { 0x9a01, 0xd14b, 0x2000 }, + { 0x1a01, 0xd14a, 0x0000 }, + { 0x1a01, 0xd14c, 0x0000 }, + { 0x8a01, 0xd16d, 0x6000 }, + { 0x9a01, 0xd15d, 0x5000 }, + { 0x9a01, 0xd155, 0x4000 }, + { 0x9a01, 0xd151, 0x3000 }, + { 0x9a01, 0xd14f, 0x2000 }, + { 0x1a01, 0xd14e, 0x0000 }, + { 0x1a01, 0xd150, 0x0000 }, + { 0x9a01, 0xd153, 0x2000 }, + { 0x1a01, 0xd152, 0x0000 }, + { 0x1a01, 0xd154, 0x0000 }, + { 0x9a01, 0xd159, 0x3000 }, + { 0x9a01, 0xd157, 0x2000 }, + { 0x1a01, 0xd156, 0x0000 }, + { 0x1a01, 0xd158, 0x0000 }, + { 0x9a01, 0xd15b, 0x2000 }, + { 0x1a01, 0xd15a, 0x0000 }, + { 0x1a01, 0xd15c, 0x0000 }, + { 0x8a01, 0xd165, 0x4000 }, + { 0x9a01, 0xd161, 0x3000 }, + { 0x9a01, 0xd15f, 0x2000 }, + { 0x1a01, 0xd15e, 0x0000 }, + { 0x1a01, 0xd160, 0x0000 }, + { 0x9a01, 0xd163, 0x2000 }, + { 0x1a01, 0xd162, 0x0000 }, + { 0x1a01, 0xd164, 0x0000 }, + { 0x8c01, 0xd169, 0x3000 }, + { 0x8c01, 0xd167, 0x2000 }, + { 0x0a01, 0xd166, 0x0000 }, + { 0x0c01, 0xd168, 0x0000 }, + { 0x9a01, 0xd16b, 0x2000 }, + { 0x1a01, 0xd16a, 0x0000 }, + { 0x1a01, 0xd16c, 0x0000 }, + { 0x8c01, 0xd17d, 0x5000 }, + { 0x8101, 0xd175, 0x4000 }, + { 0x8a01, 0xd171, 0x3000 }, + { 0x8a01, 0xd16f, 0x2000 }, + { 0x0a01, 0xd16e, 0x0000 }, + { 0x0a01, 0xd170, 0x0000 }, + { 0x8101, 0xd173, 0x2000 }, + { 0x0a01, 0xd172, 0x0000 }, + { 0x0101, 0xd174, 0x0000 }, + { 0x8101, 0xd179, 0x3000 }, + { 0x8101, 0xd177, 0x2000 }, + { 0x0101, 0xd176, 0x0000 }, + { 0x0101, 0xd178, 0x0000 }, + { 0x8c01, 0xd17b, 0x2000 }, + { 0x0101, 0xd17a, 0x0000 }, + { 0x0c01, 0xd17c, 0x0000 }, + { 0x8c01, 0xd185, 0x4000 }, + { 0x8c01, 0xd181, 0x3000 }, + { 0x8c01, 0xd17f, 0x2000 }, + { 0x0c01, 0xd17e, 0x0000 }, + { 0x0c01, 0xd180, 0x0000 }, + { 0x9a01, 0xd183, 0x2000 }, + { 0x0c01, 0xd182, 0x0000 }, + { 0x1a01, 0xd184, 0x0000 }, + { 0x8c01, 0xd189, 0x3000 }, + { 0x8c01, 0xd187, 0x2000 }, + { 0x0c01, 0xd186, 0x0000 }, + { 0x0c01, 0xd188, 0x0000 }, + { 0x8c01, 0xd18b, 0x2000 }, + { 0x0c01, 0xd18a, 0x0000 }, + { 0x1a01, 0xd18c, 0x0000 }, + { 0x9a01, 0xd32f, 0x8000 }, + { 0x9a01, 0xd1cd, 0x7000 }, + { 0x8c01, 0xd1ad, 0x6000 }, + { 0x9a01, 0xd19d, 0x5000 }, + { 0x9a01, 0xd195, 0x4000 }, + { 0x9a01, 0xd191, 0x3000 }, + { 0x9a01, 0xd18f, 0x2000 }, + { 0x1a01, 0xd18e, 0x0000 }, + { 0x1a01, 0xd190, 0x0000 }, + { 0x9a01, 0xd193, 0x2000 }, + { 0x1a01, 0xd192, 0x0000 }, + { 0x1a01, 0xd194, 0x0000 }, + { 0x9a01, 0xd199, 0x3000 }, + { 0x9a01, 0xd197, 0x2000 }, + { 0x1a01, 0xd196, 0x0000 }, + { 0x1a01, 0xd198, 0x0000 }, + { 0x9a01, 0xd19b, 0x2000 }, + { 0x1a01, 0xd19a, 0x0000 }, + { 0x1a01, 0xd19c, 0x0000 }, + { 0x9a01, 0xd1a5, 0x4000 }, + { 0x9a01, 0xd1a1, 0x3000 }, + { 0x9a01, 0xd19f, 0x2000 }, + { 0x1a01, 0xd19e, 0x0000 }, + { 0x1a01, 0xd1a0, 0x0000 }, + { 0x9a01, 0xd1a3, 0x2000 }, + { 0x1a01, 0xd1a2, 0x0000 }, + { 0x1a01, 0xd1a4, 0x0000 }, + { 0x9a01, 0xd1a9, 0x3000 }, + { 0x9a01, 0xd1a7, 0x2000 }, + { 0x1a01, 0xd1a6, 0x0000 }, + { 0x1a01, 0xd1a8, 0x0000 }, + { 0x8c01, 0xd1ab, 0x2000 }, + { 0x0c01, 0xd1aa, 0x0000 }, + { 0x0c01, 0xd1ac, 0x0000 }, + { 0x9a01, 0xd1bd, 0x5000 }, + { 0x9a01, 0xd1b5, 0x4000 }, + { 0x9a01, 0xd1b1, 0x3000 }, + { 0x9a01, 0xd1af, 0x2000 }, + { 0x1a01, 0xd1ae, 0x0000 }, + { 0x1a01, 0xd1b0, 0x0000 }, + { 0x9a01, 0xd1b3, 0x2000 }, + { 0x1a01, 0xd1b2, 0x0000 }, + { 0x1a01, 0xd1b4, 0x0000 }, + { 0x9a01, 0xd1b9, 0x3000 }, + { 0x9a01, 0xd1b7, 0x2000 }, + { 0x1a01, 0xd1b6, 0x0000 }, + { 0x1a01, 0xd1b8, 0x0000 }, + { 0x9a01, 0xd1bb, 0x2000 }, + { 0x1a01, 0xd1ba, 0x0000 }, + { 0x1a01, 0xd1bc, 0x0000 }, + { 0x9a01, 0xd1c5, 0x4000 }, + { 0x9a01, 0xd1c1, 0x3000 }, + { 0x9a01, 0xd1bf, 0x2000 }, + { 0x1a01, 0xd1be, 0x0000 }, + { 0x1a01, 0xd1c0, 0x0000 }, + { 0x9a01, 0xd1c3, 0x2000 }, + { 0x1a01, 0xd1c2, 0x0000 }, + { 0x1a01, 0xd1c4, 0x0000 }, + { 0x9a01, 0xd1c9, 0x3000 }, + { 0x9a01, 0xd1c7, 0x2000 }, + { 0x1a01, 0xd1c6, 0x0000 }, + { 0x1a01, 0xd1c8, 0x0000 }, + { 0x9a01, 0xd1cb, 0x2000 }, + { 0x1a01, 0xd1ca, 0x0000 }, + { 0x1a01, 0xd1cc, 0x0000 }, + { 0x9a01, 0xd30f, 0x6000 }, + { 0x9a01, 0xd1dd, 0x5000 }, + { 0x9a01, 0xd1d5, 0x4000 }, + { 0x9a01, 0xd1d1, 0x3000 }, + { 0x9a01, 0xd1cf, 0x2000 }, + { 0x1a01, 0xd1ce, 0x0000 }, + { 0x1a01, 0xd1d0, 0x0000 }, + { 0x9a01, 0xd1d3, 0x2000 }, + { 0x1a01, 0xd1d2, 0x0000 }, + { 0x1a01, 0xd1d4, 0x0000 }, + { 0x9a01, 0xd1d9, 0x3000 }, + { 0x9a01, 0xd1d7, 0x2000 }, + { 0x1a01, 0xd1d6, 0x0000 }, + { 0x1a01, 0xd1d8, 0x0000 }, + { 0x9a01, 0xd1db, 0x2000 }, + { 0x1a01, 0xd1da, 0x0000 }, + { 0x1a01, 0xd1dc, 0x0000 }, + { 0x9a01, 0xd307, 0x4000 }, + { 0x9a01, 0xd303, 0x3000 }, + { 0x9a01, 0xd301, 0x2000 }, + { 0x1a01, 0xd300, 0x0000 }, + { 0x1a01, 0xd302, 0x0000 }, + { 0x9a01, 0xd305, 0x2000 }, + { 0x1a01, 0xd304, 0x0000 }, + { 0x1a01, 0xd306, 0x0000 }, + { 0x9a01, 0xd30b, 0x3000 }, + { 0x9a01, 0xd309, 0x2000 }, + { 0x1a01, 0xd308, 0x0000 }, + { 0x1a01, 0xd30a, 0x0000 }, + { 0x9a01, 0xd30d, 0x2000 }, + { 0x1a01, 0xd30c, 0x0000 }, + { 0x1a01, 0xd30e, 0x0000 }, + { 0x9a01, 0xd31f, 0x5000 }, + { 0x9a01, 0xd317, 0x4000 }, + { 0x9a01, 0xd313, 0x3000 }, + { 0x9a01, 0xd311, 0x2000 }, + { 0x1a01, 0xd310, 0x0000 }, + { 0x1a01, 0xd312, 0x0000 }, + { 0x9a01, 0xd315, 0x2000 }, + { 0x1a01, 0xd314, 0x0000 }, + { 0x1a01, 0xd316, 0x0000 }, + { 0x9a01, 0xd31b, 0x3000 }, + { 0x9a01, 0xd319, 0x2000 }, + { 0x1a01, 0xd318, 0x0000 }, + { 0x1a01, 0xd31a, 0x0000 }, + { 0x9a01, 0xd31d, 0x2000 }, + { 0x1a01, 0xd31c, 0x0000 }, + { 0x1a01, 0xd31e, 0x0000 }, + { 0x9a01, 0xd327, 0x4000 }, + { 0x9a01, 0xd323, 0x3000 }, + { 0x9a01, 0xd321, 0x2000 }, + { 0x1a01, 0xd320, 0x0000 }, + { 0x1a01, 0xd322, 0x0000 }, + { 0x9a01, 0xd325, 0x2000 }, + { 0x1a01, 0xd324, 0x0000 }, + { 0x1a01, 0xd326, 0x0000 }, + { 0x9a01, 0xd32b, 0x3000 }, + { 0x9a01, 0xd329, 0x2000 }, + { 0x1a01, 0xd328, 0x0000 }, + { 0x1a01, 0xd32a, 0x0000 }, + { 0x9a01, 0xd32d, 0x2000 }, + { 0x1a01, 0xd32c, 0x0000 }, + { 0x1a01, 0xd32e, 0x0000 }, + { 0x8901, 0xd418, 0x7000 }, + { 0x9a01, 0xd34f, 0x6000 }, + { 0x9a01, 0xd33f, 0x5000 }, + { 0x9a01, 0xd337, 0x4000 }, + { 0x9a01, 0xd333, 0x3000 }, + { 0x9a01, 0xd331, 0x2000 }, + { 0x1a01, 0xd330, 0x0000 }, + { 0x1a01, 0xd332, 0x0000 }, + { 0x9a01, 0xd335, 0x2000 }, + { 0x1a01, 0xd334, 0x0000 }, + { 0x1a01, 0xd336, 0x0000 }, + { 0x9a01, 0xd33b, 0x3000 }, + { 0x9a01, 0xd339, 0x2000 }, + { 0x1a01, 0xd338, 0x0000 }, + { 0x1a01, 0xd33a, 0x0000 }, + { 0x9a01, 0xd33d, 0x2000 }, + { 0x1a01, 0xd33c, 0x0000 }, + { 0x1a01, 0xd33e, 0x0000 }, + { 0x9a01, 0xd347, 0x4000 }, + { 0x9a01, 0xd343, 0x3000 }, + { 0x9a01, 0xd341, 0x2000 }, + { 0x1a01, 0xd340, 0x0000 }, + { 0x1a01, 0xd342, 0x0000 }, + { 0x9a01, 0xd345, 0x2000 }, + { 0x1a01, 0xd344, 0x0000 }, + { 0x1a01, 0xd346, 0x0000 }, + { 0x9a01, 0xd34b, 0x3000 }, + { 0x9a01, 0xd349, 0x2000 }, + { 0x1a01, 0xd348, 0x0000 }, + { 0x1a01, 0xd34a, 0x0000 }, + { 0x9a01, 0xd34d, 0x2000 }, + { 0x1a01, 0xd34c, 0x0000 }, + { 0x1a01, 0xd34e, 0x0000 }, + { 0x8901, 0xd408, 0x5000 }, + { 0x8901, 0xd400, 0x4000 }, + { 0x9a01, 0xd353, 0x3000 }, + { 0x9a01, 0xd351, 0x2000 }, + { 0x1a01, 0xd350, 0x0000 }, + { 0x1a01, 0xd352, 0x0000 }, + { 0x9a01, 0xd355, 0x2000 }, + { 0x1a01, 0xd354, 0x0000 }, + { 0x1a01, 0xd356, 0x0000 }, + { 0x8901, 0xd404, 0x3000 }, + { 0x8901, 0xd402, 0x2000 }, + { 0x0901, 0xd401, 0x0000 }, + { 0x0901, 0xd403, 0x0000 }, + { 0x8901, 0xd406, 0x2000 }, + { 0x0901, 0xd405, 0x0000 }, + { 0x0901, 0xd407, 0x0000 }, + { 0x8901, 0xd410, 0x4000 }, + { 0x8901, 0xd40c, 0x3000 }, + { 0x8901, 0xd40a, 0x2000 }, + { 0x0901, 0xd409, 0x0000 }, + { 0x0901, 0xd40b, 0x0000 }, + { 0x8901, 0xd40e, 0x2000 }, + { 0x0901, 0xd40d, 0x0000 }, + { 0x0901, 0xd40f, 0x0000 }, + { 0x8901, 0xd414, 0x3000 }, + { 0x8901, 0xd412, 0x2000 }, + { 0x0901, 0xd411, 0x0000 }, + { 0x0901, 0xd413, 0x0000 }, + { 0x8901, 0xd416, 0x2000 }, + { 0x0901, 0xd415, 0x0000 }, + { 0x0901, 0xd417, 0x0000 }, + { 0x8901, 0xd438, 0x6000 }, + { 0x8501, 0xd428, 0x5000 }, + { 0x8501, 0xd420, 0x4000 }, + { 0x8501, 0xd41c, 0x3000 }, + { 0x8501, 0xd41a, 0x2000 }, + { 0x0901, 0xd419, 0x0000 }, + { 0x0501, 0xd41b, 0x0000 }, + { 0x8501, 0xd41e, 0x2000 }, + { 0x0501, 0xd41d, 0x0000 }, + { 0x0501, 0xd41f, 0x0000 }, + { 0x8501, 0xd424, 0x3000 }, + { 0x8501, 0xd422, 0x2000 }, + { 0x0501, 0xd421, 0x0000 }, + { 0x0501, 0xd423, 0x0000 }, + { 0x8501, 0xd426, 0x2000 }, + { 0x0501, 0xd425, 0x0000 }, + { 0x0501, 0xd427, 0x0000 }, + { 0x8501, 0xd430, 0x4000 }, + { 0x8501, 0xd42c, 0x3000 }, + { 0x8501, 0xd42a, 0x2000 }, + { 0x0501, 0xd429, 0x0000 }, + { 0x0501, 0xd42b, 0x0000 }, + { 0x8501, 0xd42e, 0x2000 }, + { 0x0501, 0xd42d, 0x0000 }, + { 0x0501, 0xd42f, 0x0000 }, + { 0x8901, 0xd434, 0x3000 }, + { 0x8501, 0xd432, 0x2000 }, + { 0x0501, 0xd431, 0x0000 }, + { 0x0501, 0xd433, 0x0000 }, + { 0x8901, 0xd436, 0x2000 }, + { 0x0901, 0xd435, 0x0000 }, + { 0x0901, 0xd437, 0x0000 }, + { 0x8901, 0xd448, 0x5000 }, + { 0x8901, 0xd440, 0x4000 }, + { 0x8901, 0xd43c, 0x3000 }, + { 0x8901, 0xd43a, 0x2000 }, + { 0x0901, 0xd439, 0x0000 }, + { 0x0901, 0xd43b, 0x0000 }, + { 0x8901, 0xd43e, 0x2000 }, + { 0x0901, 0xd43d, 0x0000 }, + { 0x0901, 0xd43f, 0x0000 }, + { 0x8901, 0xd444, 0x3000 }, + { 0x8901, 0xd442, 0x2000 }, + { 0x0901, 0xd441, 0x0000 }, + { 0x0901, 0xd443, 0x0000 }, + { 0x8901, 0xd446, 0x2000 }, + { 0x0901, 0xd445, 0x0000 }, + { 0x0901, 0xd447, 0x0000 }, + { 0x8501, 0xd450, 0x4000 }, + { 0x8901, 0xd44c, 0x3000 }, + { 0x8901, 0xd44a, 0x2000 }, + { 0x0901, 0xd449, 0x0000 }, + { 0x0901, 0xd44b, 0x0000 }, + { 0x8501, 0xd44e, 0x2000 }, + { 0x0901, 0xd44d, 0x0000 }, + { 0x0501, 0xd44f, 0x0000 }, + { 0x8501, 0xd454, 0x3000 }, + { 0x8501, 0xd452, 0x2000 }, + { 0x0501, 0xd451, 0x0000 }, + { 0x0501, 0xd453, 0x0000 }, + { 0x8501, 0xd457, 0x2000 }, + { 0x0501, 0xd456, 0x0000 }, + { 0x0501, 0xd458, 0x0000 }, + { 0x8702, 0xf876, 0xb000 }, + { 0x8901, 0xd670, 0xa000 }, + { 0x8901, 0xd570, 0x9000 }, + { 0x8901, 0xd4e4, 0x8000 }, + { 0x8501, 0xd499, 0x7000 }, + { 0x8901, 0xd479, 0x6000 }, + { 0x8901, 0xd469, 0x5000 }, + { 0x8501, 0xd461, 0x4000 }, + { 0x8501, 0xd45d, 0x3000 }, + { 0x8501, 0xd45b, 0x2000 }, + { 0x0501, 0xd45a, 0x0000 }, + { 0x0501, 0xd45c, 0x0000 }, + { 0x8501, 0xd45f, 0x2000 }, + { 0x0501, 0xd45e, 0x0000 }, + { 0x0501, 0xd460, 0x0000 }, + { 0x8501, 0xd465, 0x3000 }, + { 0x8501, 0xd463, 0x2000 }, + { 0x0501, 0xd462, 0x0000 }, + { 0x0501, 0xd464, 0x0000 }, + { 0x8501, 0xd467, 0x2000 }, + { 0x0501, 0xd466, 0x0000 }, + { 0x0901, 0xd468, 0x0000 }, + { 0x8901, 0xd471, 0x4000 }, + { 0x8901, 0xd46d, 0x3000 }, + { 0x8901, 0xd46b, 0x2000 }, + { 0x0901, 0xd46a, 0x0000 }, + { 0x0901, 0xd46c, 0x0000 }, + { 0x8901, 0xd46f, 0x2000 }, + { 0x0901, 0xd46e, 0x0000 }, + { 0x0901, 0xd470, 0x0000 }, + { 0x8901, 0xd475, 0x3000 }, + { 0x8901, 0xd473, 0x2000 }, + { 0x0901, 0xd472, 0x0000 }, + { 0x0901, 0xd474, 0x0000 }, + { 0x8901, 0xd477, 0x2000 }, + { 0x0901, 0xd476, 0x0000 }, + { 0x0901, 0xd478, 0x0000 }, + { 0x8501, 0xd489, 0x5000 }, + { 0x8901, 0xd481, 0x4000 }, + { 0x8901, 0xd47d, 0x3000 }, + { 0x8901, 0xd47b, 0x2000 }, + { 0x0901, 0xd47a, 0x0000 }, + { 0x0901, 0xd47c, 0x0000 }, + { 0x8901, 0xd47f, 0x2000 }, + { 0x0901, 0xd47e, 0x0000 }, + { 0x0901, 0xd480, 0x0000 }, + { 0x8501, 0xd485, 0x3000 }, + { 0x8501, 0xd483, 0x2000 }, + { 0x0501, 0xd482, 0x0000 }, + { 0x0501, 0xd484, 0x0000 }, + { 0x8501, 0xd487, 0x2000 }, + { 0x0501, 0xd486, 0x0000 }, + { 0x0501, 0xd488, 0x0000 }, + { 0x8501, 0xd491, 0x4000 }, + { 0x8501, 0xd48d, 0x3000 }, + { 0x8501, 0xd48b, 0x2000 }, + { 0x0501, 0xd48a, 0x0000 }, + { 0x0501, 0xd48c, 0x0000 }, + { 0x8501, 0xd48f, 0x2000 }, + { 0x0501, 0xd48e, 0x0000 }, + { 0x0501, 0xd490, 0x0000 }, + { 0x8501, 0xd495, 0x3000 }, + { 0x8501, 0xd493, 0x2000 }, + { 0x0501, 0xd492, 0x0000 }, + { 0x0501, 0xd494, 0x0000 }, + { 0x8501, 0xd497, 0x2000 }, + { 0x0501, 0xd496, 0x0000 }, + { 0x0501, 0xd498, 0x0000 }, + { 0x8501, 0xd4c3, 0x6000 }, + { 0x8901, 0xd4b1, 0x5000 }, + { 0x8901, 0xd4a6, 0x4000 }, + { 0x8901, 0xd49e, 0x3000 }, + { 0x8501, 0xd49b, 0x2000 }, + { 0x0501, 0xd49a, 0x0000 }, + { 0x0901, 0xd49c, 0x0000 }, + { 0x8901, 0xd4a2, 0x2000 }, + { 0x0901, 0xd49f, 0x0000 }, + { 0x0901, 0xd4a5, 0x0000 }, + { 0x8901, 0xd4ac, 0x3000 }, + { 0x8901, 0xd4aa, 0x2000 }, + { 0x0901, 0xd4a9, 0x0000 }, + { 0x0901, 0xd4ab, 0x0000 }, + { 0x8901, 0xd4af, 0x2000 }, + { 0x0901, 0xd4ae, 0x0000 }, + { 0x0901, 0xd4b0, 0x0000 }, + { 0x8501, 0xd4b9, 0x4000 }, + { 0x8901, 0xd4b5, 0x3000 }, + { 0x8901, 0xd4b3, 0x2000 }, + { 0x0901, 0xd4b2, 0x0000 }, + { 0x0901, 0xd4b4, 0x0000 }, + { 0x8501, 0xd4b7, 0x2000 }, + { 0x0501, 0xd4b6, 0x0000 }, + { 0x0501, 0xd4b8, 0x0000 }, + { 0x8501, 0xd4bf, 0x3000 }, + { 0x8501, 0xd4bd, 0x2000 }, + { 0x0501, 0xd4bb, 0x0000 }, + { 0x0501, 0xd4be, 0x0000 }, + { 0x8501, 0xd4c1, 0x2000 }, + { 0x0501, 0xd4c0, 0x0000 }, + { 0x0501, 0xd4c2, 0x0000 }, + { 0x8901, 0xd4d4, 0x5000 }, + { 0x8501, 0xd4cc, 0x4000 }, + { 0x8501, 0xd4c8, 0x3000 }, + { 0x8501, 0xd4c6, 0x2000 }, + { 0x0501, 0xd4c5, 0x0000 }, + { 0x0501, 0xd4c7, 0x0000 }, + { 0x8501, 0xd4ca, 0x2000 }, + { 0x0501, 0xd4c9, 0x0000 }, + { 0x0501, 0xd4cb, 0x0000 }, + { 0x8901, 0xd4d0, 0x3000 }, + { 0x8501, 0xd4ce, 0x2000 }, + { 0x0501, 0xd4cd, 0x0000 }, + { 0x0501, 0xd4cf, 0x0000 }, + { 0x8901, 0xd4d2, 0x2000 }, + { 0x0901, 0xd4d1, 0x0000 }, + { 0x0901, 0xd4d3, 0x0000 }, + { 0x8901, 0xd4dc, 0x4000 }, + { 0x8901, 0xd4d8, 0x3000 }, + { 0x8901, 0xd4d6, 0x2000 }, + { 0x0901, 0xd4d5, 0x0000 }, + { 0x0901, 0xd4d7, 0x0000 }, + { 0x8901, 0xd4da, 0x2000 }, + { 0x0901, 0xd4d9, 0x0000 }, + { 0x0901, 0xd4db, 0x0000 }, + { 0x8901, 0xd4e0, 0x3000 }, + { 0x8901, 0xd4de, 0x2000 }, + { 0x0901, 0xd4dd, 0x0000 }, + { 0x0901, 0xd4df, 0x0000 }, + { 0x8901, 0xd4e2, 0x2000 }, + { 0x0901, 0xd4e1, 0x0000 }, + { 0x0901, 0xd4e3, 0x0000 }, + { 0x8501, 0xd529, 0x7000 }, + { 0x8901, 0xd504, 0x6000 }, + { 0x8501, 0xd4f4, 0x5000 }, + { 0x8501, 0xd4ec, 0x4000 }, + { 0x8901, 0xd4e8, 0x3000 }, + { 0x8901, 0xd4e6, 0x2000 }, + { 0x0901, 0xd4e5, 0x0000 }, + { 0x0901, 0xd4e7, 0x0000 }, + { 0x8501, 0xd4ea, 0x2000 }, + { 0x0901, 0xd4e9, 0x0000 }, + { 0x0501, 0xd4eb, 0x0000 }, + { 0x8501, 0xd4f0, 0x3000 }, + { 0x8501, 0xd4ee, 0x2000 }, + { 0x0501, 0xd4ed, 0x0000 }, + { 0x0501, 0xd4ef, 0x0000 }, + { 0x8501, 0xd4f2, 0x2000 }, + { 0x0501, 0xd4f1, 0x0000 }, + { 0x0501, 0xd4f3, 0x0000 }, + { 0x8501, 0xd4fc, 0x4000 }, + { 0x8501, 0xd4f8, 0x3000 }, + { 0x8501, 0xd4f6, 0x2000 }, + { 0x0501, 0xd4f5, 0x0000 }, + { 0x0501, 0xd4f7, 0x0000 }, + { 0x8501, 0xd4fa, 0x2000 }, + { 0x0501, 0xd4f9, 0x0000 }, + { 0x0501, 0xd4fb, 0x0000 }, + { 0x8501, 0xd500, 0x3000 }, + { 0x8501, 0xd4fe, 0x2000 }, + { 0x0501, 0xd4fd, 0x0000 }, + { 0x0501, 0xd4ff, 0x0000 }, + { 0x8501, 0xd502, 0x2000 }, + { 0x0501, 0xd501, 0x0000 }, + { 0x0501, 0xd503, 0x0000 }, + { 0x8901, 0xd518, 0x5000 }, + { 0x8901, 0xd50f, 0x4000 }, + { 0x8901, 0xd509, 0x3000 }, + { 0x8901, 0xd507, 0x2000 }, + { 0x0901, 0xd505, 0x0000 }, + { 0x0901, 0xd508, 0x0000 }, + { 0x8901, 0xd50d, 0x2000 }, + { 0x0901, 0xd50a, 0x0000 }, + { 0x0901, 0xd50e, 0x0000 }, + { 0x8901, 0xd513, 0x3000 }, + { 0x8901, 0xd511, 0x2000 }, + { 0x0901, 0xd510, 0x0000 }, + { 0x0901, 0xd512, 0x0000 }, + { 0x8901, 0xd516, 0x2000 }, + { 0x0901, 0xd514, 0x0000 }, + { 0x0901, 0xd517, 0x0000 }, + { 0x8501, 0xd521, 0x4000 }, + { 0x8901, 0xd51c, 0x3000 }, + { 0x8901, 0xd51a, 0x2000 }, + { 0x0901, 0xd519, 0x0000 }, + { 0x0901, 0xd51b, 0x0000 }, + { 0x8501, 0xd51f, 0x2000 }, + { 0x0501, 0xd51e, 0x0000 }, + { 0x0501, 0xd520, 0x0000 }, + { 0x8501, 0xd525, 0x3000 }, + { 0x8501, 0xd523, 0x2000 }, + { 0x0501, 0xd522, 0x0000 }, + { 0x0501, 0xd524, 0x0000 }, + { 0x8501, 0xd527, 0x2000 }, + { 0x0501, 0xd526, 0x0000 }, + { 0x0501, 0xd528, 0x0000 }, + { 0x8901, 0xd54f, 0x6000 }, + { 0x8901, 0xd539, 0x5000 }, + { 0x8501, 0xd531, 0x4000 }, + { 0x8501, 0xd52d, 0x3000 }, + { 0x8501, 0xd52b, 0x2000 }, + { 0x0501, 0xd52a, 0x0000 }, + { 0x0501, 0xd52c, 0x0000 }, + { 0x8501, 0xd52f, 0x2000 }, + { 0x0501, 0xd52e, 0x0000 }, + { 0x0501, 0xd530, 0x0000 }, + { 0x8501, 0xd535, 0x3000 }, + { 0x8501, 0xd533, 0x2000 }, + { 0x0501, 0xd532, 0x0000 }, + { 0x0501, 0xd534, 0x0000 }, + { 0x8501, 0xd537, 0x2000 }, + { 0x0501, 0xd536, 0x0000 }, + { 0x0901, 0xd538, 0x0000 }, + { 0x8901, 0xd543, 0x4000 }, + { 0x8901, 0xd53e, 0x3000 }, + { 0x8901, 0xd53c, 0x2000 }, + { 0x0901, 0xd53b, 0x0000 }, + { 0x0901, 0xd53d, 0x0000 }, + { 0x8901, 0xd541, 0x2000 }, + { 0x0901, 0xd540, 0x0000 }, + { 0x0901, 0xd542, 0x0000 }, + { 0x8901, 0xd54b, 0x3000 }, + { 0x8901, 0xd546, 0x2000 }, + { 0x0901, 0xd544, 0x0000 }, + { 0x0901, 0xd54a, 0x0000 }, + { 0x8901, 0xd54d, 0x2000 }, + { 0x0901, 0xd54c, 0x0000 }, + { 0x0901, 0xd54e, 0x0000 }, + { 0x8501, 0xd560, 0x5000 }, + { 0x8501, 0xd558, 0x4000 }, + { 0x8501, 0xd554, 0x3000 }, + { 0x8501, 0xd552, 0x2000 }, + { 0x0901, 0xd550, 0x0000 }, + { 0x0501, 0xd553, 0x0000 }, + { 0x8501, 0xd556, 0x2000 }, + { 0x0501, 0xd555, 0x0000 }, + { 0x0501, 0xd557, 0x0000 }, + { 0x8501, 0xd55c, 0x3000 }, + { 0x8501, 0xd55a, 0x2000 }, + { 0x0501, 0xd559, 0x0000 }, + { 0x0501, 0xd55b, 0x0000 }, + { 0x8501, 0xd55e, 0x2000 }, + { 0x0501, 0xd55d, 0x0000 }, + { 0x0501, 0xd55f, 0x0000 }, + { 0x8501, 0xd568, 0x4000 }, + { 0x8501, 0xd564, 0x3000 }, + { 0x8501, 0xd562, 0x2000 }, + { 0x0501, 0xd561, 0x0000 }, + { 0x0501, 0xd563, 0x0000 }, + { 0x8501, 0xd566, 0x2000 }, + { 0x0501, 0xd565, 0x0000 }, + { 0x0501, 0xd567, 0x0000 }, + { 0x8901, 0xd56c, 0x3000 }, + { 0x8501, 0xd56a, 0x2000 }, + { 0x0501, 0xd569, 0x0000 }, + { 0x0501, 0xd56b, 0x0000 }, + { 0x8901, 0xd56e, 0x2000 }, + { 0x0901, 0xd56d, 0x0000 }, + { 0x0901, 0xd56f, 0x0000 }, + { 0x8501, 0xd5f0, 0x8000 }, + { 0x8901, 0xd5b0, 0x7000 }, + { 0x8501, 0xd590, 0x6000 }, + { 0x8901, 0xd580, 0x5000 }, + { 0x8901, 0xd578, 0x4000 }, + { 0x8901, 0xd574, 0x3000 }, + { 0x8901, 0xd572, 0x2000 }, + { 0x0901, 0xd571, 0x0000 }, + { 0x0901, 0xd573, 0x0000 }, + { 0x8901, 0xd576, 0x2000 }, + { 0x0901, 0xd575, 0x0000 }, + { 0x0901, 0xd577, 0x0000 }, + { 0x8901, 0xd57c, 0x3000 }, + { 0x8901, 0xd57a, 0x2000 }, + { 0x0901, 0xd579, 0x0000 }, + { 0x0901, 0xd57b, 0x0000 }, + { 0x8901, 0xd57e, 0x2000 }, + { 0x0901, 0xd57d, 0x0000 }, + { 0x0901, 0xd57f, 0x0000 }, + { 0x8501, 0xd588, 0x4000 }, + { 0x8901, 0xd584, 0x3000 }, + { 0x8901, 0xd582, 0x2000 }, + { 0x0901, 0xd581, 0x0000 }, + { 0x0901, 0xd583, 0x0000 }, + { 0x8501, 0xd586, 0x2000 }, + { 0x0901, 0xd585, 0x0000 }, + { 0x0501, 0xd587, 0x0000 }, + { 0x8501, 0xd58c, 0x3000 }, + { 0x8501, 0xd58a, 0x2000 }, + { 0x0501, 0xd589, 0x0000 }, + { 0x0501, 0xd58b, 0x0000 }, + { 0x8501, 0xd58e, 0x2000 }, + { 0x0501, 0xd58d, 0x0000 }, + { 0x0501, 0xd58f, 0x0000 }, + { 0x8901, 0xd5a0, 0x5000 }, + { 0x8501, 0xd598, 0x4000 }, + { 0x8501, 0xd594, 0x3000 }, + { 0x8501, 0xd592, 0x2000 }, + { 0x0501, 0xd591, 0x0000 }, + { 0x0501, 0xd593, 0x0000 }, + { 0x8501, 0xd596, 0x2000 }, + { 0x0501, 0xd595, 0x0000 }, + { 0x0501, 0xd597, 0x0000 }, + { 0x8501, 0xd59c, 0x3000 }, + { 0x8501, 0xd59a, 0x2000 }, + { 0x0501, 0xd599, 0x0000 }, + { 0x0501, 0xd59b, 0x0000 }, + { 0x8501, 0xd59e, 0x2000 }, + { 0x0501, 0xd59d, 0x0000 }, + { 0x0501, 0xd59f, 0x0000 }, + { 0x8901, 0xd5a8, 0x4000 }, + { 0x8901, 0xd5a4, 0x3000 }, + { 0x8901, 0xd5a2, 0x2000 }, + { 0x0901, 0xd5a1, 0x0000 }, + { 0x0901, 0xd5a3, 0x0000 }, + { 0x8901, 0xd5a6, 0x2000 }, + { 0x0901, 0xd5a5, 0x0000 }, + { 0x0901, 0xd5a7, 0x0000 }, + { 0x8901, 0xd5ac, 0x3000 }, + { 0x8901, 0xd5aa, 0x2000 }, + { 0x0901, 0xd5a9, 0x0000 }, + { 0x0901, 0xd5ab, 0x0000 }, + { 0x8901, 0xd5ae, 0x2000 }, + { 0x0901, 0xd5ad, 0x0000 }, + { 0x0901, 0xd5af, 0x0000 }, + { 0x8501, 0xd5d0, 0x6000 }, + { 0x8501, 0xd5c0, 0x5000 }, + { 0x8901, 0xd5b8, 0x4000 }, + { 0x8901, 0xd5b4, 0x3000 }, + { 0x8901, 0xd5b2, 0x2000 }, + { 0x0901, 0xd5b1, 0x0000 }, + { 0x0901, 0xd5b3, 0x0000 }, + { 0x8901, 0xd5b6, 0x2000 }, + { 0x0901, 0xd5b5, 0x0000 }, + { 0x0901, 0xd5b7, 0x0000 }, + { 0x8501, 0xd5bc, 0x3000 }, + { 0x8501, 0xd5ba, 0x2000 }, + { 0x0901, 0xd5b9, 0x0000 }, + { 0x0501, 0xd5bb, 0x0000 }, + { 0x8501, 0xd5be, 0x2000 }, + { 0x0501, 0xd5bd, 0x0000 }, + { 0x0501, 0xd5bf, 0x0000 }, + { 0x8501, 0xd5c8, 0x4000 }, + { 0x8501, 0xd5c4, 0x3000 }, + { 0x8501, 0xd5c2, 0x2000 }, + { 0x0501, 0xd5c1, 0x0000 }, + { 0x0501, 0xd5c3, 0x0000 }, + { 0x8501, 0xd5c6, 0x2000 }, + { 0x0501, 0xd5c5, 0x0000 }, + { 0x0501, 0xd5c7, 0x0000 }, + { 0x8501, 0xd5cc, 0x3000 }, + { 0x8501, 0xd5ca, 0x2000 }, + { 0x0501, 0xd5c9, 0x0000 }, + { 0x0501, 0xd5cb, 0x0000 }, + { 0x8501, 0xd5ce, 0x2000 }, + { 0x0501, 0xd5cd, 0x0000 }, + { 0x0501, 0xd5cf, 0x0000 }, + { 0x8901, 0xd5e0, 0x5000 }, + { 0x8901, 0xd5d8, 0x4000 }, + { 0x8901, 0xd5d4, 0x3000 }, + { 0x8501, 0xd5d2, 0x2000 }, + { 0x0501, 0xd5d1, 0x0000 }, + { 0x0501, 0xd5d3, 0x0000 }, + { 0x8901, 0xd5d6, 0x2000 }, + { 0x0901, 0xd5d5, 0x0000 }, + { 0x0901, 0xd5d7, 0x0000 }, + { 0x8901, 0xd5dc, 0x3000 }, + { 0x8901, 0xd5da, 0x2000 }, + { 0x0901, 0xd5d9, 0x0000 }, + { 0x0901, 0xd5db, 0x0000 }, + { 0x8901, 0xd5de, 0x2000 }, + { 0x0901, 0xd5dd, 0x0000 }, + { 0x0901, 0xd5df, 0x0000 }, + { 0x8901, 0xd5e8, 0x4000 }, + { 0x8901, 0xd5e4, 0x3000 }, + { 0x8901, 0xd5e2, 0x2000 }, + { 0x0901, 0xd5e1, 0x0000 }, + { 0x0901, 0xd5e3, 0x0000 }, + { 0x8901, 0xd5e6, 0x2000 }, + { 0x0901, 0xd5e5, 0x0000 }, + { 0x0901, 0xd5e7, 0x0000 }, + { 0x8901, 0xd5ec, 0x3000 }, + { 0x8901, 0xd5ea, 0x2000 }, + { 0x0901, 0xd5e9, 0x0000 }, + { 0x0901, 0xd5eb, 0x0000 }, + { 0x8501, 0xd5ee, 0x2000 }, + { 0x0901, 0xd5ed, 0x0000 }, + { 0x0501, 0xd5ef, 0x0000 }, + { 0x8501, 0xd630, 0x7000 }, + { 0x8901, 0xd610, 0x6000 }, + { 0x8501, 0xd600, 0x5000 }, + { 0x8501, 0xd5f8, 0x4000 }, + { 0x8501, 0xd5f4, 0x3000 }, + { 0x8501, 0xd5f2, 0x2000 }, + { 0x0501, 0xd5f1, 0x0000 }, + { 0x0501, 0xd5f3, 0x0000 }, + { 0x8501, 0xd5f6, 0x2000 }, + { 0x0501, 0xd5f5, 0x0000 }, + { 0x0501, 0xd5f7, 0x0000 }, + { 0x8501, 0xd5fc, 0x3000 }, + { 0x8501, 0xd5fa, 0x2000 }, + { 0x0501, 0xd5f9, 0x0000 }, + { 0x0501, 0xd5fb, 0x0000 }, + { 0x8501, 0xd5fe, 0x2000 }, + { 0x0501, 0xd5fd, 0x0000 }, + { 0x0501, 0xd5ff, 0x0000 }, + { 0x8901, 0xd608, 0x4000 }, + { 0x8501, 0xd604, 0x3000 }, + { 0x8501, 0xd602, 0x2000 }, + { 0x0501, 0xd601, 0x0000 }, + { 0x0501, 0xd603, 0x0000 }, + { 0x8501, 0xd606, 0x2000 }, + { 0x0501, 0xd605, 0x0000 }, + { 0x0501, 0xd607, 0x0000 }, + { 0x8901, 0xd60c, 0x3000 }, + { 0x8901, 0xd60a, 0x2000 }, + { 0x0901, 0xd609, 0x0000 }, + { 0x0901, 0xd60b, 0x0000 }, + { 0x8901, 0xd60e, 0x2000 }, + { 0x0901, 0xd60d, 0x0000 }, + { 0x0901, 0xd60f, 0x0000 }, + { 0x8901, 0xd620, 0x5000 }, + { 0x8901, 0xd618, 0x4000 }, + { 0x8901, 0xd614, 0x3000 }, + { 0x8901, 0xd612, 0x2000 }, + { 0x0901, 0xd611, 0x0000 }, + { 0x0901, 0xd613, 0x0000 }, + { 0x8901, 0xd616, 0x2000 }, + { 0x0901, 0xd615, 0x0000 }, + { 0x0901, 0xd617, 0x0000 }, + { 0x8901, 0xd61c, 0x3000 }, + { 0x8901, 0xd61a, 0x2000 }, + { 0x0901, 0xd619, 0x0000 }, + { 0x0901, 0xd61b, 0x0000 }, + { 0x8901, 0xd61e, 0x2000 }, + { 0x0901, 0xd61d, 0x0000 }, + { 0x0901, 0xd61f, 0x0000 }, + { 0x8501, 0xd628, 0x4000 }, + { 0x8501, 0xd624, 0x3000 }, + { 0x8501, 0xd622, 0x2000 }, + { 0x0901, 0xd621, 0x0000 }, + { 0x0501, 0xd623, 0x0000 }, + { 0x8501, 0xd626, 0x2000 }, + { 0x0501, 0xd625, 0x0000 }, + { 0x0501, 0xd627, 0x0000 }, + { 0x8501, 0xd62c, 0x3000 }, + { 0x8501, 0xd62a, 0x2000 }, + { 0x0501, 0xd629, 0x0000 }, + { 0x0501, 0xd62b, 0x0000 }, + { 0x8501, 0xd62e, 0x2000 }, + { 0x0501, 0xd62d, 0x0000 }, + { 0x0501, 0xd62f, 0x0000 }, + { 0x8901, 0xd650, 0x6000 }, + { 0x8901, 0xd640, 0x5000 }, + { 0x8501, 0xd638, 0x4000 }, + { 0x8501, 0xd634, 0x3000 }, + { 0x8501, 0xd632, 0x2000 }, + { 0x0501, 0xd631, 0x0000 }, + { 0x0501, 0xd633, 0x0000 }, + { 0x8501, 0xd636, 0x2000 }, + { 0x0501, 0xd635, 0x0000 }, + { 0x0501, 0xd637, 0x0000 }, + { 0x8901, 0xd63c, 0x3000 }, + { 0x8501, 0xd63a, 0x2000 }, + { 0x0501, 0xd639, 0x0000 }, + { 0x0501, 0xd63b, 0x0000 }, + { 0x8901, 0xd63e, 0x2000 }, + { 0x0901, 0xd63d, 0x0000 }, + { 0x0901, 0xd63f, 0x0000 }, + { 0x8901, 0xd648, 0x4000 }, + { 0x8901, 0xd644, 0x3000 }, + { 0x8901, 0xd642, 0x2000 }, + { 0x0901, 0xd641, 0x0000 }, + { 0x0901, 0xd643, 0x0000 }, + { 0x8901, 0xd646, 0x2000 }, + { 0x0901, 0xd645, 0x0000 }, + { 0x0901, 0xd647, 0x0000 }, + { 0x8901, 0xd64c, 0x3000 }, + { 0x8901, 0xd64a, 0x2000 }, + { 0x0901, 0xd649, 0x0000 }, + { 0x0901, 0xd64b, 0x0000 }, + { 0x8901, 0xd64e, 0x2000 }, + { 0x0901, 0xd64d, 0x0000 }, + { 0x0901, 0xd64f, 0x0000 }, + { 0x8501, 0xd660, 0x5000 }, + { 0x8501, 0xd658, 0x4000 }, + { 0x8901, 0xd654, 0x3000 }, + { 0x8901, 0xd652, 0x2000 }, + { 0x0901, 0xd651, 0x0000 }, + { 0x0901, 0xd653, 0x0000 }, + { 0x8501, 0xd656, 0x2000 }, + { 0x0901, 0xd655, 0x0000 }, + { 0x0501, 0xd657, 0x0000 }, + { 0x8501, 0xd65c, 0x3000 }, + { 0x8501, 0xd65a, 0x2000 }, + { 0x0501, 0xd659, 0x0000 }, + { 0x0501, 0xd65b, 0x0000 }, + { 0x8501, 0xd65e, 0x2000 }, + { 0x0501, 0xd65d, 0x0000 }, + { 0x0501, 0xd65f, 0x0000 }, + { 0x8501, 0xd668, 0x4000 }, + { 0x8501, 0xd664, 0x3000 }, + { 0x8501, 0xd662, 0x2000 }, + { 0x0501, 0xd661, 0x0000 }, + { 0x0501, 0xd663, 0x0000 }, + { 0x8501, 0xd666, 0x2000 }, + { 0x0501, 0xd665, 0x0000 }, + { 0x0501, 0xd667, 0x0000 }, + { 0x8501, 0xd66c, 0x3000 }, + { 0x8501, 0xd66a, 0x2000 }, + { 0x0501, 0xd669, 0x0000 }, + { 0x0501, 0xd66b, 0x0000 }, + { 0x8501, 0xd66e, 0x2000 }, + { 0x0501, 0xd66d, 0x0000 }, + { 0x0501, 0xd66f, 0x0000 }, + { 0x8501, 0xd774, 0x9000 }, + { 0x8901, 0xd6f4, 0x8000 }, + { 0x8901, 0xd6b4, 0x7000 }, + { 0x8501, 0xd690, 0x6000 }, + { 0x8901, 0xd680, 0x5000 }, + { 0x8901, 0xd678, 0x4000 }, + { 0x8901, 0xd674, 0x3000 }, + { 0x8901, 0xd672, 0x2000 }, + { 0x0901, 0xd671, 0x0000 }, + { 0x0901, 0xd673, 0x0000 }, + { 0x8901, 0xd676, 0x2000 }, + { 0x0901, 0xd675, 0x0000 }, + { 0x0901, 0xd677, 0x0000 }, + { 0x8901, 0xd67c, 0x3000 }, + { 0x8901, 0xd67a, 0x2000 }, + { 0x0901, 0xd679, 0x0000 }, + { 0x0901, 0xd67b, 0x0000 }, + { 0x8901, 0xd67e, 0x2000 }, + { 0x0901, 0xd67d, 0x0000 }, + { 0x0901, 0xd67f, 0x0000 }, + { 0x8901, 0xd688, 0x4000 }, + { 0x8901, 0xd684, 0x3000 }, + { 0x8901, 0xd682, 0x2000 }, + { 0x0901, 0xd681, 0x0000 }, + { 0x0901, 0xd683, 0x0000 }, + { 0x8901, 0xd686, 0x2000 }, + { 0x0901, 0xd685, 0x0000 }, + { 0x0901, 0xd687, 0x0000 }, + { 0x8501, 0xd68c, 0x3000 }, + { 0x8501, 0xd68a, 0x2000 }, + { 0x0901, 0xd689, 0x0000 }, + { 0x0501, 0xd68b, 0x0000 }, + { 0x8501, 0xd68e, 0x2000 }, + { 0x0501, 0xd68d, 0x0000 }, + { 0x0501, 0xd68f, 0x0000 }, + { 0x8501, 0xd6a0, 0x5000 }, + { 0x8501, 0xd698, 0x4000 }, + { 0x8501, 0xd694, 0x3000 }, + { 0x8501, 0xd692, 0x2000 }, + { 0x0501, 0xd691, 0x0000 }, + { 0x0501, 0xd693, 0x0000 }, + { 0x8501, 0xd696, 0x2000 }, + { 0x0501, 0xd695, 0x0000 }, + { 0x0501, 0xd697, 0x0000 }, + { 0x8501, 0xd69c, 0x3000 }, + { 0x8501, 0xd69a, 0x2000 }, + { 0x0501, 0xd699, 0x0000 }, + { 0x0501, 0xd69b, 0x0000 }, + { 0x8501, 0xd69e, 0x2000 }, + { 0x0501, 0xd69d, 0x0000 }, + { 0x0501, 0xd69f, 0x0000 }, + { 0x8901, 0xd6ac, 0x4000 }, + { 0x8901, 0xd6a8, 0x3000 }, + { 0x8501, 0xd6a2, 0x2000 }, + { 0x0501, 0xd6a1, 0x0000 }, + { 0x0501, 0xd6a3, 0x0000 }, + { 0x8901, 0xd6aa, 0x2000 }, + { 0x0901, 0xd6a9, 0x0000 }, + { 0x0901, 0xd6ab, 0x0000 }, + { 0x8901, 0xd6b0, 0x3000 }, + { 0x8901, 0xd6ae, 0x2000 }, + { 0x0901, 0xd6ad, 0x0000 }, + { 0x0901, 0xd6af, 0x0000 }, + { 0x8901, 0xd6b2, 0x2000 }, + { 0x0901, 0xd6b1, 0x0000 }, + { 0x0901, 0xd6b3, 0x0000 }, + { 0x8501, 0xd6d4, 0x6000 }, + { 0x8501, 0xd6c4, 0x5000 }, + { 0x8901, 0xd6bc, 0x4000 }, + { 0x8901, 0xd6b8, 0x3000 }, + { 0x8901, 0xd6b6, 0x2000 }, + { 0x0901, 0xd6b5, 0x0000 }, + { 0x0901, 0xd6b7, 0x0000 }, + { 0x8901, 0xd6ba, 0x2000 }, + { 0x0901, 0xd6b9, 0x0000 }, + { 0x0901, 0xd6bb, 0x0000 }, + { 0x8901, 0xd6c0, 0x3000 }, + { 0x8901, 0xd6be, 0x2000 }, + { 0x0901, 0xd6bd, 0x0000 }, + { 0x0901, 0xd6bf, 0x0000 }, + { 0x8501, 0xd6c2, 0x2000 }, + { 0x1901, 0xd6c1, 0x0000 }, + { 0x0501, 0xd6c3, 0x0000 }, + { 0x8501, 0xd6cc, 0x4000 }, + { 0x8501, 0xd6c8, 0x3000 }, + { 0x8501, 0xd6c6, 0x2000 }, + { 0x0501, 0xd6c5, 0x0000 }, + { 0x0501, 0xd6c7, 0x0000 }, + { 0x8501, 0xd6ca, 0x2000 }, + { 0x0501, 0xd6c9, 0x0000 }, + { 0x0501, 0xd6cb, 0x0000 }, + { 0x8501, 0xd6d0, 0x3000 }, + { 0x8501, 0xd6ce, 0x2000 }, + { 0x0501, 0xd6cd, 0x0000 }, + { 0x0501, 0xd6cf, 0x0000 }, + { 0x8501, 0xd6d2, 0x2000 }, + { 0x0501, 0xd6d1, 0x0000 }, + { 0x0501, 0xd6d3, 0x0000 }, + { 0x8901, 0xd6e4, 0x5000 }, + { 0x8501, 0xd6dc, 0x4000 }, + { 0x8501, 0xd6d8, 0x3000 }, + { 0x8501, 0xd6d6, 0x2000 }, + { 0x0501, 0xd6d5, 0x0000 }, + { 0x0501, 0xd6d7, 0x0000 }, + { 0x8501, 0xd6da, 0x2000 }, + { 0x0501, 0xd6d9, 0x0000 }, + { 0x1901, 0xd6db, 0x0000 }, + { 0x8501, 0xd6e0, 0x3000 }, + { 0x8501, 0xd6de, 0x2000 }, + { 0x0501, 0xd6dd, 0x0000 }, + { 0x0501, 0xd6df, 0x0000 }, + { 0x8901, 0xd6e2, 0x2000 }, + { 0x0501, 0xd6e1, 0x0000 }, + { 0x0901, 0xd6e3, 0x0000 }, + { 0x8901, 0xd6ec, 0x4000 }, + { 0x8901, 0xd6e8, 0x3000 }, + { 0x8901, 0xd6e6, 0x2000 }, + { 0x0901, 0xd6e5, 0x0000 }, + { 0x0901, 0xd6e7, 0x0000 }, + { 0x8901, 0xd6ea, 0x2000 }, + { 0x0901, 0xd6e9, 0x0000 }, + { 0x0901, 0xd6eb, 0x0000 }, + { 0x8901, 0xd6f0, 0x3000 }, + { 0x8901, 0xd6ee, 0x2000 }, + { 0x0901, 0xd6ed, 0x0000 }, + { 0x0901, 0xd6ef, 0x0000 }, + { 0x8901, 0xd6f2, 0x2000 }, + { 0x0901, 0xd6f1, 0x0000 }, + { 0x0901, 0xd6f3, 0x0000 }, + { 0x8901, 0xd734, 0x7000 }, + { 0x8501, 0xd714, 0x6000 }, + { 0x8501, 0xd704, 0x5000 }, + { 0x8501, 0xd6fc, 0x4000 }, + { 0x8901, 0xd6f8, 0x3000 }, + { 0x8901, 0xd6f6, 0x2000 }, + { 0x0901, 0xd6f5, 0x0000 }, + { 0x0901, 0xd6f7, 0x0000 }, + { 0x8901, 0xd6fa, 0x2000 }, + { 0x0901, 0xd6f9, 0x0000 }, + { 0x1901, 0xd6fb, 0x0000 }, + { 0x8501, 0xd700, 0x3000 }, + { 0x8501, 0xd6fe, 0x2000 }, + { 0x0501, 0xd6fd, 0x0000 }, + { 0x0501, 0xd6ff, 0x0000 }, + { 0x8501, 0xd702, 0x2000 }, + { 0x0501, 0xd701, 0x0000 }, + { 0x0501, 0xd703, 0x0000 }, + { 0x8501, 0xd70c, 0x4000 }, + { 0x8501, 0xd708, 0x3000 }, + { 0x8501, 0xd706, 0x2000 }, + { 0x0501, 0xd705, 0x0000 }, + { 0x0501, 0xd707, 0x0000 }, + { 0x8501, 0xd70a, 0x2000 }, + { 0x0501, 0xd709, 0x0000 }, + { 0x0501, 0xd70b, 0x0000 }, + { 0x8501, 0xd710, 0x3000 }, + { 0x8501, 0xd70e, 0x2000 }, + { 0x0501, 0xd70d, 0x0000 }, + { 0x0501, 0xd70f, 0x0000 }, + { 0x8501, 0xd712, 0x2000 }, + { 0x0501, 0xd711, 0x0000 }, + { 0x0501, 0xd713, 0x0000 }, + { 0x8901, 0xd724, 0x5000 }, + { 0x8901, 0xd71c, 0x4000 }, + { 0x8501, 0xd718, 0x3000 }, + { 0x8501, 0xd716, 0x2000 }, + { 0x1901, 0xd715, 0x0000 }, + { 0x0501, 0xd717, 0x0000 }, + { 0x8501, 0xd71a, 0x2000 }, + { 0x0501, 0xd719, 0x0000 }, + { 0x0501, 0xd71b, 0x0000 }, + { 0x8901, 0xd720, 0x3000 }, + { 0x8901, 0xd71e, 0x2000 }, + { 0x0901, 0xd71d, 0x0000 }, + { 0x0901, 0xd71f, 0x0000 }, + { 0x8901, 0xd722, 0x2000 }, + { 0x0901, 0xd721, 0x0000 }, + { 0x0901, 0xd723, 0x0000 }, + { 0x8901, 0xd72c, 0x4000 }, + { 0x8901, 0xd728, 0x3000 }, + { 0x8901, 0xd726, 0x2000 }, + { 0x0901, 0xd725, 0x0000 }, + { 0x0901, 0xd727, 0x0000 }, + { 0x8901, 0xd72a, 0x2000 }, + { 0x0901, 0xd729, 0x0000 }, + { 0x0901, 0xd72b, 0x0000 }, + { 0x8901, 0xd730, 0x3000 }, + { 0x8901, 0xd72e, 0x2000 }, + { 0x0901, 0xd72d, 0x0000 }, + { 0x0901, 0xd72f, 0x0000 }, + { 0x8901, 0xd732, 0x2000 }, + { 0x0901, 0xd731, 0x0000 }, + { 0x0901, 0xd733, 0x0000 }, + { 0x8501, 0xd754, 0x6000 }, + { 0x8501, 0xd744, 0x5000 }, + { 0x8501, 0xd73c, 0x4000 }, + { 0x8501, 0xd738, 0x3000 }, + { 0x8501, 0xd736, 0x2000 }, + { 0x1901, 0xd735, 0x0000 }, + { 0x0501, 0xd737, 0x0000 }, + { 0x8501, 0xd73a, 0x2000 }, + { 0x0501, 0xd739, 0x0000 }, + { 0x0501, 0xd73b, 0x0000 }, + { 0x8501, 0xd740, 0x3000 }, + { 0x8501, 0xd73e, 0x2000 }, + { 0x0501, 0xd73d, 0x0000 }, + { 0x0501, 0xd73f, 0x0000 }, + { 0x8501, 0xd742, 0x2000 }, + { 0x0501, 0xd741, 0x0000 }, + { 0x0501, 0xd743, 0x0000 }, + { 0x8501, 0xd74c, 0x4000 }, + { 0x8501, 0xd748, 0x3000 }, + { 0x8501, 0xd746, 0x2000 }, + { 0x0501, 0xd745, 0x0000 }, + { 0x0501, 0xd747, 0x0000 }, + { 0x8501, 0xd74a, 0x2000 }, + { 0x0501, 0xd749, 0x0000 }, + { 0x0501, 0xd74b, 0x0000 }, + { 0x8501, 0xd750, 0x3000 }, + { 0x8501, 0xd74e, 0x2000 }, + { 0x0501, 0xd74d, 0x0000 }, + { 0x1901, 0xd74f, 0x0000 }, + { 0x8501, 0xd752, 0x2000 }, + { 0x0501, 0xd751, 0x0000 }, + { 0x0501, 0xd753, 0x0000 }, + { 0x8901, 0xd764, 0x5000 }, + { 0x8901, 0xd75c, 0x4000 }, + { 0x8901, 0xd758, 0x3000 }, + { 0x8901, 0xd756, 0x2000 }, + { 0x0501, 0xd755, 0x0000 }, + { 0x0901, 0xd757, 0x0000 }, + { 0x8901, 0xd75a, 0x2000 }, + { 0x0901, 0xd759, 0x0000 }, + { 0x0901, 0xd75b, 0x0000 }, + { 0x8901, 0xd760, 0x3000 }, + { 0x8901, 0xd75e, 0x2000 }, + { 0x0901, 0xd75d, 0x0000 }, + { 0x0901, 0xd75f, 0x0000 }, + { 0x8901, 0xd762, 0x2000 }, + { 0x0901, 0xd761, 0x0000 }, + { 0x0901, 0xd763, 0x0000 }, + { 0x8901, 0xd76c, 0x4000 }, + { 0x8901, 0xd768, 0x3000 }, + { 0x8901, 0xd766, 0x2000 }, + { 0x0901, 0xd765, 0x0000 }, + { 0x0901, 0xd767, 0x0000 }, + { 0x8901, 0xd76a, 0x2000 }, + { 0x0901, 0xd769, 0x0000 }, + { 0x0901, 0xd76b, 0x0000 }, + { 0x8501, 0xd770, 0x3000 }, + { 0x8901, 0xd76e, 0x2000 }, + { 0x0901, 0xd76d, 0x0000 }, + { 0x1901, 0xd76f, 0x0000 }, + { 0x8501, 0xd772, 0x2000 }, + { 0x0501, 0xd771, 0x0000 }, + { 0x0501, 0xd773, 0x0000 }, + { 0x8d01, 0xd7f8, 0x8000 }, + { 0x8501, 0xd7b4, 0x7000 }, + { 0x8901, 0xd794, 0x6000 }, + { 0x8501, 0xd784, 0x5000 }, + { 0x8501, 0xd77c, 0x4000 }, + { 0x8501, 0xd778, 0x3000 }, + { 0x8501, 0xd776, 0x2000 }, + { 0x0501, 0xd775, 0x0000 }, + { 0x0501, 0xd777, 0x0000 }, + { 0x8501, 0xd77a, 0x2000 }, + { 0x0501, 0xd779, 0x0000 }, + { 0x0501, 0xd77b, 0x0000 }, + { 0x8501, 0xd780, 0x3000 }, + { 0x8501, 0xd77e, 0x2000 }, + { 0x0501, 0xd77d, 0x0000 }, + { 0x0501, 0xd77f, 0x0000 }, + { 0x8501, 0xd782, 0x2000 }, + { 0x0501, 0xd781, 0x0000 }, + { 0x0501, 0xd783, 0x0000 }, + { 0x8501, 0xd78c, 0x4000 }, + { 0x8501, 0xd788, 0x3000 }, + { 0x8501, 0xd786, 0x2000 }, + { 0x0501, 0xd785, 0x0000 }, + { 0x0501, 0xd787, 0x0000 }, + { 0x8501, 0xd78a, 0x2000 }, + { 0x1901, 0xd789, 0x0000 }, + { 0x0501, 0xd78b, 0x0000 }, + { 0x8901, 0xd790, 0x3000 }, + { 0x8501, 0xd78e, 0x2000 }, + { 0x0501, 0xd78d, 0x0000 }, + { 0x0501, 0xd78f, 0x0000 }, + { 0x8901, 0xd792, 0x2000 }, + { 0x0901, 0xd791, 0x0000 }, + { 0x0901, 0xd793, 0x0000 }, + { 0x8901, 0xd7a4, 0x5000 }, + { 0x8901, 0xd79c, 0x4000 }, + { 0x8901, 0xd798, 0x3000 }, + { 0x8901, 0xd796, 0x2000 }, + { 0x0901, 0xd795, 0x0000 }, + { 0x0901, 0xd797, 0x0000 }, + { 0x8901, 0xd79a, 0x2000 }, + { 0x0901, 0xd799, 0x0000 }, + { 0x0901, 0xd79b, 0x0000 }, + { 0x8901, 0xd7a0, 0x3000 }, + { 0x8901, 0xd79e, 0x2000 }, + { 0x0901, 0xd79d, 0x0000 }, + { 0x0901, 0xd79f, 0x0000 }, + { 0x8901, 0xd7a2, 0x2000 }, + { 0x0901, 0xd7a1, 0x0000 }, + { 0x0901, 0xd7a3, 0x0000 }, + { 0x8501, 0xd7ac, 0x4000 }, + { 0x8901, 0xd7a8, 0x3000 }, + { 0x8901, 0xd7a6, 0x2000 }, + { 0x0901, 0xd7a5, 0x0000 }, + { 0x0901, 0xd7a7, 0x0000 }, + { 0x8501, 0xd7aa, 0x2000 }, + { 0x1901, 0xd7a9, 0x0000 }, + { 0x0501, 0xd7ab, 0x0000 }, + { 0x8501, 0xd7b0, 0x3000 }, + { 0x8501, 0xd7ae, 0x2000 }, + { 0x0501, 0xd7ad, 0x0000 }, + { 0x0501, 0xd7af, 0x0000 }, + { 0x8501, 0xd7b2, 0x2000 }, + { 0x0501, 0xd7b1, 0x0000 }, + { 0x0501, 0xd7b3, 0x0000 }, + { 0x8d01, 0xd7d8, 0x6000 }, + { 0x8501, 0xd7c4, 0x5000 }, + { 0x8501, 0xd7bc, 0x4000 }, + { 0x8501, 0xd7b8, 0x3000 }, + { 0x8501, 0xd7b6, 0x2000 }, + { 0x0501, 0xd7b5, 0x0000 }, + { 0x0501, 0xd7b7, 0x0000 }, + { 0x8501, 0xd7ba, 0x2000 }, + { 0x0501, 0xd7b9, 0x0000 }, + { 0x0501, 0xd7bb, 0x0000 }, + { 0x8501, 0xd7c0, 0x3000 }, + { 0x8501, 0xd7be, 0x2000 }, + { 0x0501, 0xd7bd, 0x0000 }, + { 0x0501, 0xd7bf, 0x0000 }, + { 0x8501, 0xd7c2, 0x2000 }, + { 0x0501, 0xd7c1, 0x0000 }, + { 0x1901, 0xd7c3, 0x0000 }, + { 0x8d01, 0xd7d0, 0x4000 }, + { 0x8501, 0xd7c8, 0x3000 }, + { 0x8501, 0xd7c6, 0x2000 }, + { 0x0501, 0xd7c5, 0x0000 }, + { 0x0501, 0xd7c7, 0x0000 }, + { 0x8d01, 0xd7ce, 0x2000 }, + { 0x0501, 0xd7c9, 0x0000 }, + { 0x0d01, 0xd7cf, 0x0000 }, + { 0x8d01, 0xd7d4, 0x3000 }, + { 0x8d01, 0xd7d2, 0x2000 }, + { 0x0d01, 0xd7d1, 0x0000 }, + { 0x0d01, 0xd7d3, 0x0000 }, + { 0x8d01, 0xd7d6, 0x2000 }, + { 0x0d01, 0xd7d5, 0x0000 }, + { 0x0d01, 0xd7d7, 0x0000 }, + { 0x8d01, 0xd7e8, 0x5000 }, + { 0x8d01, 0xd7e0, 0x4000 }, + { 0x8d01, 0xd7dc, 0x3000 }, + { 0x8d01, 0xd7da, 0x2000 }, + { 0x0d01, 0xd7d9, 0x0000 }, + { 0x0d01, 0xd7db, 0x0000 }, + { 0x8d01, 0xd7de, 0x2000 }, + { 0x0d01, 0xd7dd, 0x0000 }, + { 0x0d01, 0xd7df, 0x0000 }, + { 0x8d01, 0xd7e4, 0x3000 }, + { 0x8d01, 0xd7e2, 0x2000 }, + { 0x0d01, 0xd7e1, 0x0000 }, + { 0x0d01, 0xd7e3, 0x0000 }, + { 0x8d01, 0xd7e6, 0x2000 }, + { 0x0d01, 0xd7e5, 0x0000 }, + { 0x0d01, 0xd7e7, 0x0000 }, + { 0x8d01, 0xd7f0, 0x4000 }, + { 0x8d01, 0xd7ec, 0x3000 }, + { 0x8d01, 0xd7ea, 0x2000 }, + { 0x0d01, 0xd7e9, 0x0000 }, + { 0x0d01, 0xd7eb, 0x0000 }, + { 0x8d01, 0xd7ee, 0x2000 }, + { 0x0d01, 0xd7ed, 0x0000 }, + { 0x0d01, 0xd7ef, 0x0000 }, + { 0x8d01, 0xd7f4, 0x3000 }, + { 0x8d01, 0xd7f2, 0x2000 }, + { 0x0d01, 0xd7f1, 0x0000 }, + { 0x0d01, 0xd7f3, 0x0000 }, + { 0x8d01, 0xd7f6, 0x2000 }, + { 0x0d01, 0xd7f5, 0x0000 }, + { 0x0d01, 0xd7f7, 0x0000 }, + { 0x8702, 0xf836, 0x7000 }, + { 0x8702, 0xf816, 0x6000 }, + { 0x8702, 0xf806, 0x5000 }, + { 0x8702, 0x0000, 0x4000 }, + { 0x8d01, 0xd7fc, 0x3000 }, + { 0x8d01, 0xd7fa, 0x2000 }, + { 0x0d01, 0xd7f9, 0x0000 }, + { 0x0d01, 0xd7fb, 0x0000 }, + { 0x8d01, 0xd7fe, 0x2000 }, + { 0x0d01, 0xd7fd, 0x0000 }, + { 0x0d01, 0xd7ff, 0x0000 }, + { 0x8702, 0xf802, 0x3000 }, + { 0x8702, 0xf800, 0x2000 }, + { 0x0702, 0xa6d6, 0x0000 }, + { 0x0702, 0xf801, 0x0000 }, + { 0x8702, 0xf804, 0x2000 }, + { 0x0702, 0xf803, 0x0000 }, + { 0x0702, 0xf805, 0x0000 }, + { 0x8702, 0xf80e, 0x4000 }, + { 0x8702, 0xf80a, 0x3000 }, + { 0x8702, 0xf808, 0x2000 }, + { 0x0702, 0xf807, 0x0000 }, + { 0x0702, 0xf809, 0x0000 }, + { 0x8702, 0xf80c, 0x2000 }, + { 0x0702, 0xf80b, 0x0000 }, + { 0x0702, 0xf80d, 0x0000 }, + { 0x8702, 0xf812, 0x3000 }, + { 0x8702, 0xf810, 0x2000 }, + { 0x0702, 0xf80f, 0x0000 }, + { 0x0702, 0xf811, 0x0000 }, + { 0x8702, 0xf814, 0x2000 }, + { 0x0702, 0xf813, 0x0000 }, + { 0x0702, 0xf815, 0x0000 }, + { 0x8702, 0xf826, 0x5000 }, + { 0x8702, 0xf81e, 0x4000 }, + { 0x8702, 0xf81a, 0x3000 }, + { 0x8702, 0xf818, 0x2000 }, + { 0x0702, 0xf817, 0x0000 }, + { 0x0702, 0xf819, 0x0000 }, + { 0x8702, 0xf81c, 0x2000 }, + { 0x0702, 0xf81b, 0x0000 }, + { 0x0702, 0xf81d, 0x0000 }, + { 0x8702, 0xf822, 0x3000 }, + { 0x8702, 0xf820, 0x2000 }, + { 0x0702, 0xf81f, 0x0000 }, + { 0x0702, 0xf821, 0x0000 }, + { 0x8702, 0xf824, 0x2000 }, + { 0x0702, 0xf823, 0x0000 }, + { 0x0702, 0xf825, 0x0000 }, + { 0x8702, 0xf82e, 0x4000 }, + { 0x8702, 0xf82a, 0x3000 }, + { 0x8702, 0xf828, 0x2000 }, + { 0x0702, 0xf827, 0x0000 }, + { 0x0702, 0xf829, 0x0000 }, + { 0x8702, 0xf82c, 0x2000 }, + { 0x0702, 0xf82b, 0x0000 }, + { 0x0702, 0xf82d, 0x0000 }, + { 0x8702, 0xf832, 0x3000 }, + { 0x8702, 0xf830, 0x2000 }, + { 0x0702, 0xf82f, 0x0000 }, + { 0x0702, 0xf831, 0x0000 }, + { 0x8702, 0xf834, 0x2000 }, + { 0x0702, 0xf833, 0x0000 }, + { 0x0702, 0xf835, 0x0000 }, + { 0x8702, 0xf856, 0x6000 }, + { 0x8702, 0xf846, 0x5000 }, + { 0x8702, 0xf83e, 0x4000 }, + { 0x8702, 0xf83a, 0x3000 }, + { 0x8702, 0xf838, 0x2000 }, + { 0x0702, 0xf837, 0x0000 }, + { 0x0702, 0xf839, 0x0000 }, + { 0x8702, 0xf83c, 0x2000 }, + { 0x0702, 0xf83b, 0x0000 }, + { 0x0702, 0xf83d, 0x0000 }, + { 0x8702, 0xf842, 0x3000 }, + { 0x8702, 0xf840, 0x2000 }, + { 0x0702, 0xf83f, 0x0000 }, + { 0x0702, 0xf841, 0x0000 }, + { 0x8702, 0xf844, 0x2000 }, + { 0x0702, 0xf843, 0x0000 }, + { 0x0702, 0xf845, 0x0000 }, + { 0x8702, 0xf84e, 0x4000 }, + { 0x8702, 0xf84a, 0x3000 }, + { 0x8702, 0xf848, 0x2000 }, + { 0x0702, 0xf847, 0x0000 }, + { 0x0702, 0xf849, 0x0000 }, + { 0x8702, 0xf84c, 0x2000 }, + { 0x0702, 0xf84b, 0x0000 }, + { 0x0702, 0xf84d, 0x0000 }, + { 0x8702, 0xf852, 0x3000 }, + { 0x8702, 0xf850, 0x2000 }, + { 0x0702, 0xf84f, 0x0000 }, + { 0x0702, 0xf851, 0x0000 }, + { 0x8702, 0xf854, 0x2000 }, + { 0x0702, 0xf853, 0x0000 }, + { 0x0702, 0xf855, 0x0000 }, + { 0x8702, 0xf866, 0x5000 }, + { 0x8702, 0xf85e, 0x4000 }, + { 0x8702, 0xf85a, 0x3000 }, + { 0x8702, 0xf858, 0x2000 }, + { 0x0702, 0xf857, 0x0000 }, + { 0x0702, 0xf859, 0x0000 }, + { 0x8702, 0xf85c, 0x2000 }, + { 0x0702, 0xf85b, 0x0000 }, + { 0x0702, 0xf85d, 0x0000 }, + { 0x8702, 0xf862, 0x3000 }, + { 0x8702, 0xf860, 0x2000 }, + { 0x0702, 0xf85f, 0x0000 }, + { 0x0702, 0xf861, 0x0000 }, + { 0x8702, 0xf864, 0x2000 }, + { 0x0702, 0xf863, 0x0000 }, + { 0x0702, 0xf865, 0x0000 }, + { 0x8702, 0xf86e, 0x4000 }, + { 0x8702, 0xf86a, 0x3000 }, + { 0x8702, 0xf868, 0x2000 }, + { 0x0702, 0xf867, 0x0000 }, + { 0x0702, 0xf869, 0x0000 }, + { 0x8702, 0xf86c, 0x2000 }, + { 0x0702, 0xf86b, 0x0000 }, + { 0x0702, 0xf86d, 0x0000 }, + { 0x8702, 0xf872, 0x3000 }, + { 0x8702, 0xf870, 0x2000 }, + { 0x0702, 0xf86f, 0x0000 }, + { 0x0702, 0xf871, 0x0000 }, + { 0x8702, 0xf874, 0x2000 }, + { 0x0702, 0xf873, 0x0000 }, + { 0x0702, 0xf875, 0x0000 }, + { 0x8702, 0xf976, 0x9000 }, + { 0x8702, 0xf8f6, 0x8000 }, + { 0x8702, 0xf8b6, 0x7000 }, + { 0x8702, 0xf896, 0x6000 }, + { 0x8702, 0xf886, 0x5000 }, + { 0x8702, 0xf87e, 0x4000 }, + { 0x8702, 0xf87a, 0x3000 }, + { 0x8702, 0xf878, 0x2000 }, + { 0x0702, 0xf877, 0x0000 }, + { 0x0702, 0xf879, 0x0000 }, + { 0x8702, 0xf87c, 0x2000 }, + { 0x0702, 0xf87b, 0x0000 }, + { 0x0702, 0xf87d, 0x0000 }, + { 0x8702, 0xf882, 0x3000 }, + { 0x8702, 0xf880, 0x2000 }, + { 0x0702, 0xf87f, 0x0000 }, + { 0x0702, 0xf881, 0x0000 }, + { 0x8702, 0xf884, 0x2000 }, + { 0x0702, 0xf883, 0x0000 }, + { 0x0702, 0xf885, 0x0000 }, + { 0x8702, 0xf88e, 0x4000 }, + { 0x8702, 0xf88a, 0x3000 }, + { 0x8702, 0xf888, 0x2000 }, + { 0x0702, 0xf887, 0x0000 }, + { 0x0702, 0xf889, 0x0000 }, + { 0x8702, 0xf88c, 0x2000 }, + { 0x0702, 0xf88b, 0x0000 }, + { 0x0702, 0xf88d, 0x0000 }, + { 0x8702, 0xf892, 0x3000 }, + { 0x8702, 0xf890, 0x2000 }, + { 0x0702, 0xf88f, 0x0000 }, + { 0x0702, 0xf891, 0x0000 }, + { 0x8702, 0xf894, 0x2000 }, + { 0x0702, 0xf893, 0x0000 }, + { 0x0702, 0xf895, 0x0000 }, + { 0x8702, 0xf8a6, 0x5000 }, + { 0x8702, 0xf89e, 0x4000 }, + { 0x8702, 0xf89a, 0x3000 }, + { 0x8702, 0xf898, 0x2000 }, + { 0x0702, 0xf897, 0x0000 }, + { 0x0702, 0xf899, 0x0000 }, + { 0x8702, 0xf89c, 0x2000 }, + { 0x0702, 0xf89b, 0x0000 }, + { 0x0702, 0xf89d, 0x0000 }, + { 0x8702, 0xf8a2, 0x3000 }, + { 0x8702, 0xf8a0, 0x2000 }, + { 0x0702, 0xf89f, 0x0000 }, + { 0x0702, 0xf8a1, 0x0000 }, + { 0x8702, 0xf8a4, 0x2000 }, + { 0x0702, 0xf8a3, 0x0000 }, + { 0x0702, 0xf8a5, 0x0000 }, + { 0x8702, 0xf8ae, 0x4000 }, + { 0x8702, 0xf8aa, 0x3000 }, + { 0x8702, 0xf8a8, 0x2000 }, + { 0x0702, 0xf8a7, 0x0000 }, + { 0x0702, 0xf8a9, 0x0000 }, + { 0x8702, 0xf8ac, 0x2000 }, + { 0x0702, 0xf8ab, 0x0000 }, + { 0x0702, 0xf8ad, 0x0000 }, + { 0x8702, 0xf8b2, 0x3000 }, + { 0x8702, 0xf8b0, 0x2000 }, + { 0x0702, 0xf8af, 0x0000 }, + { 0x0702, 0xf8b1, 0x0000 }, + { 0x8702, 0xf8b4, 0x2000 }, + { 0x0702, 0xf8b3, 0x0000 }, + { 0x0702, 0xf8b5, 0x0000 }, + { 0x8702, 0xf8d6, 0x6000 }, + { 0x8702, 0xf8c6, 0x5000 }, + { 0x8702, 0xf8be, 0x4000 }, + { 0x8702, 0xf8ba, 0x3000 }, + { 0x8702, 0xf8b8, 0x2000 }, + { 0x0702, 0xf8b7, 0x0000 }, + { 0x0702, 0xf8b9, 0x0000 }, + { 0x8702, 0xf8bc, 0x2000 }, + { 0x0702, 0xf8bb, 0x0000 }, + { 0x0702, 0xf8bd, 0x0000 }, + { 0x8702, 0xf8c2, 0x3000 }, + { 0x8702, 0xf8c0, 0x2000 }, + { 0x0702, 0xf8bf, 0x0000 }, + { 0x0702, 0xf8c1, 0x0000 }, + { 0x8702, 0xf8c4, 0x2000 }, + { 0x0702, 0xf8c3, 0x0000 }, + { 0x0702, 0xf8c5, 0x0000 }, + { 0x8702, 0xf8ce, 0x4000 }, + { 0x8702, 0xf8ca, 0x3000 }, + { 0x8702, 0xf8c8, 0x2000 }, + { 0x0702, 0xf8c7, 0x0000 }, + { 0x0702, 0xf8c9, 0x0000 }, + { 0x8702, 0xf8cc, 0x2000 }, + { 0x0702, 0xf8cb, 0x0000 }, + { 0x0702, 0xf8cd, 0x0000 }, + { 0x8702, 0xf8d2, 0x3000 }, + { 0x8702, 0xf8d0, 0x2000 }, + { 0x0702, 0xf8cf, 0x0000 }, + { 0x0702, 0xf8d1, 0x0000 }, + { 0x8702, 0xf8d4, 0x2000 }, + { 0x0702, 0xf8d3, 0x0000 }, + { 0x0702, 0xf8d5, 0x0000 }, + { 0x8702, 0xf8e6, 0x5000 }, + { 0x8702, 0xf8de, 0x4000 }, + { 0x8702, 0xf8da, 0x3000 }, + { 0x8702, 0xf8d8, 0x2000 }, + { 0x0702, 0xf8d7, 0x0000 }, + { 0x0702, 0xf8d9, 0x0000 }, + { 0x8702, 0xf8dc, 0x2000 }, + { 0x0702, 0xf8db, 0x0000 }, + { 0x0702, 0xf8dd, 0x0000 }, + { 0x8702, 0xf8e2, 0x3000 }, + { 0x8702, 0xf8e0, 0x2000 }, + { 0x0702, 0xf8df, 0x0000 }, + { 0x0702, 0xf8e1, 0x0000 }, + { 0x8702, 0xf8e4, 0x2000 }, + { 0x0702, 0xf8e3, 0x0000 }, + { 0x0702, 0xf8e5, 0x0000 }, + { 0x8702, 0xf8ee, 0x4000 }, + { 0x8702, 0xf8ea, 0x3000 }, + { 0x8702, 0xf8e8, 0x2000 }, + { 0x0702, 0xf8e7, 0x0000 }, + { 0x0702, 0xf8e9, 0x0000 }, + { 0x8702, 0xf8ec, 0x2000 }, + { 0x0702, 0xf8eb, 0x0000 }, + { 0x0702, 0xf8ed, 0x0000 }, + { 0x8702, 0xf8f2, 0x3000 }, + { 0x8702, 0xf8f0, 0x2000 }, + { 0x0702, 0xf8ef, 0x0000 }, + { 0x0702, 0xf8f1, 0x0000 }, + { 0x8702, 0xf8f4, 0x2000 }, + { 0x0702, 0xf8f3, 0x0000 }, + { 0x0702, 0xf8f5, 0x0000 }, + { 0x8702, 0xf936, 0x7000 }, + { 0x8702, 0xf916, 0x6000 }, + { 0x8702, 0xf906, 0x5000 }, + { 0x8702, 0xf8fe, 0x4000 }, + { 0x8702, 0xf8fa, 0x3000 }, + { 0x8702, 0xf8f8, 0x2000 }, + { 0x0702, 0xf8f7, 0x0000 }, + { 0x0702, 0xf8f9, 0x0000 }, + { 0x8702, 0xf8fc, 0x2000 }, + { 0x0702, 0xf8fb, 0x0000 }, + { 0x0702, 0xf8fd, 0x0000 }, + { 0x8702, 0xf902, 0x3000 }, + { 0x8702, 0xf900, 0x2000 }, + { 0x0702, 0xf8ff, 0x0000 }, + { 0x0702, 0xf901, 0x0000 }, + { 0x8702, 0xf904, 0x2000 }, + { 0x0702, 0xf903, 0x0000 }, + { 0x0702, 0xf905, 0x0000 }, + { 0x8702, 0xf90e, 0x4000 }, + { 0x8702, 0xf90a, 0x3000 }, + { 0x8702, 0xf908, 0x2000 }, + { 0x0702, 0xf907, 0x0000 }, + { 0x0702, 0xf909, 0x0000 }, + { 0x8702, 0xf90c, 0x2000 }, + { 0x0702, 0xf90b, 0x0000 }, + { 0x0702, 0xf90d, 0x0000 }, + { 0x8702, 0xf912, 0x3000 }, + { 0x8702, 0xf910, 0x2000 }, + { 0x0702, 0xf90f, 0x0000 }, + { 0x0702, 0xf911, 0x0000 }, + { 0x8702, 0xf914, 0x2000 }, + { 0x0702, 0xf913, 0x0000 }, + { 0x0702, 0xf915, 0x0000 }, + { 0x8702, 0xf926, 0x5000 }, + { 0x8702, 0xf91e, 0x4000 }, + { 0x8702, 0xf91a, 0x3000 }, + { 0x8702, 0xf918, 0x2000 }, + { 0x0702, 0xf917, 0x0000 }, + { 0x0702, 0xf919, 0x0000 }, + { 0x8702, 0xf91c, 0x2000 }, + { 0x0702, 0xf91b, 0x0000 }, + { 0x0702, 0xf91d, 0x0000 }, + { 0x8702, 0xf922, 0x3000 }, + { 0x8702, 0xf920, 0x2000 }, + { 0x0702, 0xf91f, 0x0000 }, + { 0x0702, 0xf921, 0x0000 }, + { 0x8702, 0xf924, 0x2000 }, + { 0x0702, 0xf923, 0x0000 }, + { 0x0702, 0xf925, 0x0000 }, + { 0x8702, 0xf92e, 0x4000 }, + { 0x8702, 0xf92a, 0x3000 }, + { 0x8702, 0xf928, 0x2000 }, + { 0x0702, 0xf927, 0x0000 }, + { 0x0702, 0xf929, 0x0000 }, + { 0x8702, 0xf92c, 0x2000 }, + { 0x0702, 0xf92b, 0x0000 }, + { 0x0702, 0xf92d, 0x0000 }, + { 0x8702, 0xf932, 0x3000 }, + { 0x8702, 0xf930, 0x2000 }, + { 0x0702, 0xf92f, 0x0000 }, + { 0x0702, 0xf931, 0x0000 }, + { 0x8702, 0xf934, 0x2000 }, + { 0x0702, 0xf933, 0x0000 }, + { 0x0702, 0xf935, 0x0000 }, + { 0x8702, 0xf956, 0x6000 }, + { 0x8702, 0xf946, 0x5000 }, + { 0x8702, 0xf93e, 0x4000 }, + { 0x8702, 0xf93a, 0x3000 }, + { 0x8702, 0xf938, 0x2000 }, + { 0x0702, 0xf937, 0x0000 }, + { 0x0702, 0xf939, 0x0000 }, + { 0x8702, 0xf93c, 0x2000 }, + { 0x0702, 0xf93b, 0x0000 }, + { 0x0702, 0xf93d, 0x0000 }, + { 0x8702, 0xf942, 0x3000 }, + { 0x8702, 0xf940, 0x2000 }, + { 0x0702, 0xf93f, 0x0000 }, + { 0x0702, 0xf941, 0x0000 }, + { 0x8702, 0xf944, 0x2000 }, + { 0x0702, 0xf943, 0x0000 }, + { 0x0702, 0xf945, 0x0000 }, + { 0x8702, 0xf94e, 0x4000 }, + { 0x8702, 0xf94a, 0x3000 }, + { 0x8702, 0xf948, 0x2000 }, + { 0x0702, 0xf947, 0x0000 }, + { 0x0702, 0xf949, 0x0000 }, + { 0x8702, 0xf94c, 0x2000 }, + { 0x0702, 0xf94b, 0x0000 }, + { 0x0702, 0xf94d, 0x0000 }, + { 0x8702, 0xf952, 0x3000 }, + { 0x8702, 0xf950, 0x2000 }, + { 0x0702, 0xf94f, 0x0000 }, + { 0x0702, 0xf951, 0x0000 }, + { 0x8702, 0xf954, 0x2000 }, + { 0x0702, 0xf953, 0x0000 }, + { 0x0702, 0xf955, 0x0000 }, + { 0x8702, 0xf966, 0x5000 }, + { 0x8702, 0xf95e, 0x4000 }, + { 0x8702, 0xf95a, 0x3000 }, + { 0x8702, 0xf958, 0x2000 }, + { 0x0702, 0xf957, 0x0000 }, + { 0x0702, 0xf959, 0x0000 }, + { 0x8702, 0xf95c, 0x2000 }, + { 0x0702, 0xf95b, 0x0000 }, + { 0x0702, 0xf95d, 0x0000 }, + { 0x8702, 0xf962, 0x3000 }, + { 0x8702, 0xf960, 0x2000 }, + { 0x0702, 0xf95f, 0x0000 }, + { 0x0702, 0xf961, 0x0000 }, + { 0x8702, 0xf964, 0x2000 }, + { 0x0702, 0xf963, 0x0000 }, + { 0x0702, 0xf965, 0x0000 }, + { 0x8702, 0xf96e, 0x4000 }, + { 0x8702, 0xf96a, 0x3000 }, + { 0x8702, 0xf968, 0x2000 }, + { 0x0702, 0xf967, 0x0000 }, + { 0x0702, 0xf969, 0x0000 }, + { 0x8702, 0xf96c, 0x2000 }, + { 0x0702, 0xf96b, 0x0000 }, + { 0x0702, 0xf96d, 0x0000 }, + { 0x8702, 0xf972, 0x3000 }, + { 0x8702, 0xf970, 0x2000 }, + { 0x0702, 0xf96f, 0x0000 }, + { 0x0702, 0xf971, 0x0000 }, + { 0x8702, 0xf974, 0x2000 }, + { 0x0702, 0xf973, 0x0000 }, + { 0x0702, 0xf975, 0x0000 }, + { 0x810e, 0x0077, 0x9000 }, + { 0x8702, 0xf9f6, 0x8000 }, + { 0x8702, 0xf9b6, 0x7000 }, + { 0x8702, 0xf996, 0x6000 }, + { 0x8702, 0xf986, 0x5000 }, + { 0x8702, 0xf97e, 0x4000 }, + { 0x8702, 0xf97a, 0x3000 }, + { 0x8702, 0xf978, 0x2000 }, + { 0x0702, 0xf977, 0x0000 }, + { 0x0702, 0xf979, 0x0000 }, + { 0x8702, 0xf97c, 0x2000 }, + { 0x0702, 0xf97b, 0x0000 }, + { 0x0702, 0xf97d, 0x0000 }, + { 0x8702, 0xf982, 0x3000 }, + { 0x8702, 0xf980, 0x2000 }, + { 0x0702, 0xf97f, 0x0000 }, + { 0x0702, 0xf981, 0x0000 }, + { 0x8702, 0xf984, 0x2000 }, + { 0x0702, 0xf983, 0x0000 }, + { 0x0702, 0xf985, 0x0000 }, + { 0x8702, 0xf98e, 0x4000 }, + { 0x8702, 0xf98a, 0x3000 }, + { 0x8702, 0xf988, 0x2000 }, + { 0x0702, 0xf987, 0x0000 }, + { 0x0702, 0xf989, 0x0000 }, + { 0x8702, 0xf98c, 0x2000 }, + { 0x0702, 0xf98b, 0x0000 }, + { 0x0702, 0xf98d, 0x0000 }, + { 0x8702, 0xf992, 0x3000 }, + { 0x8702, 0xf990, 0x2000 }, + { 0x0702, 0xf98f, 0x0000 }, + { 0x0702, 0xf991, 0x0000 }, + { 0x8702, 0xf994, 0x2000 }, + { 0x0702, 0xf993, 0x0000 }, + { 0x0702, 0xf995, 0x0000 }, + { 0x8702, 0xf9a6, 0x5000 }, + { 0x8702, 0xf99e, 0x4000 }, + { 0x8702, 0xf99a, 0x3000 }, + { 0x8702, 0xf998, 0x2000 }, + { 0x0702, 0xf997, 0x0000 }, + { 0x0702, 0xf999, 0x0000 }, + { 0x8702, 0xf99c, 0x2000 }, + { 0x0702, 0xf99b, 0x0000 }, + { 0x0702, 0xf99d, 0x0000 }, + { 0x8702, 0xf9a2, 0x3000 }, + { 0x8702, 0xf9a0, 0x2000 }, + { 0x0702, 0xf99f, 0x0000 }, + { 0x0702, 0xf9a1, 0x0000 }, + { 0x8702, 0xf9a4, 0x2000 }, + { 0x0702, 0xf9a3, 0x0000 }, + { 0x0702, 0xf9a5, 0x0000 }, + { 0x8702, 0xf9ae, 0x4000 }, + { 0x8702, 0xf9aa, 0x3000 }, + { 0x8702, 0xf9a8, 0x2000 }, + { 0x0702, 0xf9a7, 0x0000 }, + { 0x0702, 0xf9a9, 0x0000 }, + { 0x8702, 0xf9ac, 0x2000 }, + { 0x0702, 0xf9ab, 0x0000 }, + { 0x0702, 0xf9ad, 0x0000 }, + { 0x8702, 0xf9b2, 0x3000 }, + { 0x8702, 0xf9b0, 0x2000 }, + { 0x0702, 0xf9af, 0x0000 }, + { 0x0702, 0xf9b1, 0x0000 }, + { 0x8702, 0xf9b4, 0x2000 }, + { 0x0702, 0xf9b3, 0x0000 }, + { 0x0702, 0xf9b5, 0x0000 }, + { 0x8702, 0xf9d6, 0x6000 }, + { 0x8702, 0xf9c6, 0x5000 }, + { 0x8702, 0xf9be, 0x4000 }, + { 0x8702, 0xf9ba, 0x3000 }, + { 0x8702, 0xf9b8, 0x2000 }, + { 0x0702, 0xf9b7, 0x0000 }, + { 0x0702, 0xf9b9, 0x0000 }, + { 0x8702, 0xf9bc, 0x2000 }, + { 0x0702, 0xf9bb, 0x0000 }, + { 0x0702, 0xf9bd, 0x0000 }, + { 0x8702, 0xf9c2, 0x3000 }, + { 0x8702, 0xf9c0, 0x2000 }, + { 0x0702, 0xf9bf, 0x0000 }, + { 0x0702, 0xf9c1, 0x0000 }, + { 0x8702, 0xf9c4, 0x2000 }, + { 0x0702, 0xf9c3, 0x0000 }, + { 0x0702, 0xf9c5, 0x0000 }, + { 0x8702, 0xf9ce, 0x4000 }, + { 0x8702, 0xf9ca, 0x3000 }, + { 0x8702, 0xf9c8, 0x2000 }, + { 0x0702, 0xf9c7, 0x0000 }, + { 0x0702, 0xf9c9, 0x0000 }, + { 0x8702, 0xf9cc, 0x2000 }, + { 0x0702, 0xf9cb, 0x0000 }, + { 0x0702, 0xf9cd, 0x0000 }, + { 0x8702, 0xf9d2, 0x3000 }, + { 0x8702, 0xf9d0, 0x2000 }, + { 0x0702, 0xf9cf, 0x0000 }, + { 0x0702, 0xf9d1, 0x0000 }, + { 0x8702, 0xf9d4, 0x2000 }, + { 0x0702, 0xf9d3, 0x0000 }, + { 0x0702, 0xf9d5, 0x0000 }, + { 0x8702, 0xf9e6, 0x5000 }, + { 0x8702, 0xf9de, 0x4000 }, + { 0x8702, 0xf9da, 0x3000 }, + { 0x8702, 0xf9d8, 0x2000 }, + { 0x0702, 0xf9d7, 0x0000 }, + { 0x0702, 0xf9d9, 0x0000 }, + { 0x8702, 0xf9dc, 0x2000 }, + { 0x0702, 0xf9db, 0x0000 }, + { 0x0702, 0xf9dd, 0x0000 }, + { 0x8702, 0xf9e2, 0x3000 }, + { 0x8702, 0xf9e0, 0x2000 }, + { 0x0702, 0xf9df, 0x0000 }, + { 0x0702, 0xf9e1, 0x0000 }, + { 0x8702, 0xf9e4, 0x2000 }, + { 0x0702, 0xf9e3, 0x0000 }, + { 0x0702, 0xf9e5, 0x0000 }, + { 0x8702, 0xf9ee, 0x4000 }, + { 0x8702, 0xf9ea, 0x3000 }, + { 0x8702, 0xf9e8, 0x2000 }, + { 0x0702, 0xf9e7, 0x0000 }, + { 0x0702, 0xf9e9, 0x0000 }, + { 0x8702, 0xf9ec, 0x2000 }, + { 0x0702, 0xf9eb, 0x0000 }, + { 0x0702, 0xf9ed, 0x0000 }, + { 0x8702, 0xf9f2, 0x3000 }, + { 0x8702, 0xf9f0, 0x2000 }, + { 0x0702, 0xf9ef, 0x0000 }, + { 0x0702, 0xf9f1, 0x0000 }, + { 0x8702, 0xf9f4, 0x2000 }, + { 0x0702, 0xf9f3, 0x0000 }, + { 0x0702, 0xf9f5, 0x0000 }, + { 0x810e, 0x0037, 0x7000 }, + { 0x8702, 0xfa16, 0x6000 }, + { 0x8702, 0xfa06, 0x5000 }, + { 0x8702, 0xf9fe, 0x4000 }, + { 0x8702, 0xf9fa, 0x3000 }, + { 0x8702, 0xf9f8, 0x2000 }, + { 0x0702, 0xf9f7, 0x0000 }, + { 0x0702, 0xf9f9, 0x0000 }, + { 0x8702, 0xf9fc, 0x2000 }, + { 0x0702, 0xf9fb, 0x0000 }, + { 0x0702, 0xf9fd, 0x0000 }, + { 0x8702, 0xfa02, 0x3000 }, + { 0x8702, 0xfa00, 0x2000 }, + { 0x0702, 0xf9ff, 0x0000 }, + { 0x0702, 0xfa01, 0x0000 }, + { 0x8702, 0xfa04, 0x2000 }, + { 0x0702, 0xfa03, 0x0000 }, + { 0x0702, 0xfa05, 0x0000 }, + { 0x8702, 0xfa0e, 0x4000 }, + { 0x8702, 0xfa0a, 0x3000 }, + { 0x8702, 0xfa08, 0x2000 }, + { 0x0702, 0xfa07, 0x0000 }, + { 0x0702, 0xfa09, 0x0000 }, + { 0x8702, 0xfa0c, 0x2000 }, + { 0x0702, 0xfa0b, 0x0000 }, + { 0x0702, 0xfa0d, 0x0000 }, + { 0x8702, 0xfa12, 0x3000 }, + { 0x8702, 0xfa10, 0x2000 }, + { 0x0702, 0xfa0f, 0x0000 }, + { 0x0702, 0xfa11, 0x0000 }, + { 0x8702, 0xfa14, 0x2000 }, + { 0x0702, 0xfa13, 0x0000 }, + { 0x0702, 0xfa15, 0x0000 }, + { 0x810e, 0x0027, 0x5000 }, + { 0x810e, 0x0001, 0x4000 }, + { 0x8702, 0xfa1a, 0x3000 }, + { 0x8702, 0xfa18, 0x2000 }, + { 0x0702, 0xfa17, 0x0000 }, + { 0x0702, 0xfa19, 0x0000 }, + { 0x8702, 0xfa1c, 0x2000 }, + { 0x0702, 0xfa1b, 0x0000 }, + { 0x0702, 0xfa1d, 0x0000 }, + { 0x810e, 0x0023, 0x3000 }, + { 0x810e, 0x0021, 0x2000 }, + { 0x010e, 0x0020, 0x0000 }, + { 0x010e, 0x0022, 0x0000 }, + { 0x810e, 0x0025, 0x2000 }, + { 0x010e, 0x0024, 0x0000 }, + { 0x010e, 0x0026, 0x0000 }, + { 0x810e, 0x002f, 0x4000 }, + { 0x810e, 0x002b, 0x3000 }, + { 0x810e, 0x0029, 0x2000 }, + { 0x010e, 0x0028, 0x0000 }, + { 0x010e, 0x002a, 0x0000 }, + { 0x810e, 0x002d, 0x2000 }, + { 0x010e, 0x002c, 0x0000 }, + { 0x010e, 0x002e, 0x0000 }, + { 0x810e, 0x0033, 0x3000 }, + { 0x810e, 0x0031, 0x2000 }, + { 0x010e, 0x0030, 0x0000 }, + { 0x010e, 0x0032, 0x0000 }, + { 0x810e, 0x0035, 0x2000 }, + { 0x010e, 0x0034, 0x0000 }, + { 0x010e, 0x0036, 0x0000 }, + { 0x810e, 0x0057, 0x6000 }, + { 0x810e, 0x0047, 0x5000 }, + { 0x810e, 0x003f, 0x4000 }, + { 0x810e, 0x003b, 0x3000 }, + { 0x810e, 0x0039, 0x2000 }, + { 0x010e, 0x0038, 0x0000 }, + { 0x010e, 0x003a, 0x0000 }, + { 0x810e, 0x003d, 0x2000 }, + { 0x010e, 0x003c, 0x0000 }, + { 0x010e, 0x003e, 0x0000 }, + { 0x810e, 0x0043, 0x3000 }, + { 0x810e, 0x0041, 0x2000 }, + { 0x010e, 0x0040, 0x0000 }, + { 0x010e, 0x0042, 0x0000 }, + { 0x810e, 0x0045, 0x2000 }, + { 0x010e, 0x0044, 0x0000 }, + { 0x010e, 0x0046, 0x0000 }, + { 0x810e, 0x004f, 0x4000 }, + { 0x810e, 0x004b, 0x3000 }, + { 0x810e, 0x0049, 0x2000 }, + { 0x010e, 0x0048, 0x0000 }, + { 0x010e, 0x004a, 0x0000 }, + { 0x810e, 0x004d, 0x2000 }, + { 0x010e, 0x004c, 0x0000 }, + { 0x010e, 0x004e, 0x0000 }, + { 0x810e, 0x0053, 0x3000 }, + { 0x810e, 0x0051, 0x2000 }, + { 0x010e, 0x0050, 0x0000 }, + { 0x010e, 0x0052, 0x0000 }, + { 0x810e, 0x0055, 0x2000 }, + { 0x010e, 0x0054, 0x0000 }, + { 0x010e, 0x0056, 0x0000 }, + { 0x810e, 0x0067, 0x5000 }, + { 0x810e, 0x005f, 0x4000 }, + { 0x810e, 0x005b, 0x3000 }, + { 0x810e, 0x0059, 0x2000 }, + { 0x010e, 0x0058, 0x0000 }, + { 0x010e, 0x005a, 0x0000 }, + { 0x810e, 0x005d, 0x2000 }, + { 0x010e, 0x005c, 0x0000 }, + { 0x010e, 0x005e, 0x0000 }, + { 0x810e, 0x0063, 0x3000 }, + { 0x810e, 0x0061, 0x2000 }, + { 0x010e, 0x0060, 0x0000 }, + { 0x010e, 0x0062, 0x0000 }, + { 0x810e, 0x0065, 0x2000 }, + { 0x010e, 0x0064, 0x0000 }, + { 0x010e, 0x0066, 0x0000 }, + { 0x810e, 0x006f, 0x4000 }, + { 0x810e, 0x006b, 0x3000 }, + { 0x810e, 0x0069, 0x2000 }, + { 0x010e, 0x0068, 0x0000 }, + { 0x010e, 0x006a, 0x0000 }, + { 0x810e, 0x006d, 0x2000 }, + { 0x010e, 0x006c, 0x0000 }, + { 0x010e, 0x006e, 0x0000 }, + { 0x810e, 0x0073, 0x3000 }, + { 0x810e, 0x0071, 0x2000 }, + { 0x010e, 0x0070, 0x0000 }, + { 0x010e, 0x0072, 0x0000 }, + { 0x810e, 0x0075, 0x2000 }, + { 0x010e, 0x0074, 0x0000 }, + { 0x010e, 0x0076, 0x0000 }, + { 0x8c0e, 0x0177, 0x8000 }, + { 0x8c0e, 0x0137, 0x7000 }, + { 0x8c0e, 0x0117, 0x6000 }, + { 0x8c0e, 0x0107, 0x5000 }, + { 0x810e, 0x007f, 0x4000 }, + { 0x810e, 0x007b, 0x3000 }, + { 0x810e, 0x0079, 0x2000 }, + { 0x010e, 0x0078, 0x0000 }, + { 0x010e, 0x007a, 0x0000 }, + { 0x810e, 0x007d, 0x2000 }, + { 0x010e, 0x007c, 0x0000 }, + { 0x010e, 0x007e, 0x0000 }, + { 0x8c0e, 0x0103, 0x3000 }, + { 0x8c0e, 0x0101, 0x2000 }, + { 0x0c0e, 0x0100, 0x0000 }, + { 0x0c0e, 0x0102, 0x0000 }, + { 0x8c0e, 0x0105, 0x2000 }, + { 0x0c0e, 0x0104, 0x0000 }, + { 0x0c0e, 0x0106, 0x0000 }, + { 0x8c0e, 0x010f, 0x4000 }, + { 0x8c0e, 0x010b, 0x3000 }, + { 0x8c0e, 0x0109, 0x2000 }, + { 0x0c0e, 0x0108, 0x0000 }, + { 0x0c0e, 0x010a, 0x0000 }, + { 0x8c0e, 0x010d, 0x2000 }, + { 0x0c0e, 0x010c, 0x0000 }, + { 0x0c0e, 0x010e, 0x0000 }, + { 0x8c0e, 0x0113, 0x3000 }, + { 0x8c0e, 0x0111, 0x2000 }, + { 0x0c0e, 0x0110, 0x0000 }, + { 0x0c0e, 0x0112, 0x0000 }, + { 0x8c0e, 0x0115, 0x2000 }, + { 0x0c0e, 0x0114, 0x0000 }, + { 0x0c0e, 0x0116, 0x0000 }, + { 0x8c0e, 0x0127, 0x5000 }, + { 0x8c0e, 0x011f, 0x4000 }, + { 0x8c0e, 0x011b, 0x3000 }, + { 0x8c0e, 0x0119, 0x2000 }, + { 0x0c0e, 0x0118, 0x0000 }, + { 0x0c0e, 0x011a, 0x0000 }, + { 0x8c0e, 0x011d, 0x2000 }, + { 0x0c0e, 0x011c, 0x0000 }, + { 0x0c0e, 0x011e, 0x0000 }, + { 0x8c0e, 0x0123, 0x3000 }, + { 0x8c0e, 0x0121, 0x2000 }, + { 0x0c0e, 0x0120, 0x0000 }, + { 0x0c0e, 0x0122, 0x0000 }, + { 0x8c0e, 0x0125, 0x2000 }, + { 0x0c0e, 0x0124, 0x0000 }, + { 0x0c0e, 0x0126, 0x0000 }, + { 0x8c0e, 0x012f, 0x4000 }, + { 0x8c0e, 0x012b, 0x3000 }, + { 0x8c0e, 0x0129, 0x2000 }, + { 0x0c0e, 0x0128, 0x0000 }, + { 0x0c0e, 0x012a, 0x0000 }, + { 0x8c0e, 0x012d, 0x2000 }, + { 0x0c0e, 0x012c, 0x0000 }, + { 0x0c0e, 0x012e, 0x0000 }, + { 0x8c0e, 0x0133, 0x3000 }, + { 0x8c0e, 0x0131, 0x2000 }, + { 0x0c0e, 0x0130, 0x0000 }, + { 0x0c0e, 0x0132, 0x0000 }, + { 0x8c0e, 0x0135, 0x2000 }, + { 0x0c0e, 0x0134, 0x0000 }, + { 0x0c0e, 0x0136, 0x0000 }, + { 0x8c0e, 0x0157, 0x6000 }, + { 0x8c0e, 0x0147, 0x5000 }, + { 0x8c0e, 0x013f, 0x4000 }, + { 0x8c0e, 0x013b, 0x3000 }, + { 0x8c0e, 0x0139, 0x2000 }, + { 0x0c0e, 0x0138, 0x0000 }, + { 0x0c0e, 0x013a, 0x0000 }, + { 0x8c0e, 0x013d, 0x2000 }, + { 0x0c0e, 0x013c, 0x0000 }, + { 0x0c0e, 0x013e, 0x0000 }, + { 0x8c0e, 0x0143, 0x3000 }, + { 0x8c0e, 0x0141, 0x2000 }, + { 0x0c0e, 0x0140, 0x0000 }, + { 0x0c0e, 0x0142, 0x0000 }, + { 0x8c0e, 0x0145, 0x2000 }, + { 0x0c0e, 0x0144, 0x0000 }, + { 0x0c0e, 0x0146, 0x0000 }, + { 0x8c0e, 0x014f, 0x4000 }, + { 0x8c0e, 0x014b, 0x3000 }, + { 0x8c0e, 0x0149, 0x2000 }, + { 0x0c0e, 0x0148, 0x0000 }, + { 0x0c0e, 0x014a, 0x0000 }, + { 0x8c0e, 0x014d, 0x2000 }, + { 0x0c0e, 0x014c, 0x0000 }, + { 0x0c0e, 0x014e, 0x0000 }, + { 0x8c0e, 0x0153, 0x3000 }, + { 0x8c0e, 0x0151, 0x2000 }, + { 0x0c0e, 0x0150, 0x0000 }, + { 0x0c0e, 0x0152, 0x0000 }, + { 0x8c0e, 0x0155, 0x2000 }, + { 0x0c0e, 0x0154, 0x0000 }, + { 0x0c0e, 0x0156, 0x0000 }, + { 0x8c0e, 0x0167, 0x5000 }, + { 0x8c0e, 0x015f, 0x4000 }, + { 0x8c0e, 0x015b, 0x3000 }, + { 0x8c0e, 0x0159, 0x2000 }, + { 0x0c0e, 0x0158, 0x0000 }, + { 0x0c0e, 0x015a, 0x0000 }, + { 0x8c0e, 0x015d, 0x2000 }, + { 0x0c0e, 0x015c, 0x0000 }, + { 0x0c0e, 0x015e, 0x0000 }, + { 0x8c0e, 0x0163, 0x3000 }, + { 0x8c0e, 0x0161, 0x2000 }, + { 0x0c0e, 0x0160, 0x0000 }, + { 0x0c0e, 0x0162, 0x0000 }, + { 0x8c0e, 0x0165, 0x2000 }, + { 0x0c0e, 0x0164, 0x0000 }, + { 0x0c0e, 0x0166, 0x0000 }, + { 0x8c0e, 0x016f, 0x4000 }, + { 0x8c0e, 0x016b, 0x3000 }, + { 0x8c0e, 0x0169, 0x2000 }, + { 0x0c0e, 0x0168, 0x0000 }, + { 0x0c0e, 0x016a, 0x0000 }, + { 0x8c0e, 0x016d, 0x2000 }, + { 0x0c0e, 0x016c, 0x0000 }, + { 0x0c0e, 0x016e, 0x0000 }, + { 0x8c0e, 0x0173, 0x3000 }, + { 0x8c0e, 0x0171, 0x2000 }, + { 0x0c0e, 0x0170, 0x0000 }, + { 0x0c0e, 0x0172, 0x0000 }, + { 0x8c0e, 0x0175, 0x2000 }, + { 0x0c0e, 0x0174, 0x0000 }, + { 0x0c0e, 0x0176, 0x0000 }, + { 0x8c0e, 0x01b7, 0x7000 }, + { 0x8c0e, 0x0197, 0x6000 }, + { 0x8c0e, 0x0187, 0x5000 }, + { 0x8c0e, 0x017f, 0x4000 }, + { 0x8c0e, 0x017b, 0x3000 }, + { 0x8c0e, 0x0179, 0x2000 }, + { 0x0c0e, 0x0178, 0x0000 }, + { 0x0c0e, 0x017a, 0x0000 }, + { 0x8c0e, 0x017d, 0x2000 }, + { 0x0c0e, 0x017c, 0x0000 }, + { 0x0c0e, 0x017e, 0x0000 }, + { 0x8c0e, 0x0183, 0x3000 }, + { 0x8c0e, 0x0181, 0x2000 }, + { 0x0c0e, 0x0180, 0x0000 }, + { 0x0c0e, 0x0182, 0x0000 }, + { 0x8c0e, 0x0185, 0x2000 }, + { 0x0c0e, 0x0184, 0x0000 }, + { 0x0c0e, 0x0186, 0x0000 }, + { 0x8c0e, 0x018f, 0x4000 }, + { 0x8c0e, 0x018b, 0x3000 }, + { 0x8c0e, 0x0189, 0x2000 }, + { 0x0c0e, 0x0188, 0x0000 }, + { 0x0c0e, 0x018a, 0x0000 }, + { 0x8c0e, 0x018d, 0x2000 }, + { 0x0c0e, 0x018c, 0x0000 }, + { 0x0c0e, 0x018e, 0x0000 }, + { 0x8c0e, 0x0193, 0x3000 }, + { 0x8c0e, 0x0191, 0x2000 }, + { 0x0c0e, 0x0190, 0x0000 }, + { 0x0c0e, 0x0192, 0x0000 }, + { 0x8c0e, 0x0195, 0x2000 }, + { 0x0c0e, 0x0194, 0x0000 }, + { 0x0c0e, 0x0196, 0x0000 }, + { 0x8c0e, 0x01a7, 0x5000 }, + { 0x8c0e, 0x019f, 0x4000 }, + { 0x8c0e, 0x019b, 0x3000 }, + { 0x8c0e, 0x0199, 0x2000 }, + { 0x0c0e, 0x0198, 0x0000 }, + { 0x0c0e, 0x019a, 0x0000 }, + { 0x8c0e, 0x019d, 0x2000 }, + { 0x0c0e, 0x019c, 0x0000 }, + { 0x0c0e, 0x019e, 0x0000 }, + { 0x8c0e, 0x01a3, 0x3000 }, + { 0x8c0e, 0x01a1, 0x2000 }, + { 0x0c0e, 0x01a0, 0x0000 }, + { 0x0c0e, 0x01a2, 0x0000 }, + { 0x8c0e, 0x01a5, 0x2000 }, + { 0x0c0e, 0x01a4, 0x0000 }, + { 0x0c0e, 0x01a6, 0x0000 }, + { 0x8c0e, 0x01af, 0x4000 }, + { 0x8c0e, 0x01ab, 0x3000 }, + { 0x8c0e, 0x01a9, 0x2000 }, + { 0x0c0e, 0x01a8, 0x0000 }, + { 0x0c0e, 0x01aa, 0x0000 }, + { 0x8c0e, 0x01ad, 0x2000 }, + { 0x0c0e, 0x01ac, 0x0000 }, + { 0x0c0e, 0x01ae, 0x0000 }, + { 0x8c0e, 0x01b3, 0x3000 }, + { 0x8c0e, 0x01b1, 0x2000 }, + { 0x0c0e, 0x01b0, 0x0000 }, + { 0x0c0e, 0x01b2, 0x0000 }, + { 0x8c0e, 0x01b5, 0x2000 }, + { 0x0c0e, 0x01b4, 0x0000 }, + { 0x0c0e, 0x01b6, 0x0000 }, + { 0x8c0e, 0x01d7, 0x6000 }, + { 0x8c0e, 0x01c7, 0x5000 }, + { 0x8c0e, 0x01bf, 0x4000 }, + { 0x8c0e, 0x01bb, 0x3000 }, + { 0x8c0e, 0x01b9, 0x2000 }, + { 0x0c0e, 0x01b8, 0x0000 }, + { 0x0c0e, 0x01ba, 0x0000 }, + { 0x8c0e, 0x01bd, 0x2000 }, + { 0x0c0e, 0x01bc, 0x0000 }, + { 0x0c0e, 0x01be, 0x0000 }, + { 0x8c0e, 0x01c3, 0x3000 }, + { 0x8c0e, 0x01c1, 0x2000 }, + { 0x0c0e, 0x01c0, 0x0000 }, + { 0x0c0e, 0x01c2, 0x0000 }, + { 0x8c0e, 0x01c5, 0x2000 }, + { 0x0c0e, 0x01c4, 0x0000 }, + { 0x0c0e, 0x01c6, 0x0000 }, + { 0x8c0e, 0x01cf, 0x4000 }, + { 0x8c0e, 0x01cb, 0x3000 }, + { 0x8c0e, 0x01c9, 0x2000 }, + { 0x0c0e, 0x01c8, 0x0000 }, + { 0x0c0e, 0x01ca, 0x0000 }, + { 0x8c0e, 0x01cd, 0x2000 }, + { 0x0c0e, 0x01cc, 0x0000 }, + { 0x0c0e, 0x01ce, 0x0000 }, + { 0x8c0e, 0x01d3, 0x3000 }, + { 0x8c0e, 0x01d1, 0x2000 }, + { 0x0c0e, 0x01d0, 0x0000 }, + { 0x0c0e, 0x01d2, 0x0000 }, + { 0x8c0e, 0x01d5, 0x2000 }, + { 0x0c0e, 0x01d4, 0x0000 }, + { 0x0c0e, 0x01d6, 0x0000 }, + { 0x8c0e, 0x01e7, 0x5000 }, + { 0x8c0e, 0x01df, 0x4000 }, + { 0x8c0e, 0x01db, 0x3000 }, + { 0x8c0e, 0x01d9, 0x2000 }, + { 0x0c0e, 0x01d8, 0x0000 }, + { 0x0c0e, 0x01da, 0x0000 }, + { 0x8c0e, 0x01dd, 0x2000 }, + { 0x0c0e, 0x01dc, 0x0000 }, + { 0x0c0e, 0x01de, 0x0000 }, + { 0x8c0e, 0x01e3, 0x3000 }, + { 0x8c0e, 0x01e1, 0x2000 }, + { 0x0c0e, 0x01e0, 0x0000 }, + { 0x0c0e, 0x01e2, 0x0000 }, + { 0x8c0e, 0x01e5, 0x2000 }, + { 0x0c0e, 0x01e4, 0x0000 }, + { 0x0c0e, 0x01e6, 0x0000 }, + { 0x8c0e, 0x01ef, 0x4000 }, + { 0x8c0e, 0x01eb, 0x3000 }, + { 0x8c0e, 0x01e9, 0x2000 }, + { 0x0c0e, 0x01e8, 0x0000 }, + { 0x0c0e, 0x01ea, 0x0000 }, + { 0x8c0e, 0x01ed, 0x2000 }, + { 0x0c0e, 0x01ec, 0x0000 }, + { 0x0c0e, 0x01ee, 0x0000 }, + { 0x830f, 0xfffd, 0x2000 }, + { 0x030f, 0x0000, 0x0000 }, + { 0x0310, 0x0000, 0x1000 }, + { 0x0310, 0xfffd, 0x0000 }, +}; diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index f489291ccb7f..64a1511a8d7b 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -108,6 +108,22 @@ static PHP_MSHUTDOWN_FUNCTION(pcre) } /* }}} */ +#define PCRE_CACHE_SIZE 4096 + +/* {{{ static pcre_clean_cache */ +static int pcre_clean_cache(void *data, void *arg TSRMLS_DC) +{ + int *num_clean = (int *)arg; + + if (*num_clean > 0) { + (*num_clean)--; + return 1; + } else { + return 0; + } +} +/* }}} */ + /* {{{ pcre_get_compiled_regex */ PHPAPI pcre* pcre_get_compiled_regex(char *regex, pcre_extra **extra, int *preg_options TSRMLS_DC) @@ -145,14 +161,22 @@ PHPAPI pcre* pcre_get_compiled_regex_ex(char *regex, pcre_extra **extra, int *pr back the compiled pattern, otherwise go on and compile it. */ regex_len = strlen(regex); if (zend_hash_find(&PCRE_G(pcre_cache), regex, regex_len+1, (void **)&pce) == SUCCESS) { + /* + * We use a quick pcre_info() check to see whether cache is corrupted, and if it + * is, we flush it and compile the pattern from scratch. + */ + if (pcre_info(pce->re, NULL, NULL) == PCRE_ERROR_BADMAGIC) { + zend_hash_clean(&PCRE_G(pcre_cache)); + } else { #if HAVE_SETLOCALE - if (!strcmp(pce->locale, locale)) { + if (!strcmp(pce->locale, locale)) { #endif - *extra = pce->extra; - *preg_options = pce->preg_options; - *compile_options = pce->compile_options; - return pce->re; + *extra = pce->extra; + *preg_options = pce->preg_options; + *compile_options = pce->compile_options; + return pce->re; #if HAVE_SETLOCALE + } } #endif } @@ -290,6 +314,16 @@ PHPAPI pcre* pcre_get_compiled_regex_ex(char *regex, pcre_extra **extra, int *pr efree(pattern); + /* + * If we reached cache limit, clean out the items from the head of the list; + * these are supposedly the oldest ones (but not necessarily the least used + * ones). + */ + if (zend_hash_num_elements(&PCRE_G(pcre_cache)) == PCRE_CACHE_SIZE) { + int num_clean = PCRE_CACHE_SIZE / 8; + zend_hash_apply_with_argument(&PCRE_G(pcre_cache), pcre_clean_cache, &num_clean TSRMLS_CC); + } + /* Store the compiled pattern and extra info in the cache. */ new_entry.re = re; new_entry.extra = *extra; @@ -727,9 +761,9 @@ static int preg_do_eval(char *eval_str, int eval_str_len, char *subject, in instead of the backref */ match = subject + offsets[backref<<1]; match_len = offsets[(backref<<1)+1] - offsets[backref<<1]; - if (match_len) - esc_match = php_addslashes(match, match_len, &esc_match_len, 0 TSRMLS_CC); - else { + if (match_len) { + esc_match = php_addslashes_ex(match, match_len, &esc_match_len, 0, 1 TSRMLS_CC); + } else { esc_match = match; esc_match_len = 0; } diff --git a/ext/pcre/tests/bug33200.phpt b/ext/pcre/tests/bug33200.phpt new file mode 100644 index 000000000000..b00b72ac28f4 --- /dev/null +++ b/ext/pcre/tests/bug33200.phpt @@ -0,0 +1,12 @@ +--TEST-- +Bug #33200 (magic_quotes_sybase = On makes 'e' modifier misbehave) +--INI-- +magic_quotes_sybase=1 +--FILE-- + +--EXPECT-- +SOME '$SAMPLE' TEXT diff --git a/ext/pdo/CREDITS b/ext/pdo/CREDITS deleted file mode 100755 index e650219359a8..000000000000 --- a/ext/pdo/CREDITS +++ /dev/null @@ -1,2 +0,0 @@ -PHP Data Objects -Wez Furlong, Marcus Boerger, Sterling Hughes, George Schlossnagle diff --git a/ext/pdo/EXPERIMENTAL b/ext/pdo/EXPERIMENTAL deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/ext/pdo/Makefile.frag b/ext/pdo/Makefile.frag deleted file mode 100644 index c28a5cee50d9..000000000000 --- a/ext/pdo/Makefile.frag +++ /dev/null @@ -1,31 +0,0 @@ -phpincludedir=$(prefix)/include/php - -PDO_HEADER_FILES= \ - php_pdo.h \ - php_pdo_driver.h - -install-pdo-headers: - echo "Installing PDO headers: $(INSTALL_ROOT)$(phpincludedir)/ext/pdo/" - $(mkinstalldirs) $(INSTALL_ROOT)$(phpincludedir)/ext/pdo - for f in $(PDO_HEADER_FILES); do \ - if test -f "$(top_srcdir)/$$f"; then \ - $(INSTALL_DATA) $(top_srcdir)/$$f $(INSTALL_ROOT)$(phpincludedir)/ext/pdo; \ - elif test -f "$(top_builddir)/$$f"; then \ - $(INSTALL_DATA) $(top_builddir)/$$f $(INSTALL_ROOT)$(phpincludedir)/ext/pdo; \ - elif test -f "$(top_srcdir)/ext/pdo/$$f"; then \ - $(INSTALL_DATA) $(top_srcdir)/ext/pdo/$$f $(INSTALL_ROOT)$(phpincludedir)/ext/pdo; \ - elif test -f "$(top_builddir)/ext/pdo/$$f"; then \ - $(INSTALL_DATA) $(top_builddir)/ext/pdo/$$f $(INSTALL_ROOT)$(phpincludedir)/ext/pdo; \ - else \ - echo "hmmm"; \ - fi \ - done; - -# mini hack -install: $(all_targets) $(install_targets) install-pdo-headers - -$(top_srcdir)/ext/pdo/pdo_sql_parser.c: $(top_srcdir)/ext/pdo/pdo_sql_parser.re - re2c -b $(top_srcdir)/ext/pdo/pdo_sql_parser.re > $@ - -$(srcdir)/pdo_sql_parser.c: $(srcdir)/pdo_sql_parser.re - re2c -b $(srcdir)/pdo_sql_parser.re > $@ diff --git a/ext/pdo/README b/ext/pdo/README deleted file mode 100755 index ea3ee74fb686..000000000000 --- a/ext/pdo/README +++ /dev/null @@ -1,56 +0,0 @@ -$Id$ - -PHP Data Objects -================ - -Concept: Data Access Abstraction - -Goals: - -1/ Be light-weight -2/ Provide common API for common database operations -3/ Be performant -4/ Keep majority of PHP specific stuff in the PDO core (such as persistent - resource management); drivers should only have to worry about getting the - data and not about PHP internals. - - -Transactions and autocommit -=========================== - -When you create a database handle, you *should* specify the autocommit -behaviour that you require. PDO will default to autocommit on. - -$dbh = new PDO("...", $user, $pass, array(PDO_ATTR_AUTOCOMMIT => true)); - -When auto-commit is on, the driver will implicitly commit each query as it is -executed. This works fine for most simple tasks but can be significantly -slower when you are making a large number of udpates. - -$dbh = new PDO("...", $user, $pass, array(PDO_ATTR_AUTOCOMMIT => false)); - -When auto-commit is off, you must then use $dbh->beginWork() to initiate a -transaction. When your work is done, you then call $dbh->commit() or -$dbh->rollBack() to persist or abort your changes respectively. -Not all databases support transactions. - -You can change the auto-commit mode at run-time: - -$dbh->setAttribute(PDO_ATTR_AUTOCOMMIT, false); - -Regardless of the error handling mode set on the database handle, if the -autocommit mode cannot be changed, an exception will be thrown. - -Some drivers will allow you to temporarily disable autocommit if you call -$dbh->beginWork(). When you commit() or rollBack() such a transaction, the -handle will switch back to autocommit mode again. If the mode could not be -changed, an exception will be raised, as noted above. - -When the database handle is closed or destroyed (or at request end for -persistent handles), the driver will implicitly rollBack(). It is your -responsibility to call commit() when you are done making changes and -autocommit is turned off. - -vim:tw=78:et - - diff --git a/ext/pdo/TODO b/ext/pdo/TODO deleted file mode 100755 index 43da3fe9a68b..000000000000 --- a/ext/pdo/TODO +++ /dev/null @@ -1,25 +0,0 @@ -$Id$ - -In no particular order: - -Low-level: - -- Scanner for :named placeholders and prepare()/execute() emulation (George) -- $dbh->quote() -- Exceptions and unified error API -- Scrollable cursors -- meta data from driver, such as server version and supported features -- field meta data from statement handles -- $dbh->exec() for one-shot SQL -- LOB support via Streams API -- persistent handles -- iterator support -- "lazy" fetch support - -Not-so-low-level: -- hash key case folding for portabilitiy, ala sqlite.assoc_case, but not using an ini option. -- fetchAll(), single row, single column fetches etc. - -Could be more... - -vim:tw=78:et diff --git a/ext/pdo/config.m4 b/ext/pdo/config.m4 deleted file mode 100755 index 60e603955056..000000000000 --- a/ext/pdo/config.m4 +++ /dev/null @@ -1,10 +0,0 @@ -dnl $Id$ -dnl config.m4 for extension pdo - -PHP_ARG_ENABLE(pdo, whether to enable PDO support, -[ --enable-pdo Enable PHP Data Objects support]) - -if test "$PHP_PDO" != "no"; then - PHP_NEW_EXTENSION(pdo, pdo.c pdo_dbh.c pdo_stmt.c pdo_sql_parser.c, $ext_shared) - PHP_ADD_MAKEFILE_FRAGMENT -fi diff --git a/ext/pdo/config.w32 b/ext/pdo/config.w32 deleted file mode 100755 index 112c7d9fcef3..000000000000 --- a/ext/pdo/config.w32 +++ /dev/null @@ -1,9 +0,0 @@ -// $Id$ -// vim:ft=javascript - -ARG_ENABLE("pdo", "Enable PHP Data Objects support", "no"); - -if (PHP_PDO != "no") { - EXTENSION('pdo', 'pdo.c pdo_dbh.c pdo_stmt.c pdo_sql_parser.c'); -} - diff --git a/ext/pdo/package.xml b/ext/pdo/package.xml deleted file mode 100755 index 963d3e939b74..000000000000 --- a/ext/pdo/package.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - - PDO - PHP Data Objects Interface - - - wez - Wez Furlong - wez@php.net - lead - - - helly - Marcus Boerger - helly@php.net - lead - - - iliaa - Ilia Alshanetsky - iliaa@php.net - lead - - - gschlossnagle - George Schlossnagle - george@omniti.com - lead - - - - PDO provides a uniform data access interface, sporting advanced features such - as prepared statements and bound parameters. PDO drivers are dynamically - loadable and may be developed independently from the core, but still accessed - using the same API. - - PHP - - alpha - 0.1.1 - 2004-05-21 - - -Note that PDO on its own is useless. -You need to install a PDO database driver to make use of it, -check http://pecl.php.net for a list of available PDO drivers. - -It is highly recommended that you update to the latest PHP 5 snapshot before using PDO. -You can obtain it from http://snaps.php.net. - -If you are running on Windows, you should download: -http://snaps.php.net/win32/php5-win32-latest.zip -http://snaps.php.net/win32/PECL_5_0/php_pdo.dll - -You can find additional PDO drivers at: -http://snaps.php.net/win32/PECL_5_0/ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ext/pdo/pdo.c b/ext/pdo/pdo.c deleted file mode 100755 index ff5f4873a3d2..000000000000 --- a/ext/pdo/pdo.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong | - | Marcus Boerger | - | Sterling Hughes | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "php_pdo.h" -#include "php_pdo_driver.h" -#include "php_pdo_int.h" -#include "zend_exceptions.h" - -ZEND_DECLARE_MODULE_GLOBALS(pdo) - -/* True global resources - no need for thread safety here */ - -/* the registry of PDO drivers */ -static HashTable pdo_driver_hash; - -/* we use persistent resources for the driver connection stuff */ -static int le_ppdo; - -/* for exceptional circumstances */ -zend_class_entry *pdo_exception_ce; - -PDO_API zend_class_entry *php_pdo_get_exception(void) -{ - return pdo_exception_ce; -} - -zend_class_entry *pdo_dbh_ce, *pdo_dbstmt_ce, *pdo_row_ce; - -/* {{{ pdo_functions[] */ -function_entry pdo_functions[] = { - {NULL, NULL, NULL} -}; -/* }}} */ - -/* {{{ pdo_module_entry */ -zend_module_entry pdo_module_entry = { - STANDARD_MODULE_HEADER, - "PDO", - pdo_functions, - PHP_MINIT(pdo), - PHP_MSHUTDOWN(pdo), - PHP_RINIT(pdo), - PHP_RSHUTDOWN(pdo), - PHP_MINFO(pdo), - "0.1.1", - STANDARD_MODULE_PROPERTIES -}; -/* }}} */ - -#ifdef COMPILE_DL_PDO -ZEND_GET_MODULE(pdo) -#endif - -/* {{{ PHP_INI */ -PHP_INI_BEGIN() - STD_PHP_INI_ENTRY("pdo.global_value", "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_pdo_globals, pdo_globals) -PHP_INI_END() -/* }}} */ - -/* {{{ php_pdo_init_globals */ -static void php_pdo_init_globals(zend_pdo_globals *pdo_globals) -{ - pdo_globals->global_value = 0; -} -/* }}} */ - -PDO_API int php_pdo_register_driver(pdo_driver_t *driver) -{ - if (driver->api_version != PDO_DRIVER_API) { - zend_error(E_ERROR, "failed api version check"); - return FAILURE; - } - if (!zend_hash_exists(&module_registry, "pdo", sizeof("pdo"))) { - zend_error(E_ERROR, "You MUST load PDO before loading any PDO drivers"); - return FAILURE; /* NOTREACHED */ - } - - return zend_hash_add(&pdo_driver_hash, (char*)driver->driver_name, driver->driver_name_len, - (void**)&driver, sizeof(driver), NULL); -} - -PDO_API void php_pdo_unregister_driver(pdo_driver_t *driver) -{ - if (!zend_hash_exists(&module_registry, "pdo", sizeof("pdo"))) { - return; - } - - zend_hash_del(&pdo_driver_hash, (char*)driver->driver_name, driver->driver_name_len); -} - -pdo_driver_t *pdo_find_driver(const char *name, int namelen) -{ - pdo_driver_t **driver = NULL; - - zend_hash_find(&pdo_driver_hash, (char*)name, namelen, (void**)&driver); - - return driver ? *driver : NULL; -} - -PDO_API int php_pdo_parse_data_source(const char *data_source, - unsigned long data_source_len, struct pdo_data_src_parser *parsed, - int nparams) -{ - int i, j; - int valstart = -1; - int semi = -1; - int optstart = 0; - int nlen; - int n_matches = 0; - - i = 0; - while (i < data_source_len) { - /* looking for NAME= */ - - if (data_source[i] == '\0') { - break; - } - - if (data_source[i] != '=') { - ++i; - continue; - } - - valstart = ++i; - - /* now we're looking for VALUE; or just VALUE */ - semi = -1; - while (i < data_source_len) { - if (data_source[i] == '\0') { - semi = i++; - break; - } - if (data_source[i] == ';') { - semi = i++; - break; - } - ++i; - } - - if (semi == -1) { - semi = i; - } - - /* find the entry in the array */ - nlen = valstart - optstart - 1; - for (j = 0; j < nparams; j++) { - if (0 == strncmp(data_source + optstart, parsed[j].optname, nlen) && parsed[j].optname[nlen] == '\0') { - /* got a match */ - if (parsed[j].freeme) { - efree(parsed[j].optval); - } - parsed[j].optval = estrndup(data_source + valstart, semi - valstart); - parsed[j].freeme = 1; - ++n_matches; - break; - } - } - - while (i < data_source_len && isspace(data_source[i])) { - i++; - } - - optstart = i; - } - - return n_matches; -} - - -/* {{{ PHP_MINIT_FUNCTION */ -PHP_MINIT_FUNCTION(pdo) -{ - zend_class_entry ce; - - ZEND_INIT_MODULE_GLOBALS(pdo, php_pdo_init_globals, NULL); - REGISTER_INI_ENTRIES(); - - zend_hash_init(&pdo_driver_hash, 0, NULL, NULL, 1); - - REGISTER_LONG_CONSTANT("PDO_PARAM_NULL", (long)PDO_PARAM_NULL, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_PARAM_INT", (long)PDO_PARAM_INT, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_PARAM_STR", (long)PDO_PARAM_STR, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_PARAM_LOB", (long)PDO_PARAM_LOB, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_PARAM_STMT", (long)PDO_PARAM_STMT, CONST_CS|CONST_PERSISTENT); - - REGISTER_LONG_CONSTANT("PDO_FETCH_LAZY", (long)PDO_FETCH_LAZY, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_FETCH_ASSOC",(long)PDO_FETCH_ASSOC, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_FETCH_NUM", (long)PDO_FETCH_NUM, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_FETCH_BOTH", (long)PDO_FETCH_BOTH, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_FETCH_OBJ", (long)PDO_FETCH_OBJ, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_FETCH_BOUND",(long)PDO_FETCH_BOUND, CONST_CS|CONST_PERSISTENT); - - REGISTER_LONG_CONSTANT("PDO_ATTR_AUTOCOMMIT", (long)PDO_ATTR_AUTOCOMMIT, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ATTR_SCROLL", (long)PDO_ATTR_SCROLL, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ATTR_PREFETCH", (long)PDO_ATTR_PREFETCH, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ATTR_TIMEOUT", (long)PDO_ATTR_TIMEOUT, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ATTR_ERRMODE", (long)PDO_ATTR_ERRMODE, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ATTR_SERVER_VERSION", (long)PDO_ATTR_SERVER_VERSION, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ATTR_CLIENT_VERSION", (long)PDO_ATTR_CLIENT_VERSION, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ATTR_SERVER_INFO", (long)PDO_ATTR_SERVER_INFO, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ATTR_CONNECTION_STATUS", (long)PDO_ATTR_CONNECTION_STATUS, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ATTR_CASE", (long)PDO_ATTR_CASE, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ATTR_CURSOR_NAME", (long)PDO_ATTR_CURSOR_NAME, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ATTR_CURSOR", (long)PDO_ATTR_CURSOR, CONST_CS|CONST_PERSISTENT); - - REGISTER_LONG_CONSTANT("PDO_ERRMODE_SILENT", (long)PDO_ERRMODE_SILENT, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ERRMODE_WARNING", (long)PDO_ERRMODE_WARNING, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ERRMODE_EXCEPTION", (long)PDO_ERRMODE_EXCEPTION, CONST_CS|CONST_PERSISTENT); - - REGISTER_LONG_CONSTANT("PDO_CASE_NATURAL", (long)PDO_CASE_NATURAL, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_CASE_LOWER", (long)PDO_CASE_LOWER, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_CASE_UPPER", (long)PDO_CASE_UPPER, CONST_CS|CONST_PERSISTENT); - - REGISTER_LONG_CONSTANT("PDO_ERR_NONE", (long)PDO_ERR_NONE, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ERR_CANT_MAP", (long)PDO_ERR_CANT_MAP, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ERR_SYNTAX", (long)PDO_ERR_SYNTAX, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ERR_CONSTRAINT", (long)PDO_ERR_CONSTRAINT, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ERR_NOT_FOUND", (long)PDO_ERR_NOT_FOUND, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ERR_ALREADY_EXISTS", (long)PDO_ERR_ALREADY_EXISTS, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ERR_NOT_IMPLEMENTED", (long)PDO_ERR_NOT_IMPLEMENTED, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ERR_MISMATCH", (long)PDO_ERR_MISMATCH, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ERR_TRUNCATED", (long)PDO_ERR_TRUNCATED, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ERR_DISCONNECTED", (long)PDO_ERR_DISCONNECTED, CONST_CS|CONST_PERSISTENT); - - INIT_CLASS_ENTRY(ce, "PDOException", NULL); - pdo_exception_ce = zend_register_internal_class_ex(&ce, zend_exception_get_default(), NULL TSRMLS_CC); - zend_declare_property_null(pdo_exception_ce, "errorInfo", sizeof("errorInfo")-1, ZEND_ACC_PUBLIC TSRMLS_CC); - - INIT_CLASS_ENTRY(ce, "PDO", pdo_dbh_functions); - ce.create_object = pdo_dbh_new; - pdo_dbh_ce = zend_register_internal_class(&ce TSRMLS_CC); - - INIT_CLASS_ENTRY(ce, "PDOStatement", pdo_dbstmt_functions); - ce.create_object = pdo_dbstmt_new; - pdo_dbstmt_ce = zend_register_internal_class(&ce TSRMLS_CC); - - INIT_CLASS_ENTRY(ce, "PDORow", pdo_row_functions); - ce.create_object = pdo_row_new; - pdo_row_ce = zend_register_internal_class(&ce TSRMLS_CC); - - return SUCCESS; -} -/* }}} */ - -/* {{{ PHP_MSHUTDOWN_FUNCTION */ -PHP_MSHUTDOWN_FUNCTION(pdo) -{ - UNREGISTER_INI_ENTRIES(); - zend_hash_destroy(&pdo_driver_hash); - return SUCCESS; -} -/* }}} */ - -/* {{{ PHP_RINIT_FUNCTION */ -PHP_RINIT_FUNCTION(pdo) -{ - return SUCCESS; -} -/* }}} */ - -/* {{{ PHP_RSHUTDOWN_FUNCTION */ -PHP_RSHUTDOWN_FUNCTION(pdo) -{ - /* TODO: visit persistent handles: for each persistent statement handle, - * remove bound parameter associations */ - return SUCCESS; -} -/* }}} */ - -/* {{{ PHP_MINFO_FUNCTION */ -PHP_MINFO_FUNCTION(pdo) -{ - php_info_print_table_start(); - php_info_print_table_header(2, "pdo support", "enabled"); - php_info_print_table_end(); - - DISPLAY_INI_ENTRIES(); -} -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo/pdo.php b/ext/pdo/pdo.php deleted file mode 100755 index 78300d82b516..000000000000 --- a/ext/pdo/pdo.php +++ /dev/null @@ -1,35 +0,0 @@ - 0)); -$stmt = $x->prepare("select NAME, VALUE from test where value like ?"); - -$the_name = 'bar%'; -$stmt->execute(array($the_name)) or die("failed to execute!"); -$stmt->bindColumn('VALUE', $value); - -while ($row = $stmt->fetch()) { - echo "name=$row[NAME] value=$row[VALUE]\n"; - echo "value is $value\n"; - echo "\n"; -} - -echo "Let's try an update\n"; - -$stmt = $x->prepare("INSERT INTO test (NAME, VALUE) VALUES (:name, :value)"); - -$stmt->bindParam(":name", $the_name, PDO_PARAM_STR, 32); -$stmt->bindParam(":value", $the_value, PDO_PARAM_STR, 32); - -for ($i = 0; $i < 4; $i++) { - $the_name = "foo" . rand(); - $the_value = "bar" . rand(); - - if (!$stmt->execute()) { - break; - } -} - -echo "All done\n"; - -?> diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c deleted file mode 100755 index ec2508290c3e..000000000000 --- a/ext/pdo/pdo_dbh.c +++ /dev/null @@ -1,703 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong | - | Marcus Boerger | - | Sterling Hughes | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -/* The PDO Database Handle Class */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "php_pdo.h" -#include "php_pdo_driver.h" -#include "php_pdo_int.h" -#include "zend_exceptions.h" - -void pdo_handle_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt TSRMLS_DC) -{ - enum pdo_error_type *pdo_err = &dbh->error_code; - const char *msg = "<>"; - char *supp = NULL; - long native_code = 0; - char *message = NULL; - zval *info = NULL; - - if (dbh->error_mode == PDO_ERRMODE_SILENT) { - return; - } - - if (stmt) { - pdo_err = &stmt->error_code; - } - - switch (*pdo_err) { - case PDO_ERR_NONE: msg = "No error"; break; - case PDO_ERR_CANT_MAP: msg = "Consult errorInfo() for more details"; break; - case PDO_ERR_SYNTAX: msg = "Syntax Error"; break; - case PDO_ERR_CONSTRAINT:msg = "Constraint violation"; break; - case PDO_ERR_NOT_FOUND: msg = "Not found"; break; - case PDO_ERR_ALREADY_EXISTS: msg = "Already exists"; break; - case PDO_ERR_NOT_IMPLEMENTED: msg = "Not Implemented"; break; - case PDO_ERR_MISMATCH: msg = "Mismatch"; break; - case PDO_ERR_TRUNCATED: msg = "Truncated"; break; - case PDO_ERR_DISCONNECTED: msg = "Disconnected"; break; - default: msg = "<>"; - } - - if (dbh->methods->fetch_err) { - - MAKE_STD_ZVAL(info); - array_init(info); - - add_next_index_long(info, *pdo_err); - - if (dbh->methods->fetch_err(dbh, stmt, info TSRMLS_CC)) { - zval **item; - - if (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(info), 1, (void**)&item)) { - native_code = Z_LVAL_PP(item); - } - - if (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(info), 2, (void**)&item)) { - supp = estrndup(Z_STRVAL_PP(item), Z_STRLEN_PP(item)); - } - } - } - - if (supp && *pdo_err == PDO_ERR_CANT_MAP) { - spprintf(&message, 0, "%ld %s", native_code, supp); - } else if (supp) { - spprintf(&message, 0, "%s: %ld %s", msg, native_code, supp); - } else { - spprintf(&message, 0, "%s", msg); - } - - if (dbh->error_mode == PDO_ERRMODE_WARNING) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", message); - - if (info) { - zval_ptr_dtor(&info); - } - } else { - zval *ex; - zend_class_entry *def_ex = zend_exception_get_default(), *pdo_ex = php_pdo_get_exception(); - - MAKE_STD_ZVAL(ex); - object_init_ex(ex, pdo_ex); - - zend_update_property_string(def_ex, ex, "message", sizeof("message")-1, message TSRMLS_CC); - zend_update_property_long(def_ex, ex, "code", sizeof("code")-1, *pdo_err TSRMLS_CC); - - if (info) { - zend_update_property(pdo_ex, ex, "errorInfo", sizeof("errorInfo")-1, info TSRMLS_CC); - } - - zend_throw_exception_object(ex TSRMLS_CC); - } - - if (message) { - efree(message); - } - - if (supp) { - efree(supp); - } -} - -/* {{{ proto object PDO::__construct(string dsn, string username, string passwd [, array driver_opts]) - */ -static PHP_FUNCTION(dbh_constructor) -{ - zval *object = getThis(); - pdo_dbh_t *dbh = NULL; - zend_bool is_persistent = FALSE; - char *data_source; - int data_source_len; - char *colon; - char *username=NULL, *password=NULL; - int usernamelen, passwordlen; - pdo_driver_t *driver = NULL; - zval *driver_options = NULL; - - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ssa!", &data_source, &data_source_len, - &username, &usernamelen, &password, &passwordlen, &driver_options)) { - ZVAL_NULL(object); - return; - } - - /* parse the data source name */ - colon = strchr(data_source, ':'); - - if (!colon) { - zend_throw_exception_ex(php_pdo_get_exception(), PDO_ERR_SYNTAX TSRMLS_CC, "invalid data source name"); - ZVAL_NULL(object); - return; - } - - driver = pdo_find_driver(data_source, colon - data_source); - - if (!driver) { - /* NB: don't want to include the data_source in the error message as - * it might contain a password */ - zend_throw_exception_ex(php_pdo_get_exception(), PDO_ERR_NOT_FOUND TSRMLS_CC, "could not find driver"); - ZVAL_NULL(object); - return; - } - - dbh = (pdo_dbh_t *) zend_object_store_get_object(object TSRMLS_CC); - - if (dbh == NULL) { - /* need this check for persistent allocations */ - zend_throw_exception_ex(php_pdo_get_exception(), PDO_ERR_NONE TSRMLS_CC, "out of memory!?"); - } - dbh->is_persistent = is_persistent; - dbh->data_source_len = strlen(colon + 1); - /* when persistent stuff is done, we should check the return values here - * too */ - dbh->data_source = (const char*)pestrdup(colon + 1, is_persistent); - dbh->username = username ? pestrdup(username, is_persistent) : NULL; - dbh->password = password ? pestrdup(password, is_persistent) : NULL; - - dbh->auto_commit = pdo_attr_lval(driver_options, PDO_ATTR_AUTOCOMMIT, 1 TSRMLS_CC); - - if (driver->db_handle_factory(dbh, driver_options TSRMLS_CC)) { - /* all set */ - - if (is_persistent) { - /* register in the persistent list etc. */ - /* we should also need to replace the object store entry, - since it was created with emalloc */ - ; - } - return; - } - - /* the connection failed; things will tidy up in free_storage */ - /* XXX raise exception */ - ZVAL_NULL(object); -} -/* }}} */ - -/* {{{ proto object PDO::prepare(string statment [, int options [, array driver_options]]) - Prepares a statement for execution and returns a statement object */ -/* TODO: options will be a PDO specific bitmask controlling such things as - * cursor type. */ -static PHP_METHOD(PDO, prepare) -{ - pdo_dbh_t *dbh = zend_object_store_get_object(getThis() TSRMLS_CC); - pdo_stmt_t *stmt; - char *statement; - int statement_len; - zval *driver_options = NULL; - long options = 0; - - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|la", &statement, - &statement_len, &options, &driver_options)) { - RETURN_FALSE; - } - - PDO_DBH_CLEAR_ERR(); - stmt = ecalloc(1, sizeof(*stmt)); - /* unconditionally keep this for later reference */ - stmt->query_string = estrndup(statement, statement_len); - stmt->query_stringlen = statement_len; - if (dbh->methods->preparer(dbh, statement, statement_len, stmt, options, driver_options TSRMLS_CC)) { - /* prepared; create a statement object for PHP land to access it */ - Z_TYPE_P(return_value) = IS_OBJECT; - Z_OBJ_HANDLE_P(return_value) = zend_objects_store_put(stmt, NULL, pdo_dbstmt_free_storage, NULL TSRMLS_CC); - Z_OBJ_HT_P(return_value) = &pdo_dbstmt_object_handlers; - - /* give it a reference to me */ - stmt->database_object_handle = *getThis(); - zend_objects_store_add_ref(getThis() TSRMLS_CC); - stmt->dbh = dbh; - - /* we haven't created a lazy object yet */ - ZVAL_NULL(&stmt->lazy_object_ref); - - stmt->refcount = 1; - return; - } - efree(stmt); - PDO_HANDLE_DBH_ERR(); - RETURN_FALSE; -} -/* }}} */ - -/* {{{ proto bool PDO::beginTransaction() - Initiates a transaction */ -static PHP_METHOD(PDO, beginTransaction) -{ - pdo_dbh_t *dbh = zend_object_store_get_object(getThis() TSRMLS_CC); - - if (dbh->in_txn) { - zend_throw_exception_ex(php_pdo_get_exception(), PDO_ERR_NONE TSRMLS_CC, "There is already an active transaction"); - RETURN_FALSE; - } - - if (!dbh->methods->begin) { - /* TODO: this should be an exception; see the auto-commit mode - * comments below */ - zend_throw_exception_ex(php_pdo_get_exception(), PDO_ERR_NONE TSRMLS_CC, "This driver doesn't support transactions"); - RETURN_FALSE; - } - - if (dbh->methods->begin(dbh TSRMLS_CC)) { - dbh->in_txn = 1; - RETURN_TRUE; - } - - PDO_HANDLE_DBH_ERR(); - RETURN_FALSE; -} -/* }}} */ - -/* {{{ proto bool PDO::commit() - Commit a transaction */ -static PHP_METHOD(PDO, commit) -{ - pdo_dbh_t *dbh = zend_object_store_get_object(getThis() TSRMLS_CC); - - if (!dbh->in_txn) { - zend_throw_exception_ex(php_pdo_get_exception(), PDO_ERR_NONE TSRMLS_CC, "There is no active transaction"); - RETURN_FALSE; - } - - if (dbh->methods->commit(dbh TSRMLS_CC)) { - dbh->in_txn = 0; - RETURN_TRUE; - } - - PDO_HANDLE_DBH_ERR(); - RETURN_FALSE; -} -/* }}} */ - -/* {{{ proto bool PDO::rollBack() - roll back a transaction */ -static PHP_METHOD(PDO, rollBack) -{ - pdo_dbh_t *dbh = zend_object_store_get_object(getThis() TSRMLS_CC); - - if (!dbh->in_txn) { - zend_throw_exception_ex(php_pdo_get_exception(), PDO_ERR_NONE TSRMLS_CC, "There is no active transaction"); - RETURN_FALSE; - } - - if (dbh->methods->rollback(dbh TSRMLS_CC)) { - dbh->in_txn = 0; - RETURN_TRUE; - } - - PDO_HANDLE_DBH_ERR(); - RETURN_FALSE; -} -/* }}} */ - -/* {{{ proto bool PDO::setAttribute(long attribute, mixed value) - Set an attribute */ -static PHP_METHOD(PDO, setAttribute) -{ - pdo_dbh_t *dbh = zend_object_store_get_object(getThis() TSRMLS_CC); - long attr; - zval *value = NULL; - - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz!", &attr, &value)) { - RETURN_FALSE; - } - - switch (attr) { - case PDO_ATTR_ERRMODE: - convert_to_long(value); - switch (Z_LVAL_P(value)) { - case PDO_ERRMODE_SILENT: - case PDO_ERRMODE_WARNING: - case PDO_ERRMODE_EXCEPTION: - dbh->error_mode = Z_LVAL_P(value); - RETURN_TRUE; - default: - zend_throw_exception_ex(php_pdo_get_exception(), PDO_ERR_SYNTAX TSRMLS_CC, "Error mode %d is invalid", Z_LVAL_P(value)); - } - RETURN_FALSE; - - case PDO_ATTR_CASE: - convert_to_long(value); - switch (Z_LVAL_P(value)) { - case PDO_CASE_NATURAL: - case PDO_CASE_UPPER: - case PDO_CASE_LOWER: - dbh->desired_case = Z_LVAL_P(value); - RETURN_TRUE; - default: - zend_throw_exception_ex(php_pdo_get_exception(), PDO_ERR_SYNTAX TSRMLS_CC, "Case folding mode %d is invalid", Z_LVAL_P(value)); - } - RETURN_FALSE; - - default: - ; - } - - if (!dbh->methods->set_attribute) { - goto fail; - } - - PDO_DBH_CLEAR_ERR(); - if (dbh->methods->set_attribute(dbh, attr, value TSRMLS_CC)) { - RETURN_TRUE; - } - -fail: - if (attr == PDO_ATTR_AUTOCOMMIT) { - zend_throw_exception_ex(php_pdo_get_exception(), PDO_ERR_NONE TSRMLS_CC, "The auto-commit mode cannot be changed for this driver"); - } else if (!dbh->methods->set_attribute) { - /* XXX: do something better here */ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "This driver doesn't support setting attributes"); - } else { - PDO_HANDLE_DBH_ERR(); - } - RETURN_FALSE; -} -/* }}} */ - -/* {{{ proto mixed PDO::getAttribute(long attribute) - Get an attribute */ -static PHP_METHOD(PDO, getAttribute) -{ - pdo_dbh_t *dbh = zend_object_store_get_object(getThis() TSRMLS_CC); - long attr; - - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &attr)) { - RETURN_FALSE; - } - - if (!dbh->methods->get_attribute) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "This driver doesn't support fetching attributes"); - RETURN_FALSE; - } - - PDO_DBH_CLEAR_ERR(); - switch (dbh->methods->get_attribute(dbh, attr, return_value TSRMLS_CC)) { - case -1: - PDO_HANDLE_DBH_ERR(); - RETURN_FALSE; - - case 0: - /* XXX: should do something better here */ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "This driver doesn't support fetching %ld attribute", attr); - break; - - default: - return; - } -} -/* }}} */ - -/* {{{ proto long PDO::exec(string query) - Execute a query that does not return a row set, returning the number of affected rows */ -static PHP_METHOD(PDO, exec) -{ - pdo_dbh_t *dbh = zend_object_store_get_object(getThis() TSRMLS_CC); - char *statement; - int statement_len; - long ret; - - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &statement, &statement_len)) { - RETURN_FALSE; - } - - if (!statement_len) { - RETURN_FALSE; - } - PDO_DBH_CLEAR_ERR(); - ret = dbh->methods->doer(dbh, statement, statement_len TSRMLS_CC); - if(ret == -1) { - PDO_HANDLE_DBH_ERR(); - RETURN_FALSE; - } else { - RETURN_LONG(ret); - } -} -/* }}} */ - - -/* {{{ proto int PDO::lastInsertId() - Returns the number id of rows that we affected by the last call to PDO::exec(). Not always meaningful. */ -static PHP_METHOD(PDO, lastInsertId) -{ - pdo_dbh_t *dbh = zend_object_store_get_object(getThis() TSRMLS_CC); - - if (ZEND_NUM_ARGS()) { - RETURN_FALSE; - } - - PDO_DBH_CLEAR_ERR(); - if (!dbh->methods->last_id) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "This driver does not support last inserted id retrieval."); - } else { - RETURN_LONG(dbh->methods->last_id(dbh TSRMLS_CC)); - } -} -/* }}} */ - -/* {{{ proto int PDO::errorCode() - Fetch the error code associated with the last operation on the database handle */ -static PHP_METHOD(PDO, errorCode) -{ - pdo_dbh_t *dbh = zend_object_store_get_object(getThis() TSRMLS_CC); - - if (ZEND_NUM_ARGS()) { - RETURN_FALSE; - } - - RETURN_LONG(dbh->error_code); -} -/* }}} */ - -/* {{{ proto int PDO::errorInfo() - Fetch extended error information associated with the last operation on the database handle */ -static PHP_METHOD(PDO, errorInfo) -{ - pdo_dbh_t *dbh = zend_object_store_get_object(getThis() TSRMLS_CC); - - if (ZEND_NUM_ARGS()) { - RETURN_FALSE; - } - - array_init(return_value); - add_next_index_long(return_value, dbh->error_code); - - if (dbh->methods->fetch_err) { - dbh->methods->fetch_err(dbh, NULL, return_value TSRMLS_CC); - } -} -/* }}} */ - - -function_entry pdo_dbh_functions[] = { - PHP_ME_MAPPING(__construct, dbh_constructor, NULL) - PHP_ME(PDO, prepare, NULL, ZEND_ACC_PUBLIC) - PHP_ME(PDO, beginTransaction,NULL, ZEND_ACC_PUBLIC) - PHP_ME(PDO, commit, NULL, ZEND_ACC_PUBLIC) - PHP_ME(PDO, rollBack, NULL, ZEND_ACC_PUBLIC) - PHP_ME(PDO, setAttribute, NULL, ZEND_ACC_PUBLIC) - PHP_ME(PDO, exec, NULL, ZEND_ACC_PUBLIC) - PHP_ME(PDO, lastInsertId, NULL, ZEND_ACC_PUBLIC) - PHP_ME(PDO, errorCode, NULL, ZEND_ACC_PUBLIC) - PHP_ME(PDO, errorInfo, NULL, ZEND_ACC_PUBLIC) - PHP_ME(PDO, getAttribute, NULL, ZEND_ACC_PUBLIC) - - {NULL, NULL, NULL} -}; - -/* {{{ overloaded object handlers for PDO class */ -static zval *dbh_prop_read(zval *object, zval *member, int type TSRMLS_DC) -{ - zval *return_value; - - MAKE_STD_ZVAL(return_value); - ZVAL_NULL(return_value); - - return return_value; -} - -static void dbh_prop_write(zval *object, zval *member, zval *value TSRMLS_DC) -{ - return; -} - -static zval *dbh_read_dim(zval *object, zval *offset, int type TSRMLS_DC) -{ - zval *return_value; - - MAKE_STD_ZVAL(return_value); - ZVAL_NULL(return_value); - - return return_value; -} - -static void dbh_write_dim(zval *object, zval *offset, zval *value TSRMLS_DC) -{ - return; -} - -static int dbh_prop_exists(zval *object, zval *member, int check_empty TSRMLS_DC) -{ - return 0; -} - -static int dbh_dim_exists(zval *object, zval *member, int check_empty TSRMLS_DC) -{ - return 0; -} - -static void dbh_prop_delete(zval *object, zval *offset TSRMLS_DC) -{ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete properties from a PDO DBH"); -} - -static void dbh_dim_delete(zval *object, zval *offset TSRMLS_DC) -{ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete dimensions from a PDO DBH"); -} - -static HashTable *dbh_get_properties(zval *object TSRMLS_DC) -{ - return NULL; -} - -static union _zend_function *dbh_method_get(zval *object, char *method_name, int method_len TSRMLS_DC) -{ - zend_function *fbc; - char *lc_method_name; - - lc_method_name = emalloc(method_len + 1); - zend_str_tolower_copy(lc_method_name, method_name, method_len); - - if (zend_hash_find(&pdo_dbh_ce->function_table, lc_method_name, method_len+1, (void**)&fbc) == FAILURE) { - efree(lc_method_name); - return NULL; - } - - efree(lc_method_name); - return fbc; -} - -static int dbh_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS) -{ - return FAILURE; -} - - -static union _zend_function *dbh_get_ctor(zval *object TSRMLS_DC) -{ - pdo_dbh_t *dbh = zend_object_store_get_object(object TSRMLS_CC); - - if(dbh->ce != pdo_dbh_ce) { - return dbh->ce->constructor; - } else { - static zend_internal_function ctor = {0}; - - ctor.type = ZEND_INTERNAL_FUNCTION; - ctor.function_name = "__construct"; - ctor.scope = pdo_dbh_ce; - ctor.handler = ZEND_FN(dbh_constructor); - - return (union _zend_function*)&ctor; - } -} - -static zend_class_entry *dbh_get_ce(zval *object TSRMLS_DC) -{ - return pdo_dbh_ce; -} - -static int dbh_get_classname(zval *object, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC) -{ - *class_name = estrndup("PDO", sizeof("PDO")-1); - *class_name_len = sizeof("PDO")-1; - return 0; -} - -static int dbh_compare(zval *object1, zval *object2 TSRMLS_DC) -{ - return -1; -} - -static zend_object_handlers pdo_dbh_object_handlers = { - ZEND_OBJECTS_STORE_HANDLERS, - dbh_prop_read, - dbh_prop_write, - dbh_read_dim, - dbh_write_dim, - NULL, - NULL, - NULL, - dbh_prop_exists, - dbh_prop_delete, - dbh_dim_exists, - dbh_dim_delete, - dbh_get_properties, - dbh_method_get, - dbh_call_method, - dbh_get_ctor, - dbh_get_ce, - dbh_get_classname, - dbh_compare, - NULL, /* cast */ - NULL -}; - -static void pdo_dbh_free_storage(zend_object *object TSRMLS_DC) -{ - pdo_dbh_t *dbh = (pdo_dbh_t*)object; - - if (!dbh) { - return; - } - - if (dbh->is_persistent) { - /* XXX: don't really free it, just delete the rsrc id */ - return; - } - - dbh->methods->closer(dbh TSRMLS_CC); - - if (dbh->data_source) { - pefree((char *)dbh->data_source, dbh->is_persistent); - } - if (dbh->username) { - pefree(dbh->username, dbh->is_persistent); - } - if (dbh->password) { - pefree(dbh->password, dbh->is_persistent); - } - - pefree(dbh, dbh->is_persistent); -} - -zend_object_value pdo_dbh_new(zend_class_entry *ce TSRMLS_DC) -{ - zend_object_value retval; - pdo_dbh_t *dbh; - - dbh = emalloc(sizeof(*dbh)); - memset(dbh, 0, sizeof(*dbh)); - dbh->ce = ce; - - retval.handle = zend_objects_store_put(dbh, NULL, pdo_dbh_free_storage, NULL TSRMLS_CC); - retval.handlers = &pdo_dbh_object_handlers; - - return retval; -} - -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo/pdo_sql_parser.c b/ext/pdo/pdo_sql_parser.c deleted file mode 100644 index 5c4ee0ac0650..000000000000 --- a/ext/pdo/pdo_sql_parser.c +++ /dev/null @@ -1,317 +0,0 @@ -/* Generated by re2c 0.5 on Fri May 21 17:33:58 2004 */ -#line 1 "/home/george/src/pecl/pdo/pdo_sql_parser.re" -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: George Schlossnagle | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#include "php.h" -#include "php_pdo_driver.h" - -#define PDO_PARSER_TEXT 1 -#define PDO_PARSER_BIND 2 -#define PDO_PARSER_BIND_POS 3 -#define PDO_PARSER_EOI 4 - -#define RET(i) {s->cur = cursor; return i; } - -#define YYCTYPE char -#define YYCURSOR cursor -#define YYLIMIT s->lim -#define YYMARKER s->ptr -#define YYFILL(n) - -typedef struct Scanner { - char *lim, *ptr, *cur, *tok; -} Scanner; - -static int scan(Scanner *s) -{ - char *cursor = s->cur; - std: - s->tok = cursor; - #line 54 - - - { - YYCTYPE yych; - unsigned int yyaccept; - static unsigned char yybm[] = { - 0, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 0, 168, 168, 168, 168, 192, - 168, 168, 168, 168, 168, 168, 168, 168, - 184, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 160, 168, 168, 168, 168, 160, - 168, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 168, 8, 168, 168, 184, - 168, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, - }; - goto yy0; -yy1: ++YYCURSOR; -yy0: - if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); - yych = *YYCURSOR; - if(yybm[0+yych] & 8) goto yy8; - if(yych <= '\000') goto yy11; - if(yych <= '&') goto yy2; - if(yych <= '\'') goto yy4; - if(yych <= '>') goto yy5; - goto yy6; -yy2: yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - if(yych >= '\001') goto yy24; -yy3: -#line 61 - { RET(PDO_PARSER_TEXT); } -yy4: yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - if(yych <= '\000') goto yy3; - if(yych == '"') goto yy3; - goto yy17; -yy5: yych = *++YYCURSOR; - if(yybm[0+yych] & 16) goto yy13; - goto yy3; -yy6: yych = *++YYCURSOR; -yy7: -#line 60 - { RET(PDO_PARSER_BIND_POS); } -yy8: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; -yy9: if(yybm[0+yych] & 8) goto yy8; -yy10: -#line 62 - { RET(PDO_PARSER_TEXT); } -yy11: yych = *++YYCURSOR; -yy12: -#line 63 - { RET(PDO_PARSER_EOI); } -yy13: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; -yy14: if(yybm[0+yych] & 16) goto yy13; -yy15: -#line 59 - { RET(PDO_PARSER_BIND); } -yy16: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; -yy17: if(yybm[0+yych] & 32) goto yy16; - if(yych <= '&') goto yy18; - if(yych <= '\'') goto yy19; - goto yy22; -yy18: YYCURSOR = YYMARKER; - switch(yyaccept){ - case 1: goto yy21; - case 0: goto yy3; - } -yy19: yyaccept = 1; - YYMARKER = ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; -yy20: if(yybm[0+yych] & 32) goto yy16; - if(yych <= '&') goto yy21; - if(yych <= '\'') goto yy19; - goto yy22; -yy21: -#line 58 - { RET(PDO_PARSER_TEXT); } -yy22: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - if(yych == '\'') goto yy16; - goto yy18; -yy23: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; -yy24: if(yybm[0+yych] & 128) goto yy23; - if(yych <= '\000') goto yy18; - if(yych <= '[') goto yy26; -yy25: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - if(yych == '"') goto yy23; - goto yy18; -yy26: yych = *++YYCURSOR; -yy27: -#line 57 - { RET(PDO_PARSER_TEXT); } -} -#line 64 - -} - -int pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, char **outquery, - int *outquery_len TSRMLS_DC) -{ - Scanner s; - char *ptr; - int t; - int bindno = 0; - int newbuffer_len; - int padding; - HashTable *params = stmt->bound_params; - struct pdo_bound_param_data *param; - /* allocate buffer for query with expanded binds, ptr is our writing pointer */ - newbuffer_len = inquery_len; - - /* calculate the possible padding factor due to quoting */ - if(stmt->dbh->max_escaped_char_length) { - padding = stmt->dbh->max_escaped_char_length; - } else { - padding = 3; - } - if(params) { - zend_hash_internal_pointer_reset(params); - while (SUCCESS == zend_hash_get_current_data(params, (void**)¶m)) { - if(param->parameter) { - convert_to_string(param->parameter); - /* accomodate a string that needs to be fully quoted - bind placeholders are at least 2 characters, so - the accomodate their own "'s - */ - newbuffer_len += padding * Z_STRLEN_P(param->parameter); - } - zend_hash_move_forward(params); - } - } - *outquery = (char *) emalloc(newbuffer_len + 1); - *outquery_len = 0; - - ptr = *outquery; - s.cur = inquery; - s.lim = inquery + inquery_len; - while((t = scan(&s)) != PDO_PARSER_EOI) { - if(t == PDO_PARSER_TEXT) { - memcpy(ptr, s.tok, s.cur - s.tok); - ptr += (s.cur - s.tok); - *outquery_len += (s.cur - s.tok); - } - else if(t == PDO_PARSER_BIND) { - if(!params) { - /* error */ - efree(*outquery); - *outquery = NULL; - return (int) (s.cur - inquery); - } - /* lookup bind first via hash and then index */ - /* stupid keys need to be null-terminated, even though we know their length */ - if((SUCCESS == zend_hash_find(params, s.tok, s.cur-s.tok,(void **)¶m)) - || - (SUCCESS == zend_hash_index_find(params, bindno, (void **)¶m))) - { - char *quotedstr; - int quotedstrlen; - /* restore the in-string key, doesn't need null-termination here */ - /* currently everything is a string here */ - - /* quote the bind value if necessary */ - if(stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter), - Z_STRLEN_P(param->parameter), "edstr, "edstrlen TSRMLS_CC)) - { - memcpy(ptr, quotedstr, quotedstrlen); - ptr += quotedstrlen; - *outquery_len += quotedstrlen; - efree(quotedstr); - } else { - memcpy(ptr, Z_STRVAL_P(param->parameter), Z_STRLEN_P(param->parameter)); - ptr += Z_STRLEN_P(param->parameter); - *outquery_len += (Z_STRLEN_P(param->parameter)); - } - } - else { - /* error and cleanup */ - efree(*outquery); - *outquery = NULL; - return (int) (s.cur - inquery); - } - bindno++; - } - else if(t == PDO_PARSER_BIND_POS) { - if(!params) { - /* error */ - efree(*outquery); - *outquery = NULL; - return (int) (s.cur - inquery); - } - /* lookup bind by index */ - if(SUCCESS == zend_hash_index_find(params, bindno, (void **)¶m)) - { - char *quotedstr; - int quotedstrlen; - /* currently everything is a string here */ - - /* quote the bind value if necessary */ - if(stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter), - Z_STRLEN_P(param->parameter), "edstr, "edstrlen TSRMLS_CC)) - { - memcpy(ptr, quotedstr, quotedstrlen); - ptr += quotedstrlen; - *outquery_len += quotedstrlen; - efree(quotedstr); - } else { - memcpy(ptr, Z_STRVAL_P(param->parameter), Z_STRLEN_P(param->parameter)); - ptr += Z_STRLEN_P(param->parameter); - *outquery_len += (Z_STRLEN_P(param->parameter)); - } - } - else { - /* error and cleanup */ - efree(*outquery); - *outquery = NULL; - return (int) (s.cur - inquery); - } - bindno++; - } - } - *ptr = '\0'; - return 0; -} - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker ft=c - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo/pdo_sql_parser.re b/ext/pdo/pdo_sql_parser.re deleted file mode 100644 index 412f70ae060f..000000000000 --- a/ext/pdo/pdo_sql_parser.re +++ /dev/null @@ -1,201 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: George Schlossnagle | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#include "php.h" -#include "php_pdo_driver.h" - -#define PDO_PARSER_TEXT 1 -#define PDO_PARSER_BIND 2 -#define PDO_PARSER_BIND_POS 3 -#define PDO_PARSER_EOI 4 - -#define RET(i) {s->cur = cursor; return i; } - -#define YYCTYPE char -#define YYCURSOR cursor -#define YYLIMIT s->lim -#define YYMARKER s->ptr -#define YYFILL(n) - -typedef struct Scanner { - char *lim, *ptr, *cur, *tok; -} Scanner; - -static int scan(Scanner *s) -{ - char *cursor = s->cur; - std: - s->tok = cursor; - /*!re2c - BINDCHR = [:][a-zA-Z0-9_]+; - QUESTION = [?]; - SPECIALS = [:?"']; - ESCQQ = [\\]["]; - ESCQ = [\\][']; - EOF = [\000]; - ANYNOEOF = [\001-\377]; - */ - - /*!re2c - (["] (ESCQQ|ANYNOEOF\[\\"])* ["]) { RET(PDO_PARSER_TEXT); } - (['] (ESCQ|ANYNOEOF\[\\"])* [']) { RET(PDO_PARSER_TEXT); } - BINDCHR { RET(PDO_PARSER_BIND); } - QUESTION { RET(PDO_PARSER_BIND_POS); } - SPECIALS { RET(PDO_PARSER_TEXT); } - (ANYNOEOF\SPECIALS)+ { RET(PDO_PARSER_TEXT); } - EOF { RET(PDO_PARSER_EOI); } - */ -} - -int pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, char **outquery, - int *outquery_len TSRMLS_DC) -{ - Scanner s; - char *ptr; - int t; - int bindno = 0; - int newbuffer_len; - int padding; - HashTable *params = stmt->bound_params; - struct pdo_bound_param_data *param; - /* allocate buffer for query with expanded binds, ptr is our writing pointer */ - newbuffer_len = inquery_len; - - /* calculate the possible padding factor due to quoting */ - if(stmt->dbh->max_escaped_char_length) { - padding = stmt->dbh->max_escaped_char_length; - } else { - padding = 3; - } - if(params) { - zend_hash_internal_pointer_reset(params); - while (SUCCESS == zend_hash_get_current_data(params, (void**)¶m)) { - if(param->parameter) { - convert_to_string(param->parameter); - /* accomodate a string that needs to be fully quoted - bind placeholders are at least 2 characters, so - the accomodate their own "'s - */ - newbuffer_len += padding * Z_STRLEN_P(param->parameter); - } - zend_hash_move_forward(params); - } - } - *outquery = (char *) emalloc(newbuffer_len + 1); - *outquery_len = 0; - - ptr = *outquery; - s.cur = inquery; - s.lim = inquery + inquery_len; - while((t = scan(&s)) != PDO_PARSER_EOI) { - if(t == PDO_PARSER_TEXT) { - memcpy(ptr, s.tok, s.cur - s.tok); - ptr += (s.cur - s.tok); - *outquery_len += (s.cur - s.tok); - } - else if(t == PDO_PARSER_BIND) { - if(!params) { - /* error */ - efree(*outquery); - *outquery = NULL; - return (int) (s.cur - inquery); - } - /* lookup bind first via hash and then index */ - /* stupid keys need to be null-terminated, even though we know their length */ - if((SUCCESS == zend_hash_find(params, s.tok, s.cur-s.tok,(void **)¶m)) - || - (SUCCESS == zend_hash_index_find(params, bindno, (void **)¶m))) - { - char *quotedstr; - int quotedstrlen; - /* restore the in-string key, doesn't need null-termination here */ - /* currently everything is a string here */ - - /* quote the bind value if necessary */ - if(stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter), - Z_STRLEN_P(param->parameter), "edstr, "edstrlen TSRMLS_CC)) - { - memcpy(ptr, quotedstr, quotedstrlen); - ptr += quotedstrlen; - *outquery_len += quotedstrlen; - efree(quotedstr); - } else { - memcpy(ptr, Z_STRVAL_P(param->parameter), Z_STRLEN_P(param->parameter)); - ptr += Z_STRLEN_P(param->parameter); - *outquery_len += (Z_STRLEN_P(param->parameter)); - } - } - else { - /* error and cleanup */ - efree(*outquery); - *outquery = NULL; - return (int) (s.cur - inquery); - } - bindno++; - } - else if(t == PDO_PARSER_BIND_POS) { - if(!params) { - /* error */ - efree(*outquery); - *outquery = NULL; - return (int) (s.cur - inquery); - } - /* lookup bind by index */ - if(SUCCESS == zend_hash_index_find(params, bindno, (void **)¶m)) - { - char *quotedstr; - int quotedstrlen; - /* currently everything is a string here */ - - /* quote the bind value if necessary */ - if(stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter), - Z_STRLEN_P(param->parameter), "edstr, "edstrlen TSRMLS_CC)) - { - memcpy(ptr, quotedstr, quotedstrlen); - ptr += quotedstrlen; - *outquery_len += quotedstrlen; - efree(quotedstr); - } else { - memcpy(ptr, Z_STRVAL_P(param->parameter), Z_STRLEN_P(param->parameter)); - ptr += Z_STRLEN_P(param->parameter); - *outquery_len += (Z_STRLEN_P(param->parameter)); - } - } - else { - /* error and cleanup */ - efree(*outquery); - *outquery = NULL; - return (int) (s.cur - inquery); - } - bindno++; - } - } - *ptr = '\0'; - return 0; -} - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker ft=c - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c deleted file mode 100755 index be704f413227..000000000000 --- a/ext/pdo/pdo_stmt.c +++ /dev/null @@ -1,1111 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong | - | Marcus Boerger | - | Sterling Hughes | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -/* The PDO Statement Handle Class */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "php_pdo.h" -#include "php_pdo_driver.h" -#include "php_pdo_int.h" -#include "php_pdo_sql_parser.h" -#include "zend_exceptions.h" - -#if COMPILE_DL_PDO -/* {{{ content from zend_arg_defs.c: - * since it is a .c file, it won't be installed for use by PECL extensions, so we include it here. */ -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_ARG_PASS_INFO(0) - ZEND_ARG_PASS_INFO(1) -ZEND_END_ARG_INFO(); - -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_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(all_args_by_ref, 1) -ZEND_END_ARG_INFO(); -/* }}} */ -#endif - -static PHP_FUNCTION(dbstmt_constructor) /* {{{ */ -{ - php_error_docref(NULL TSRMLS_CC, E_ERROR, "You should not create a PDOStatement manually"); -} -/* }}} */ - -/* trigger callback hook for parameters */ -static int dispatch_param_event(pdo_stmt_t *stmt, enum pdo_param_event event_type TSRMLS_DC) -{ - int ret = 1, is_param = 1; - struct pdo_bound_param_data *param; - HashTable *ht; - - if (!stmt->methods->param_hook) { - return 1; - } - - ht = stmt->bound_params; - -iterate: - if (ht) { - zend_hash_internal_pointer_reset(ht); - while (SUCCESS == zend_hash_get_current_data(ht, (void**)¶m)) { - - if (!stmt->methods->param_hook(stmt, param, event_type TSRMLS_CC)) { - ret = 0; - break; - } - - zend_hash_move_forward(ht); - } - } - if (ret && is_param) { - ht = stmt->bound_columns; - is_param = 0; - goto iterate; - } - - return ret; -} - -static int describe_columns(pdo_stmt_t *stmt TSRMLS_DC) -{ - int col; - - stmt->columns = ecalloc(stmt->column_count, sizeof(struct pdo_column_data)); - - for (col = 0; col < stmt->column_count; col++) { - if (!stmt->methods->describer(stmt, col TSRMLS_CC)) { - return 0; - } - - /* if we are applying case conversions on column names, do so now */ - if (stmt->dbh->native_case != stmt->dbh->desired_case && stmt->dbh->desired_case != PDO_CASE_NATURAL) { - char *s = stmt->columns[col].name; - - switch (stmt->dbh->desired_case) { - case PDO_CASE_UPPER: - while (*s != '\0') { - *s = toupper(*s); - s++; - } - break; - case PDO_CASE_LOWER: - while (*s != '\0') { - *s = tolower(*s); - s++; - } - break; - default: - ; - } - } - - /* update the column index on named bound parameters */ - if (stmt->bound_params) { - struct pdo_bound_param_data *param; - - if (SUCCESS == zend_hash_find(stmt->bound_params, stmt->columns[col].name, - stmt->columns[col].namelen, (void**)¶m)) { - param->paramno = col; - } - } - if (stmt->bound_columns) { - struct pdo_bound_param_data *param; - - if (SUCCESS == zend_hash_find(stmt->bound_columns, stmt->columns[col].name, - stmt->columns[col].namelen, (void**)¶m)) { - param->paramno = col; - } - } - - } - return 1; -} - -static void get_lazy_object(pdo_stmt_t *stmt, zval *return_value TSRMLS_DC) -{ - if (Z_TYPE(stmt->lazy_object_ref) == IS_NULL) { - Z_TYPE(stmt->lazy_object_ref) = IS_OBJECT; - Z_OBJ_HANDLE(stmt->lazy_object_ref) = zend_objects_store_put(stmt, NULL, pdo_row_free_storage, NULL TSRMLS_CC); - Z_OBJ_HT(stmt->lazy_object_ref) = &pdo_row_object_handlers; - stmt->refcount++; - } - Z_TYPE_P(return_value) = IS_OBJECT; - Z_OBJ_HANDLE_P(return_value) = Z_OBJ_HANDLE(stmt->lazy_object_ref); - Z_OBJ_HT_P(return_value) = Z_OBJ_HT(stmt->lazy_object_ref); -} - -static void param_dtor(void *data) -{ - struct pdo_bound_param_data *param = (struct pdo_bound_param_data *)data; - TSRMLS_FETCH(); - - /* tell the driver that it is going away */ - if (param->stmt->methods->param_hook) { - param->stmt->methods->param_hook(param->stmt, param, PDO_PARAM_EVT_FREE TSRMLS_CC); - } - - if (param->name) { - efree(param->name); - } - - zval_ptr_dtor(&(param->parameter)); - if (param->driver_params) { - zval_ptr_dtor(&(param->driver_params)); - } -} - -static int really_register_bound_param(struct pdo_bound_param_data *param, pdo_stmt_t *stmt, int is_param TSRMLS_DC) -{ - HashTable *hash; - struct pdo_bound_param_data *pparam = NULL; - - hash = is_param ? stmt->bound_params : stmt->bound_columns; - - if (!hash) { - ALLOC_HASHTABLE(hash); - zend_hash_init(hash, 13, NULL, param_dtor, 0); - - if (is_param) { - stmt->bound_params = hash; - } else { - stmt->bound_columns = hash; - } - } - - if (param->param_type == PDO_PARAM_STR && param->max_value_len <= 0) { - convert_to_string(param->parameter); - /* XXX: need to provide a way to set this to something sane, or - * investigate a better way to set the length of output parameters in - * the drivers themselves */ - param->max_value_len = Z_STRLEN_P(param->parameter); - } - - param->stmt = stmt; - param->is_param = is_param; - - ZVAL_ADDREF(param->parameter); - if (param->driver_params) { - ZVAL_ADDREF(param->driver_params); - } - - if (param->name && stmt->columns) { - /* try to map the name to the column */ - int i; - - for (i = 0; i < stmt->column_count; i++) { - if (strcmp(stmt->columns[i].name, param->name) == 0) { - param->paramno = i; - break; - } - } - - if (param->paramno == -1) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Did not found column name '%s' in the defined columns; it will not be bound", param->name); - } - } - - if (param->name) { - param->name = estrndup(param->name, param->namelen); - zend_hash_update(hash, param->name, param->namelen, param, sizeof(*param), (void**)&pparam); - } else { - zend_hash_index_update(hash, param->paramno, param, sizeof(*param), (void**)&pparam); - } - - /* tell the driver we just created a parameter */ - if (stmt->methods->param_hook) { - return stmt->methods->param_hook(stmt, pparam, PDO_PARAM_EVT_ALLOC TSRMLS_CC); - } - - return 1; -} - - -/* {{{ proto bool PDOStatement::execute([array $bound_input_params]) - Execute a prepared statement, optionally binding parameters */ -static PHP_METHOD(PDOStatement, execute) -{ - pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(getThis() TSRMLS_CC); - zval *input_params = NULL; - int ret = 1; - - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &input_params)) { - RETURN_FALSE; - } - - PDO_STMT_CLEAR_ERR(); - - if (input_params) { - struct pdo_bound_param_data param; - zval **tmp; - uint str_length; - ulong num_index; - - zend_hash_internal_pointer_reset(Z_ARRVAL_P(input_params)); - while (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(input_params), (void*)&tmp)) { - memset(¶m, 0, sizeof(param)); - - if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(Z_ARRVAL_P(input_params), - ¶m.name, &str_length, &num_index, 0, NULL)) { - /* yes this is correct. we don't want to count the null byte. ask wez */ - param.namelen = str_length - 1; - param.paramno = -1; - } else { - /* we're okay to be zero based here */ - if (num_index < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid parameter index"); - RETURN_FALSE; - } - param.paramno = num_index; - } - - param.param_type = PDO_PARAM_STR; - param.parameter = *tmp; - - if (!really_register_bound_param(¶m, stmt, 1 TSRMLS_CC)) { - RETURN_FALSE; - } - - zend_hash_move_forward(Z_ARRVAL_P(input_params)); - } - } - - if (!stmt->dbh->supports_placeholders) { - int error_pos; - /* handle the emulated parameter binding, - * stmt->active_query_string holds the query with binds expanded and - * quoted. - */ - if((error_pos = pdo_parse_params(stmt, stmt->query_string, stmt->query_stringlen, - &stmt->active_query_string, &stmt->active_query_stringlen)) != 0) { - // parse error in handling the query - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error emulating placeholder binding in query at %.*s....", error_pos, stmt->query_string); - RETURN_FALSE; - } - } else if (!dispatch_param_event(stmt, PDO_PARAM_EVT_EXEC_PRE TSRMLS_CC)) { - PDO_HANDLE_STMT_ERR(); - RETURN_FALSE; - } - if (stmt->methods->executer(stmt TSRMLS_CC)) { - if (stmt->active_query_string) { - efree(stmt->active_query_string); - stmt->active_query_string = NULL; - } - if (!stmt->executed) { - /* this is the first execute */ - - if (stmt->dbh->alloc_own_columns) { - /* for "big boy" drivers, we need to allocate memory to fetch - * the results into, so lets do that now */ - ret = describe_columns(stmt TSRMLS_CC); - } - - stmt->executed = 1; - } - - if (ret && !dispatch_param_event(stmt, PDO_PARAM_EVT_EXEC_POST TSRMLS_CC)) { - RETURN_FALSE; - } - - RETURN_BOOL(ret); - } - if (stmt->active_query_string) { - efree(stmt->active_query_string); - stmt->active_query_string = NULL; - } - PDO_HANDLE_STMT_ERR(); - RETURN_FALSE; -} -/* }}} */ - -static inline void fetch_value(pdo_stmt_t *stmt, zval *dest, int colno TSRMLS_DC) -{ - struct pdo_column_data *col; - char *value = NULL; - unsigned long value_len = 0; - - col = &stmt->columns[colno]; - - value = NULL; - value_len = 0; - - stmt->methods->get_col(stmt, colno, &value, &value_len TSRMLS_CC); - - switch (col->param_type) { - case PDO_PARAM_STR: - if (value) { - ZVAL_STRINGL(dest, value, value_len, 1); - break; - } - default: - ZVAL_NULL(dest); - } -} - -static int do_fetch_common(pdo_stmt_t *stmt, int do_bind TSRMLS_DC) -{ - if (!dispatch_param_event(stmt, PDO_PARAM_EVT_FETCH_PRE TSRMLS_CC)) { - return 0; - } - - if (!stmt->methods->fetcher(stmt TSRMLS_CC)) { - return 0; - } - - /* some drivers might need to describe the columns now */ - if (!stmt->columns && !describe_columns(stmt TSRMLS_CC)) { - return 0; - } - - if (!dispatch_param_event(stmt, PDO_PARAM_EVT_FETCH_POST TSRMLS_CC)) { - return 0; - } - - if (do_bind && stmt->bound_columns) { - /* update those bound column variables now */ - struct pdo_bound_param_data *param; - - zend_hash_internal_pointer_reset(stmt->bound_columns); - while (SUCCESS == zend_hash_get_current_data(stmt->bound_columns, (void**)¶m)) { - if (param->paramno >= 0) { - convert_to_string(param->parameter); - - /* delete old value */ - zval_dtor(param->parameter); - - /* set new value */ - fetch_value(stmt, param->parameter, param->paramno TSRMLS_CC); - - /* TODO: some smart thing that avoids duplicating the value in the - * general loop below. For now, if you're binding output columns, - * it's better to use LAZY or BOUND fetches if you want to shave - * off those cycles */ - } - - zend_hash_move_forward(stmt->bound_columns); - } - } - - return 1; -} - -/* perform a fetch. If do_bind is true, update any bound columns. - * If return_value is not null, store values into it according to HOW. */ -static int do_fetch(pdo_stmt_t *stmt, int do_bind, zval *return_value, enum pdo_fetch_type how TSRMLS_DC) -{ - enum pdo_fetch_type really_how = how; - - if (!do_fetch_common(stmt, do_bind TSRMLS_CC)) { - return 0; - } - - if (how == PDO_FETCH_BOUND) { - RETVAL_TRUE; - return 1; - } - - if (return_value) { - int i; - - if (how == PDO_FETCH_LAZY) { - get_lazy_object(stmt, return_value TSRMLS_CC); - return 1; - } - - array_init(return_value); - - if (how == PDO_FETCH_OBJ) { - how = PDO_FETCH_ASSOC; - } - - for (i = 0; i < stmt->column_count; i++) { - zval *val; - MAKE_STD_ZVAL(val); - fetch_value(stmt, val, i TSRMLS_CC); - - if (how == PDO_FETCH_ASSOC || how == PDO_FETCH_BOTH) { - add_assoc_zval(return_value, stmt->columns[i].name, val); - } - if (how == PDO_FETCH_NUM || how == PDO_FETCH_BOTH) { - add_next_index_zval(return_value, val); - } - - if (how == PDO_FETCH_BOTH) { - ZVAL_ADDREF(val); - } - } - - if (really_how == PDO_FETCH_OBJ) { - object_and_properties_init(return_value, ZEND_STANDARD_CLASS_DEF_PTR, Z_ARRVAL_P(return_value)); - } - } - - return 1; -} - -/* {{{ proto mixed PDOStatement::fetch([int $how = PDO_FETCH_BOTH]) - Fetches the next row and returns it, or false if there are no more rows */ -static PHP_METHOD(PDOStatement, fetch) -{ - long how = PDO_FETCH_BOTH; - pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(getThis() TSRMLS_CC); - - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &how)) { - RETURN_FALSE; - } - - PDO_STMT_CLEAR_ERR(); - if (!do_fetch(stmt, TRUE, return_value, how TSRMLS_CC)) { - PDO_HANDLE_STMT_ERR(); - RETURN_FALSE; - } -} -/* }}} */ - -/* {{{ proto string PDOStatement::fetchSingle() - Returns a data of the 1st column in the result set. */ -static PHP_METHOD(PDOStatement, fetchSingle) -{ - pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(getThis() TSRMLS_CC); - - if (ZEND_NUM_ARGS()) { - RETURN_FALSE; - } - - PDO_STMT_CLEAR_ERR(); - if (!do_fetch_common(stmt, TRUE TSRMLS_CC)) { - PDO_HANDLE_STMT_ERR(); - RETURN_FALSE; - } - - fetch_value(stmt, return_value, 0 TSRMLS_CC); -} -/* }}} */ - -/* {{{ proto array PDOStatement::fetchAll([int $how = PDO_FETCH_BOTH]) - Returns an array of all of the results. */ -static PHP_METHOD(PDOStatement, fetchAll) -{ - pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(getThis() TSRMLS_CC); - long how = PDO_FETCH_BOTH; - zval *data; - - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &how)) { - RETURN_FALSE; - } - - PDO_STMT_CLEAR_ERR(); - MAKE_STD_ZVAL(data); - if (!do_fetch(stmt, TRUE, data, how TSRMLS_CC)) { - FREE_ZVAL(data); - PDO_HANDLE_STMT_ERR(); - RETURN_FALSE; - } - - array_init(return_value); - do { - add_next_index_zval(return_value, data); - MAKE_STD_ZVAL(data); - } while (do_fetch(stmt, TRUE, data, how TSRMLS_CC)); - FREE_ZVAL(data); -} -/* }}} */ - -static int register_bound_param(INTERNAL_FUNCTION_PARAMETERS, pdo_stmt_t *stmt, int is_param) -{ - struct pdo_bound_param_data param = {0}; - - param.paramno = -1; - param.param_type = PDO_PARAM_STR; - - if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, - "lz|llz!", ¶m.paramno, ¶m.parameter, ¶m.param_type, ¶m.max_value_len, - ¶m.driver_params)) { - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|llz!", ¶m.name, - ¶m.namelen, ¶m.parameter, ¶m.param_type, ¶m.max_value_len, - ¶m.driver_params)) { - return 0; - } - } - - if (param.paramno > 0) { - --param.paramno; /* make it zero-based internally */ - } else if (!param.name) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid parameter number: columns are 1-based"); - return 0; - } - - return really_register_bound_param(¶m, stmt, is_param TSRMLS_CC); -} - -/* {{{ proto bool PDOStatement::bindParam(mixed $paramno, mixed &$param [, int $type [, int $maxlen [, mixed $driverdata]]]) - bind a parameter to a PHP variable. $paramno is the 1-based position of the placeholder in the SQL statement (but can be the parameter name for drivers that support named placeholders). This isn't supported by all drivers. It should be called prior to execute(). */ -static PHP_METHOD(PDOStatement, bindParam) -{ - pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(getThis() TSRMLS_CC); - RETURN_BOOL(register_bound_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, stmt, TRUE)); -} -/* }}} */ - -/* {{{ proto bool PDOStatement::bindColumn(mixed $column, mixed &$param [, int $type [, int $maxlen [, mixed $driverdata]]]) - bind a column to a PHP variable. On each row fetch $param will contain the value of the corresponding column. $column is the 1-based offset of the column, or the column name. For portability, don't call this before execute(). */ -static PHP_METHOD(PDOStatement, bindColumn) -{ - pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(getThis() TSRMLS_CC); - RETURN_BOOL(register_bound_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, stmt, FALSE)); -} -/* }}} */ - -/* {{{ proto int PDOStatement::rowCount() - Returns the number of rows in a result set, or the number of rows affected by the last execute(). It is not always meaningful. */ -static PHP_METHOD(PDOStatement, rowCount) -{ - pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(getThis() TSRMLS_CC); - - php_error_docref(NULL TSRMLS_CC, E_WARNING, "This statement is not a scrollable cursor and does not know the row count"); - RETURN_FALSE; -} -/* }}} */ - -/* {{{ proto int PDOStatement::errorCode() - Fetch the error code associated with the last operation on the statement handle */ -static PHP_METHOD(PDOStatement, errorCode) -{ - pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(getThis() TSRMLS_CC); - - if (ZEND_NUM_ARGS()) { - RETURN_FALSE; - } - - RETURN_LONG(stmt->error_code); -} -/* }}} */ - -/* {{{ proto array PDOStatement::errorInfo() - Fetch extended error information associated with the last operation on the statement handle */ -static PHP_METHOD(PDOStatement, errorInfo) -{ - pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(getThis() TSRMLS_CC); - - if (ZEND_NUM_ARGS()) { - RETURN_FALSE; - } - - array_init(return_value); - add_next_index_long(return_value, stmt->error_code); - - if (stmt->dbh->methods->fetch_err) { - stmt->dbh->methods->fetch_err(stmt->dbh, stmt, return_value TSRMLS_CC); - } -} -/* }}} */ - -/* {{{ proto bool PDOStatement::setAttribute(long attribute, mixed value) - Set an attribute */ -static PHP_METHOD(PDOStatement, setAttribute) -{ - pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(getThis() TSRMLS_CC); - long attr; - zval *value = NULL; - - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz!", &attr, &value)) { - RETURN_FALSE; - } - - if (!stmt->methods->set_attribute) { - goto fail; - } - - PDO_STMT_CLEAR_ERR(); - if (stmt->methods->set_attribute(stmt, attr, value TSRMLS_CC)) { - RETURN_TRUE; - } - -fail: - if (!stmt->methods->set_attribute) { - /* XXX: do something better here */ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "This driver doesn't support setting attributes"); - } else { - PDO_HANDLE_STMT_ERR(); - } - RETURN_FALSE; -} -/* }}} */ - -/* {{{ proto mixed PDOStatement::getAttribute(long attribute) - Get an attribute */ -static PHP_METHOD(PDOStatement, getAttribute) -{ - pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(getThis() TSRMLS_CC); - long attr; - - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &attr)) { - RETURN_FALSE; - } - - if (!stmt->methods->get_attribute) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "This driver doesn't support fetching attributes"); - RETURN_FALSE; - } - - PDO_STMT_CLEAR_ERR(); - switch (stmt->methods->get_attribute(stmt, attr, return_value TSRMLS_CC)) { - case -1: - PDO_HANDLE_STMT_ERR(); - RETURN_FALSE; - - case 0: - /* XXX: should do something better here */ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "This driver doesn't support fetching %ld attribute", attr); - break; - - default: - return; - } -} -/* }}} */ - -function_entry pdo_dbstmt_functions[] = { - PHP_ME(PDOStatement, execute, NULL, ZEND_ACC_PUBLIC) - PHP_ME(PDOStatement, fetch, NULL, ZEND_ACC_PUBLIC) - PHP_ME(PDOStatement, bindParam, second_arg_force_ref, ZEND_ACC_PUBLIC) - PHP_ME(PDOStatement, bindColumn, second_arg_force_ref, ZEND_ACC_PUBLIC) - PHP_ME(PDOStatement, rowCount, NULL, ZEND_ACC_PUBLIC) - PHP_ME(PDOStatement, fetchSingle, NULL, ZEND_ACC_PUBLIC) - PHP_ME(PDOStatement, fetchAll, NULL, ZEND_ACC_PUBLIC) - PHP_ME(PDOStatement, errorCode, NULL, ZEND_ACC_PUBLIC) - PHP_ME(PDOStatement, errorInfo, NULL, ZEND_ACC_PUBLIC) - PHP_ME(PDOStatement, setAttribute, NULL, ZEND_ACC_PUBLIC) - PHP_ME(PDOStatement, getAttribute, NULL, ZEND_ACC_PUBLIC) - {NULL, NULL, NULL} -}; - -/* {{{ overloaded handlers for PDOStatement class */ -static zval *dbstmt_prop_read(zval *object, zval *member, int type TSRMLS_DC) -{ - zval *return_value; - pdo_stmt_t * stmt = (pdo_stmt_t *) zend_object_store_get_object(object TSRMLS_CC); - - convert_to_string(member); - - if(strcmp(Z_STRVAL_P(member), "queryString") == 0) { - MAKE_STD_ZVAL(return_value); - ZVAL_STRINGL(return_value, stmt->query_string, stmt->query_stringlen, 1); - } else { - MAKE_STD_ZVAL(return_value); - ZVAL_NULL(return_value); - } - return return_value; -} - -static void dbstmt_prop_write(zval *object, zval *member, zval *value TSRMLS_DC) -{ - return; -} - -static zval *dbstmt_read_dim(zval *object, zval *offset, int type TSRMLS_DC) -{ - zval *return_value; - - MAKE_STD_ZVAL(return_value); - ZVAL_NULL(return_value); - - return return_value; -} - -static void dbstmt_write_dim(zval *object, zval *offset, zval *value TSRMLS_DC) -{ - return; -} - -static int dbstmt_prop_exists(zval *object, zval *member, int check_empty TSRMLS_DC) -{ - return 0; -} - -static int dbstmt_dim_exists(zval *object, zval *member, int check_empty TSRMLS_DC) -{ - return 0; -} - -static void dbstmt_prop_delete(zval *object, zval *offset TSRMLS_DC) -{ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete properties from a PDOStatement"); -} - -static void dbstmt_dim_delete(zval *object, zval *offset TSRMLS_DC) -{ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete dimensions from a PDOStatement"); -} - -static HashTable *dbstmt_get_properties(zval *object TSRMLS_DC) -{ - return NULL; -} - -static union _zend_function *dbstmt_method_get(zval *object, char *method_name, int method_len TSRMLS_DC) -{ - zend_function *fbc; - char *lc_method_name; - - lc_method_name = emalloc(method_len + 1); - zend_str_tolower_copy(lc_method_name, method_name, method_len); - - if (zend_hash_find(&pdo_dbstmt_ce->function_table, lc_method_name, method_len+1, (void**)&fbc) == FAILURE) { - efree(lc_method_name); - return NULL; - } - - efree(lc_method_name); - return fbc; -} - -static int dbstmt_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS) -{ - return FAILURE; -} - -static union _zend_function *dbstmt_get_ctor(zval *object TSRMLS_DC) -{ - static zend_internal_function ctor = {0}; - - ctor.type = ZEND_INTERNAL_FUNCTION; - ctor.function_name = "__construct"; - ctor.scope = pdo_dbstmt_ce; - ctor.handler = ZEND_FN(dbstmt_constructor); - - return (union _zend_function*)&ctor; -} - -static zend_class_entry *dbstmt_get_ce(zval *object TSRMLS_DC) -{ - return pdo_dbstmt_ce; -} - -static int dbstmt_get_classname(zval *object, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC) -{ - *class_name = estrndup("PDOStatement", sizeof("PDOStatement")-1); - *class_name_len = sizeof("PDOStatement")-1; - return 0; -} - -static int dbstmt_compare(zval *object1, zval *object2 TSRMLS_DC) -{ - return -1; -} - -zend_object_handlers pdo_dbstmt_object_handlers = { - ZEND_OBJECTS_STORE_HANDLERS, - dbstmt_prop_read, - dbstmt_prop_write, - dbstmt_read_dim, - dbstmt_write_dim, - NULL, - NULL, - NULL, - dbstmt_prop_exists, - dbstmt_prop_delete, - dbstmt_dim_exists, - dbstmt_dim_delete, - dbstmt_get_properties, - dbstmt_method_get, - dbstmt_call_method, - dbstmt_get_ctor, - dbstmt_get_ce, - dbstmt_get_classname, - dbstmt_compare, - NULL, /* cast */ - NULL -}; - -static void free_statement(pdo_stmt_t *stmt TSRMLS_DC) -{ - if (stmt->methods && stmt->methods->dtor) { - stmt->methods->dtor(stmt TSRMLS_CC); - } - if (stmt->query_string) { - efree(stmt->query_string); - } - - if (stmt->column_count) { - int i; - struct pdo_column_data *cols = stmt->columns; - - for (i = 0; i < stmt->column_count; i++) { - efree(cols[i].name); - } - } - if (stmt->columns) { - efree(stmt->columns); - } - - if (stmt->bound_params) { - zend_hash_destroy(stmt->bound_params); - FREE_HASHTABLE(stmt->bound_params); - } - if (stmt->bound_columns) { - zend_hash_destroy(stmt->bound_columns); - FREE_HASHTABLE(stmt->bound_columns); - } - - zend_objects_store_del_ref(&stmt->database_object_handle TSRMLS_CC); - efree(stmt); -} - -void pdo_dbstmt_free_storage(zend_object *object TSRMLS_DC) -{ - pdo_stmt_t *stmt = (pdo_stmt_t*)object; - - if (--stmt->refcount == 0) { - free_statement(stmt TSRMLS_CC); - } -} - -zend_object_value pdo_dbstmt_new(zend_class_entry *ce TSRMLS_DC) -{ - zend_object_value retval; - - retval.handle = zend_objects_store_put(NULL, NULL, pdo_dbstmt_free_storage, NULL TSRMLS_CC); - retval.handlers = &pdo_dbstmt_object_handlers; - - return retval; -} -/* }}} */ - -/* {{{ overloaded handlers for PDORow class (used by PDO_FETCH_LAZY) */ - -function_entry pdo_row_functions[] = { - {NULL, NULL, NULL} -}; - -static zval *row_prop_or_dim_read(zval *object, zval *member, int type TSRMLS_DC) -{ - zval *return_value; - pdo_stmt_t * stmt = (pdo_stmt_t *) zend_object_store_get_object(object TSRMLS_CC); - int colno = -1; - - MAKE_STD_ZVAL(return_value); - - if (Z_TYPE_P(member) == IS_LONG) { - if (Z_LVAL_P(member) >= 0 && Z_LVAL_P(member) < stmt->column_count) { - fetch_value(stmt, return_value, Z_LVAL_P(member) TSRMLS_CC); - } - } else { - convert_to_string(member); - /* TODO: replace this with a hash of available column names to column - * numbers */ - for (colno = 0; colno < stmt->column_count; colno++) { - if (strcmp(stmt->columns[colno].name, Z_STRVAL_P(member)) == 0) { - fetch_value(stmt, return_value, colno TSRMLS_CC); - break; - } - } - } - - return return_value; -} - -static void row_prop_or_dim_write(zval *object, zval *member, zval *value TSRMLS_DC) -{ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "This PDORow is not from a writable result set"); -} - -static int row_prop_or_dim_exists(zval *object, zval *member, int check_empty TSRMLS_DC) -{ - pdo_stmt_t * stmt = (pdo_stmt_t *) zend_object_store_get_object(object TSRMLS_CC); - int colno = -1; - - if (Z_TYPE_P(member) == IS_LONG) { - return Z_LVAL_P(member) >= 0 && Z_LVAL_P(member) < stmt->column_count; - } else { - convert_to_string(member); - - /* TODO: replace this with a hash of available column names to column - * numbers */ - for (colno = 0; colno < stmt->column_count; colno++) { - if (strcmp(stmt->columns[colno].name, Z_STRVAL_P(member)) == 0) { - return 1; - } - } - } - - return 0; -} - -static void row_prop_or_dim_delete(zval *object, zval *offset TSRMLS_DC) -{ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete properties from a PDORow"); -} - -static HashTable *row_get_properties(zval *object TSRMLS_DC) -{ - zval *tmp; - pdo_stmt_t * stmt = (pdo_stmt_t *) zend_object_store_get_object(object TSRMLS_CC); - int i; - HashTable *ht; - - MAKE_STD_ZVAL(tmp); - array_init(tmp); - - for (i = 0; i < stmt->column_count; i++) { - zval *val; - MAKE_STD_ZVAL(val); - fetch_value(stmt, val, i TSRMLS_CC); - - add_assoc_zval(tmp, stmt->columns[i].name, val); - } - - ht = Z_ARRVAL_P(tmp); - - ZVAL_NULL(tmp); - FREE_ZVAL(tmp); - - return ht; -} - -static union _zend_function *row_method_get(zval *object, char *method_name, int method_len TSRMLS_DC) -{ - zend_function *fbc; - char *lc_method_name; - - lc_method_name = emalloc(method_len + 1); - zend_str_tolower_copy(lc_method_name, method_name, method_len); - - if (zend_hash_find(&pdo_row_ce->function_table, lc_method_name, method_len+1, (void**)&fbc) == FAILURE) { - efree(lc_method_name); - return NULL; - } - - efree(lc_method_name); - return fbc; -} - -static int row_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS) -{ - return FAILURE; -} - -static union _zend_function *row_get_ctor(zval *object TSRMLS_DC) -{ - static zend_internal_function ctor = {0}; - - ctor.type = ZEND_INTERNAL_FUNCTION; - ctor.function_name = "__construct"; - ctor.scope = pdo_row_ce; - ctor.handler = ZEND_FN(dbstmt_constructor); - - return (union _zend_function*)&ctor; -} - -static zend_class_entry *row_get_ce(zval *object TSRMLS_DC) -{ - return pdo_dbstmt_ce; -} - -static int row_get_classname(zval *object, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC) -{ - *class_name = estrndup("PDORow", sizeof("PDORow")-1); - *class_name_len = sizeof("PDORow")-1; - return 0; -} - -static int row_compare(zval *object1, zval *object2 TSRMLS_DC) -{ - return -1; -} - -zend_object_handlers pdo_row_object_handlers = { - ZEND_OBJECTS_STORE_HANDLERS, - row_prop_or_dim_read, - row_prop_or_dim_write, - row_prop_or_dim_read, - row_prop_or_dim_write, - NULL, - NULL, - NULL, - row_prop_or_dim_exists, - row_prop_or_dim_delete, - row_prop_or_dim_exists, - row_prop_or_dim_delete, - row_get_properties, - row_method_get, - row_call_method, - row_get_ctor, - row_get_ce, - row_get_classname, - row_compare, - NULL, /* cast */ - NULL -}; - -void pdo_row_free_storage(zend_object *object TSRMLS_DC) -{ - pdo_stmt_t *stmt = (pdo_stmt_t*)object; - - ZVAL_NULL(&stmt->lazy_object_ref); - - if (--stmt->refcount == 0) { - free_statement(stmt TSRMLS_CC); - } -} - -zend_object_value pdo_row_new(zend_class_entry *ce TSRMLS_DC) -{ - zend_object_value retval; - - retval.handle = zend_objects_store_put(NULL, NULL, pdo_row_free_storage, NULL TSRMLS_CC); - retval.handlers = &pdo_row_object_handlers; - - return retval; -} -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo/php_pdo.h b/ext/pdo/php_pdo.h deleted file mode 100755 index a7fbd90894f5..000000000000 --- a/ext/pdo/php_pdo.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifndef PHP_PDO_H -#define PHP_PDO_H - -extern zend_module_entry pdo_module_entry; -#define phpext_pdo_ptr &pdo_module_entry - -#ifdef PHP_WIN32 -# ifdef PDO_EXPORTS -# define PDO_API __declspec(dllexport) -# elif defined(COMPILE_DL_PDO) -# define PDO_API __declspec(dllimport) -# else -# define PDO_API /* nothing special */ -# endif -#else -# define PDO_API /* nothing special */ -#endif - -#ifdef ZTS -# include "TSRM.h" -#endif - -PHP_MINIT_FUNCTION(pdo); -PHP_MSHUTDOWN_FUNCTION(pdo); -PHP_RINIT_FUNCTION(pdo); -PHP_RSHUTDOWN_FUNCTION(pdo); -PHP_MINFO_FUNCTION(pdo); - -ZEND_BEGIN_MODULE_GLOBALS(pdo) - long global_value; -ZEND_END_MODULE_GLOBALS(pdo) - -#ifdef ZTS -# define PDOG(v) TSRMG(pdo_globals_id, zend_pdo_globals *, v) -#else -# define PDOG(v) (pdo_globals.v) -#endif - -#endif /* PHP_PDO_H */ - - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo/php_pdo_driver.h b/ext/pdo/php_pdo_driver.h deleted file mode 100755 index a661604bb0b6..000000000000 --- a/ext/pdo/php_pdo_driver.h +++ /dev/null @@ -1,415 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifndef PHP_PDO_DRIVER_H -#define PHP_PDO_DRIVER_H - -#include "php_pdo.h" - -/* forward declarations */ -typedef struct _pdo_dbh_t pdo_dbh_t; -typedef struct _pdo_stmt_t pdo_stmt_t; -struct pdo_bound_param_data; - -#ifndef TRUE -# define TRUE 1 -#endif -#ifndef FALSE -# define FALSE 0 -#endif - -#define PDO_DRIVER_API 20040513 - -enum pdo_param_type { - PDO_PARAM_NULL, - PDO_PARAM_INT, - PDO_PARAM_STR, - PDO_PARAM_LOB, - PDO_PARAM_STMT, /* hierarchical result set */ - -}; - -enum pdo_fetch_type { - PDO_FETCH_LAZY, - PDO_FETCH_ASSOC, - PDO_FETCH_NUM, - PDO_FETCH_BOTH, - PDO_FETCH_OBJ, - PDO_FETCH_BOUND, /* return true/false only; rely on bound columns */ -}; - -enum pdo_attribute_type { - PDO_ATTR_AUTOCOMMIT, /* use to turn on or off auto-commit mode */ - PDO_ATTR_SCROLL, /* ask for a scrollable cursor (when you prepare()) */ - PDO_ATTR_PREFETCH, /* configure the prefetch size for drivers that support it */ - PDO_ATTR_TIMEOUT, /* connection timeout in seconds */ - PDO_ATTR_ERRMODE, /* control how errors are handled */ - PDO_ATTR_SERVER_VERSION, /* database server version */ - PDO_ATTR_CLIENT_VERSION, /* client library version */ - PDO_ATTR_SERVER_INFO, /* server information */ - PDO_ATTR_CONNECTION_STATUS, /* connection status */ - PDO_ATTR_CASE, /* control case folding for portability */ - PDO_ATTR_CURSOR_NAME, /* name a cursor for use in "WHERE CURRENT OF " */ - PDO_ATTR_CURSOR, /* cursor type */ - - /* this defines the start of the range for driver specific options. - * Drivers should define their own attribute constants beginning with this - * value. */ - PDO_ATTR_DRIVER_SPECIFIC = 1000 -}; - -enum pdo_cursor_type { - PDO_CURSOR_FWDONLY, /* forward only cursor (default) */ - PDO_CURSOR_SCROLL, /* scrollable cursor */ -}; - -/* generic error code values. - * Don't want to go overboard with these. - * */ -enum pdo_error_type { - PDO_ERR_NONE, /* no error condition */ - PDO_ERR_CANT_MAP, /* no way to map native error to the generic codes; consult the native error for more info */ - PDO_ERR_SYNTAX, - PDO_ERR_CONSTRAINT, - PDO_ERR_NOT_FOUND, - PDO_ERR_ALREADY_EXISTS, - PDO_ERR_NOT_IMPLEMENTED, - PDO_ERR_MISMATCH, - PDO_ERR_TRUNCATED, - PDO_ERR_DISCONNECTED, -}; - -enum pdo_error_mode { - PDO_ERRMODE_SILENT, /* just set error codes */ - PDO_ERRMODE_WARNING, /* raise E_WARNING */ - PDO_ERRMODE_EXCEPTION, /* throw exceptions */ -}; - -enum pdo_case_conversion { - PDO_CASE_NATURAL, - PDO_CASE_UPPER, - PDO_CASE_LOWER -}; - -/* {{{ utils for reading attributes set as driver_options */ -static inline long pdo_attr_lval(zval *options, enum pdo_fetch_type option_name, long defval TSRMLS_DC) -{ - zval **v; - - if (options && SUCCESS == zend_hash_index_find(Z_ARRVAL_P(options), option_name, (void**)&v)) { - convert_to_long_ex(v); - return Z_LVAL_PP(v); - } - return defval; -} -/* }}} */ - -/* This structure is registered with PDO when a PDO driver extension is - * initialized */ -typedef struct { - const char *driver_name; - unsigned long driver_name_len; - unsigned long api_version; /* needs to be compatible with PDO */ - -#define PDO_DRIVER_HEADER(name) \ - #name, sizeof(#name)-1, \ - PDO_DRIVER_API - - /* create driver specific portion of the database handle and stash it into - * the dbh. dbh contains the data source string and flags for this - * instance */ - int (*db_handle_factory)(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC); - -} pdo_driver_t; - -/* {{{ methods for a database handle */ - -/* close or otherwise disconnect the database */ -typedef int (*pdo_dbh_close_func)(pdo_dbh_t *dbh TSRMLS_DC); - -/* prepare a statement and stash driver specific portion into stmt */ -typedef int (*pdo_dbh_prepare_func)(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, long options, zval *driver_options TSRMLS_DC); - -/* execute a statement (that does not return a result set) */ -typedef long (*pdo_dbh_do_func)(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC); - -/* quote a string */ -typedef int (*pdo_dbh_quote_func)(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen TSRMLS_DC); - -/* transaction related */ -typedef int (*pdo_dbh_txn_func)(pdo_dbh_t *dbh TSRMLS_DC); - -/* setting of attributes */ -typedef int (*pdo_dbh_set_attr_func)(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC); - -/* return last insert id */ -typedef long (*pdo_dbh_last_id_func)(pdo_dbh_t *dbh TSRMLS_DC); - -/* fetch error information. if stmt is not null, fetch information pertaining - * to the statement, otherwise fetch global error information. The driver - * should add the following information to the array "info" in this order: - * - native error code - * - string representation of the error code ... any other optional driver - * specific data ... */ -typedef int (*pdo_dbh_fetch_error_func)(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC); - -/* fetching of attributes */ -typedef int (*pdo_dbh_get_attr_func)(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC); - -struct pdo_dbh_methods { - pdo_dbh_close_func closer; - pdo_dbh_prepare_func preparer; - pdo_dbh_do_func doer; - pdo_dbh_quote_func quoter; - pdo_dbh_txn_func begin; - pdo_dbh_txn_func commit; - pdo_dbh_txn_func rollback; - pdo_dbh_set_attr_func set_attribute; - pdo_dbh_last_id_func last_id; - pdo_dbh_fetch_error_func fetch_err; - pdo_dbh_get_attr_func get_attribute; -}; - -/* }}} */ - -/* {{{ methods for a statement handle */ - -/* free the statement handle */ -typedef int (*pdo_stmt_dtor_func)(pdo_stmt_t *stmt TSRMLS_DC); - -/* start the query */ -typedef int (*pdo_stmt_execute_func)(pdo_stmt_t *stmt TSRMLS_DC); - -/* causes the next row in the set to be fetched; indicates if there are no - * more rows */ -typedef int (*pdo_stmt_fetch_func)(pdo_stmt_t *stmt TSRMLS_DC); - -/* queries information about the type of a column, by index (0 based). - * Driver should populate stmt->columns[colno] with appropriate info */ -typedef int (*pdo_stmt_describe_col_func)(pdo_stmt_t *stmt, int colno TSRMLS_DC); - -/* retrieves pointer and size of the value for a column */ -typedef int (*pdo_stmt_get_col_data_func)(pdo_stmt_t *stmt, int colno, char **ptr, unsigned long *len TSRMLS_DC); - -/* hook for bound params */ -enum pdo_param_event { - PDO_PARAM_EVT_ALLOC, - PDO_PARAM_EVT_FREE, - PDO_PARAM_EVT_EXEC_PRE, - PDO_PARAM_EVT_EXEC_POST, - PDO_PARAM_EVT_FETCH_PRE, - PDO_PARAM_EVT_FETCH_POST, -}; - -typedef int (*pdo_stmt_param_hook_func)(pdo_stmt_t *stmt, struct pdo_bound_param_data *param, enum pdo_param_event event_type TSRMLS_DC); - -/* setting of attributes */ -typedef int (*pdo_stmt_set_attr_func)(pdo_stmt_t *stmt, long attr, zval *val TSRMLS_DC); - -/* fetching of attributes */ -typedef int (*pdo_stmt_get_attr_func)(pdo_stmt_t *stmt, long attr, zval *val TSRMLS_DC); - - -struct pdo_stmt_methods { - pdo_stmt_dtor_func dtor; - pdo_stmt_execute_func executer; - pdo_stmt_fetch_func fetcher; - pdo_stmt_describe_col_func describer; - pdo_stmt_get_col_data_func get_col; - pdo_stmt_param_hook_func param_hook; - pdo_stmt_set_attr_func set_attribute; - pdo_stmt_get_attr_func get_attribute; -}; - -/* }}} */ - -enum pdo_placeholder_support { - PDO_PLACEHOLDER_NONE=0, - PDO_PLACEHOLDER_NAMED=1, - PDO_PLACEHOLDER_POSITIONAL=2 -}; - -/* represents a connection to a database */ -struct _pdo_dbh_t { - /* driver specific methods */ - struct pdo_dbh_methods *methods; - /* driver specific data */ - void *driver_data; - - /* credentials */ - char *username, *password; - - /* if true, then data stored and pointed at by this handle must all be - * persistently allocated */ - unsigned is_persistent:1; - - /* if true, driver should act as though a COMMIT were executed between - * each executed statement; otherwise, COMMIT must be carried out manually - * */ - unsigned auto_commit:1; - - /* if true, the handle has been closed and will not function anymore */ - unsigned is_closed:1; - - /* if true, the driver requires that memory be allocated explicitly for - * the columns that are returned */ - unsigned alloc_own_columns:1; - - /* if true, the driver supports placeholders and can implement - * bindParam() for its prepared statements, if false, PDO should - * emulate prepare and bind on its behalf */ - unsigned supports_placeholders:2; - - /* if true, commit or rollBack is allowed to be called */ - unsigned in_txn:1; - - /* max length a single character can become after correct quoting */ - unsigned max_escaped_char_length:3; - - /* the sum of the number of bits here and the bit fields preceeding should - * equal 32 */ - unsigned _reserved_flags:22; - - /* data source string used to open this handle */ - const char *data_source; - unsigned long data_source_len; - - /* the global error code. */ - enum pdo_error_type error_code; - - enum pdo_error_mode error_mode; - - enum pdo_case_conversion native_case, desired_case; - - /* needed for inheritance to work */ - zend_class_entry *ce; -#if 0 - /* persistent hash key associated with this handle */ - const char *persistent_id; - /* and the list id associated with it */ - int persistent_rsrc_id; -#endif -}; - -/* describes a column */ -struct pdo_column_data { - char *name; - long namelen; - unsigned long maxlen; - enum pdo_param_type param_type; - unsigned long precision; -}; - -/* describes a bound parameter */ -struct pdo_bound_param_data { - long paramno; /* if -1, then it has a name, and we don't know the index *yet* */ - char *name; - long namelen; - - long max_value_len; /* as a hint for pre-allocation */ - - zval *parameter; /* the variable itself */ - enum pdo_param_type param_type; /* desired or suggested type */ - - zval *driver_params; /* optional parameter(s) for the driver */ - void *driver_data; - - pdo_stmt_t *stmt; /* for convenience in dtor */ - int is_param; /* parameter or column ? */ -}; - -/* represents a prepared statement */ -struct _pdo_stmt_t { - /* driver specifics */ - struct pdo_stmt_methods *methods; - void *driver_data; - - /* if true, we've already successfully executed this statement at least - * once */ - unsigned executed:1; - unsigned _reserved:31; - - /* the number of columns in the result set; not valid until after - * the statement has been executed at least once. In some cases, might - * not be valid until fetch (at the driver level) has been called at least once. - * */ - int column_count; - struct pdo_column_data *columns; - - /* we want to keep the dbh alive while we live, so we own a reference */ - zval database_object_handle; - pdo_dbh_t *dbh; - - /* keep track of bound input parameters. Some drivers support - * input/output parameters, but you can't rely on that working */ - HashTable *bound_params; - /* keep track of PHP variables bound to named (or positional) columns - * in the result set */ - HashTable *bound_columns; - - /* not always meaningful */ - long row_count; - - /* used to hold the statement's current query */ - char *query_string; - int query_stringlen; - - /* the copy of the query with expanded binds ONLY for emulated-prepare drivers */ - char *active_query_string; - int active_query_stringlen; - - /* the cursor specific error code. */ - enum pdo_error_type error_code; - - /* for lazy fetches, we always return the same lazy object handle. - * Let's keep it here. */ - zval lazy_object_ref; - unsigned long refcount; -}; - -/* call this in MINIT to register your PDO driver */ -PDO_API int php_pdo_register_driver(pdo_driver_t *driver); -/* call this in MSHUTDOWN to unregister your PDO driver */ -PDO_API void php_pdo_unregister_driver(pdo_driver_t *driver); - -/* For the convenience of drivers, this function will parse a data source - * string, of the form "name=value; name2=value2" and populate variables - * according to the data you pass in and array of pdo_data_src_parser structures */ -struct pdo_data_src_parser { - const char *optname; - char *optval; - int freeme; -}; - -PDO_API int php_pdo_parse_data_source(const char *data_source, - unsigned long data_source_len, struct pdo_data_src_parser *parsed, - int nparams); - -PDO_API zend_class_entry *php_pdo_get_exception(void); - -#endif /* PHP_PDO_DRIVER_H */ -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo/php_pdo_int.h b/ext/pdo/php_pdo_int.h deleted file mode 100755 index 882ee904e1c3..000000000000 --- a/ext/pdo/php_pdo_int.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong | - | Marcus Boerger | - | Sterling Hughes | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -/* Stuff private to the PDO extension and not for consumption by PDO drivers - * */ -extern zend_class_entry *pdo_exception_ce; - -extern zend_object_value pdo_dbh_new(zend_class_entry *ce TSRMLS_DC); -extern function_entry pdo_dbh_functions[]; -extern zend_class_entry *pdo_dbh_ce; - -extern zend_object_value pdo_dbstmt_new(zend_class_entry *ce TSRMLS_DC); -extern function_entry pdo_dbstmt_functions[]; -extern zend_class_entry *pdo_dbstmt_ce; -void pdo_dbstmt_free_storage(zend_object *object TSRMLS_DC); -extern zend_object_handlers pdo_dbstmt_object_handlers; - -extern zend_object_value pdo_row_new(zend_class_entry *ce TSRMLS_DC); -extern function_entry pdo_row_functions[]; -extern zend_class_entry *pdo_row_ce; -void pdo_row_free_storage(zend_object *object TSRMLS_DC); -extern zend_object_handlers pdo_row_object_handlers; - - -extern pdo_driver_t *pdo_find_driver(const char *name, int namelen); - -extern void pdo_handle_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt TSRMLS_DC); - -#define PDO_DBH_CLEAR_ERR() dbh->error_code = PDO_ERR_NONE -#define PDO_STMT_CLEAR_ERR() stmt->error_code = PDO_ERR_NONE -#define PDO_HANDLE_DBH_ERR() if (dbh->error_code) { pdo_handle_error(dbh, NULL TSRMLS_CC); } -#define PDO_HANDLE_STMT_ERR() if (stmt->error_code) { pdo_handle_error(stmt->dbh, stmt TSRMLS_CC); } - - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo/php_pdo_sql_parser.h b/ext/pdo/php_pdo_sql_parser.h deleted file mode 100644 index 4bb92cc2122a..000000000000 --- a/ext/pdo/php_pdo_sql_parser.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: George Schlossnagle | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifndef PHP_PDO_MYSQL_SQL_PARSER_H -#define PHP_PDO_MYSQL_SQL_PARSER_H -#include "php.h" -int pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, char **outquery, - int *outquery_len); - -#endif diff --git a/ext/pdo_firebird/CREDITS b/ext/pdo_firebird/CREDITS deleted file mode 100644 index a33294b69c0e..000000000000 --- a/ext/pdo_firebird/CREDITS +++ /dev/null @@ -1,2 +0,0 @@ -Firebird/InterBase driver for PDO -Ard Biesheuvel diff --git a/ext/pdo_firebird/EXPERIMENTAL b/ext/pdo_firebird/EXPERIMENTAL deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/ext/pdo_firebird/config.m4 b/ext/pdo_firebird/config.m4 deleted file mode 100644 index 8af5e9b6d050..000000000000 --- a/ext/pdo_firebird/config.m4 +++ /dev/null @@ -1,49 +0,0 @@ -dnl -dnl $Id$ -dnl - -PHP_ARG_WITH(pdo-firebird,for Firebird support for PDO, -[ --with-pdo-firebird[=DIR] Include Firebird support for PDO. DIR is the Firebird base - install directory, defaults to /opt/firebird]) - -if test "$PHP_PDO_FIREBIRD" != "no"; then - if test "$PHP_PDO_FIREBIRD" = "yes"; then - FIREBIRD_INCDIR=/opt/firebird/include - FIREBIRD_LIBDIR=/opt/firebird/lib - else - FIREBIRD_INCDIR=$PHP_PDO_FIREBIRD/include - FIREBIRD_LIBDIR=$PHP_PDO_FIREBIRD/lib - fi - - PHP_CHECK_LIBRARY(gds, isc_detach_database, - [ - FIREBIRD_LIBNAME=gds - ], [ - PHP_CHECK_LIBRARY(ib_util, isc_detach_database, - [ - FIREBIRD_LIBNAME=ib_util - ], [ - AC_MSG_ERROR([libgds or libib_util not found! Check config.log for more information.]) - ], [ - -L$FIREBIRD_LIBDIR - ]) - ], [ - -L$FIREBIRD_LIBDIR - ]) - - if test -f $prefix/include/php/ext/pdo/php_pdo_driver.h; then - pdo_inc_path=$prefix/include/php/ext - elif test -f $abs_srcdir/include/php/ext/pdo/php_pdo_driver.h; then - pdo_inc_path=$abs_srcdir/ext - elif test -f ext/pdo/php_pdo_driver.h; then - pdo_inc_path=ext - else - AC_MSG_ERROR([Cannot find php_pdo_driver.h.]) - fi - - PHP_ADD_LIBRARY_WITH_PATH($FIREBIRD_LIBNAME, $FIREBIRD_LIBDIR, PDO_FIREBIRD_SHARED_LIBADD) - PHP_ADD_INCLUDE($FIREBIRD_INCDIR) - AC_DEFINE(HAVE_PDO_FIREBIRD,1,[ ]) - PHP_NEW_EXTENSION(pdo_firebird, pdo_firebird.c firebird_driver.c firebird_statement.c, $ext_shared,,-I$pdo_inc_path) - PHP_SUBST(PDO_FIREBIRD_SHARED_LIBADD) -fi diff --git a/ext/pdo_firebird/config.w32 b/ext/pdo_firebird/config.w32 deleted file mode 100644 index 30b87c2d1d63..000000000000 --- a/ext/pdo_firebird/config.w32 +++ /dev/null @@ -1,18 +0,0 @@ -// $Id$ -// vim:ft=javascript - -ARG_WITH("pdo-firebird", "Firebird support for PDO", "no"); - -if (PHP_PDO_FIREBIRD != "no") { - - if ((CHECK_LIB("fbclient_ms.lib", "pdo_firebird", PHP_PHP_BUILD + "\\interbase\\lib_ms;" + PHP_PDO_FIREBIRD) - || CHECK_LIB("gds32_ms.lib", "pdo_firebird", PHP_PHP_BUILD + "\\interbase\\lib_ms;" + PHP_PDO_FIREBIRD) - ) && CHECK_HEADER_ADD_INCLUDE("ibase.h", "CFLAGS_PDO_FIREBIRD", PHP_PHP_BUILD + "\\interbase\\include;" + PHP_PDO_FIREBIRD)) { - - EXTENSION("pdo_firebird", "pdo_firebird.c firebird_driver.c firebird_statement.c"); - ADD_FLAG('CFLAGS_PDO_FIREBIRD', "/I ..\\pecl"); - } else { - WARNING("pdo_firebird not enabled; libraries and headers not found"); - } - ADD_EXTENSION_DEP('pdo_firebird', 'pdo'); -} diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c deleted file mode 100644 index 251e80ef5f71..000000000000 --- a/ext/pdo_firebird/firebird_driver.c +++ /dev/null @@ -1,659 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Ard Biesheuvel | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#define _GNU_SOURCE - -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "pdo/php_pdo.h" -#include "pdo/php_pdo_driver.h" -#include "php_pdo_firebird.h" -#include "php_pdo_firebird_int.h" - -static int firebird_alloc_prepare_stmt(pdo_dbh_t*, const char*, long, XSQLDA*, isc_stmt_handle*, - HashTable* TSRMLS_DC); - -/* map driver specific error message to PDO error */ -void _firebird_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, char const *file, long line TSRMLS_DC) /* {{{ */ -{ - pdo_firebird_db_handle *H = stmt ? ((pdo_firebird_stmt *)stmt->driver_data)->H - : (pdo_firebird_db_handle *)dbh->driver_data; - enum pdo_error_type *const error_code = stmt ? &stmt->error_code : &dbh->error_code; - - switch (isc_sqlcode(H->isc_status)) { - - case 0: - *error_code = PDO_ERR_NONE; - break; - default: - *error_code = PDO_ERR_CANT_MAP; - break; - case -104: - *error_code = PDO_ERR_SYNTAX; - break; - case -530: - case -803: - *error_code = PDO_ERR_CONSTRAINT; - break; - case -204: - case -205: - case -206: - case -829: - *error_code = PDO_ERR_NOT_FOUND; - break; - - *error_code = PDO_ERR_ALREADY_EXISTS; - break; - - *error_code = PDO_ERR_NOT_IMPLEMENTED; - break; - case -313: - case -804: - *error_code = PDO_ERR_MISMATCH; - break; - case -303: - case -314: - case -413: - *error_code = PDO_ERR_TRUNCATED; - break; - - *error_code = PDO_ERR_DISCONNECTED; - break; - } -} -/* }}} */ - -#define RECORD_ERROR(dbh) _firebird_error(dbh, NULL, __FILE__, __LINE__ TSRMLS_CC) - -/* called by PDO to close a db handle */ -static int firebird_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */ -{ - pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; - - if (dbh->in_txn) { - if (dbh->auto_commit) { - if (isc_commit_transaction(H->isc_status, &H->tr)) { - RECORD_ERROR(dbh); - } - } else { - if (isc_rollback_transaction(H->isc_status, &H->tr)) { - RECORD_ERROR(dbh); - } - } - } - - if (isc_detach_database(H->isc_status, &H->db)) { - RECORD_ERROR(dbh); - } - - pefree(H, dbh->is_persistent); - - return 0; -} -/* }}} */ - -/* called by PDO to prepare an SQL query */ -static int firebird_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, /* {{{ */ - pdo_stmt_t *stmt, long options, zval *driver_options TSRMLS_DC) -{ - pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; - pdo_firebird_stmt *S = NULL; - HashTable *np; - - do { - isc_stmt_handle s = NULL; - XSQLDA num_sqlda; - static char const info[] = { isc_info_sql_stmt_type }; - char result[8]; - - num_sqlda.version = PDO_FB_SQLDA_VERSION; - num_sqlda.sqln = 1; - - ALLOC_HASHTABLE(np); - zend_hash_init(np, 8, NULL, NULL, 0); - - /* allocate and prepare statement */ - if (!firebird_alloc_prepare_stmt(dbh, sql, sql_len, &num_sqlda, &s, np TSRMLS_CC)) { - break; - } - - /* allocate a statement handle struct of the right size (struct out_sqlda is inlined) */ - S = ecalloc(1, sizeof(*S)-sizeof(XSQLDA) + XSQLDA_LENGTH(num_sqlda.sqld)); - S->H = H; - S->stmt = s; - S->fetch_buf = ecalloc(1,sizeof(char*) * num_sqlda.sqld); - S->out_sqlda.version = PDO_FB_SQLDA_VERSION; - S->out_sqlda.sqln = stmt->column_count = num_sqlda.sqld; - S->named_params = np; - - /* determine the statement type */ - if (isc_dsql_sql_info(H->isc_status, &s, sizeof(info), const_cast(info), sizeof(result), - result)) { - break; - } - S->statement_type = result[3]; - - /* fill the output sqlda with information about the prepared query */ - if (isc_dsql_describe(H->isc_status, &s, PDO_FB_SQLDA_VERSION, &S->out_sqlda)) { - RECORD_ERROR(dbh); - break; - } - - /* allocate the input descriptors */ - if (isc_dsql_describe_bind(H->isc_status, &s, PDO_FB_SQLDA_VERSION, &num_sqlda)) { - break; - } - - if (num_sqlda.sqld) { - S->in_sqlda = ecalloc(1,XSQLDA_LENGTH(num_sqlda.sqld)); - S->in_sqlda->version = PDO_FB_SQLDA_VERSION; - S->in_sqlda->sqln = num_sqlda.sqld; - - if (isc_dsql_describe_bind(H->isc_status, &s, PDO_FB_SQLDA_VERSION, S->in_sqlda)) { - break; - } - } - - stmt->driver_data = S; - stmt->methods = &firebird_stmt_methods; - - return 1; - - } while (0); - - RECORD_ERROR(dbh); - - zend_hash_destroy(np); - FREE_HASHTABLE(np); - - if (S) { - if (S->in_sqlda) { - efree(S->in_sqlda); - } - efree(S); - } - - return 0; -} -/* }}} */ - -/* called by PDO to execute a statement that doesn't produce a result set */ -static long firebird_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC) /* {{{ */ -{ - pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; - isc_stmt_handle stmt = NULL; - static char const info_count[] = { isc_info_sql_records }; - char result[64]; - int ret = 0; - XSQLDA in_sqlda, out_sqlda; - - /* TODO no placeholders in exec() for now */ - in_sqlda.version = out_sqlda.version = PDO_FB_SQLDA_VERSION; - in_sqlda.sqld = out_sqlda.sqld = 0; - - /* allocate and prepare statement */ - if (!firebird_alloc_prepare_stmt(dbh, sql, sql_len, &out_sqlda, &stmt, 0 TSRMLS_CC)) { - return -1; - } - - /* execute the statement */ - if (isc_dsql_execute2(H->isc_status, &H->tr, &stmt, PDO_FB_SQLDA_VERSION, &in_sqlda, &out_sqlda)) { - RECORD_ERROR(dbh); - return -1; - } - - /* find out how many rows were affected */ - if (isc_dsql_sql_info(H->isc_status, &stmt, sizeof(info_count), const_cast(info_count), - sizeof(result), result)) { - RECORD_ERROR(dbh); - return -1; - } - - if (result[0] == isc_info_sql_records) { - unsigned i = 3, result_size = isc_vax_integer(&result[1],2); - - while (result[i] != isc_info_end && i < result_size) { - short len = (short)isc_vax_integer(&result[i+1],2); - if (result[i] != isc_info_req_select_count) { - ret += isc_vax_integer(&result[i+3],len); - } - i += len+3; - } - } - - /* commit if we're in auto_commit mode */ - if (dbh->auto_commit && isc_commit_retaining(H->isc_status, &H->tr)) { - RECORD_ERROR(dbh); - } - - return ret; -} -/* }}} */ - -/* called by the PDO SQL parser to add quotes to values that are copied into SQL */ -static int firebird_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, /* {{{ */ - char **quoted, int *quotedlen TSRMLS_DC) -{ - int qcount = 0; - char const *c; - - /* Firebird only requires single quotes to be doubled if string lengths are used */ - - /* count the number of ' characters */ - for (c = unquoted; (c = strchr(c,'\'')); qcount++, c++); - - if (!qcount) { - return 0; - } else { - char const *l, *r; - char *c; - - *quotedlen = unquotedlen + qcount; - *quoted = c = emalloc(*quotedlen+1); - - /* foreach (chunk that ends in a quote) */ - for (l = unquoted; (r = strchr(l,'\'')); l = r+1) { - - /* copy the chunk */ - strncpy(c, l, r-l); - c += (r-l); - - /* add the second quote */ - *c++ = '\''; - } - - /* copy the remainder */ - strncpy(c, l, *quotedlen-(c-*quoted)); - - return 1; - } -} -/* }}} */ - -/* called by PDO to start a transaction */ -static int firebird_handle_begin(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */ -{ - pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; - char tpb[8] = { isc_tpb_version3 }, *ptpb = tpb+1; -#if abies_0 - if (dbh->transaction_flags & PDO_TRANS_ISOLATION_LEVEL) { - if (dbh->transaction_flags & PDO_TRANS_READ_UNCOMMITTED) { - /* this is a poor fit, but it's all we have */ - *ptpb++ = isc_tpb_read_committed; - *ptpb++ = isc_tpb_rec_version; - dbh->transaction_flags &= ~(PDO_TRANS_ISOLATION_LEVEL^PDO_TRANS_READ_UNCOMMITTED); - } else if (dbh->transaction_flags & PDO_TRANS_READ_COMMITTED) { - *ptpb++ = isc_tpb_read_committed; - *ptpb++ = isc_tpb_no_rec_version; - dbh->transaction_flags &= ~(PDO_TRANS_ISOLATION_LEVEL^PDO_TRANS_READ_COMMITTED); - } else if (dbh->transaction_flags & PDO_TRANS_REPEATABLE_READ) { - *ptpb++ = isc_tpb_concurrency; - dbh->transaction_flags &= ~(PDO_TRANS_ISOLATION_LEVEL^PDO_TRANS_REPEATABLE_READ); - } else { - *ptpb++ = isc_tpb_consistency; - dbh->transaction_flags &= ~(PDO_TRANS_ISOLATION_LEVEL^PDO_TRANS_SERIALIZABLE); - } - } - - if (dbh->transaction_flags & PDO_TRANS_ACCESS_MODE) { - if (dbh->transaction_flags & PDO_TRANS_READONLY) { - *ptpb++ = isc_tpb_read; - dbh->transaction_flags &= ~(PDO_TRANS_ACCESS_MODE^PDO_TRANS_READONLY); - } else { - *ptpb++ = isc_tpb_write; - dbh->transaction_flags &= ~(PDO_TRANS_ACCESS_MODE^PDO_TRANS_READWRITE); - } - } - - if (dbh->transaction_flags & PDO_TRANS_CONFLICT_RESOLUTION) { - if (dbh->transaction_flags & PDO_TRANS_RETRY) { - *ptpb++ = isc_tpb_wait; - dbh->transaction_flags &= ~(PDO_TRANS_CONFLICT_RESOLUTION^PDO_TRANS_RETRY); - } else { - *ptpb++ = isc_tpb_nowait; - dbh->transaction_flags &= ~(PDO_TRANS_CONFLICT_RESOLUTION^PDO_TRANS_ABORT); - } - } -#endif - if (isc_start_transaction(H->isc_status, &H->tr, 1, &H->db, (unsigned short)(ptpb-tpb), tpb)) { - RECORD_ERROR(dbh); - return 0; - } - return 1; -} -/* }}} */ - -/* called by PDO to commit a transaction */ -static int firebird_handle_commit(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */ -{ - pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; - - if (isc_commit_transaction(H->isc_status, &H->tr)) { - RECORD_ERROR(dbh); - return 0; - } - return 1; -} -/* }}} */ - -/* called by PDO to rollback a transaction */ -static int firebird_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */ -{ - pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; - - if (isc_rollback_transaction(H->isc_status, &H->tr)) { - RECORD_ERROR(dbh); - return 0; - } - return 1; -} -/* }}} */ - -/* used by prepare and exec to allocate a statement handle and prepare the SQL */ -static int firebird_alloc_prepare_stmt(pdo_dbh_t *dbh, const char *sql, long sql_len, /* {{{ */ - XSQLDA *out_sqlda, isc_stmt_handle *s, HashTable *named_params TSRMLS_DC) -{ - pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; - char *c, *new_sql, in_quote, in_param, pname[64], *ppname; - long l, pindex = -1; - - /* Firebird allows SQL statements up to 64k, so bail if it doesn't fit */ - if (sql_len > SHORT_MAX) { - dbh->error_code = PDO_ERR_TRUNCATED; - return 0; - } - - /* start a new transaction implicitly if auto_commit is enabled and no transaction is open */ - if (dbh->auto_commit && !dbh->in_txn) { - /* dbh->transaction_flags = PDO_TRANS_READ_UNCOMMITTED; */ - - if (!firebird_handle_begin(dbh TSRMLS_CC)) { - return 0; - } - dbh->in_txn = 1; - } - - /* allocate the statement */ - if (isc_dsql_allocate_statement(H->isc_status, &H->db, s)) { - RECORD_ERROR(dbh); - return 0; - } - - /* in order to support named params, which Firebird itself doesn't, - we need to replace :foo by ?, and store the name we just replaced */ - new_sql = c = emalloc(sql_len+1); - - for (l = in_quote = in_param = 0; l <= sql_len; ++l) { - if ( !(in_quote ^= (sql[l] == '\''))) { - if (!in_param) { - switch (sql[l]) { - case ':': - in_param = 1; - ppname = pname; - case '?': - *c++ = '?'; - ++pindex; - continue; - } - } else { - if ((in_param &= (sql[l] == '_') || (sql[l] >= 'A' && sql[l] <= 'Z') - || (sql[l] >= 'a' && sql[l] <= 'z') || (sql[l] >= '0' && sql[l] <= '9'))) { - *ppname++ = sql[l]; - continue; - } else { - *ppname++ = 0; - if (named_params) { - zend_hash_update(named_params, pname, (unsigned int)(ppname-pname), - (void*)&pindex, sizeof(long)+1,NULL); - } - } - } - } - *c++ = sql[l]; - } - - /* prepare the statement */ - if (isc_dsql_prepare(H->isc_status, &H->tr, s, 0, new_sql, PDO_FB_DIALECT, out_sqlda)) { - RECORD_ERROR(dbh); - efree(new_sql); - return 0; - } - - efree(new_sql); - return 1; -} -/* }}} */ - -/* called by PDO to set a driver-specific dbh attribute */ -static int firebird_handle_set_attribute(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC) /* {{{ */ -{ - pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; - - switch (attr) { - case PDO_ATTR_AUTOCOMMIT: - - convert_to_boolean(val); - - /* ignore if the new value equals the old one */ - if (dbh->auto_commit ^ Z_BVAL_P(val)) { - if (dbh->in_txn) { - if (Z_BVAL_P(val)) { - /* turning on auto_commit with an open transaction is illegal, because - we won't know what to do with it */ - H->last_app_error = "Cannot enable auto-commit while a transaction is already open"; - return 0; - } else { - /* close the transaction */ - if (!firebird_handle_commit(dbh TSRMLS_CC)) { - break; - } - dbh->in_txn = 0; - } - } - dbh->auto_commit = Z_BVAL_P(val); - } - return 1; - } - return 0; -} -/* }}} */ - -/* callback to used to report database server info */ -static void firebird_info_cb(void *arg, char const *s) /* {{{ */ -{ - if (arg) { - if (*(char*)arg) { /* second call */ - strcat(arg, " "); - } - strcat(arg, s); - } -} -/* }}} */ - -/* called by PDO to get a driver-specific dbh attribute */ -static int firebird_handle_get_attribute(pdo_dbh_t const *dbh, long attr, zval *val TSRMLS_DC) /* {{{ */ -{ - pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; - - switch (attr) { - char tmp[200]; - - case PDO_ATTR_AUTOCOMMIT: - ZVAL_LONG(val,dbh->auto_commit); - return 1; - - case PDO_ATTR_CONNECTION_STATUS: - ZVAL_BOOL(val, !isc_version(&H->db, firebird_info_cb, NULL)); - return 1; - - case PDO_ATTR_CLIENT_VERSION: { -#if defined(__GNUC__) || defined(PHP_WIN32) - info_func_t info_func = NULL; -#ifdef __GNUC__ - info_func = (info_func_t)dlsym(RTLD_DEFAULT, "isc_get_client_version"); -#else - HMODULE l = GetModuleHandle("fbclient"); - - if (!l && !(l = GetModuleHandle("gds32"))) { - break; - } - info_func = (info_func_t)GetProcAddress(l, "isc_get_client_version"); -#endif - if (info_func) { - info_func(tmp); - ZVAL_STRING(val,tmp,1); - } else { - ZVAL_STRING(val,"Firebird 1.0/Interbase 6",1); - } -#else - ZVAL_NULL(val); -#endif - } - return 1; - - case PDO_ATTR_SERVER_VERSION: - case PDO_ATTR_SERVER_INFO: - *tmp = 0; - - if (!isc_version(&H->db, firebird_info_cb, (void*)tmp)) { - ZVAL_STRING(val,tmp,1); - return 1; - } - } - return 0; -} -/* }}} */ - -/* called by PDO to retrieve driver-specific information about an error that has occurred */ -static int pdo_firebird_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC) /* {{{ */ -{ - pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; - ISC_STATUS *s = H->isc_status; - char buf[400]; - long i = 0, l, sqlcode = isc_sqlcode(s); - - if (sqlcode) { - add_next_index_long(info, sqlcode); - - while ((l = isc_interprete(&buf[i],&s))) { - i += l; - strcpy(&buf[i++], " "); - } - add_next_index_string(info, buf, 1); - } else { - add_next_index_long(info, -999); - add_next_index_string(info, const_cast(H->last_app_error),1); - } - return 1; -} -/* }}} */ - -static struct pdo_dbh_methods firebird_methods = { /* {{{ */ - firebird_handle_closer, - firebird_handle_preparer, - firebird_handle_doer, - firebird_handle_quoter, - firebird_handle_begin, - firebird_handle_commit, - firebird_handle_rollback, - firebird_handle_set_attribute, - NULL, /* last_id not supported */ - pdo_firebird_fetch_error_func, - firebird_handle_get_attribute, -}; -/* }}} */ - -/* the driver-specific PDO handle constructor */ -static int pdo_firebird_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */ -{ - struct pdo_data_src_parser vars[] = { - { "dbname", NULL, 0 }, - { "charset", NULL, 0 }, - { "role", NULL, 0 } - }; - int i, ret = 0; - pdo_firebird_db_handle *H = dbh->driver_data = pecalloc(1,sizeof(*H),dbh->is_persistent); - - php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 2); - - do { - static char const dpb_flags[] = { - isc_dpb_user_name, isc_dpb_password, isc_dpb_lc_ctype, isc_dpb_sql_role_name }; - char const *dpb_values[] = { dbh->username, dbh->password, vars[1].optval, vars[2].optval }; - char dpb_buffer[256] = { isc_dpb_version1 }, *dpb; - - dpb = dpb_buffer + 1; - - /* loop through all the provided arguments and set dpb fields accordingly */ - for (i = 0; i < sizeof(dpb_flags); ++i) { - if (dpb_values[i]) { - dpb += sprintf(dpb, "%c%c%s", dpb_flags[i], (unsigned char)strlen(dpb_values[i]), - dpb_values[i]); - } - } - - /* fire it up baby! */ - if (isc_attach_database(H->isc_status, 0, vars[0].optval, &H->db,(short)(dpb-dpb_buffer), - dpb_buffer)) { - break; - } - - dbh->methods = &firebird_methods; - dbh->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL; - dbh->native_case = PDO_CASE_UPPER; - dbh->alloc_own_columns = 1; - - ret = 1; - - } while (0); - - for (i = 0; i < sizeof(vars)/sizeof(vars[0]); ++i) { - if (vars[i].freeme) { - efree(vars[i].optval); - } - } - - if (!ret) { - firebird_handle_closer(dbh TSRMLS_CC); - } - - return ret; -} -/* }}} */ - -pdo_driver_t pdo_firebird_driver = { /* {{{ */ - PDO_DRIVER_HEADER(firebird), - pdo_firebird_handle_factory -}; -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c deleted file mode 100644 index ee325453ec97..000000000000 --- a/ext/pdo_firebird/firebird_statement.c +++ /dev/null @@ -1,696 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Ard Biesheuvel | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "pdo/php_pdo.h" -#include "pdo/php_pdo_driver.h" -#include "php_pdo_firebird.h" -#include "php_pdo_firebird_int.h" - -#include - -#define RECORD_ERROR(stmt) _firebird_error(NULL, stmt, __FILE__, __LINE__ TSRMLS_CC) - -/* free the allocated space for passing field values to the db and back */ -static void free_sqlda(XSQLDA const *sqlda) /* {{{ */ -{ - int i; - - for (i = 0; i < sqlda->sqld; ++i) { - XSQLVAR const *var = &sqlda->sqlvar[i]; - - if (var->sqlind) { - efree(var->sqlind); - } - } -} -/* }}} */ - -/* called by PDO to clean up a statement handle */ -static int firebird_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */ -{ - pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data; - int result = 1, i; - - /* release the statement */ - if (isc_dsql_free_statement(S->H->isc_status, &S->stmt, DSQL_drop)) { - RECORD_ERROR(stmt); - result = 0; - } - - /* clean up the fetch buffers if they have been used */ - for (i = 0; i < S->out_sqlda.sqld; ++i) { - if (S->fetch_buf[i]) { - efree(S->fetch_buf[i]); - } - } - efree(S->fetch_buf); - - zend_hash_destroy(S->named_params); - FREE_HASHTABLE(S->named_params); - - /* clean up the input descriptor */ - if (S->in_sqlda) { - free_sqlda(S->in_sqlda); - efree(S->in_sqlda); - } - - free_sqlda(&S->out_sqlda); - efree(S); - - return result; -} -/* }}} */ - -/* called by PDO to execute a prepared query */ -static int firebird_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */ -{ - pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data; - pdo_firebird_db_handle *H = S->H; - - do { - /* named cursors should be closed first */ - if (*S->name && isc_dsql_free_statement(H->isc_status, &S->stmt, DSQL_close)) { - break; - } - - /* assume all params have been bound */ - - if ((S->statement_type == isc_info_sql_stmt_exec_procedure && - isc_dsql_execute2(H->isc_status, &H->tr, &S->stmt, PDO_FB_SQLDA_VERSION, - S->in_sqlda, &S->out_sqlda)) - || isc_dsql_execute(H->isc_status, &H->tr, &S->stmt, PDO_FB_SQLDA_VERSION, - S->in_sqlda)) { - break; - } - - /* commit? */ - if (stmt->dbh->auto_commit && isc_commit_retaining(H->isc_status, &H->tr)) { - break; - } - - *S->name = 0; - S->exhausted = 0; - - return 1; - } while (0); - - RECORD_ERROR(stmt); - - return 0; -} -/* }}} */ - -/* called by PDO to fetch the next row from a statement */ -static int firebird_stmt_fetch(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */ -{ - pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data; - pdo_firebird_db_handle *H = S->H; - - if (!stmt->executed) { - stmt->error_code = PDO_ERR_CANT_MAP; - H->last_app_error = "Cannot fetch from a closed cursor"; - } else if (!S->exhausted) { - - /* an EXECUTE PROCEDURE statement can be fetched from once, without calling the API, because - * the result was returned in the execute call */ - if (S->statement_type == isc_info_sql_stmt_exec_procedure) { - S->exhausted = 1; - } else { - if (isc_dsql_fetch(H->isc_status, &S->stmt, PDO_FB_SQLDA_VERSION, &S->out_sqlda)) { - if (H->isc_status[0] && H->isc_status[1]) { - RECORD_ERROR(stmt); - } - S->exhausted = 1; - return 0; - } - } - return 1; - } - return 0; -} -/* }}} */ - -/* called by PDO to retrieve information about the fields being returned */ -static int firebird_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC) /* {{{ */ -{ - pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data; - struct pdo_column_data *col = &stmt->columns[colno]; - XSQLVAR *var = &S->out_sqlda.sqlvar[colno]; - - /* allocate storage for the column */ - var->sqlind = (void*)emalloc(var->sqllen + 2*sizeof(short)); - var->sqldata = &((char*)var->sqlind)[sizeof(short)]; - - col->precision = -var->sqlscale; - col->maxlen = var->sqllen; - col->namelen = var->aliasname_length; - col->name = estrndup(var->aliasname,var->aliasname_length); - - return 1; -} -/* }}} */ - -#if abies_0 -/* internal function to override return types of parameters */ -static void set_param_type(enum pdo_param_type *param_type, XSQLVAR const *var) /* {{{ */ -{ - /* set the param type after the field type */ - switch (var->sqltype & ~1) { - case SQL_INT64: -#if SIZEOF_LONG < 8 - if (0) /* always a string if its size exceeds native long */ -#endif - case SQL_SHORT: - case SQL_LONG: - if (var->sqlscale == 0) { - *param_type = PDO_PARAM_INT; - break; - } - case SQL_TEXT: - case SQL_VARYING: - case SQL_TYPE_DATE: - case SQL_TYPE_TIME: - case SQL_TIMESTAMP: - case SQL_BLOB: - *param_type = PDO_PARAM_STR; - break; - case SQL_FLOAT: - case SQL_DOUBLE: - *param_type = PDO_PARAM_DBL; - break; - } -} -/* }}} */ -#endif - -#define FETCH_BUF(buf,type,len,lenvar) ((buf) = (buf) ? (buf) : \ - emalloc((len) ? (len * sizeof(type)) : ((*(unsigned long*)lenvar) = sizeof(type)))) - -/* fetch a blob into a fetch buffer */ -static int firebird_fetch_blob(pdo_stmt_t *stmt, int colno, char **ptr, /* {{{ */ - unsigned long *len, ISC_QUAD *blob_id TSRMLS_DC) -{ - pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data; - pdo_firebird_db_handle *H = S->H; - isc_blob_handle blobh = NULL; - char const bl_item = isc_info_blob_total_length; - char bl_info[20]; - unsigned short i; - int result = *len = 0; - - if (isc_open_blob(H->isc_status, &H->db, &H->tr, &blobh, blob_id)) { - RECORD_ERROR(stmt); - return 0; - } - - if (isc_blob_info(H->isc_status, &blobh, 1, const_cast(&bl_item), - sizeof(bl_info), bl_info)) { - RECORD_ERROR(stmt); - goto fetch_blob_end; - } - - /* find total length of blob's data */ - for (i = 0; i < sizeof(bl_info); ) { - unsigned short item_len; - char item = bl_info[i++]; - - if (item == isc_info_end || item == isc_info_truncated || item == isc_info_error - || i >= sizeof(bl_info)) { - H->last_app_error = "Couldn't determine BLOB size"; - goto fetch_blob_end; - } - - item_len = (unsigned short) isc_vax_integer(&bl_info[i], 2); - - if (item == isc_info_blob_total_length) { - *len = isc_vax_integer(&bl_info[i+2], item_len); - break; - } - i += item_len+2; - } - - /* we've found the blob's length, now fetch! */ - - if (*len) { - unsigned long cur_len; - unsigned short seg_len; - ISC_STATUS stat; - - *ptr = S->fetch_buf[colno] = erealloc(*ptr, *len+1); - - for (cur_len = stat = 0; (!stat || stat == isc_segment) && cur_len < *len; cur_len += seg_len) { - - unsigned short chunk_size = (*len-cur_len) > USHRT_MAX ? USHRT_MAX - : (unsigned short)(*len-cur_len); - - stat = isc_get_segment(H->isc_status, &blobh, &seg_len, chunk_size, &(*ptr)[cur_len]); - } - - (*ptr)[*len++] = '\0'; - - if (H->isc_status[0] == 1 && (stat != 0 && stat != isc_segstr_eof && stat != isc_segment)) { - H->last_app_error = "Error reading from BLOB"; - goto fetch_blob_end; - } - } - result = 1; - -fetch_blob_end: - if (isc_close_blob(H->isc_status, &blobh)) { - RECORD_ERROR(stmt); - return 0; - } - return result; -} -/* }}} */ - -static int firebird_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, /* {{{ */ - unsigned long *len TSRMLS_DC) -{ - pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data; - XSQLVAR const *var = &S->out_sqlda.sqlvar[colno]; - - if (*var->sqlind == -1) { - /* A NULL value */ - *ptr = NULL; - *len = 0; - } else { - /* override the column param type */ - /* set_param_type(&stmt->columns[colno].param_type,var); */ - stmt->columns[colno].param_type = PDO_PARAM_STR; - - if (var->sqlscale < 0) { - static ISC_INT64 const scales[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, - 100000000, 1000000000, 1000000000, LL_LIT(10000000000),LL_LIT(100000000000), - LL_LIT(10000000000000), LL_LIT(100000000000000),LL_LIT(1000000000000000), - LL_LIT(1000000000000000),LL_LIT(1000000000000000000) }; - ISC_INT64 n, f = scales[-var->sqlscale]; - - switch (var->sqltype & ~1) { - case SQL_SHORT: - n = *(short*)var->sqldata; - break; - case SQL_LONG: - n = *(ISC_LONG*)var->sqldata; - break; - case SQL_INT64: - n = *(ISC_INT64*)var->sqldata; - } - - *ptr = FETCH_BUF(S->fetch_buf[colno], char, 24, NULL); - - if (n >= 0) { - *len = sprintf(*ptr, "%" LL_MASK "d.%0*" LL_MASK "d", - n / f, -var->sqlscale, n % f); - } else if (n < -f) { - *len = sprintf(*ptr, "%" LL_MASK "d.%0*" LL_MASK "d", - n / f, -var->sqlscale, -n % f); - } else { - *len = sprintf(*ptr, "-0.%0*" LL_MASK "d", -var->sqlscale, -n % f); - } - } else { - switch (var->sqltype & ~1) { - struct tm t; - char *fmt; - -/** -* For the time being, this code has been changed to convert every returned value to a string -* before passing it back up to the PDO driver. -*/ - - case SQL_VARYING: - *ptr = &var->sqldata[2]; - *len = *(short*)var->sqldata; - break; - case SQL_TEXT: - *ptr = var->sqldata; - *len = var->sqllen; - break; -// --- cut here --- - case SQL_SHORT: - *ptr = FETCH_BUF(S->fetch_buf[colno], char, 24, NULL); - *len = sprintf(*ptr, "%d", *(short*)var->sqldata); - break; - case SQL_LONG: - *ptr = FETCH_BUF(S->fetch_buf[colno], char, 24, NULL); - *len = sprintf(*ptr, "%ld", *(ISC_LONG*)var->sqldata); - break; - case SQL_INT64: - *ptr = FETCH_BUF(S->fetch_buf[colno], char, 24, NULL); - *len = sprintf(*ptr, "%" LL_MASK "d", *(ISC_INT64*)var->sqldata); - break; - case SQL_FLOAT: - *ptr = FETCH_BUF(S->fetch_buf[colno], char, 24, NULL); - *len = sprintf(*ptr, "%f", *(float*)var->sqldata); - break; - case SQL_DOUBLE: - *ptr = FETCH_BUF(S->fetch_buf[colno], char, 24, NULL); - *len = sprintf(*ptr, "%f" , *(double*)var->sqldata); - break; -// --- cut here --- -#if abies_0 - case SQL_SHORT: - *ptr = FETCH_BUF(S->fetch_buf[colno], long, 0, *len); - *(long*)*ptr = *(short*)var->sqldata; - break; - case SQL_LONG: -#if SIZEOF_LONG == 8 - *ptr = FETCH_BUF(S->fetch_buf[colno], long, 0, *len); - *(long*)*ptr = *(ISC_LONG*)var->sqldata; -#else - *ptr = var->sqldata; -#endif - break; - case SQL_INT64: - *len = sizeof(long); -#if SIZEOF_LONG == 8 - *ptr = var->sqldata; -#else - *ptr = FETCH_BUF(S->fetch_buf[colno], char, 20, NULL); - *len = sprintf(*ptr, "%" LL_MASK "d", *(ISC_INT64*)var->sqldata); -#endif - break; - case SQL_FLOAT: - *ptr = FETCH_BUF(S->fetch_buf[colno], double, 0, *len); - *(double*)*ptr = *(float*)var->sqldata; - break; - case SQL_DOUBLE: - *ptr = var->sqldata; - *len = sizeof(double); - break; -#endif - case SQL_TYPE_DATE: - isc_decode_sql_date((ISC_DATE*)var->sqldata, &t); - fmt = INI_STR("ibase.dateformat"); - if (0) { - case SQL_TYPE_TIME: - isc_decode_sql_time((ISC_TIME*)var->sqldata, &t); - fmt = INI_STR("ibase.timeformat"); - } else if (0) { - case SQL_TIMESTAMP: - isc_decode_timestamp((ISC_TIMESTAMP*)var->sqldata, &t); - fmt = INI_STR("ibase.timestampformat"); - } - - /* convert the timestamp into a string */ - *ptr = FETCH_BUF(S->fetch_buf[colno], char, *len = 80, NULL); - *len = strftime(*ptr, *len, fmt, &t); - break; - case SQL_BLOB: - return firebird_fetch_blob(stmt,colno,ptr,len, - (ISC_QUAD*)var->sqldata TSRMLS_CC); - } - } - } - return 1; -} -/* }}} */ - -static int firebird_bind_blob(pdo_stmt_t *stmt, ISC_QUAD *blob_id, zval *param TSRMLS_DC) -{ - pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data; - pdo_firebird_db_handle *H = S->H; - isc_blob_handle h = NULL; - unsigned long put_cnt = 0, rem_cnt; - unsigned short chunk_size; - int result = 1; - - if (isc_create_blob(H->isc_status, &H->db, &H->tr, &h, blob_id)) { - RECORD_ERROR(stmt); - return 0; - } - - SEPARATE_ZVAL(¶m); - - convert_to_string_ex(¶m); - - for (rem_cnt = Z_STRLEN_P(param); rem_cnt > 0; rem_cnt -= chunk_size) { - - chunk_size = rem_cnt > USHRT_MAX ? USHRT_MAX : (unsigned short)rem_cnt; - - if (isc_put_segment(H->isc_status, &h, chunk_size, &Z_STRVAL_P(param)[put_cnt])) { - RECORD_ERROR(stmt); - result = 0; - break; - } - put_cnt += chunk_size; - } - - zval_dtor(param); - - if (isc_close_blob(H->isc_status, &h)) { - RECORD_ERROR(stmt); - return 0; - } - return result; -} - -static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param, /* {{{ */ - enum pdo_param_event event_type TSRMLS_DC) -{ - pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data; - XSQLDA *sqlda = param->is_param ? S->in_sqlda : &S->out_sqlda; - XSQLVAR *var; - - if (event_type == PDO_PARAM_EVT_FREE) { /* not used */ - return 1; - } - - if (!sqlda || param->paramno >= sqlda->sqld) { - stmt->error_code = PDO_ERR_NOT_FOUND; - S->H->last_app_error = "Invalid parameter index"; - return 0; - } - if (param->is_param && param->paramno == -1) { - long *index; - - /* try to determine the index by looking in the named_params hash */ - if (SUCCESS == zend_hash_find(S->named_params, param->name, param->namelen+1, (void*)&index)) { - param->paramno = *index; - } else { - /* ... or by looking in the input descriptor */ - int i; - - for (i = 0; i < sqlda->sqld; ++i) { - XSQLVAR *var = &sqlda->sqlvar[i]; - - if ((var->aliasname_length && !strncasecmp(param->name, var->aliasname, - min(param->namelen, var->aliasname_length))) - || (var->sqlname_length && !strncasecmp(param->name, var->sqlname, - min(param->namelen, var->sqlname_length)))) { - param->paramno = i; - break; - } - } - if (i >= sqlda->sqld) { - stmt->error_code = PDO_ERR_NOT_FOUND; - S->H->last_app_error = "Invalid parameter name"; - return 0; - } - } - } - - var = &sqlda->sqlvar[param->paramno]; - - switch (event_type) { - char *value; - unsigned long value_len; - - case PDO_PARAM_EVT_ALLOC: - if (param->is_param) { - /* allocate the parameter */ - var->sqlind = (void*)emalloc(var->sqllen + 2*sizeof(short)); - var->sqldata = &((char*)var->sqlind)[sizeof(short)]; - } - break; - - case PDO_PARAM_EVT_EXEC_PRE: - if (!param->is_param) { - break; - } - - *var->sqlind = 0; - - switch (var->sqltype & ~1) { - case SQL_ARRAY: - stmt->error_code = PDO_ERR_NOT_IMPLEMENTED; - S->H->last_app_error = "Cannot bind to array field"; - return 0; - - case SQL_BLOB: - return firebird_bind_blob(stmt, (ISC_QUAD*)var->sqldata, - param->parameter TSRMLS_CC); - } - - /* check if a NULL should be inserted */ - switch (Z_TYPE_P(param->parameter)) { - int force_null; - - case IS_LONG: - var->sqltype = sizeof(long) == 8 ? SQL_INT64 : SQL_LONG; - var->sqldata = (void*)&Z_LVAL_P(param->parameter); - var->sqllen = sizeof(long); - break; - case IS_DOUBLE: - var->sqltype = SQL_DOUBLE; - var->sqldata = (void*)&Z_DVAL_P(param->parameter); - var->sqllen = sizeof(double); - break; - case IS_STRING: - force_null = 0; - - /* for these types, an empty string can be handled like a NULL value */ - switch (var->sqltype & ~1) { - case SQL_SHORT: - case SQL_LONG: - case SQL_INT64: - case SQL_FLOAT: - case SQL_DOUBLE: - case SQL_TIMESTAMP: - case SQL_TYPE_DATE: - case SQL_TYPE_TIME: - force_null = (Z_STRLEN_P(param->parameter) == 0); - } - if (!force_null) { - var->sqltype = SQL_TEXT; - var->sqldata = Z_STRVAL_P(param->parameter); - var->sqllen = Z_STRLEN_P(param->parameter); - break; - } - case IS_NULL: - /* complain if this field doesn't allow NULL values */ - if (~var->sqltype & 1) { - stmt->error_code = PDO_ERR_CONSTRAINT; - S->H->last_app_error = "Parameter requires non-null value"; - return 0; - } - *var->sqlind = -1; - break; - default: - stmt->error_code = PDO_ERR_NOT_IMPLEMENTED; - S->H->last_app_error = "Binding arrays/objects is not supported"; - return 0; - } - break; - - case PDO_PARAM_EVT_FETCH_POST: - value = NULL; - value_len = 0; - - if (firebird_stmt_get_col(stmt, param->paramno, &value, &value_len TSRMLS_CC)) { - switch (param->param_type) { - case PDO_PARAM_STR: - if (value) { - ZVAL_STRINGL(param->parameter, value, value_len, 1); - break; - } - case PDO_PARAM_INT: - if (value) { - ZVAL_LONG(param->parameter, *(long*)value); - break; - } -#if abies_0 - case PDO_PARAM_DBL: - if (value) { - ZVAL_DOUBLE(param->parameter, *(double*)value); - break; - } -#endif - default: - ZVAL_NULL(param->parameter); - } - return 1; - } - return 0; - default: - ; - } - return 1; -} -/* }}} */ - -static int firebird_stmt_set_attribute(pdo_stmt_t *stmt, long attr, zval *val TSRMLS_DC) /* {{{ */ -{ - pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data; - - switch (attr) { - default: - return 0; - case PDO_ATTR_CURSOR_NAME: - convert_to_string(val); - - if (isc_dsql_set_cursor_name(S->H->isc_status, &S->stmt, Z_STRVAL_P(val),0)) { - RECORD_ERROR(stmt); - return 0; - } - strncpy(S->name, Z_STRVAL_P(val), sizeof(S->name)); - S->name[sizeof(S->name)] = 0; - break; - } - return 1; -} -/* }}} */ - -static int firebird_stmt_get_attribute(pdo_stmt_t *stmt, long attr, zval *val TSRMLS_DC) /* {{{ */ -{ - pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data; - - switch (attr) { - default: - return 0; - case PDO_ATTR_CURSOR_NAME: - if (*S->name) { - ZVAL_STRING(val,S->name,1); - } else { - ZVAL_NULL(val); - } - break; - } - return 1; -} -/* }}} */ - -struct pdo_stmt_methods firebird_stmt_methods = { /* {{{ */ - firebird_stmt_dtor, - firebird_stmt_execute, - firebird_stmt_fetch, - firebird_stmt_describe, - firebird_stmt_get_col, - firebird_stmt_param_hook, - firebird_stmt_set_attribute, - firebird_stmt_get_attribute -}; -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo_firebird/package.xml b/ext/pdo_firebird/package.xml deleted file mode 100644 index 92973b9b121b..000000000000 --- a/ext/pdo_firebird/package.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - PDO_FIREBIRD - Firebird/InterBase 6 driver for PDO - - - abies - Ard Biesheuvel - abies@php.net - lead - - - - - - - This extension provides a Firebird/InterBase driver for PDO. It supports - all versions of Firebird and InterBase versions 6 and up. - - PHP - - alpha - 0.1 - 2004-06-23 - - - To compile and run this module, you will need to have the main PDO module and Firebird's - or InterBase's client library installed on your system. - - - - - - - - - - - - - - - connect.phpt - ddl.phpt - execute.phpt - - - - - - - - - diff --git a/ext/pdo_firebird/pdo_firebird.c b/ext/pdo_firebird/pdo_firebird.c deleted file mode 100644 index 4e635469428f..000000000000 --- a/ext/pdo_firebird/pdo_firebird.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Ard Biesheuvel | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "pdo/php_pdo.h" -#include "pdo/php_pdo_driver.h" -#include "php_pdo_firebird.h" -#include "php_pdo_firebird_int.h" - -function_entry pdo_firebird_functions[] = { /* {{{ */ - {NULL, NULL, NULL} -}; -/* }}} */ - -zend_module_entry pdo_firebird_module_entry = { /* {{{ */ - STANDARD_MODULE_HEADER, - "PDO_Firebird", - pdo_firebird_functions, - PHP_MINIT(pdo_firebird), - PHP_MSHUTDOWN(pdo_firebird), - NULL, - NULL, - PHP_MINFO(pdo_firebird), - "0.1", - STANDARD_MODULE_PROPERTIES -}; -/* }}} */ - -#ifdef COMPILE_DL_PDO_FIREBIRD -ZEND_GET_MODULE(pdo_firebird) -#endif - -PHP_MINIT_FUNCTION(pdo_firebird) /* {{{ */ -{ - php_pdo_register_driver(&pdo_firebird_driver); - - return SUCCESS; -} -/* }}} */ - -PHP_MSHUTDOWN_FUNCTION(pdo_firebird) /* {{{ */ -{ - php_pdo_unregister_driver(&pdo_firebird_driver); - - return SUCCESS; -} -/* }}} */ - -PHP_MINFO_FUNCTION(pdo_firebird) /* {{{ */ -{ - php_info_print_table_start(); - php_info_print_table_header(2, "PDO Driver for Firebird/InterBase", "enabled"); - php_info_print_table_end(); -} -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo_firebird/php_pdo_firebird.h b/ext/pdo_firebird/php_pdo_firebird.h deleted file mode 100644 index 83b2e9304a26..000000000000 --- a/ext/pdo_firebird/php_pdo_firebird.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Ard Biesheuvel | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifndef PHP_PDO_FIREBIRD_H -#define PHP_PDO_FIREBIRD_H - -extern zend_module_entry pdo_firebird_module_entry; -#define phpext_pdo_firebird_ptr &pdo_firebird_module_entry - -#ifdef PHP_WIN32 -# ifdef PDO_FIREBIRD_EXPORTS -# define PDO_FB_API __declspec(dllexport) -# elif defined(COMPILE_DL_PDO_FIREBIRD) -# define PDO_FB_API __declspec(dllimport) -# else -# define PDO_FB_API -# endif -#else -# define PDO_FB_API -#endif - -#ifdef ZTS -#include "TSRM.h" -#endif - -PHP_MINIT_FUNCTION(pdo_firebird); -PHP_MSHUTDOWN_FUNCTION(pdo_firebird); -PHP_RINIT_FUNCTION(pdo_firebird); -PHP_RSHUTDOWN_FUNCTION(pdo_firebird); -PHP_MINFO_FUNCTION(pdo_firebird); - -#endif /* PHP_PDO_FIREBIRD_H */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo_firebird/php_pdo_firebird_int.h b/ext/pdo_firebird/php_pdo_firebird_int.h deleted file mode 100644 index 7e0e2e66a81a..000000000000 --- a/ext/pdo_firebird/php_pdo_firebird_int.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Ard Biesheuvel | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifndef PHP_PDO_FIREBIRD_INT_H -#define PHP_PDO_FIREBIRD_INT_H - -#include - -#ifdef SQLDA_VERSION -#define PDO_FB_SQLDA_VERSION SQLDA_VERSION -#else -#define PDO_FB_SQLDA_VERSION 1 -#endif - -#define PDO_FB_DIALECT 3 - -#define SHORT_MAX (1 << (8*sizeof(short)-1)) - -#if SIZEOF_LONG == 8 -# define LL_MASK l -# define LL_LIT(lit) lit ## L -#else -# ifdef PHP_WIN32 -# define LL_MASK "I64" -# define LL_LIT(lit) lit ## I64 -# else -# define LL_MASK "ll" -# define LL_LIT(lit) lit ## LL -# endif -#endif - -/* Firebird API has a couple of missing const decls in its API */ -#define const_cast(s) ((char*)(s)) - -#ifdef PHP_WIN32 -typedef void (__stdcall *info_func_t)(char*); -#else -typedef void (*info_func_t)(char*); -#endif - -#ifndef min -#define min(a,b) ((a)<(b)?(a):(b)) -#endif - -typedef struct { - - /* the result of the last API call */ - ISC_STATUS isc_status[20]; - - /* the connection handle */ - isc_db_handle db; - - /* the transaction handle */ - isc_tr_handle tr; - - /* the last error that didn't come from the API */ - char const *last_app_error; - -} pdo_firebird_db_handle; - - -typedef struct { - - /* the link that owns this statement */ - pdo_firebird_db_handle *H; - - /* the statement handle */ - isc_stmt_handle stmt; - - /* the name of the cursor (if it has one) */ - char name[32]; - - /* the type of statement that was issued */ - char statement_type:8; - - /* whether EOF was reached for this statement */ - unsigned exhausted:1; - - unsigned _reserved:23; - - /* the named params that were converted to ?'s by the driver */ - HashTable *named_params; - - /* allocated space to convert fields values to other types */ - char **fetch_buf; - - /* the input SQLDA */ - XSQLDA *in_sqlda; - - /* the output SQLDA */ - XSQLDA out_sqlda; /* last member */ - -} pdo_firebird_stmt; - -extern pdo_driver_t pdo_firebird_driver; - -extern struct pdo_stmt_methods firebird_stmt_methods; - -void _firebird_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, char const *file, long line TSRMLS_DC); - -#endif /* PHP_PDO_FIREBIRD_INT_H */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo_firebird/tests/connect.phpt b/ext/pdo_firebird/tests/connect.phpt deleted file mode 100644 index e4bb8ef54eac..000000000000 --- a/ext/pdo_firebird/tests/connect.phpt +++ /dev/null @@ -1,16 +0,0 @@ ---TEST-- -PDO_Firebird: connect/disconnect ---SKIPIF-- - ---FILE-- - ---EXPECT-- -done diff --git a/ext/pdo_firebird/tests/ddl.phpt b/ext/pdo_firebird/tests/ddl.phpt deleted file mode 100644 index 7709bb3f078f..000000000000 --- a/ext/pdo_firebird/tests/ddl.phpt +++ /dev/null @@ -1,37 +0,0 @@ ---TEST-- -PDO_Firebird: DDL/transactions ---SKIPIF-- - ---FILE-- -setAttribute(PDO_ATTR_ERRMODE, PDO_ERRMODE_WARNING); - - $db->exec("CREATE TABLE ddl (id INT NOT NULL PRIMARY KEY, text BLOB SUB_TYPE 1)"); - $db->exec("CREATE GENERATOR gen_ddl_id"); - $db->exec("CREATE TRIGGER ddl_bi FOR ddl BEFORE INSERT AS - BEGIN IF (NEW.id IS NULL) THEN NEW.id=GEN_ID(gen_ddl_id,1); END"); - - $db->setAttribute(PDO_ATTR_AUTOCOMMIT,0); - - $db->beginTransaction(); - var_dump($db->exec("INSERT INTO ddl (text) VALUES ('bla')")); - var_dump($db->exec("UPDATE ddl SET text='blabla'")); - $db->rollback(); - - $db->beginTransaction(); - var_dump($db->exec("DELETE FROM ddl")); - $db->commit(); - - unset($db); - echo "done\n"; - -?> ---EXPECT-- -int(1) -int(1) -int(0) -done diff --git a/ext/pdo_firebird/tests/execute.phpt b/ext/pdo_firebird/tests/execute.phpt deleted file mode 100644 index 89750483255f..000000000000 --- a/ext/pdo_firebird/tests/execute.phpt +++ /dev/null @@ -1,65 +0,0 @@ ---TEST-- -PDO_Firebird: prepare/execute/binding ---SKIPIF-- - ---INI-- -ibase.timestampformat=%Y-%m-%d %H:%M:%S ---FILE-- -getAttribute(PDO_ATTR_CONNECTION_STATUS)); - - $db->setAttribute(PDO_ATTR_ERRMODE, PDO_ERRMODE_WARNING); - - $db->exec("CREATE TABLE ddl (id SMALLINT NOT NULL PRIMARY KEY, text VARCHAR(32), - datetime TIMESTAMP DEFAULT '2000-02-12' NOT NULL)"); - $db->exec("INSERT INTO ddl (id,text) VALUES (1,'bla')"); - - $s = $db->prepare("SELECT * FROM ddl WHERE id=? FOR UPDATE"); - - $s->bindParam(1,$id = 0); - $s->bindColumn("TEXT",$var = null); - $id = 1; - $s->execute(); - $s->setAttribute(PDO_ATTR_CURSOR_NAME, "c"); - - var_dump($id); - - var_dump($s->fetch()); - - var_dump($var); - - var_dump($db->exec("UPDATE ddl SET id=2 WHERE CURRENT OF c")); - - var_dump($s->fetch()); - - unset($s); - unset($db); - echo "done\n"; - -?> ---EXPECT-- -bool(true) -int(1) -array(6) { - ["ID"]=> - string(1) "1" - [0]=> - string(1) "1" - ["TEXT"]=> - string(3) "bla" - [1]=> - string(3) "bla" - ["DATETIME"]=> - string(19) "2000-02-12 00:00:00" - [2]=> - string(19) "2000-02-12 00:00:00" -} -string(3) "bla" -int(1) -bool(false) -done diff --git a/ext/pdo_firebird/tests/skipif.inc b/ext/pdo_firebird/tests/skipif.inc deleted file mode 100644 index 5a6cd372d108..000000000000 --- a/ext/pdo_firebird/tests/skipif.inc +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/ext/pdo_firebird/tests/testdb.inc b/ext/pdo_firebird/tests/testdb.inc deleted file mode 100644 index f6951a7b1328..000000000000 --- a/ext/pdo_firebird/tests/testdb.inc +++ /dev/null @@ -1,34 +0,0 @@ - | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "pdo/php_pdo.h" -#include "pdo/php_pdo_driver.h" -#include "php_pdo_mysql.h" -#include "php_pdo_mysql_int.h" - -int _pdo_mysql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int line TSRMLS_DC) /* {{{ */ -{ - pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data; - enum pdo_error_type *pdo_err = stmt ? &stmt->error_code : &dbh->error_code; - pdo_mysql_error_info *einfo = &H->einfo; - - einfo->errcode = mysql_errno(H->server); - einfo->file = file; - einfo->line = line; - - if (einfo->errmsg) { - efree(einfo->errmsg); - einfo->errmsg = NULL; - } - - if (einfo->errcode) { - einfo->errmsg = estrdup(mysql_error(H->server)); - } else { /* no error */ - *pdo_err = PDO_ERR_NONE; - return 0; - } - - switch (einfo->errcode) { - case 1007: /* database already exists */ - case 1050: /* table already exists */ - case 1086: /* file already exists */ - case 1125: /* function already exists */ - *pdo_err = PDO_ERR_ALREADY_EXISTS; - break; - - case 1008: /* database does not exist */ - case 1029: /* view does not exist */ - case 1072: /* key column does not exist */ - case 1091: /* column/key does not exist */ - case 1146: /* table does not exist */ - case 1176: /* key not found in table */ - *pdo_err = PDO_ERR_NOT_FOUND; - break; - - case 1152: /* aborted connection */ - case 1154: /* cannot read from connection pipe */ - case 1184: /* aborted new connection */ - case 1159: /* timeout */ - case 1160: /* timeout */ - case 1161: /* timeout */ - *pdo_err = PDO_ERR_DISCONNECTED; - break; - - case 1089: /* unsupported sub-key */ - case 1163: /* blob/text not supported inside table */ - case 1164: /* no auto-incremenet support */ - case 1174: /* no RAID support */ - case 1178: /* table handler does not support something */ - case 1185: /* binary dump not supported */ - case 1214: /* FULLTEXT not supported */ - case 1235: /* something not supported by MySQL version */ - *pdo_err = PDO_ERR_NOT_IMPLEMENTED; - break; - - case 1252: /* character set mismatch */ - *pdo_err = PDO_ERR_MISMATCH; - break; - - case 1264: /* data truncated */ - *pdo_err = PDO_ERR_TRUNCATED; - break; - - case 1169: /* unique constraint */ - case 1216: /* foreign key constraint */ - case 1217: /* foreign key constraint */ - *pdo_err = PDO_ERR_CONSTRAINT; - break; - - case 1064: /* query parse error */ - case 1065: /* empty query */ - /* XXX: MySQL has all sorts of errors that can be considered syntax errors, specifically - dealing with table creation & modifications, do we want to include them here? - */ - *pdo_err = PDO_ERR_SYNTAX; - break; - - default: - *pdo_err = PDO_ERR_CANT_MAP; - break; - } - - if (!dbh->methods) { - zend_throw_exception_ex(php_pdo_get_exception(), *pdo_err TSRMLS_CC, "[%d] %s", - einfo->errcode, einfo->errmsg); - } - - return einfo->errcode; -} -/* }}} */ - -static int pdo_mysql_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC) -{ - pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data; - pdo_mysql_error_info *einfo = &H->einfo; - - if (einfo->errcode) { - add_next_index_long(info, einfo->errcode); - add_next_index_string(info, einfo->errmsg, 1); - } - - return 1; -} - -static int mysql_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */ -{ - pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data; - - if (H) { - if (H->server) { - mysql_close(H->server); - H->server = NULL; - } - if (H->einfo.errmsg) { - efree(H->einfo.errmsg); - H->einfo.errmsg = NULL; - } - efree(H); - H = NULL; - } - return 0; -} -/* }}} */ - -static int mysql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, long options, zval *driver_options TSRMLS_DC) -{ - pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data; - pdo_mysql_stmt *S = ecalloc(1, sizeof(pdo_mysql_stmt)); - - S->H = H; - stmt->driver_data = S; - stmt->methods = &mysql_stmt_methods; - - return 1; -} - -static long mysql_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC) -{ - pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data; - - if (mysql_real_query(H->server, sql, sql_len)) { - pdo_mysql_error(dbh); - return -1; - } else { - return mysql_affected_rows(H->server); - } -} - -static long pdo_mysql_last_insert_id(pdo_dbh_t *dbh TSRMLS_DC) -{ - pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data; - - return (long) mysql_insert_id(H->server); -} - -static int mysql_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen TSRMLS_DC) -{ - pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data; - *quoted = emalloc(2*unquotedlen + 3); - (*quoted)[0] = '"'; - *quotedlen = mysql_real_escape_string(H->server, *quoted + 1, unquoted, unquotedlen); - (*quoted)[*quotedlen + 1] = '"'; - (*quoted)[*quotedlen + 2] = '\0'; - *quotedlen += 2; - return 1; -} - -static int pdo_mysql_get_attribute(pdo_dbh_t *dbh, long attr, zval *return_value TSRMLS_DC) -{ - pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data; - - switch (attr) { - case PDO_ATTR_CLIENT_VERSION: - ZVAL_STRING(return_value, (char *)mysql_get_client_info(), 1); - break; - - case PDO_ATTR_SERVER_VERSION: - ZVAL_STRING(return_value, (char *)mysql_get_server_info(H->server), 1); - break; - - case PDO_ATTR_CONNECTION_STATUS: - ZVAL_STRING(return_value, (char *)mysql_get_host_info(H->server), 1); - break; - - case PDO_ATTR_SERVER_INFO: { - char *tmp; - - if ((tmp = (char *)mysql_stat(H->server))) { - ZVAL_STRING(return_value, tmp, 1); - } else { - pdo_mysql_error(dbh); - return -1; - } - } - break; - - default: - return 0; - } - - return 1; -} - -static struct pdo_dbh_methods mysql_methods = { - mysql_handle_closer, - mysql_handle_preparer, - mysql_handle_doer, - mysql_handle_quoter, - NULL, - NULL, - NULL, - NULL, - pdo_mysql_last_insert_id, - pdo_mysql_fetch_error_func, - pdo_mysql_get_attribute -}; - -#ifndef PDO_MYSQL_UNIX_ADDR -# define PDO_MYSQL_UNIX_ADDR "MySQL" -#endif - -static int pdo_mysql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */ -{ - pdo_mysql_db_handle *H; - int i, ret = 0; - char *host = NULL, *unix_socket = NULL; - unsigned int port; - char *dbname; - struct pdo_data_src_parser vars[] = { - { "charset", NULL, 0 }, - { "dbname", "", 0 }, - { "host", "localhost", 0 }, - { "port", "3306", 0 }, - { "unix_socket", PDO_MYSQL_UNIX_ADDR, 0 }, - }; - - php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 4); - - H = pecalloc(1, sizeof(pdo_mysql_db_handle), dbh->is_persistent); - - H->einfo.errcode = 0; - H->einfo.errmsg = NULL; - - /* allocate an environment */ - - /* handle for the server */ - H->server = mysql_init(NULL); - dbh->driver_data = H; - - /* handle MySQL options */ - if (driver_options) { - long connect_timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, 30 TSRMLS_CC); - - if (mysql_options(H->server, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&connect_timeout)) { - pdo_mysql_error(dbh); - goto cleanup; - } - } - - if (vars[2].optval && strcmp("localhost", vars[2].optval)) { - host = vars[2].optval; - port = atoi(vars[3].optval); - } else { - host = "."; - unix_socket = vars[4].optval; - } - dbname = vars[1].optval; - if (mysql_real_connect(H->server, host, dbh->username, dbh->password, dbname, port, unix_socket, 0) == NULL) { - pdo_mysql_error(dbh); - goto cleanup; - } - - H->attached = 1; - - dbh->methods = &mysql_methods; - dbh->alloc_own_columns = 1; - dbh->supports_placeholders = 0; - dbh->max_escaped_char_length = 2; - - ret = 1; - -cleanup: - for (i = 0; i < sizeof(vars)/sizeof(vars[0]); i++) { - if (vars[i].freeme) { - efree(vars[i].optval); - } - } - - return ret; -} -/* }}} */ - -pdo_driver_t pdo_mysql_driver = { - PDO_DRIVER_HEADER(mysql), - pdo_mysql_handle_factory -}; - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo_mysql/mysql_statement.c b/ext/pdo_mysql/mysql_statement.c deleted file mode 100755 index 0714debe25c7..000000000000 --- a/ext/pdo_mysql/mysql_statement.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: George Schlossnagle | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "pdo/php_pdo.h" -#include "pdo/php_pdo_driver.h" -#include "php_pdo_mysql.h" -#include "php_pdo_mysql_int.h" - - -static int pdo_mysql_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC) -{ - pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data; - int i; - - if (S->result) { - /* free the resource */ - mysql_free_result(S->result); - S->result = NULL; - } - if(S->cols) { - efree(S->cols); - S->cols = NULL; - } - efree(S); - return 1; -} - -static int pdo_mysql_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC) -{ - pdo_dbh_t *dbh = stmt->dbh; - pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data; - pdo_mysql_db_handle *H = S->H; - - if (stmt->executed) { - /* ensure that we free any previous unfetched results */ - if(S->result) { - mysql_free_result(S->result); - S->result = NULL; - } - } - if (mysql_real_query(H->server, stmt->active_query_string, stmt->active_query_stringlen) != 0) { - pdo_mysql_error_stmt(stmt); - return 0; - } - if ((S->result = mysql_use_result(H->server)) == NULL) { - /* could've been INSERT/UPDATE/DELETE query */ - if (!mysql_affected_rows(H->server)) { - pdo_mysql_error_stmt(stmt); - return 0; - } - return 1; - } - if (!stmt->executed) { - stmt->column_count = (int) mysql_num_fields(S->result); - S->cols = ecalloc(stmt->column_count, sizeof(pdo_mysql_column)); - } - return 1; -} - -static int pdo_mysql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param, - enum pdo_param_event event_type TSRMLS_DC) -{ - return 1; -} - -static int pdo_mysql_stmt_fetch(pdo_stmt_t *stmt TSRMLS_DC) -{ - pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data; - if (!S->result) { - return 0; - } - if((S->current_data = mysql_fetch_row(S->result)) == NULL) { - /* there seems to be no way of distinguishing 'no data' from 'error' */ - pdo_mysql_error_stmt(stmt); - return 0; - } - S->current_lengths = mysql_fetch_lengths(S->result); - return 1; -} - -static int pdo_mysql_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC) -{ - pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data; - MYSQL_RES *R = S->result; - MYSQL_FIELD *F; - struct pdo_column_data *cols = stmt->columns; - unsigned int num_fields, i; - - if (!S->result) { - return 0; - } - /* fetch all on demand, this seems easiest - ** if we've been here before bail out - */ - if(cols[0].name) { - return 1; - } - num_fields = mysql_num_fields(R); - F = mysql_fetch_fields(R); - for(i=0; i < num_fields; i++) { - int namelen; - namelen = strlen(F[i].name); - cols[i].precision = F[i].decimals; - cols[i].maxlen = F[i].length; - cols[i].namelen = namelen; - /* FIXME where does this get freed? */ - cols[i].name = estrndup(F[i].name, namelen + 1); - cols[i].param_type = PDO_PARAM_STR; - } - return 1; -} - -static int pdo_mysql_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, unsigned long *len TSRMLS_DC) -{ - pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data; - if(S->current_data == NULL || !S->result) { - return 0; - } - if(colno >= mysql_num_fields(S->result)) { - /* error invalid column */ - pdo_mysql_error_stmt(stmt); - return 0; - } - *ptr = S->current_data[colno]; - *len = S->current_lengths[colno]; - return 1; -} - -struct pdo_stmt_methods mysql_stmt_methods = { - pdo_mysql_stmt_dtor, - pdo_mysql_stmt_execute, - pdo_mysql_stmt_fetch, - pdo_mysql_stmt_describe, - pdo_mysql_stmt_get_col, - pdo_mysql_stmt_param_hook -}; - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo_mysql/package.xml b/ext/pdo_mysql/package.xml deleted file mode 100644 index 0ac427e985cc..000000000000 --- a/ext/pdo_mysql/package.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - pdo_mysql - Mysql 3.x/4.0 driver for PDO - - - gschlossnagle - George Schlossnagle - george@omniti.com - lead - - - iliaa - Ilia Alshanetsky - iliaa@php.net - lead - - - - This extension provides a Mysql 3.x/4.0 driver for PDO. - - PHP - - alpha - 0.1 - 2004-05-18 - - - Hope it works! - - - - - - - - - - - - - - - - - - diff --git a/ext/pdo_mysql/pdo_mysql.c b/ext/pdo_mysql/pdo_mysql.c deleted file mode 100755 index 25583db84532..000000000000 --- a/ext/pdo_mysql/pdo_mysql.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: George Schlossnagle | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "pdo/php_pdo.h" -#include "pdo/php_pdo_driver.h" -#include "php_pdo_mysql.h" -#include "php_pdo_mysql_int.h" - -/* {{{ pdo_mysql_functions[] */ -function_entry pdo_mysql_functions[] = { - {NULL, NULL, NULL} -}; -/* }}} */ - -/* {{{ pdo_mysql_module_entry */ -zend_module_entry pdo_mysql_module_entry = { - STANDARD_MODULE_HEADER, - "pdo_mysql", - pdo_mysql_functions, - PHP_MINIT(pdo_mysql), - PHP_MSHUTDOWN(pdo_mysql), - NULL, - NULL, - PHP_MINFO(pdo_mysql), - "0.1", - STANDARD_MODULE_PROPERTIES -}; -/* }}} */ - -#ifdef COMPILE_DL_PDO_MYSQL -ZEND_GET_MODULE(pdo_mysql) -#endif - -/* true global environment */ - -/* {{{ PHP_MINIT_FUNCTION - */ -PHP_MINIT_FUNCTION(pdo_mysql) -{ - return php_pdo_register_driver(&pdo_mysql_driver); -} -/* }}} */ - -/* {{{ PHP_MSHUTDOWN_FUNCTION - */ -PHP_MSHUTDOWN_FUNCTION(pdo_mysql) -{ - php_pdo_unregister_driver(&pdo_mysql_driver); - return SUCCESS; -} -/* }}} */ - -/* {{{ PHP_MINFO_FUNCTION - */ -PHP_MINFO_FUNCTION(pdo_mysql) -{ - php_info_print_table_start(); - php_info_print_table_header(2, "PDO Driver for MySQL 3.x Client Libraries", "enabled"); - php_info_print_table_end(); -} -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo_mysql/php_pdo_mysql.h b/ext/pdo_mysql/php_pdo_mysql.h deleted file mode 100755 index 1fed28bd5e1d..000000000000 --- a/ext/pdo_mysql/php_pdo_mysql.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: George Schlossnagle | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifndef PHP_PDO_MYSQL_H -#define PHP_PDO_MYSQL_H - -extern zend_module_entry pdo_mysql_module_entry; -#define phpext_pdo_mysql_ptr &pdo_mysql_module_entry - -#ifdef PHP_WIN32 -#define PHP_PDO_MYSQL_API __declspec(dllexport) -#else -#define PHP_PDO_MYSQL_API -#endif - -#ifdef ZTS -#include "TSRM.h" -#endif - -PHP_MINIT_FUNCTION(pdo_mysql); -PHP_MSHUTDOWN_FUNCTION(pdo_mysql); -PHP_RINIT_FUNCTION(pdo_mysql); -PHP_RSHUTDOWN_FUNCTION(pdo_mysql); -PHP_MINFO_FUNCTION(pdo_mysql); - -#endif /* PHP_PDO_MYSQL_H */ - - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo_mysql/php_pdo_mysql_int.h b/ext/pdo_mysql/php_pdo_mysql_int.h deleted file mode 100755 index 8498bb0f89f8..000000000000 --- a/ext/pdo_mysql/php_pdo_mysql_int.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: George Schlossnagle | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifndef PHP_PDO_MYSQL_INT_H -#define PHP_PDO_MYSQL_INT_H - -#include - -typedef struct { - const char *file; - int line; - unsigned int errcode; - char *errmsg; -} pdo_mysql_error_info; - -/* stuff we use in a mySQL database handle */ -typedef struct { - MYSQL *server; - - unsigned attached:1; - unsigned _reserved:31; - - pdo_mysql_error_info einfo; -} pdo_mysql_db_handle; - -typedef struct { - MYSQL_FIELD *def; -} pdo_mysql_column; - -typedef struct { - pdo_mysql_db_handle *H; - MYSQL_RES *result; - MYSQL_ROW current_data; - long *current_lengths; - pdo_mysql_column *cols; -} pdo_mysql_stmt; - -typedef struct { - char *repr; - long repr_len; - int mysql_type; - void *thing; /* for LOBS, REFCURSORS etc. */ -} pdo_mysql_bound_param; - -extern pdo_driver_t pdo_mysql_driver; - -extern int _pdo_mysql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int line TSRMLS_DC); -#define pdo_mysql_error(s) _pdo_mysql_error(s, NULL, __FILE__, __LINE__ TSRMLS_CC) -#define pdo_mysql_error_stmt(s) _pdo_mysql_error(stmt->dbh, stmt, __FILE__, __LINE__ TSRMLS_CC) - -extern struct pdo_stmt_methods mysql_stmt_methods; -#endif diff --git a/ext/pdo_oci/CREDITS b/ext/pdo_oci/CREDITS deleted file mode 100755 index 63e863a22dd9..000000000000 --- a/ext/pdo_oci/CREDITS +++ /dev/null @@ -1,2 +0,0 @@ -Oracle (OCI) driver for PDO -Wez Furlong diff --git a/ext/pdo_oci/EXPERIMENTAL b/ext/pdo_oci/EXPERIMENTAL deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/ext/pdo_oci/config.m4 b/ext/pdo_oci/config.m4 deleted file mode 100755 index 7b31a953fc05..000000000000 --- a/ext/pdo_oci/config.m4 +++ /dev/null @@ -1,142 +0,0 @@ -dnl $Id$ - -AC_DEFUN(AC_PDO_OCI_VERSION,[ - AC_MSG_CHECKING([Oracle version]) - if test -s "$PDO_OCI_DIR/orainst/unix.rgs"; then - PDO_OCI_VERSION=`grep '"ocommon"' $PDO_OCI_DIR/orainst/unix.rgs | sed 's/[ ][ ]*/:/g' | cut -d: -f 6 | cut -c 2-4` - test -z "$PDO_OCI_VERSION" && PDO_OCI_VERSION=7.3 - elif test -f $PDO_OCI_DIR/lib/libclntsh.$SHLIB_SUFFIX_NAME.10.1; then - PDO_OCI_VERSION=10.1 - elif test -f $PDO_OCI_DIR/lib/libclntsh.$SHLIB_SUFFIX_NAME.9.0; then - PDO_OCI_VERSION=9.0 - elif test -f $PDO_OCI_DIR/lib/libclntsh.$SHLIB_SUFFIX_NAME.8.0; then - PDO_OCI_VERSION=8.1 - elif test -f $PDO_OCI_DIR/lib/libclntsh.$SHLIB_SUFFIX_NAME.1.0; then - PDO_OCI_VERSION=8.0 - elif test -f $PDO_OCI_DIR/lib/libclntsh.a; then - if test -f $PDO_OCI_DIR/lib/libcore4.a; then - PDO_OCI_VERSION=8.0 - else - PDO_OCI_VERSION=8.1 - fi - else - AC_MSG_ERROR(Oracle-OCI needed libraries not found under $PDO_OCI_DIR) - fi - AC_MSG_RESULT($PDO_OCI_VERSION) -]) - -PHP_ARG_WITH(pdo-oci, Oracle OCI support for PDO, -[ --with-pdo-oci[=DIR] Include Oracle-oci support. Default DIR is ORACLE_HOME.]) - -if test "$PHP_PDO_OCI" != "no"; then - AC_MSG_CHECKING([Oracle Install-Dir]) - if test "$PHP_PDO_OCI" = "yes" -o -z "$PHP_PDO_OCI"; then - PDO_OCI_DIR=$ORACLE_HOME - else - PDO_OCI_DIR=$PHP_PDO_OCI - fi - AC_MSG_RESULT($PDO_OCI_DIR :$PHP_PDO_OCI:) - - if test -d "$PDO_OCI_DIR/rdbms/public"; then - PHP_ADD_INCLUDE($PDO_OCI_DIR/rdbms/public) - PDO_OCI_INCLUDES="$PDO_OCI_INCLUDES -I$PDO_OCI_DIR/rdbms/public" - fi - if test -d "$PDO_OCI_DIR/rdbms/demo"; then - PHP_ADD_INCLUDE($PDO_OCI_DIR/rdbms/demo) - PDO_OCI_INCLUDES="$PDO_OCI_INCLUDES -I$PDO_OCI_DIR/rdbms/demo" - fi - if test -d "$PDO_OCI_DIR/network/public"; then - PHP_ADD_INCLUDE($PDO_OCI_DIR/network/public) - PDO_OCI_INCLUDES="$PDO_OCI_INCLUDES -I$PDO_OCI_DIR/network/public" - fi - if test -d "$PDO_OCI_DIR/plsql/public"; then - PHP_ADD_INCLUDE($PDO_OCI_DIR/plsql/public) - PDO_OCI_INCLUDES="$PDO_OCI_INCLUDES -I$PDO_OCI_DIR/plsql/public" - fi - - if test -f "$PDO_OCI_DIR/lib/sysliblist"; then - PHP_EVAL_LIBLINE(`cat $PDO_OCI_DIR/lib/sysliblist`, PDO_OCI_SYSLIB) - elif test -f "$PDO_OCI_DIR/rdbms/lib/sysliblist"; then - PHP_EVAL_LIBLINE(`cat $PDO_OCI_DIR/rdbms/lib/sysliblist`, PDO_OCI_SYSLIB) - fi - - AC_PDO_OCI_VERSION($PDO_OCI_DIR) - case $PDO_OCI_VERSION in - 8.0) - PHP_ADD_LIBRARY_WITH_PATH(nlsrtl3, "", PDO_OCI_SHARED_LIBADD) - PHP_ADD_LIBRARY_WITH_PATH(core4, "", PDO_OCI_SHARED_LIBADD) - PHP_ADD_LIBRARY_WITH_PATH(psa, "", PDO_OCI_SHARED_LIBADD) - PHP_ADD_LIBRARY_WITH_PATH(clntsh, $PDO_OCI_DIR/lib, PDO_OCI_SHARED_LIBADD) - ;; - - 8.1) - PHP_ADD_LIBRARY(clntsh, 1, PDO_OCI_SHARED_LIBADD) - PHP_ADD_LIBPATH($PDO_OCI_DIR/lib, PDO_OCI_SHARED_LIBADD) - ;; - - 9.0) - PHP_ADD_LIBRARY(clntsh, 1, PDO_OCI_SHARED_LIBADD) - PHP_ADD_LIBPATH($PDO_OCI_DIR/lib, PDO_OCI_SHARED_LIBADD) - - ;; - - 10.1) - PHP_ADD_LIBRARY(clntsh, 1, PDO_OCI_SHARED_LIBADD) - PHP_ADD_LIBPATH($PDO_OCI_DIR/lib, PDO_OCI_SHARED_LIBADD) - ;; - *) - AC_MSG_ERROR(Unsupported Oracle version!) - ;; - esac - - PHP_CHECK_LIBRARY(clntsh, OCIEnvCreate, - [ - AC_DEFINE(HAVE_OCIENVCREATE,1,[ ]) - ], [], [ - -L$PDO_OCI_DIR/lib $PDO_OCI_SHARED_LIBADD - ]) - - PHP_CHECK_LIBRARY(clntsh, OCIEnvNlsCreate, - [ - AC_DEFINE(HAVE_OCIENVNLSCREATE,1,[ ]) - ], [], [ - -L$PDO_OCI_DIR/lib $PDO_OCI_SHARED_LIBADD - ]) - - dnl - dnl Check if we need to add -locijdbc8 - dnl - PHP_CHECK_LIBRARY(clntsh, OCILobIsTemporary, - [ - AC_DEFINE(HAVE_OCILOBISTEMPORARY,1,[ ]) - ], [ - PHP_CHECK_LIBRARY(ocijdbc8, OCILobIsTemporary, - [ - PHP_ADD_LIBRARY(ocijdbc8, 1, PDO_OCI_SHARED_LIBADD) - AC_DEFINE(HAVE_OCILOBISTEMPORARY,1,[ ]) - ], [], [ - -L$PDO_OCI_DIR/lib $PDO_OCI_SHARED_LIBADD - ]) - ], [ - -L$PDO_OCI_DIR/lib $PDO_OCI_SHARED_LIBADD - ]) - - dnl - dnl Check if we have collections - dnl - PHP_CHECK_LIBRARY(clntsh, OCICollAssign, - [ - AC_DEFINE(HAVE_OCICOLLASSIGN,1,[ ]) - ], [], [ - -L$PDO_OCI_DIR/lib $PDO_OCI_SHARED_LIBADD - ]) - - - - PHP_NEW_EXTENSION(pdo_oci, pdo_oci.c oci_driver.c oci_statement.c, $ext_shared,,-I\$prefix/include/php/ext) - - PHP_SUBST_OLD(PDO_OCI_SHARED_LIBADD) - PHP_SUBST_OLD(PDO_OCI_DIR) - PHP_SUBST_OLD(PDO_OCI_VERSION) - -fi diff --git a/ext/pdo_oci/config.w32 b/ext/pdo_oci/config.w32 deleted file mode 100755 index 353e28f71103..000000000000 --- a/ext/pdo_oci/config.w32 +++ /dev/null @@ -1,42 +0,0 @@ -// $Id$ -// vim:ft=javascript - -ARG_WITH("pdo-oci", "Oracle OCI support for PDO", "no"); - -if (PHP_PDO_OCI != "no") { - - php_oci_dirs = new Array( - PHP_PDO_OCI, - PHP_PDO_OCI + "\\oci", - PHP_PHP_BUILD + "\\oci92", - PHP_PHP_BUILD + "\\oci805" - ); - - php_oci_lib_paths = ""; - php_oci_inc_paths = ""; - - // find the oracle install - for (i = 0; i < php_oci_dirs.length; i++) { - php_oci_lib_paths += php_oci_dirs[i] + "\\lib;"; - php_oci_lib_paths += php_oci_dirs[i] + "\\lib\\msvc;"; - php_oci_inc_paths += php_oci_dirs[i] + "\\include;"; - } - - pdo_oci_header = CHECK_HEADER_ADD_INCLUDE("oci.h", "CFLAGS_PDO_OCI", php_oci_inc_paths); - - if (pdo_oci_header && CHECK_LIB("oci.lib", "pdo_oci", php_oci_lib_paths)) { - - EXTENSION('pdo_oci', 'pdo_oci.c oci_driver.c oci_statement.c'); - ADD_FLAG('CFLAGS_PDO_OCI', "/I ..\\pecl"); - - /* probe for some functions not present in older versions */ - pdo_oci_inc_dir = FSO.GetFolder(pdo_oci_header); - CHECK_FUNC_IN_HEADER('oci.h', 'OCIEnvCreate', pdo_oci_inc_dir); - CHECK_FUNC_IN_HEADER('ociap.h', 'OCIEnvNlsCreate', pdo_oci_inc_dir); - - } else { - WARNING("pdo-oci not enabled; libraries and headers not found"); - } - ADD_EXTENSION_DEP('pdo_oci', 'pdo'); -} - diff --git a/ext/pdo_oci/oci_driver.c b/ext/pdo_oci/oci_driver.c deleted file mode 100755 index 6d56186296ad..000000000000 --- a/ext/pdo_oci/oci_driver.c +++ /dev/null @@ -1,480 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "pdo/php_pdo.h" -#include "pdo/php_pdo_driver.h" -#include "php_pdo_oci.h" -#include "php_pdo_oci_int.h" - -static int pdo_oci_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC) /* {{{ */ -{ - pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data; - pdo_oci_error_info *einfo; - - einfo = &H->einfo; - - if (stmt) { - pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data; - - if (S->einfo.errmsg) { - einfo = &S->einfo; - } - } - - add_next_index_long(info, einfo->errcode); - add_next_index_string(info, einfo->errmsg, 1); - - return 1; -} -/* }}} */ - -ub4 _oci_error(OCIError *err, pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *what, sword status, const char *file, int line TSRMLS_DC) /* {{{ */ -{ - text errbuf[1024] = "<>"; - pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data; - pdo_oci_error_info *einfo; - pdo_oci_stmt *S = NULL; - enum pdo_error_type *pdo_err = &dbh->error_code; - - einfo = &H->einfo; - - if (stmt) { - S = (pdo_oci_stmt*)stmt->driver_data; - einfo = &S->einfo; - pdo_err = &stmt->error_code; - } - - einfo->errcode = 0; - einfo->file = file; - einfo->line = line; - if (einfo->errmsg) { - efree(einfo->errmsg); - einfo->errmsg = NULL; - } - - switch (status) { - case OCI_SUCCESS: - *pdo_err = PDO_ERR_NONE; - break; - case OCI_ERROR: - OCIErrorGet(err, (ub4)1, NULL, &einfo->errcode, errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR); - spprintf(&einfo->errmsg, 0, "%s: %s (%s:%d)", what, errbuf, file, line); - break; - case OCI_SUCCESS_WITH_INFO: - OCIErrorGet(err, (ub4)1, NULL, &einfo->errcode, errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR); - spprintf(&einfo->errmsg, 0, "%s: OCI_SUCCESS_WITH_INFO: %s (%s:%d)", what, errbuf, file, line); - break; - case OCI_NEED_DATA: - spprintf(&einfo->errmsg, 0, "%s: OCI_NEED_DATA (%s:%d)", what, file, line); - break; - case OCI_NO_DATA: - spprintf(&einfo->errmsg, 0, "%s: OCI_NO_DATA (%s:%d)", what, file, line); - break; - case OCI_INVALID_HANDLE: - spprintf(&einfo->errmsg, 0, "%s: OCI_INVALID_HANDLE (%s:%d)", what, file, line); - break; - case OCI_STILL_EXECUTING: - spprintf(&einfo->errmsg, 0, "%s: OCI_STILL_EXECUTING (%s:%d)", what, file, line); - break; - case OCI_CONTINUE: - spprintf(&einfo->errmsg, 0, "%s: OCI_CONTINUE (%s:%d)", what, file, line); - break; - } - - switch (einfo->errcode) { - case 1013: /* user requested cancel of current operation */ - zend_bailout(); - break; - - case 955: /* ORA-00955: name is already used by an existing object */ - *pdo_err = PDO_ERR_ALREADY_EXISTS; - break; - - case 12154: /* ORA-12154: TNS:could not resolve service name */ - *pdo_err = PDO_ERR_NOT_FOUND; - break; - - case 22: /* ORA-00022: invalid session id */ - case 1012: /* ORA-01012: */ - case 3113: /* ORA-03133: end of file on communication channel */ - case 604: - case 1041: - /* consider the connection closed */ - dbh->is_closed = 1; - H->attached = 0; - *pdo_err = PDO_ERR_DISCONNECTED; - break; - - default: - *pdo_err = PDO_ERR_CANT_MAP; - } - - /* little mini hack so that we can use this code from the dbh ctor */ - if (!dbh->methods) { - zend_throw_exception_ex(php_pdo_get_exception(), *pdo_err TSRMLS_CC, einfo->errmsg); - } - - return einfo->errcode; -} -/* }}} */ - -static int oci_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */ -{ - pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data; - - if (H->svc) { - /* rollback any outstanding work */ - OCITransRollback(H->svc, H->err, 0); - } - - if (H->session) { - OCIHandleFree(H->session, OCI_HTYPE_SESSION); - H->session = NULL; - } - - if (H->svc) { - OCIHandleFree(H->svc, OCI_HTYPE_SVCCTX); - H->svc = NULL; - } - - if (H->server && H->attached) { - H->last_err = OCIServerDetach(H->server, H->err, OCI_DEFAULT); - if (H->last_err) { - oci_drv_error("OCIServerDetach"); - } - H->attached = 0; - } - - if (H->server) { - OCIHandleFree(H->server, OCI_HTYPE_SERVER); - H->server = NULL; - } - - OCIHandleFree(H->err, OCI_HTYPE_ERROR); - H->err = NULL; - - if (H->charset && H->env) { - OCIHandleFree(H->env, OCI_HTYPE_ENV); - H->env = NULL; - } - - pefree(H, dbh->is_persistent); - - return 0; -} -/* }}} */ - -static int oci_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, long options, zval *driver_options TSRMLS_DC) /* {{{ */ -{ - pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data; - pdo_oci_stmt *S = ecalloc(1, sizeof(*S)); - - S->H = H; - - /* create an OCI statement handle */ - OCIHandleAlloc(H->env, (dvoid*)&S->stmt, OCI_HTYPE_STMT, 0, NULL); - - /* and our own private error handle */ - OCIHandleAlloc(H->env, (dvoid*)&S->err, OCI_HTYPE_ERROR, 0, NULL); - - if (sql_len) { - H->last_err = OCIStmtPrepare(S->stmt, H->err, (text*)sql, sql_len, OCI_NTV_SYNTAX, OCI_DEFAULT); - - if (H->last_err) { - H->last_err = oci_drv_error("OCIStmtPrepare"); - OCIHandleFree(S->stmt, OCI_HTYPE_STMT); - OCIHandleFree(S->err, OCI_HTYPE_ERROR); - efree(S); - return 0; - } - } - - stmt->driver_data = S; - stmt->methods = &oci_stmt_methods; - - return 1; -} -/* }}} */ - -static long oci_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC) /* {{{ */ -{ - pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data; - OCIStmt *stmt; - ub2 stmt_type; - ub4 rowcount; - int ret = -1; - - OCIHandleAlloc(H->env, (dvoid*)&stmt, OCI_HTYPE_STMT, 0, NULL); - - H->last_err = OCIStmtPrepare(stmt, H->err, (text*)sql, sql_len, OCI_NTV_SYNTAX, OCI_DEFAULT); - if (H->last_err) { - H->last_err = oci_drv_error("OCIStmtPrepare"); - OCIHandleFree(stmt, OCI_HTYPE_STMT); - return -1; - } - - H->last_err = OCIAttrGet(stmt, OCI_HTYPE_STMT, &stmt_type, 0, OCI_ATTR_STMT_TYPE, H->err); - - if (stmt_type == OCI_STMT_SELECT) { - /* invalid usage; cancel it */ - OCIHandleFree(stmt, OCI_HTYPE_STMT); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "issuing a SELECT query here is invalid"); - return -1; - } - - /* now we are good to go */ - H->last_err = OCIStmtExecute(H->svc, stmt, H->err, 1, 0, NULL, NULL, - (dbh->auto_commit && !dbh->in_txn) ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT); - - if (H->last_err) { - H->last_err = oci_drv_error("OCIStmtExecute"); - } else { - /* return the number of affected rows */ - H->last_err = OCIAttrGet(stmt, OCI_HTYPE_STMT, &rowcount, 0, OCI_ATTR_ROW_COUNT, H->err); - ret = rowcount; - } - - OCIHandleFree(stmt, OCI_HTYPE_STMT); - - return ret; -} -/* }}} */ - -static int oci_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen TSRMLS_DC) /* {{{ */ -{ - pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data; - - return 0; -} -/* }}} */ - -static int oci_handle_begin(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */ -{ - /* with Oracle, there is nothing special to be done */ - return 1; -} -/* }}} */ - -static int oci_handle_commit(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */ -{ - pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data; - - H->last_err = OCITransCommit(H->svc, H->err, 0); - - if (H->last_err) { - H->last_err = oci_drv_error("OCITransCommit"); - return 0; - } - return 1; -} -/* }}} */ - -static int oci_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */ -{ - pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data; - - H->last_err = OCITransRollback(H->svc, H->err, 0); - - if (H->last_err) { - H->last_err = oci_drv_error("OCITransRollback"); - return 0; - } - return 1; -} -/* }}} */ - -static int oci_handle_set_attribute(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC) /* {{{ */ -{ - pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data; - - if (attr == PDO_ATTR_AUTOCOMMIT) { - if (dbh->in_txn) { - /* Assume they want to commit whatever is outstanding */ - H->last_err = OCITransCommit(H->svc, H->err, 0); - - if (H->last_err) { - H->last_err = oci_drv_error("OCITransCommit"); - return 0; - } - dbh->in_txn = 0; - } - - convert_to_long(val); - - dbh->auto_commit = Z_LVAL_P(val); - return 1; - } else { - return 0; - } - -} -/* }}} */ - -static struct pdo_dbh_methods oci_methods = { - oci_handle_closer, - oci_handle_preparer, - oci_handle_doer, - oci_handle_quoter, - oci_handle_begin, - oci_handle_commit, - oci_handle_rollback, - oci_handle_set_attribute, - NULL, - pdo_oci_fetch_error_func, -}; - -static int pdo_oci_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */ -{ - pdo_oci_db_handle *H; - int i, ret = 0; - struct pdo_data_src_parser vars[] = { - { "charset", NULL, 0 }, - { "dbname", "", 0 } - }; - - php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 4); - - H = pecalloc(1, sizeof(*H), dbh->is_persistent); - dbh->driver_data = H; - - /* allocate an environment */ -#if HAVE_OCIENVNLSCREATE - if (vars[0].optval) { - H->charset = OCINlsCharSetNameToId(pdo_oci_Env, vars[0].optval); - if (H->charset) { - OCIEnvNlsCreate(&H->env, PDO_OCI_INIT_MODE, 0, NULL, NULL, NULL, 0, NULL, H->charset, H->charset); - } - } -#endif - if (H->env == NULL) { - /* use the global environment */ - H->env = pdo_oci_Env; - } - - /* something to hold errors */ - OCIHandleAlloc(H->env, (dvoid **)&H->err, OCI_HTYPE_ERROR, 0, NULL); - - /* handle for the server */ - OCIHandleAlloc(H->env, (dvoid **)&H->server, OCI_HTYPE_SERVER, 0, NULL); - - H->last_err = OCIServerAttach(H->server, H->err, (text*)vars[1].optval, - strlen(vars[1].optval), OCI_DEFAULT); - - if (H->last_err) { - oci_drv_error("pdo_oci_handle_factory"); - goto cleanup; - } - - H->attached = 1; - - /* create a service context */ - H->last_err = OCIHandleAlloc(H->env, (dvoid**)&H->svc, OCI_HTYPE_SVCCTX, 0, NULL); - if (H->last_err) { - oci_drv_error("OCIHandleAlloc: OCI_HTYPE_SVCCTX"); - goto cleanup; - } - - H->last_err = OCIHandleAlloc(H->env, (dvoid**)&H->session, OCI_HTYPE_SESSION, 0, NULL); - if (H->last_err) { - oci_drv_error("OCIHandleAlloc: OCI_HTYPE_SESSION"); - goto cleanup; - } - - /* set server handle into service handle */ - H->last_err = OCIAttrSet(H->svc, OCI_HTYPE_SVCCTX, H->server, 0, OCI_ATTR_SERVER, H->err); - if (H->last_err) { - oci_drv_error("OCIAttrSet: OCI_ATTR_SERVER"); - goto cleanup; - } - - /* username */ - H->last_err = OCIAttrSet(H->session, OCI_HTYPE_SESSION, - dbh->username, strlen(dbh->username), - OCI_ATTR_USERNAME, H->err); - if (H->last_err) { - oci_drv_error("OCIAttrSet: OCI_ATTR_USERNAME"); - goto cleanup; - } - - /* password */ - H->last_err = OCIAttrSet(H->session, OCI_HTYPE_SESSION, - dbh->password, strlen(dbh->password), - OCI_ATTR_PASSWORD, H->err); - if (H->last_err) { - oci_drv_error("OCIAttrSet: OCI_ATTR_PASSWORD"); - goto cleanup; - } - - /* Now fire up the session */ - H->last_err = OCISessionBegin(H->svc, H->err, H->session, OCI_CRED_RDBMS, OCI_DEFAULT); - if (H->last_err) { - oci_drv_error("OCISessionBegin:"); - goto cleanup; - } - - /* set the server handle into service handle */ - H->last_err = OCIAttrSet(H->svc, OCI_HTYPE_SVCCTX, H->session, 0, OCI_ATTR_SESSION, H->err); - if (H->last_err) { - oci_drv_error("OCIAttrSet: OCI_ATTR_SESSION:"); - goto cleanup; - } - - dbh->methods = &oci_methods; - dbh->alloc_own_columns = 1; - dbh->supports_placeholders = PDO_PLACEHOLDER_NAMED; - dbh->native_case = PDO_CASE_UPPER; - - ret = 1; - -cleanup: - for (i = 0; i < sizeof(vars)/sizeof(vars[0]); i++) { - if (vars[i].freeme) { - efree(vars[i].optval); - } - } - - if (!ret) { - oci_handle_closer(dbh TSRMLS_CC); - } - - return ret; -} -/* }}} */ - -pdo_driver_t pdo_oci_driver = { - PDO_DRIVER_HEADER(oci), - pdo_oci_handle_factory -}; - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo_oci/oci_statement.c b/ext/pdo_oci/oci_statement.c deleted file mode 100755 index 05a3dfe89c91..000000000000 --- a/ext/pdo_oci/oci_statement.c +++ /dev/null @@ -1,420 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "pdo/php_pdo.h" -#include "pdo/php_pdo_driver.h" -#include "php_pdo_oci.h" -#include "php_pdo_oci_int.h" - -#define STMT_CALL(name, params) \ - S->last_err = name params; \ - S->last_err = _oci_error(S->err, stmt->dbh, stmt, #name, S->last_err, __FILE__, __LINE__ TSRMLS_CC); \ - if (S->last_err) { \ - return 0; \ - } - -#define STMT_CALL_MSG(name, msg, params) \ - S->last_err = name params; \ - S->last_err = _oci_error(S->err, stmt->dbh, stmt, #name ": " #msg, S->last_err, __FILE__, __LINE__ TSRMLS_CC); \ - if (S->last_err) { \ - return 0; \ - } - - -static int oci_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC) -{ - pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data; - HashTable *BC = stmt->bound_columns; - HashTable *BP = stmt->bound_params; - - int i; - - if (S->stmt) { - /* cancel server side resources for the statement if we didn't - * fetch it all */ - OCIStmtFetch(S->stmt, S->err, 0, OCI_FETCH_NEXT, OCI_DEFAULT); - - /* free the handle */ - OCIHandleFree(S->stmt, OCI_HTYPE_STMT); - S->stmt = NULL; - } - if (S->err) { - OCIHandleFree(S->err, OCI_HTYPE_ERROR); - S->err = NULL; - } - - if (BC) { - zend_hash_destroy(BC); - efree(stmt->bound_columns); - } - - if (BP) { - zend_hash_destroy(BP); - efree(stmt->bound_params); - } - - if (S->cols) { - for (i = 0; i < stmt->column_count; i++) { - if (S->cols[i].data) { - efree(S->cols[i].data); - } - } - efree(S->cols); - S->cols = NULL; - } - efree(S); - - return 1; -} - -static int oci_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC) -{ - pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data; - ub4 rowcount; - - if (!S->stmt_type) { - STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_STMT_TYPE", - (S->stmt, OCI_HTYPE_STMT, &S->stmt_type, 0, OCI_ATTR_STMT_TYPE, S->err)); - } - - if (stmt->executed) { - /* ensure that we cancel the cursor from a previous fetch */ - OCIStmtFetch(S->stmt, S->err, 0, OCI_FETCH_NEXT, OCI_DEFAULT); - } - - STMT_CALL(OCIStmtExecute, (S->H->svc, S->stmt, S->err, - S->stmt_type == OCI_STMT_SELECT ? 0 : 1, 0, NULL, NULL, - (stmt->dbh->auto_commit && !stmt->dbh->in_txn) ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT)); - - if (!stmt->executed) { - ub4 colcount; - /* do first-time-only definition of bind/mapping stuff */ - - /* how many columns do we have ? */ - STMT_CALL_MSG(OCIAttrGet, "ATTR_PARAM_COUNT", - (S->stmt, OCI_HTYPE_STMT, &colcount, 0, OCI_ATTR_PARAM_COUNT, S->err)); - - stmt->column_count = (int)colcount; - - S->cols = ecalloc(colcount, sizeof(pdo_oci_column)); - } - - STMT_CALL_MSG(OCIAttrGet, "ATTR_ROW_COUNT", - (S->stmt, OCI_HTYPE_STMT, &rowcount, 0, OCI_ATTR_ROW_COUNT, S->err)); - stmt->row_count = (long)rowcount; - - return 1; -} - -static sb4 oci_bind_input_cb(dvoid *ctx, OCIBind *bindp, ub4 iter, ub4 index, dvoid **bufpp, - ub4 *alenp, ub1 *piecep, dvoid **indpp) -{ - struct pdo_bound_param_data *param = (struct pdo_bound_param_data*)ctx; - pdo_oci_bound_param *P = (pdo_oci_bound_param*)ecalloc(1, sizeof(pdo_oci_bound_param)); - TSRMLS_FETCH(); - - if (!param || !param->parameter) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "param is NULL in oci_bind_input_cb; this should not happen"); - return OCI_ERROR; - } - - *indpp = &P->indicator; - - if (ZVAL_IS_NULL(param->parameter)) { - /* insert a NULL value into the column */ - P->indicator = -1; /* NULL */ - *bufpp = 0; - *alenp = -1; - } else if (!P->thing) { - /* regular string bind */ - convert_to_string(param->parameter); - *bufpp = Z_STRVAL_P(param->parameter); - *alenp = Z_STRLEN_P(param->parameter); - } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "P->thing should not be set??"); - return OCI_ERROR; - } - - *piecep = OCI_ONE_PIECE; - return OCI_CONTINUE; -} - -static sb4 oci_bind_output_cb(dvoid *ctx, OCIBind *bindp, ub4 iter, ub4 index, dvoid **bufpp, ub4 **alenpp, - ub1 *piecep, dvoid **indpp, ub2 **rcodepp) -{ - struct pdo_bound_param_data *param = (struct pdo_bound_param_data*)ctx; - pdo_oci_bound_param *P = (pdo_oci_bound_param*)ecalloc(1, sizeof(pdo_oci_bound_param)); - TSRMLS_FETCH(); - - if (!param || !param->parameter) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "param is NULL in oci_bind_output_cb; this should not happen"); - return OCI_ERROR; - } - - if (Z_TYPE_P(param->parameter) == IS_OBJECT || Z_TYPE_P(param->parameter) == IS_RESOURCE) { - return OCI_CONTINUE; - } - - convert_to_string(param->parameter); - zval_dtor(param->parameter); - - Z_STRLEN_P(param->parameter) = param->max_value_len; - Z_STRVAL_P(param->parameter) = emalloc(Z_STRLEN_P(param->parameter)+1); - - - *alenpp = &P->actual_len; - *bufpp = Z_STRVAL_P(param->parameter); - *piecep = OCI_ONE_PIECE; - *rcodepp = &P->retcode; - *indpp = &P->indicator; - - return OCI_CONTINUE; -} - -static int oci_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param, - enum pdo_param_event event_type TSRMLS_DC) -{ - pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data; - - /* we're only interested in parameters for prepared SQL right now */ - if (param->is_param) { - pdo_oci_bound_param *P; - sb4 value_sz = -1; - - P = (pdo_oci_bound_param*)param->driver_data; - - switch (event_type) { - case PDO_PARAM_EVT_ALLOC: - P = (pdo_oci_bound_param*)ecalloc(1, sizeof(pdo_oci_bound_param)); - param->driver_data = P; - - /* figure out what we're doing */ - switch (param->param_type) { - case PDO_PARAM_LOB: - case PDO_PARAM_STMT: - return 0; - - case PDO_PARAM_STR: - default: - P->oci_type = SQLT_CHR; - convert_to_string(param->parameter); - value_sz = param->max_value_len + 1; - P->actual_len = Z_STRLEN_P(param->parameter); - - } - - if (param->name) { - STMT_CALL(OCIBindByName, (S->stmt, - &P->bind, S->err, (text*)param->name, - param->namelen, 0, value_sz, P->oci_type, - &P->indicator, 0, &P->retcode, 0, 0, - OCI_DATA_AT_EXEC)); - } else { - STMT_CALL(OCIBindByPos, (S->stmt, - &P->bind, S->err, param->paramno+1, - 0, value_sz, P->oci_type, - &P->indicator, 0, &P->retcode, 0, 0, - OCI_DATA_AT_EXEC)); - } - - STMT_CALL(OCIBindDynamic, (P->bind, - S->err, - param, oci_bind_input_cb, - param, oci_bind_output_cb)); - - return 1; - - case PDO_PARAM_EVT_EXEC_PRE: - P->indicator = 0; - return 1; - - case PDO_PARAM_EVT_EXEC_POST: - /* fixup stuff set in motion in oci_bind_output_cb */ - if (P->indicator == -1) { - /* set up a NULL value */ - if (Z_TYPE_P(param->parameter) == IS_STRING && Z_STRVAL_P(param->parameter) != empty_string) { - /* OCI likes to stick non-terminated strings in things */ - *Z_STRVAL_P(param->parameter) = '\0'; - } - zval_dtor(param->parameter); - ZVAL_NULL(param->parameter); - } else if (Z_TYPE_P(param->parameter) == IS_STRING && Z_STRVAL_P(param->parameter) != empty_string) { - Z_STRLEN_P(param->parameter) = P->actual_len; - Z_STRVAL_P(param->parameter) = erealloc(Z_STRVAL_P(param->parameter), P->actual_len+1); - Z_STRVAL_P(param->parameter)[P->actual_len] = '\0'; - } - - return 1; - } - } - - return 1; -} - -static int oci_stmt_fetch(pdo_stmt_t *stmt TSRMLS_DC) -{ - pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data; - - S->last_err = OCIStmtFetch(S->stmt, S->err, 1, OCI_FETCH_NEXT, OCI_DEFAULT); - - if (S->last_err == OCI_NO_DATA) { - /* no (more) data */ - return 0; - } - - if (S->last_err == OCI_NEED_DATA) { - oci_stmt_error("OCI_NEED_DATA"); - return 0; - } - - if (S->last_err == OCI_SUCCESS_WITH_INFO || S->last_err == OCI_SUCCESS) { - return 1; - } - - oci_stmt_error("OCIStmtFetch"); - - return 0; -} - -static int oci_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC) -{ - pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data; - OCIParam *param = NULL; - text *colname; - ub2 dtype, data_size, scale, precis; - ub4 namelen; - struct pdo_column_data *col = &stmt->columns[colno]; - zend_bool dyn = FALSE; - - /* describe the column */ - STMT_CALL(OCIParamGet, (S->stmt, OCI_HTYPE_STMT, S->err, (dvoid*)¶m, colno+1)); - - /* what type ? */ - STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_DATA_TYPE", - (param, OCI_DTYPE_PARAM, &dtype, 0, OCI_ATTR_DATA_TYPE, S->err)); - - /* how big ? */ - STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_DATA_SIZE", - (param, OCI_DTYPE_PARAM, &data_size, 0, OCI_ATTR_DATA_SIZE, S->err)); - - /* scale ? */ - STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_SCALE", - (param, OCI_DTYPE_PARAM, &scale, 0, OCI_ATTR_SCALE, S->err)); - - /* precision ? */ - STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_PRECISION", - (param, OCI_DTYPE_PARAM, &precis, 0, OCI_ATTR_PRECISION, S->err)); - - /* name ? */ - STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_NAME", - (param, OCI_DTYPE_PARAM, &colname, &namelen, OCI_ATTR_NAME, S->err)); - - col->precision = scale; - col->maxlen = data_size; - col->namelen = namelen; - col->name = estrndup(colname, namelen); - - /* how much room do we need to store the field */ - switch (dtype) { - case SQLT_BIN: - default: - dyn = FALSE; - if (dtype == SQLT_DAT || dtype == SQLT_NUM -#ifdef SQLT_TIMESTAMP - || dtype == SQLT_TIMESTAMP -#endif -#ifdef SQLT_TIMESTAMP_TZ - || dtype == SQLT_TIMESTAMP_TZ -#endif - ) { - /* should be big enough for most date formats and numbers */ - S->cols[colno].datalen = 512; - } else { - S->cols[colno].datalen = col->maxlen + 1; /* 1 for NUL terminator */ - } - if (dtype == SQLT_BIN) { - S->cols[colno].datalen *= 3; - } - S->cols[colno].data = emalloc(S->cols[colno].datalen); - dtype = SQLT_CHR; - - /* returning data as a string */ - col->param_type = PDO_PARAM_STR; - } - - if (!dyn) { - STMT_CALL(OCIDefineByPos, (S->stmt, &S->cols[colno].def, S->err, colno+1, - S->cols[colno].data, S->cols[colno].datalen, dtype, &S->cols[colno].indicator, - &S->cols[colno].fetched_len, &S->cols[colno].retcode, OCI_DEFAULT)); - } - - return 1; -} - -static int oci_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, unsigned long *len TSRMLS_DC) -{ - pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data; - pdo_oci_column *C = &S->cols[colno]; - - /* check the indicator to ensure that the data is intact */ - if (C->indicator == -1) { - /* A NULL value */ - *ptr = NULL; - *len = 0; - return 1; - } else if (C->indicator == 0) { - /* it was stored perfectly */ - *ptr = C->data; - *len = C->fetched_len; - return 1; - } else { - /* it was truncated */ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "column %d data was too large for buffer and was truncated to fit it", colno); - - *ptr = C->data; - *len = C->fetched_len; - return 1; - } -} - -struct pdo_stmt_methods oci_stmt_methods = { - oci_stmt_dtor, - oci_stmt_execute, - oci_stmt_fetch, - oci_stmt_describe, - oci_stmt_get_col, - oci_stmt_param_hook -}; - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo_oci/package.xml b/ext/pdo_oci/package.xml deleted file mode 100755 index df6f3b9e0253..000000000000 --- a/ext/pdo_oci/package.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - PDO_OCI - Oracle Call Interface driver for PDO - - - wez - Wez Furlong - wez@php.net - lead - - - - This extension provides an Oracle driver for PDO. - - PHP - - alpha - 0.1 - 2004-05-21 - - - You need to install the PDO core module before you can make use of this one. - You also require Oracle OCI 8 or higher client libraries installed on the machine where you intend to build and/or use it. - - If you are running on windows, you can download the binary from here: - http://snaps.php.net/win32/PECL_5_0/php_pdo_oci.dll - - - - - - - - - - - - - - - - - - - diff --git a/ext/pdo_oci/pdo_oci.c b/ext/pdo_oci/pdo_oci.c deleted file mode 100755 index 5712f8634d7d..000000000000 --- a/ext/pdo_oci/pdo_oci.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "pdo/php_pdo.h" -#include "pdo/php_pdo_driver.h" -#include "php_pdo_oci.h" -#include "php_pdo_oci_int.h" - -/* {{{ pdo_oci_functions[] */ -function_entry pdo_oci_functions[] = { - {NULL, NULL, NULL} -}; -/* }}} */ - -/* {{{ pdo_oci_module_entry */ -zend_module_entry pdo_oci_module_entry = { - STANDARD_MODULE_HEADER, - "PDO_OCI", - pdo_oci_functions, - PHP_MINIT(pdo_oci), - PHP_MSHUTDOWN(pdo_oci), - NULL, - NULL, - PHP_MINFO(pdo_oci), - "0.1", - STANDARD_MODULE_PROPERTIES -}; -/* }}} */ - -#ifdef COMPILE_DL_PDO_OCI -ZEND_GET_MODULE(pdo_oci) -#endif - -const ub4 PDO_OCI_INIT_MODE = -#if 0 && defined(OCI_SHARED) - /* shared mode is known to be bad for PHP */ - OCI_SHARED -#else - OCI_DEFAULT -#endif -#ifdef OCI_OBJECT - |OCI_OBJECT -#endif -#ifdef ZTS - |OCI_THREADED -#endif - ; - -/* true global environment */ -OCIEnv *pdo_oci_Env = NULL; - -/* {{{ PHP_MINIT_FUNCTION - */ -PHP_MINIT_FUNCTION(pdo_oci) -{ - php_pdo_register_driver(&pdo_oci_driver); - -#if HAVE_OCIENVCREATE - OCIEnvCreate(&pdo_oci_Env, PDO_OCI_INIT_MODE, NULL, NULL, NULL, NULL, 0, NULL); -#else - OCIInitialize(PDO_OCI_INIT_MODE, NULL, NULL, NULL, NULL); - OCIEnvInit(&pdo_oci_Env, OCI_DEFAULT, 0, NULL); -#endif - - return SUCCESS; -} -/* }}} */ - -/* {{{ PHP_MSHUTDOWN_FUNCTION - */ -PHP_MSHUTDOWN_FUNCTION(pdo_oci) -{ - php_pdo_unregister_driver(&pdo_oci_driver); - OCIHandleFree((dvoid*)pdo_oci_Env, OCI_HTYPE_ENV); - return SUCCESS; -} -/* }}} */ - -/* {{{ PHP_MINFO_FUNCTION - */ -PHP_MINFO_FUNCTION(pdo_oci) -{ - php_info_print_table_start(); - php_info_print_table_header(2, "PDO Driver for OCI 8 and later", "enabled"); - php_info_print_table_end(); -} -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo_oci/php_pdo_oci.h b/ext/pdo_oci/php_pdo_oci.h deleted file mode 100755 index fe9f24749fe0..000000000000 --- a/ext/pdo_oci/php_pdo_oci.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifndef PHP_PDO_OCI_H -#define PHP_PDO_OCI_H - -extern zend_module_entry pdo_oci_module_entry; -#define phpext_pdo_oci_ptr &pdo_oci_module_entry - -#ifdef PHP_WIN32 -#define PHP_PDO_OCI_API __declspec(dllexport) -#else -#define PHP_PDO_OCI_API -#endif - -#ifdef ZTS -#include "TSRM.h" -#endif - -PHP_MINIT_FUNCTION(pdo_oci); -PHP_MSHUTDOWN_FUNCTION(pdo_oci); -PHP_RINIT_FUNCTION(pdo_oci); -PHP_RSHUTDOWN_FUNCTION(pdo_oci); -PHP_MINFO_FUNCTION(pdo_oci); - -#endif /* PHP_PDO_OCI_H */ - - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo_oci/php_pdo_oci_int.h b/ext/pdo_oci/php_pdo_oci_int.h deleted file mode 100755 index d20baba47ca3..000000000000 --- a/ext/pdo_oci/php_pdo_oci_int.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#include - -typedef struct { - const char *file; - int line; - sb4 errcode; - char *errmsg; -} pdo_oci_error_info; - -/* stuff we use in an OCI database handle */ -typedef struct { - OCIServer *server; - OCISession *session; - OCIEnv *env; - OCIError *err; - OCISvcCtx *svc; - /* OCI9; 0 == use NLS_LANG */ - ub2 charset; - sword last_err; - - unsigned attached:1; - unsigned _reserved:31; - - pdo_oci_error_info einfo; -} pdo_oci_db_handle; - -typedef struct { - OCIDefine *def; - ub2 fetched_len; - ub2 retcode; - sb2 indicator; - - char *data; - unsigned long datalen; - -} pdo_oci_column; - -typedef struct { - pdo_oci_db_handle *H; - OCIStmt *stmt; - OCIError *err; - sword last_err; - ub2 stmt_type; - - pdo_oci_column *cols; - pdo_oci_error_info einfo; -} pdo_oci_stmt; - -typedef struct { - OCIBind *bind; /* allocated by OCI */ - sb2 oci_type; - sb2 indicator; - ub2 retcode; - - ub4 actual_len; - - dvoid *thing; /* for LOBS, REFCURSORS etc. */ -} pdo_oci_bound_param; - -extern const ub4 PDO_OCI_INIT_MODE; -extern pdo_driver_t pdo_oci_driver; -extern OCIEnv *pdo_oci_Env; - -ub4 _oci_error(OCIError *err, pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *what, sword status, const char *file, int line TSRMLS_DC); -#define oci_drv_error(w) _oci_error(H->err, dbh, NULL, w, H->last_err, __FILE__, __LINE__ TSRMLS_CC) -#define oci_stmt_error(w) _oci_error(S->err, stmt->dbh, stmt, w, S->last_err, __FILE__, __LINE__ TSRMLS_CC) - -extern struct pdo_stmt_methods oci_stmt_methods; - diff --git a/ext/pdo_oci/tests/connect.phpt b/ext/pdo_oci/tests/connect.phpt deleted file mode 100644 index 9c79e86a4054..000000000000 --- a/ext/pdo_oci/tests/connect.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -PDO_OCI: connect ---SKIPIF-- - ---FILE-- - ---EXPECT-- -done diff --git a/ext/pdo_oci/tests/settings.inc b/ext/pdo_oci/tests/settings.inc deleted file mode 100644 index cbbaeda491fe..000000000000 --- a/ext/pdo_oci/tests/settings.inc +++ /dev/null @@ -1,13 +0,0 @@ - diff --git a/ext/pdo_odbc/CREDITS b/ext/pdo_odbc/CREDITS deleted file mode 100755 index b5af9df356b8..000000000000 --- a/ext/pdo_odbc/CREDITS +++ /dev/null @@ -1,2 +0,0 @@ -ODBC driver for PDO -Wez Furlong diff --git a/ext/pdo_odbc/EXPERIMENTAL b/ext/pdo_odbc/EXPERIMENTAL deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/ext/pdo_odbc/config.m4 b/ext/pdo_odbc/config.m4 deleted file mode 100755 index e69a8a6bc73c..000000000000 --- a/ext/pdo_odbc/config.m4 +++ /dev/null @@ -1,111 +0,0 @@ -dnl $Id$ -dnl config.m4 for extension pdo_odbc - -AC_DEFUN(PDO_ODBC_HELP_TEXT, [[ - --with-pdo-odbc=flavour,dir Add support for "flavour" ODBC drivers, - looking for include and lib dirs under "dir" - - flavour can be one of: - ibm-db2, unixODBC - - You may omit the ,dir part to use a reasonable default for - the flavour you have selected. e.g.: - --with-pdo-odbc=unixODBC - will check for unixODBC under /usr/local - - This extension will always be created as a shared extension - named pdo_odbc.so -]]) - -PHP_ARG_WITH(pdo-odbc, ODBC v3 driver for PDO, PDO_ODBC_HELP_TEXT) - -AC_DEFUN([PDO_ODBC_CHECK_HEADER],[ - if test -f $PDO_ODBC_INCDIR/$1 ; then - AC_DEFINE([HAVE_]translit($1,a-z_.-,A-Z___), 1, [ ]) - fi -]) - -AC_MSG_CHECKING(which ODBC flavour you want) -if test "$PHP_PDO_ODBC" != "no" && test "$PHP_PDO_ODBC" != "yes" ; then - pdo_odbc_flavour=`echo $withval | cut -d, -f1` - pdo_odbc_dir=`echo $withval | cut -d, -f2` - - if test "$pdo_odbc_dir" = "$withval" ; then - pdo_odbc_dir="" - fi - - case $pdo_odbc_flavour in - ibm-db2) - pdo_odbc_def_libdir=/home/db2inst/sqllib/lib - pdo_odbc_def_incdir=/home/db2inst1/sqllib/include - pdo_odbc_def_lib=-ldb2 - ;; - - unixODBC) - pdo_odbc_def_libdir=/usr/local/lib - pdo_odbc_def_incdir=/usr/local/include - pdo_odbc_def_lib=-lodbc - ;; - - *) - AC_MSG_ERROR(Unknown ODBC flavour $pdo_odbc_flavour -PDO_ODBC_HELP_TEXT -) - ;; - esac - - if test "$pdo_odbc_dir" != "" ; then - PDO_ODBC_INCDIR="$pdo_odbc_dir/include" - PDO_ODBC_LIBDIR="$pdo_odbc_dir/lib" - else - PDO_ODBC_INCDIR="$pdo_odbc_def_incdir" - PDO_ODBC_LIBDIR="$pdo_odbc_def_libdir" - fi - - AC_MSG_RESULT([$pdo_odbc_flavour - libs $PDO_ODBC_LIBDIR, - headers $PDO_ODBC_INCDIR]) - - if ! test -d "$PDO_ODBC_LIBDIR" ; then - AC_MSG_WARN([library dir $PDO_ODBC_LIBDIR does not exist]) - fi - - dnl yick time - PDO_ODBC_CHECK_HEADER(odbc.h) - PDO_ODBC_CHECK_HEADER(iodbc.h) - PDO_ODBC_CHECK_HEADER(sqlunix.h) - PDO_ODBC_CHECK_HEADER(sqltypes.h) - PDO_ODBC_CHECK_HEADER(sqlucode.h) - PDO_ODBC_CHECK_HEADER(sql.h) - PDO_ODBC_CHECK_HEADER(isql.h) - PDO_ODBC_CHECK_HEADER(sqlext.h) - PDO_ODBC_CHECK_HEADER(isqlext.h) - PDO_ODBC_CHECK_HEADER(udbcext.h) - PDO_ODBC_CHECK_HEADER(sqlcli1.h) - PDO_ODBC_CHECK_HEADER(LibraryManager.h) - PDO_ODBC_CHECK_HEADER(cli0core.h) - PDO_ODBC_CHECK_HEADER(cli0ext.h) - PDO_ODBC_CHECK_HEADER(cli0cli.h) - PDO_ODBC_CHECK_HEADER(cli0defs.h) - PDO_ODBC_CHECK_HEADER(cli0env.h) - - PDO_ODBC_INCLUDE="-I$PDO_ODBC_INCDIR -DPDO_ODBC_TYPE=\\\"$pdo_odbc_flavour\\\"" - PDO_ODBC_LFLAGS="-L$PDO_ODBC_LIBDIR" - PDO_ODBC_LIBS="$pdo_odbc_def_lib" - - LDFLAGS="$PDO_ODBC_LFLAGS $PDO_ODBC_LIBS -lm -ldl" - AC_TRY_LINK_FUNC([SQLAllocHandle],[],[ - AC_MSG_ERROR([[Your ODBC libraries either do not exist, or do not appear to be ODBC3 compatible]]) - ]) - LDFLAGS=$save_old_LDFLAGS - PHP_EVAL_LIBLINE($PDO_ODBC_LIBS $PDO_ODBC_LFLAGS, [PDO_ODBC_SHARED_LIBADD]) - PHP_SUBST(PDO_ODBC_SHARED_LIBADD) - - PHP_NEW_EXTENSION(pdo_odbc, pdo_odbc.c odbc_driver.c odbc_stmt.c, yes,,-I\$prefix/include/php/ext $PDO_ODBC_INCLUDE) -else - AC_MSG_ERROR( -Unknown ODBC flavour $PHP_PDO_ODBC -PDO_ODBC_HELP_TEXT -) -fi - diff --git a/ext/pdo_odbc/config.w32 b/ext/pdo_odbc/config.w32 deleted file mode 100755 index d7cc443f17ae..000000000000 --- a/ext/pdo_odbc/config.w32 +++ /dev/null @@ -1,15 +0,0 @@ -// $Id$ -// vim:ft=javascript - -ARG_WITH("pdo-odbc", "ODBC support for PDO", "no"); - -if (PHP_PDO_ODBC != "no") { - if (CHECK_LIB("odbc32.lib", "pdo_odbc") && CHECK_LIB("odbccp32.lib", "pdo_odbc")) { - EXTENSION("pdo_odbc", "pdo_odbc.c odbc_driver.c odbc_stmt.c"); - CHECK_HEADER_ADD_INCLUDE('sql.h', 'CFLAGS_PDO_ODBC'); - CHECK_HEADER_ADD_INCLUDE('sqlext.h', 'CFLAGS_PDO_ODBC'); - ADD_FLAG('CFLAGS_PDO_ODBC', "/I ..\\pecl"); - } - ADD_EXTENSION_DEP('pdo_odbc', 'pdo'); -} - diff --git a/ext/pdo_odbc/odbc_driver.c b/ext/pdo_odbc/odbc_driver.c deleted file mode 100755 index e3d557bb0074..000000000000 --- a/ext/pdo_odbc/odbc_driver.c +++ /dev/null @@ -1,410 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "pdo/php_pdo.h" -#include "pdo/php_pdo_driver.h" -#include "php_pdo_odbc.h" -#include "php_pdo_odbc_int.h" - -static struct { - char state[6]; - enum pdo_error_type err; -} odbc_to_pdo_err_map[] = { - /* this table maps ODBC V3 SQLSTATE codes to PDO_ERR codes */ - { "42S01", PDO_ERR_ALREADY_EXISTS }, - { "42S11", PDO_ERR_ALREADY_EXISTS }, - { "42S21", PDO_ERR_ALREADY_EXISTS }, - { "IM001", PDO_ERR_NOT_IMPLEMENTED }, - { "42S22", PDO_ERR_NOT_FOUND }, - { "42S12", PDO_ERR_NOT_FOUND }, - { "42S02", PDO_ERR_NOT_FOUND }, - { "42000", PDO_ERR_SYNTAX }, - { "23000", PDO_ERR_CONSTRAINT }, - { "22025", PDO_ERR_SYNTAX }, - { "22019", PDO_ERR_SYNTAX }, - { "22018", PDO_ERR_SYNTAX }, - { "08S01", PDO_ERR_DISCONNECTED }, - { "01S07", PDO_ERR_TRUNCATED }, - -}; - -static HashTable err_hash; - -void pdo_odbc_fini_error_table(void) -{ - zend_hash_destroy(&err_hash); -} - -void pdo_odbc_init_error_table(void) -{ - int i; - - zend_hash_init(&err_hash, 0, NULL, NULL, 1); - - for (i = 0; i < sizeof(odbc_to_pdo_err_map)/sizeof(odbc_to_pdo_err_map[0]); i++) { - zend_hash_add(&err_hash, odbc_to_pdo_err_map[i].state, sizeof(odbc_to_pdo_err_map[i].state), - &odbc_to_pdo_err_map[i].err, sizeof(odbc_to_pdo_err_map[i].err), NULL); - } -} - -static enum pdo_error_type pdo_odbc_map_error(char *state) -{ - enum pdo_error_type *p_err; - if (SUCCESS == zend_hash_find(&err_hash, state, sizeof(odbc_to_pdo_err_map[0].state), (void**)&p_err)) { - return *p_err; - } - return PDO_ERR_CANT_MAP; -} - -static int pdo_odbc_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC) -{ - pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data; - pdo_odbc_errinfo *einfo = &H->einfo; - pdo_odbc_stmt *S = NULL; - char *message = NULL; - - if (stmt) { - S = (pdo_odbc_stmt*)stmt->driver_data; - einfo = &S->einfo; - } - - spprintf(&message, 0, "%s: %d %s [SQL State %s] (%s:%d)", - einfo->what, einfo->last_error, einfo->last_err_msg, einfo->last_state, einfo->file, einfo->line); - - add_next_index_long(info, einfo->last_error); - add_next_index_string(info, message, 0); - add_next_index_string(info, einfo->last_state, 1); - - return 1; -} - - -void pdo_odbc_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, PDO_ODBC_HSTMT statement, char *what, const char *file, int line TSRMLS_DC) /* {{{ */ -{ - RETCODE rc; - SWORD errmsgsize; - pdo_odbc_db_handle *H = (pdo_odbc_db_handle*)dbh->driver_data; - pdo_odbc_errinfo *einfo = &H->einfo; - pdo_odbc_stmt *S = NULL; - enum pdo_error_type *pdo_err = &dbh->error_code; - - if (stmt) { - S = (pdo_odbc_stmt*)stmt->driver_data; - - einfo = &S->einfo; - pdo_err = &stmt->error_code; - } - - if (statement == SQL_NULL_HSTMT && S) { - statement = S->stmt; - } - - rc = SQLError(H->env, H->dbc, statement, einfo->last_state, &einfo->last_error, - einfo->last_err_msg, sizeof(einfo->last_err_msg)-1, &errmsgsize); - - einfo->last_err_msg[errmsgsize] = '\0'; - einfo->file = file; - einfo->line = line; - einfo->what = what; - - *pdo_err = pdo_odbc_map_error(einfo->last_state); - - if (!dbh->methods) { - zend_throw_exception_ex(php_pdo_get_exception(), *pdo_err TSRMLS_CC, "%s: %d %s [SQL State %s]", - what, einfo->last_error, einfo->last_err_msg, einfo->last_state); - } -} -/* }}} */ - -static int odbc_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) -{ - pdo_odbc_db_handle *H = (pdo_odbc_db_handle*)dbh->driver_data; - - if (H->dbc != SQL_NULL_HANDLE) { - SQLEndTran(SQL_HANDLE_DBC, H->dbc, SQL_ROLLBACK); - SQLDisconnect(H->dbc); - SQLFreeHandle(SQL_HANDLE_DBC, H->dbc); - } - SQLFreeHandle(SQL_HANDLE_ENV, H->env); - pefree(H, dbh->is_persistent); - - return 0; -} - -static int odbc_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, long options, zval *driver_options TSRMLS_DC) -{ - RETCODE rc; - pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data; - pdo_odbc_stmt *S = ecalloc(1, sizeof(*S)); - enum pdo_cursor_type cursor_type = PDO_CURSOR_FWDONLY; - - S->H = H; - - rc = SQLAllocHandle(SQL_HANDLE_STMT, H->dbc, &S->stmt); - - if (rc == SQL_INVALID_HANDLE || rc == SQL_ERROR) { - efree(S); - pdo_odbc_drv_error("SQLAllocStmt"); - return 0; - } - - cursor_type = pdo_attr_lval(driver_options, PDO_ATTR_CURSOR, PDO_CURSOR_FWDONLY TSRMLS_CC); - if (cursor_type != PDO_CURSOR_FWDONLY) { - SQLUINTEGER cursor; - - switch (cursor_type) { - case PDO_CURSOR_SCROLL: - cursor = SQL_CURSOR_STATIC; - default: - ; - } - - rc = SQLSetStmtAttr(S->stmt, SQL_CURSOR_TYPE, (void*)cursor, SQL_IS_UINTEGER); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - pdo_odbc_stmt_error("SQLSetStmtOption: SQL_CURSOR_TYPE"); - SQLFreeHandle(SQL_HANDLE_STMT, S->stmt); - return 0; - } - } - - rc = SQLPrepare(S->stmt, (char*)sql, SQL_NTS); - - if (rc != SQL_SUCCESS) { - pdo_odbc_stmt_error("SQLPrepare"); - } - - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - SQLFreeHandle(SQL_HANDLE_STMT, S->stmt); - return 0; - } - - stmt->driver_data = S; - stmt->methods = &odbc_stmt_methods; - - return 1; -} - -static long odbc_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC) -{ - pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data; - RETCODE rc; - long row_count = -1; - PDO_ODBC_HSTMT stmt; - - rc = SQLAllocHandle(SQL_HANDLE_STMT, H->dbc, &stmt); - if (rc != SQL_SUCCESS) { - pdo_odbc_drv_error("SQLAllocHandle: STMT"); - return -1; - } - - rc = SQLExecDirect(stmt, (char *)sql, sql_len); - - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - pdo_odbc_doer_error("SQLExecDirect"); - goto out; - } - - rc = SQLRowCount(stmt, &row_count); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - pdo_odbc_doer_error("SQLRowCount"); - goto out; - } -out: - SQLFreeHandle(SQL_HANDLE_STMT, stmt); - return row_count; -} - -static int odbc_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen TSRMLS_DC) -{ - pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data; - - return 0; -} - -static int odbc_handle_begin(pdo_dbh_t *dbh TSRMLS_DC) -{ - /* with ODBC, there is nothing special to be done */ - return 1; -} - -static int odbc_handle_commit(pdo_dbh_t *dbh TSRMLS_DC) -{ - pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data; - RETCODE rc; - - rc = SQLEndTran(SQL_HANDLE_DBC, H->dbc, SQL_COMMIT); - - if (rc != SQL_SUCCESS) { - pdo_odbc_drv_error("SQLEndTran: Commit"); - - if (rc != SQL_SUCCESS_WITH_INFO) { - return 0; - } - } - return 1; -} - -static int odbc_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC) -{ - pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data; - RETCODE rc; - - rc = SQLEndTran(SQL_HANDLE_DBC, H->dbc, SQL_ROLLBACK); - - if (rc != SQL_SUCCESS) { - pdo_odbc_drv_error("SQLEndTran: Rollback"); - - if (rc != SQL_SUCCESS_WITH_INFO) { - return 0; - } - } - return 1; -} - - - -static struct pdo_dbh_methods odbc_methods = { - odbc_handle_closer, - odbc_handle_preparer, - odbc_handle_doer, - odbc_handle_quoter, - odbc_handle_begin, - odbc_handle_commit, - odbc_handle_rollback, - NULL, /* set attr */ - NULL, /* last id */ - pdo_odbc_fetch_error_func, - NULL, /* get attr */ -}; - -static int pdo_odbc_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */ -{ - pdo_odbc_db_handle *H; - RETCODE rc; - int use_direct = 0; - SQLUINTEGER cursor_lib; - - H = pecalloc(1, sizeof(*H), dbh->is_persistent); - - dbh->driver_data = H; - - SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &H->env); - rc = SQLSetEnvAttr(H->env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0); - - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - pdo_odbc_drv_error("SQLSetEnvAttr: ODBC3"); - odbc_handle_closer(dbh TSRMLS_CC); - return 0; - } - -#ifdef SQL_ATTR_CONNECTION_POOLING - if (pdo_odbc_pool_on != SQL_CP_OFF) { - rc = SQLSetEnvAttr(H->env, SQL_ATTR_CP_MATCH, (void*)pdo_odbc_pool_mode, 0); - if (rc != SQL_SUCCESS) { - pdo_odbc_drv_error("SQLSetEnvAttr: SQL_ATTR_CP_MATCH"); - odbc_handle_closer(dbh TSRMLS_CC); - return 0; - } - } -#endif - - rc = SQLAllocHandle(SQL_HANDLE_DBC, H->env, &H->dbc); - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - pdo_odbc_drv_error("SQLAllocHandle (DBC)"); - odbc_handle_closer(dbh TSRMLS_CC); - return 0; - } - - if (!dbh->auto_commit) { - rc = SQLSetConnectAttr(H->dbc, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF, SQL_IS_UINTEGER); - if (rc != SQL_SUCCESS) { - pdo_odbc_drv_error("SQLSetConnectAttr AUTOCOMMIT = OFF"); - odbc_handle_closer(dbh TSRMLS_CC); - return 0; - } - } - - /* set up the cursor library, if needed, or if configured explicitly */ - cursor_lib = pdo_attr_lval(driver_options, PDO_ODBC_ATTR_USE_CURSOR_LIBRARY, SQL_CUR_USE_IF_NEEDED TSRMLS_CC); - rc = SQLSetConnectAttr(H->dbc, SQL_ODBC_CURSORS, (void*)cursor_lib, SQL_IS_UINTEGER); - if (rc != SQL_SUCCESS) { - pdo_odbc_drv_error("SQLSetConnectAttr SQL_ODBC_CURSORS"); - odbc_handle_closer(dbh TSRMLS_CC); - return 0; - } - - - if (strchr(dbh->data_source, ';')) { - char dsnbuf[1024]; - short dsnbuflen; - - use_direct = 1; - - /* Force UID and PWD to be set in the DSN */ - if (*dbh->username && !strstr(dbh->data_source, "uid") && !strstr(dbh->data_source, "UID")) { - char *dsn = pemalloc(strlen(dbh->data_source) + strlen(dbh->username) + strlen(dbh->password) + sizeof(";UID=;PWD="), dbh->is_persistent); - sprintf(dsn, "%s;UID=%s;PWD=%s", dbh->data_source, dbh->username, dbh->password); - pefree((char*)dbh->data_source, dbh->is_persistent); - dbh->data_source = dsn; - } - - rc = SQLDriverConnect(H->dbc, NULL, (char*)dbh->data_source, strlen(dbh->data_source), - dsnbuf, sizeof(dsnbuf)-1, &dsnbuflen, SQL_DRIVER_NOPROMPT); - } - if (!use_direct) { - rc = SQLConnect(H->dbc, (char*)dbh->data_source, SQL_NTS, dbh->username, SQL_NTS, dbh->password, SQL_NTS); - } - - if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { - pdo_odbc_drv_error(use_direct ? "SQLDriverConnect" : "SQLConnect"); - odbc_handle_closer(dbh TSRMLS_CC); - return 0; - } - - /* TODO: if we want to play nicely, we should check to see if the driver really supports ODBC v3 or not */ - - dbh->methods = &odbc_methods; - dbh->alloc_own_columns = 1; - dbh->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL; - - return 1; -} -/* }}} */ - -pdo_driver_t pdo_odbc_driver = { - PDO_DRIVER_HEADER(odbc), - pdo_odbc_handle_factory -}; - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo_odbc/odbc_stmt.c b/ext/pdo_odbc/odbc_stmt.c deleted file mode 100755 index 807b6078030d..000000000000 --- a/ext/pdo_odbc/odbc_stmt.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "pdo/php_pdo.h" -#include "pdo/php_pdo_driver.h" -#include "php_pdo_odbc.h" -#include "php_pdo_odbc_int.h" - -static int odbc_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC) -{ - pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data; - int i; - - if (S->stmt != SQL_NULL_HANDLE) { - if (stmt->executed) { - SQLCancel(S->stmt); - } - SQLFreeHandle(SQL_HANDLE_STMT, S->stmt); - S->stmt = SQL_NULL_HANDLE; - } - - if (S->cols) { - for (i = 0; i < stmt->column_count; i++) { - if (S->cols[i].data) { - efree(S->cols[i].data); - } - } - efree(S->cols); - S->cols = NULL; - } - efree(S); - - return 1; -} - -static int odbc_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC) -{ - RETCODE rc; - pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data; - - if (stmt->executed) { - SQLCancel(S->stmt); - } - - rc = SQLExecute(S->stmt); - - switch (rc) { - case SQL_SUCCESS: - break; - case SQL_NO_DATA_FOUND: - case SQL_SUCCESS_WITH_INFO: - pdo_odbc_stmt_error("SQLExecute"); - break; - - default: - pdo_odbc_stmt_error("SQLExecute"); - return 0; - } - - if (!stmt->executed) { - /* do first-time-only definition of bind/mapping stuff */ - SQLSMALLINT colcount; - - /* how many columns do we have ? */ - SQLNumResultCols(S->stmt, &colcount); - - stmt->column_count = (int)colcount; - - S->cols = ecalloc(colcount, sizeof(pdo_odbc_column)); - } - - return 1; -} - -static int odbc_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param, - enum pdo_param_event event_type TSRMLS_DC) -{ - pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data; - RETCODE rc; - SWORD sqltype, ctype, scale, nullable; - UDWORD precision; - - /* we're only interested in parameters for prepared SQL right now */ - if (param->is_param) { - - switch (event_type) { - case PDO_PARAM_EVT_ALLOC: - - /* figure out what we're doing */ - switch (param->param_type) { - case PDO_PARAM_LOB: - case PDO_PARAM_STMT: - return 0; - - case PDO_PARAM_STR: - default: - convert_to_string(param->parameter); - } - - SQLDescribeParam(S->stmt, param->paramno+1, &sqltype, &precision, &scale, &nullable); - if (sqltype == SQL_BINARY || sqltype == SQL_VARBINARY || sqltype == SQL_LONGVARBINARY) { - ctype = SQL_C_BINARY; - } else { - ctype = SQL_C_CHAR; - } - - rc = SQLBindParameter(S->stmt, param->paramno+1, - SQL_PARAM_INPUT, ctype, sqltype, precision, scale, - Z_STRVAL_P(param->parameter), 0, - /* XXX: this has the wrong type for DB2 */ - &Z_STRLEN_P(param->parameter) - ); - - return 1; - } - } - return 1; -} - -static int odbc_stmt_fetch(pdo_stmt_t *stmt TSRMLS_DC) -{ - pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data; - RETCODE rc; - - rc = SQLFetch(S->stmt); - - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - return 1; - } - - if (rc == SQL_NO_DATA) { - return 0; - } - - pdo_odbc_stmt_error("SQLFetch"); - - return 0; -} - -static int odbc_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC) -{ - pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data; - struct pdo_column_data *col = &stmt->columns[colno]; - zend_bool dyn = FALSE; - RETCODE rc; - SWORD colnamelen; - SDWORD colsize; - - rc = SQLDescribeCol(S->stmt, colno+1, S->cols[colno].colname, - sizeof(S->cols[colno].colname)-1, &colnamelen, - &S->cols[colno].coltype, &colsize, NULL, NULL); - - col->maxlen = S->cols[colno].datalen = colsize; - col->namelen = colnamelen; - col->name = S->cols[colno].colname; - - S->cols[colno].data = emalloc(colsize+1); - - /* returning data as a string */ - col->param_type = PDO_PARAM_STR; - - /* tell ODBC to put it straight into our buffer */ - rc = SQLBindCol(S->stmt, colno+1, SQL_C_CHAR, S->cols[colno].data, - S->cols[colno].datalen, &S->cols[colno].fetched_len); - - return 1; -} - -static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, unsigned long *len TSRMLS_DC) -{ - pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data; - pdo_odbc_column *C = &S->cols[colno]; - - /* check the indicator to ensure that the data is intact */ - if (C->fetched_len == SQL_NULL_DATA) { - /* A NULL value */ - *ptr = NULL; - *len = 0; - return 1; - } else if (C->fetched_len >= 0) { - /* it was stored perfectly */ - *ptr = C->data; - *len = C->fetched_len; - return 1; - } else { - /* no data? */ - *ptr = NULL; - *len = 0; - return 1; - } -} - -static int odbc_stmt_set_param(pdo_stmt_t *stmt, long attr, zval *val TSRMLS_DC) -{ - SQLRETURN rc; - pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data; - - switch (attr) { - case PDO_ATTR_CURSOR_NAME: - convert_to_string(val); - rc = SQLSetCursorName(S->stmt, Z_STRVAL_P(val), Z_STRLEN_P(val)); - - if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { - return 1; - } - pdo_odbc_stmt_error("SQLSetCursorName"); - return 0; - - default: - strcpy(S->einfo.last_err_msg, "Unknown Attribute"); - S->einfo.what = "setAttribute"; - stmt->error_code = PDO_ERR_NOT_IMPLEMENTED; - S->einfo.last_state[0] = '\0'; - return -1; - } - - -} - -struct pdo_stmt_methods odbc_stmt_methods = { - odbc_stmt_dtor, - odbc_stmt_execute, - odbc_stmt_fetch, - odbc_stmt_describe, - odbc_stmt_get_col, - odbc_stmt_param_hook, - odbc_stmt_set_param, - NULL -}; - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo_odbc/package.xml b/ext/pdo_odbc/package.xml deleted file mode 100755 index 7b86564b46eb..000000000000 --- a/ext/pdo_odbc/package.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - PDO_ODBC - ODBC v3 Interface driver for PDO - - - wez - Wez Furlong - wez@php.net - lead - - - - - - - This extension provides an ODBC v3 driver for PDO. It supports unixODBC - and IBM DB2 libraries, and will support more in future releases. - - PHP - - alpha - 0.1.1 - 2004-05-22 - - - You need to install the PDO core module before you can make use of this one. - You also require either IBM DB2 CLI libraries or unixODBC. - - If you are running on windows, you can download the binary from here: - http://snaps.php.net/win32/PECL_5_0/php_pdo_odbc.dll - - This release features working error reporting(!) and ODBC connection pooling. - - - - - - - - - - - - - - - - - - - diff --git a/ext/pdo_odbc/pdo_odbc.c b/ext/pdo_odbc/pdo_odbc.c deleted file mode 100755 index e8dc26b5aee5..000000000000 --- a/ext/pdo_odbc/pdo_odbc.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "pdo/php_pdo.h" -#include "pdo/php_pdo_driver.h" -#include "php_pdo_odbc.h" -#include "php_pdo_odbc_int.h" - -#ifdef PHP_WIN32 -# define PDO_ODBC_TYPE "Win32" -#endif - -#ifndef PDO_ODBC_TYPE -# warning Please fix configure to give your ODBC libraries a name -# define PDO_ODBC_TYPE "Unknown" -#endif - -/* {{{ pdo_odbc_functions[] */ -function_entry pdo_odbc_functions[] = { - {NULL, NULL, NULL} -}; -/* }}} */ - -/* {{{ pdo_odbc_module_entry */ -zend_module_entry pdo_odbc_module_entry = { - STANDARD_MODULE_HEADER, - "PDO_ODBC", - pdo_odbc_functions, - PHP_MINIT(pdo_odbc), - PHP_MSHUTDOWN(pdo_odbc), - NULL, - NULL, - PHP_MINFO(pdo_odbc), - "0.1.1", - STANDARD_MODULE_PROPERTIES -}; -/* }}} */ - -#ifdef COMPILE_DL_PDO_ODBC -ZEND_GET_MODULE(pdo_odbc) -#endif - -#ifdef SQL_ATTR_CONNECTION_POOLING -SQLUINTEGER pdo_odbc_pool_on = SQL_CP_OFF; -SQLUINTEGER pdo_odbc_pool_mode = SQL_CP_ONE_PER_HENV; -#endif - -/* {{{ PHP_MINIT_FUNCTION */ -PHP_MINIT_FUNCTION(pdo_odbc) -{ -#ifdef SQL_ATTR_CONNECTION_POOLING - char *pooling_val = NULL; -#endif - - if (FAILURE == php_pdo_register_driver(&pdo_odbc_driver)) { - return FAILURE; - } - - pdo_odbc_init_error_table(); - -#ifdef SQL_ATTR_CONNECTION_POOLING - /* ugh, we don't really .ini stuff in PDO, but since ODBC connection - * pooling is process wide, we can't set it from within the scope of a - * request without affecting others, which goes against our isolated request - * policy. So, we use cfg_get_string here to check it this once. - * */ - if (FAILURE == cfg_get_string("pdo_odbc.connection_pooling", &pooling_val) || pooling_val == NULL) { - pooling_val = "strict"; - } - if (strcasecmp(pooling_val, "strict") == 0 || strcmp(pooling_val, "1") == 0) { - pdo_odbc_pool_on = SQL_CP_ONE_PER_HENV; - pdo_odbc_pool_mode = SQL_CP_STRICT_MATCH; - } else if (strcasecmp(pooling_val, "relaxed") == 0) { - pdo_odbc_pool_on = SQL_CP_ONE_PER_HENV; - pdo_odbc_pool_mode = SQL_CP_RELAXED_MATCH; - } else if (*pooling_val == '\0' || strcasecmp(pooling_val, "off") == 0) { - pdo_odbc_pool_on = SQL_CP_OFF; - } else { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "Error in pdo_odbc.connection_pooling configuration. Value MUST be one of 'strict', 'relaxed' or 'off'"); - return FAILURE; - } - - if (pdo_odbc_pool_on != SQL_CP_OFF) { - SQLSetEnvAttr(SQL_NULL_HANDLE, SQL_ATTR_CONNECTION_POOLING, (void*)pdo_odbc_pool_on, 0); - } -#endif - - REGISTER_LONG_CONSTANT("PDO_ODBC_ATTR_USE_CURSOR_LIBRARY", PDO_ODBC_ATTR_USE_CURSOR_LIBRARY, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ODBC_SQL_USE_IF_NEEDED", SQL_CUR_USE_IF_NEEDED, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ODBC_SQL_USE_DRIVER", SQL_CUR_USE_DRIVER, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PDO_ODBC_SQL_USE_ODBC", SQL_CUR_USE_ODBC, CONST_CS|CONST_PERSISTENT); - - return SUCCESS; -} -/* }}} */ - -/* {{{ PHP_MSHUTDOWN_FUNCTION - */ -PHP_MSHUTDOWN_FUNCTION(pdo_odbc) -{ - php_pdo_unregister_driver(&pdo_odbc_driver); - pdo_odbc_fini_error_table(); - return SUCCESS; -} -/* }}} */ - -/* {{{ PHP_MINFO_FUNCTION - */ -PHP_MINFO_FUNCTION(pdo_odbc) -{ - php_info_print_table_start(); - php_info_print_table_header(2, "PDO Driver for ODBC (" PDO_ODBC_TYPE ")" , "enabled"); -#ifdef SQL_ATTR_CONNECTION_POOLING - php_info_print_table_row(2, "ODBC Connection Pooling", pdo_odbc_pool_on == SQL_CP_OFF ? - "Disabled" : (pdo_odbc_pool_mode == SQL_CP_STRICT_MATCH ? "Enabled, strict matching" : "Enabled, relaxed matching")); -#else - php_info_print_table_row(2, "ODBC Connection Pooling", "Not supported in this build"); -#endif - php_info_print_table_end(); - -} -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo_odbc/php_pdo_odbc.h b/ext/pdo_odbc/php_pdo_odbc.h deleted file mode 100644 index 1c2dcf41978f..000000000000 --- a/ext/pdo_odbc/php_pdo_odbc.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifndef PHP_PDO_ODBC_H -#define PHP_PDO_ODBC_H - -extern zend_module_entry pdo_odbc_module_entry; -#define phpext_pdo_odbc_ptr &pdo_odbc_module_entry - -#ifdef PHP_WIN32 -#define PHP_PDO_ODBC_API __declspec(dllexport) -#else -#define PHP_PDO_ODBC_API -#endif - -#ifdef ZTS -#include "TSRM.h" -#endif - -PHP_MINIT_FUNCTION(pdo_odbc); -PHP_MSHUTDOWN_FUNCTION(pdo_odbc); -PHP_RINIT_FUNCTION(pdo_odbc); -PHP_RSHUTDOWN_FUNCTION(pdo_odbc); -PHP_MINFO_FUNCTION(pdo_odbc); - -PHP_FUNCTION(confirm_pdo_odbc_compiled); /* For testing, remove later. */ - -/* - Declare any global variables you may need between the BEGIN - and END macros here: - -ZEND_BEGIN_MODULE_GLOBALS(pdo_odbc) - long global_value; - char *global_string; -ZEND_END_MODULE_GLOBALS(pdo_odbc) -*/ - -/* In every utility function you add that needs to use variables - in php_pdo_odbc_globals, call TSRMLS_FETCH(); after declaring other - variables used by that function, or better yet, pass in TSRMLS_CC - after the last function argument and declare your utility function - with TSRMLS_DC after the last declared argument. Always refer to - the globals in your function as PDO_ODBC_G(variable). You are - encouraged to rename these macros something shorter, see - examples in any other php module directory. -*/ - -#ifdef ZTS -#define PDO_ODBC_G(v) TSRMG(pdo_odbc_globals_id, zend_pdo_odbc_globals *, v) -#else -#define PDO_ODBC_G(v) (pdo_odbc_globals.v) -#endif - -#endif /* PHP_PDO_ODBC_H */ - - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo_odbc/php_pdo_odbc_int.h b/ext/pdo_odbc/php_pdo_odbc_int.h deleted file mode 100755 index e249be56872f..000000000000 --- a/ext/pdo_odbc/php_pdo_odbc_int.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -/* {{{ Roll a dice, pick a header at random... */ -#if HAVE_SQLCLI1_H -# include -# if defined(DB268K) && HAVE_LIBRARYMANAGER_H -# include -# endif -#endif - -#if HAVE_ODBC_H -# include -#endif - -#if HAVE_IODBC_H -# include -#endif - -#if HAVE_SQLUNIX_H && !defined(PHP_WIN32) -# include -#endif - -#if HAVE_SQLTYPES_H -# include -#endif - -#if HAVE_SQLUCODE_H -# include -#endif - -#if HAVE_SQL_H -# include -#endif - -#if HAVE_ISQL_H -# include -#endif - -#if HAVE_SQLEXT_H -# include -#endif - -#if HAVE_ISQLEXT_H -# include -#endif - -#if HAVE_UDBCEXT_H -# include -#endif - -#if HAVE_CLI0CORE_H -# include -#endif - -#if HAVE_CLI0EXT1_H -# include -#endif - -#if HAVE_CLI0CLI_H -# include -#endif - -#if HAVE_CLI0DEFS_H -# include -#endif - -#if HAVE_CLI0ENV_H -# include -#endif - -/* }}} */ - -/* {{{ Figure out the type for handles */ -#if !defined(HENV) && !defined(SQLHENV) && defined(SQLHANDLE) -# define PDO_ODBC_HENV SQLHANDLE -# define PDO_ODBC_HDBC SQLHANDLE -# define PDO_ODBC_HSTMT SQLHANDLE -#elif !defined(HENV) && (defined(SQLHENV) || defined(DB2CLI_VER)) -# define PDO_ODBC_HENV SQLHENV -# define PDO_ODBC_HDBC SQLHDBC -# define PDO_ODBC_HSTMT SQLHSTMT -#else -# define PDO_ODBC_HENV HENV -# define PDO_ODBC_HDBC HDBC -# define PDO_ODBC_HSTMT HSTMT -#endif -/* }}} */ - -typedef struct { - char last_state[6]; - char last_err_msg[SQL_MAX_MESSAGE_LENGTH]; - SDWORD last_error; - const char *file, *what; - int line; -} pdo_odbc_errinfo; - -typedef struct { - PDO_ODBC_HENV env; - PDO_ODBC_HDBC dbc; - pdo_odbc_errinfo einfo; -} pdo_odbc_db_handle; - -typedef struct { - char *data; - unsigned long datalen; - long fetched_len; - SWORD coltype; - char colname[32]; -} pdo_odbc_column; - -typedef struct { - PDO_ODBC_HSTMT stmt; - pdo_odbc_column *cols; - pdo_odbc_db_handle *H; - pdo_odbc_errinfo einfo; -} pdo_odbc_stmt; - -extern pdo_driver_t pdo_odbc_driver; -extern struct pdo_stmt_methods odbc_stmt_methods; - -void pdo_odbc_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, PDO_ODBC_HSTMT statement, char *what, const char *file, int line TSRMLS_DC); -#define pdo_odbc_drv_error(what) pdo_odbc_error(dbh, NULL, SQL_NULL_HSTMT, what, __FILE__, __LINE__ TSRMLS_CC) -#define pdo_odbc_stmt_error(what) pdo_odbc_error(stmt->dbh, stmt, SQL_NULL_HSTMT, what, __FILE__, __LINE__ TSRMLS_CC) -#define pdo_odbc_doer_error(what) pdo_odbc_error(dbh, NULL, stmt, what, __FILE__, __LINE__ TSRMLS_CC) - -void pdo_odbc_init_error_table(void); -void pdo_odbc_fini_error_table(void); - -#ifdef SQL_ATTR_CONNECTION_POOLING -extern SQLUINTEGER pdo_odbc_pool_on; -extern SQLUINTEGER pdo_odbc_pool_mode; -#endif - -enum { - PDO_ODBC_ATTR_USE_CURSOR_LIBRARY = PDO_ATTR_DRIVER_SPECIFIC, -}; - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo_pgsql/CREDITS b/ext/pdo_pgsql/CREDITS deleted file mode 100644 index bbb7b944282b..000000000000 --- a/ext/pdo_pgsql/CREDITS +++ /dev/null @@ -1,2 +0,0 @@ -PostgreSQL driver for PDO -Edin Kadribasic, Ilia Alshanetsky diff --git a/ext/pdo_pgsql/config.m4 b/ext/pdo_pgsql/config.m4 deleted file mode 100644 index 66b4949beaf9..000000000000 --- a/ext/pdo_pgsql/config.m4 +++ /dev/null @@ -1,101 +0,0 @@ -dnl -dnl $Id$ -dnl - -AC_DEFUN(PHP_PGSQL_CHECK_FUNCTIONS,[ -]) - -PHP_ARG_WITH(pdo-pgsql,for PostgreSQL support for PDO, -[ --with-pdo-pgsql[=DIR] Include PDO PostgreSQL support. DIR - is the PostgreSQL base install directory - or the path to pg_config.]) - -if test "$PHP_PDO_PGSQL" != "no"; then - PHP_EXPAND_PATH($PGSQL_INCLUDE, PGSQL_INCLUDE) - - AC_MSG_CHECKING(for pg_config) - for i in $PHP_PDO_PGSQL $PHP_PDO_PGSQL/bin /usr/local/pgsql/bin /usr/local/bin /usr/bin ""; do - if test -x $i/pg_config; then - PG_CONFIG="$i/pg_config" - break; - fi - done - - if test -n "$PG_CONFIG"; then - AC_MSG_RESULT([$PG_CONFIG]) - PGSQL_INCLUDE=`$PG_CONFIG --includedir` - PGSQL_LIBDIR=`$PG_CONFIG --libdir` - AC_DEFINE(HAVE_PG_CONFIG_H,1,[Whether to have pg_config.h]) - else - AC_MSG_RESULT(not found) - if test "$PHP_PDO_PGSQL" = "yes"; then - PGSQL_SEARCH_PATHS="/usr /usr/local /usr/local/pgsql" - else - PGSQL_SEARCH_PATHS=$PHP_PDO_PGSQL - fi - - for i in $PGSQL_SEARCH_PATHS; do - for j in include include/pgsql include/postgres include/postgresql ""; do - if test -r "$i/$j/libpq-fe.h"; then - PGSQL_INC_BASE=$i - PGSQL_INCLUDE=$i/$j - if test -r "$i/$j/pg_config.h"; then - AC_DEFINE(HAVE_PG_CONFIG_H,1,[Whether to have pg_config.h]) - fi - fi - done - - for j in lib lib/pgsql lib/postgres lib/postgresql ""; do - if test -f "$i/$j/libpq.so" || test -f "$i/$j/libpq.a"; then - PGSQL_LIBDIR=$i/$j - fi - done - done - fi - - if test -z "$PGSQL_INCLUDE"; then - AC_MSG_ERROR(Cannot find libpq-fe.h. Please specify correct PostgreSQL installation path) - fi - - if test -z "$PGSQL_LIBDIR"; then - AC_MSG_ERROR(Cannot find libpq.so. Please specify correct PostgreSQL installation path) - fi - - if test -z "$PGSQL_INCLUDE" -a -z "$PGSQL_LIBDIR" ; then - AC_MSG_ERROR([Unable to find libpq anywhere under $withval]) - fi - - AC_DEFINE(HAVE_PDO_PGSQL,1,[Whether to build PostgreSQL for PDO support or not]) - old_LIBS=$LIBS - old_LDFLAGS=$LDFLAGS - LDFLAGS="$LDFLAGS -L$PGSQL_LIBDIR" - AC_CHECK_LIB(pq, PQescapeString,AC_DEFINE(HAVE_PQESCAPE,1,[PostgreSQL 7.2.0 or later])) - AC_CHECK_LIB(pq, PQsetnonblocking,AC_DEFINE(HAVE_PQSETNONBLOCKING,1,[PostgreSQL 7.0.x or later])) - AC_CHECK_LIB(pq, PQcmdTuples,AC_DEFINE(HAVE_PQCMDTUPLES,1,[Broken libpq under windows])) - AC_CHECK_LIB(pq, PQoidValue,AC_DEFINE(HAVE_PQOIDVALUE,1,[Older PostgreSQL])) - AC_CHECK_LIB(pq, PQclientEncoding,AC_DEFINE(HAVE_PQCLIENTENCODING,1,[PostgreSQL 7.0.x or later])) - AC_CHECK_LIB(pq, PQparameterStatus,AC_DEFINE(HAVE_PQPARAMETERSTATUS,1,[PostgreSQL 7.4 or later])) - AC_CHECK_LIB(pq, PQprotocolVersion,AC_DEFINE(HAVE_PQPROTOCOLVERSION,1,[PostgreSQL 7.4 or later])) - AC_CHECK_LIB(pq, PQtransactionStatus,AC_DEFINE(HAVE_PGTRANSACTIONSTATUS,1,[PostgreSQL 7.4 or later])) - AC_CHECK_LIB(pq, pg_encoding_to_char,AC_DEFINE(HAVE_PGSQL_WITH_MULTIBYTE_SUPPORT,1,[Whether libpq is compiled with --enable-multibye])) - LIBS=$old_LIBS - LDFLAGS=$old_LDFLAGS - - PHP_ADD_LIBRARY_WITH_PATH(pq, $PGSQL_LIBDIR, PDO_PGSQL_SHARED_LIBADD) - PHP_SUBST(PDO_PGSQL_SHARED_LIBADD) - - PHP_ADD_INCLUDE($PGSQL_INCLUDE) - -dnl find PDO sources - if test -f $prefix/include/php/ext/pdo/php_pdo_driver.h; then - pdo_inc_path=$prefix/include/php/ext - elif test -f $abs_srcdir/ext/pdo/php_pdo_driver.h; then - pdo_inc_path=$abs_srcdir/ext - elif test -f ext/pdo/php_pdo_driver.h; then - pdo_inc_path=ext - else - AC_MSG_ERROR([Cannot find php_pdo_driver.h.]) - fi - - PHP_NEW_EXTENSION(pdo_pgsql, pdo_pgsql.c pgsql_driver.c pgsql_statement.c, $ext_shared,,-I$pdo_inc_path) -fi diff --git a/ext/pdo_pgsql/config.w32 b/ext/pdo_pgsql/config.w32 deleted file mode 100644 index eaa232dfc9b1..000000000000 --- a/ext/pdo_pgsql/config.w32 +++ /dev/null @@ -1,16 +0,0 @@ -// $Id$ -// vim:ft=javascript - -ARG_WITH("pdo-pgsql", "PostgreSQL support for PDO", "no"); - -if (PHP_PDO_PGSQL != "no") { - if (CHECK_LIB("libpq.lib", "pdo_pgsql", PHP_PDO_PGSQL) && - CHECK_HEADER_ADD_INCLUDE("libpq-fe.h", "CFLAGS_PDO_PGSQL", PHP_PDO_PGSQL + ";" + PHP_PHP_BUILD + "\\include\\pgsql")) { - EXTENSION("pdo_pgsql", "pdo_pgsql.c pgsql_driver.c pgsql_statement.c"); - ADD_FLAG('CFLAGS_PDO_PGSQL', "/I ..\\pecl"); - AC_DEFINE('HAVE_PDO_PGSQL', 1, 'Have PostgreSQL library'); - } else { - WARNING("pdo_pgsql not enabled; libraries and headers not found"); - } - ADD_EXTENSION_DEP('pdo_pgsql', 'pdo'); -} diff --git a/ext/pdo_pgsql/package.xml b/ext/pdo_pgsql/package.xml deleted file mode 100644 index 290f66bdbffa..000000000000 --- a/ext/pdo_pgsql/package.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - PDO_PGSQL - PostgreSQL driver for PDO - - - edink - Edin Kadribasic - edink@php.net - lead - - - iliaa - Ilia Alshanetsky - iliaa@php.net - lead - - - - This extension provides an PostgreSQL driver for PDO. - - PHP - - alpha - 0.1 - 2004-05-21 - - - You need to install the PDO core module before you can make use of this one. - You also require PostgreSQL client libraries installed on the machine where you intend to build and/or use it. - - If you are running on windows, you can download the binary from here: - http://snaps.php.net/win32/PECL_5_0/php_pdo_pgsql.dll - - - - - - - - - - - - - - - - - - - diff --git a/ext/pdo_pgsql/pdo_pgsql.c b/ext/pdo_pgsql/pdo_pgsql.c deleted file mode 100644 index f6c4616e7a69..000000000000 --- a/ext/pdo_pgsql/pdo_pgsql.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Edin Kadribasic | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "pdo/php_pdo.h" -#include "pdo/php_pdo_driver.h" -#include "php_pdo_pgsql.h" -#include "php_pdo_pgsql_int.h" - -/* {{{ pdo_pgsql_functions[] */ -function_entry pdo_pgsql_functions[] = { - {NULL, NULL, NULL} -}; -/* }}} */ - -/* {{{ pdo_pgsql_module_entry */ -zend_module_entry pdo_pgsql_module_entry = { - STANDARD_MODULE_HEADER, - "pdo_pgsql", - pdo_pgsql_functions, - PHP_MINIT(pdo_pgsql), - PHP_MSHUTDOWN(pdo_pgsql), - PHP_RINIT(pdo_pgsql), - PHP_RSHUTDOWN(pdo_pgsql), - PHP_MINFO(pdo_pgsql), - "0.1", - STANDARD_MODULE_PROPERTIES -}; -/* }}} */ - -#ifdef COMPILE_DL_PDO_PGSQL -ZEND_GET_MODULE(pdo_pgsql) -#endif - -/* true global environment */ - -/* {{{ PHP_MINIT_FUNCTION - */ -PHP_MINIT_FUNCTION(pdo_pgsql) -{ - php_pdo_register_driver(&pdo_pgsql_driver); - return SUCCESS; -} -/* }}} */ - -/* {{{ PHP_MSHUTDOWN_FUNCTION - */ -PHP_MSHUTDOWN_FUNCTION(pdo_pgsql) -{ - php_pdo_unregister_driver(&pdo_pgsql_driver); - return SUCCESS; -} -/* }}} */ - -/* {{{ PHP_RINIT_FUNCTION - */ -PHP_RINIT_FUNCTION(pdo_pgsql) -{ - // php_pdo_register_driver(&pdo_pgsql_driver); - return SUCCESS; -} -/* }}} */ - -/* {{{ PHP_MSHUTDOWN_FUNCTION - */ -PHP_RSHUTDOWN_FUNCTION(pdo_pgsql) -{ - // php_pdo_unregister_driver(&pdo_pgsql_driver); - return SUCCESS; -} -/* }}} */ - -/* {{{ PHP_MINFO_FUNCTION - */ -PHP_MINFO_FUNCTION(pdo_pgsql) -{ - php_info_print_table_start(); - php_info_print_table_header(2, "PDO Driver for PostgreSQL", "enabled"); - php_info_print_table_end(); -} -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c deleted file mode 100644 index 063c34ed61b2..000000000000 --- a/ext/pdo_pgsql/pgsql_driver.c +++ /dev/null @@ -1,345 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Edin Kadribasic | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "pdo/php_pdo.h" -#include "pdo/php_pdo_driver.h" - -#include "pg_config.h" /* needed for PG_VERSION */ -#include "php_pdo_pgsql.h" -#include "php_pdo_pgsql_int.h" - -int _pdo_pgsql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, int errcode, const char *file, int line TSRMLS_DC) /* {{{ */ -{ - pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; - enum pdo_error_type *pdo_err = stmt ? &stmt->error_code : &dbh->error_code; - pdo_pgsql_error_info *einfo = &H->einfo; - char *errmsg = PQerrorMessage(H->server); - - einfo->errcode = errcode; - einfo->file = file; - einfo->line = line; - - if (einfo->errmsg) { - efree(einfo->errmsg); - einfo->errmsg = NULL; - } - - switch (errcode) { - case PGRES_EMPTY_QUERY: - *pdo_err = PDO_ERR_SYNTAX; - break; - - default: - *pdo_err = PDO_ERR_CANT_MAP; - break; - } - - if (errmsg) { - einfo->errmsg = estrdup(errmsg); - } - - return errcode; -} -/* }}} */ - -static int pdo_pgsql_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC) /* {{{ */ -{ - pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; - pdo_pgsql_error_info *einfo = &H->einfo; - - if (einfo->errcode) { - add_next_index_long(info, einfo->errcode); - add_next_index_string(info, einfo->errmsg, 1); - } - - return 1; -} -/* }}} */ - -static int pgsql_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */ -{ - pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; - if (H) { - if (H->server) { - PQfinish(H->server); - H->server = NULL; - } - if (H->einfo.errmsg) { - efree(H->einfo.errmsg); - H->einfo.errmsg = NULL; - } - pefree(H, dbh->is_persistent); - H = NULL; - } - return 0; -} -/* }}} */ - -static int pgsql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, long options, zval *driver_options TSRMLS_DC) -{ - pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; - pdo_pgsql_stmt *S = ecalloc(1, sizeof(pdo_pgsql_stmt)); - - S->H = H; - stmt->driver_data = S; - stmt->methods = &pgsql_stmt_methods; - - return 1; -} - -static long pgsql_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC) -{ - pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; - PGresult *res; - - if (!(res = PQexec(H->server, sql))) { - /* fatal error */ - pdo_pgsql_error(dbh, PGRES_FATAL_ERROR); - return 0; - } else { - ExecStatusType qs = PQresultStatus(res); - if (qs != PGRES_COMMAND_OK && qs != PGRES_TUPLES_OK) { - pdo_pgsql_error(dbh, qs); - PQclear(res); - return 0; - } - H->pgoid = PQoidValue(res); - PQclear(res); - } - - return 1; -} - -static int pgsql_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen TSRMLS_DC) -{ - unsigned char *escaped; - - /* escapedlen returned by PQescapeBytea() accounts for trailing 0 */ - escaped = PQescapeBytea(unquoted, unquotedlen, quotedlen); - *quotedlen += 1; - *quoted = emalloc(*quotedlen + 1); - memcpy((*quoted)+1, escaped, *quotedlen-2); - (*quoted)[0] = '\''; - (*quoted)[*quotedlen-1] = '\''; - (*quoted)[*quotedlen] = '\0'; - free(escaped); - - return 1; -} - -static long pdo_pgsql_last_insert_id(pdo_dbh_t *dbh TSRMLS_DC) -{ - pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; - - if (H->pgoid == InvalidOid) { - return -1; - } - - return (long) H->pgoid; -} - -static int pdo_pgsql_get_attribute(pdo_dbh_t *dbh, long attr, zval *return_value TSRMLS_DC) -{ - pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; - - switch (attr) { - case PDO_ATTR_CLIENT_VERSION: - ZVAL_STRING(return_value, PG_VERSION, 1); - break; - - case PDO_ATTR_SERVER_VERSION: -#ifdef HAVE_PQPROTOCOLVERSION - if (PQprotocolVersion(H->server) >= 3) { /* PostgreSQL 7.4 or later */ - ZVAL_STRING(return_value, (char*)PQparameterStatus(H->server, "server_version"), 1); - } else /* emulate above via a query */ -#endif - { - PGresult *res = PQexec(H->server, "SELECT VERSION()"); - if (res && PQresultStatus(res) == PGRES_TUPLES_OK) { - ZVAL_STRING(return_value, (char *)PQgetvalue(res, 0, 0), 1); - } - - if (res) { - PQclear(res); - } - } - break; - - case PDO_ATTR_CONNECTION_STATUS: - switch (PQstatus(H->server)) { - case CONNECTION_STARTED: - ZVAL_STRINGL(return_value, "Waiting for connection to be made.", sizeof("Waiting for connection to be made.")-1, 1); - break; - - case CONNECTION_MADE: - case CONNECTION_OK: - ZVAL_STRINGL(return_value, "Connection OK; waiting to send.", sizeof("Connection OK; waiting to send.")-1, 1); - break; - - case CONNECTION_AWAITING_RESPONSE: - ZVAL_STRINGL(return_value, "Waiting for a response from the server.", sizeof("Waiting for a response from the server.")-1, 1); - break; - - case CONNECTION_AUTH_OK: - ZVAL_STRINGL(return_value, "Received authentication; waiting for backend start-up to finish.", sizeof("Received authentication; waiting for backend start-up to finish.")-1, 1); - break; -#ifdef CONNECTION_SSL_STARTUP - case CONNECTION_SSL_STARTUP: - ZVAL_STRINGL(return_value, "Negotiating SSL encryption.", sizeof("Negotiating SSL encryption.")-1, 1); - break; -#endif - case CONNECTION_SETENV: - ZVAL_STRINGL(return_value, "Negotiating environment-driven parameter settings.", sizeof("Negotiating environment-driven parameter settings.")-1, 1); - break; - - case CONNECTION_BAD: - default: - ZVAL_STRINGL(return_value, "Bad connection.", sizeof("Bad connection.")-1, 1); - break; - } - break; - - case PDO_ATTR_SERVER_INFO: { - int spid = PQbackendPID(H->server); - char *tmp; -#ifdef HAVE_PQPROTOCOLVERSION - spprintf(&tmp, 0, - "PID: %d; Client Encoding: %s; Is Superuser: %s; Session Authorization: %s; Date Style: %s", - spid, - (char*)PQparameterStatus(H->server, "client_encoding"), - (char*)PQparameterStatus(H->server, "is_superuser"), - (char*)PQparameterStatus(H->server, "session_authorization"), - (char*)PQparameterStatus(H->server, "DateStyle")); -#else - spprintf(&tmp, 0, "PID: %d", spid); -#endif - ZVAL_STRING(return_value, tmp, 0); - } - break; - - default: - return 0; - } - - return 1; -} - -static int pdo_pgsql_transaction_cmd(const char *cmd, pdo_dbh_t *dbh TSRMLS_DC) -{ - pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; - PGresult *res; - int ret = 1; - - res = PQexec(H->server, cmd); - - if (PQresultStatus(res) != PGRES_COMMAND_OK) { - ret = 0; - } - - PQclear(res); - return ret; -} - -static int pgsql_handle_begin(pdo_dbh_t *dbh TSRMLS_DC) -{ - return pdo_pgsql_transaction_cmd("BEGIN", dbh TSRMLS_CC); -} - -static int pgsql_handle_commit(pdo_dbh_t *dbh TSRMLS_DC) -{ - return pdo_pgsql_transaction_cmd("COMMIT", dbh TSRMLS_CC); -} - -static int pgsql_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC) -{ - return pdo_pgsql_transaction_cmd("ROLLBACK", dbh TSRMLS_CC); -} - -static struct pdo_dbh_methods pgsql_methods = { - pgsql_handle_closer, - pgsql_handle_preparer, - pgsql_handle_doer, - pgsql_handle_quoter, - pgsql_handle_begin, - pgsql_handle_commit, - pgsql_handle_rollback, - NULL, - pdo_pgsql_last_insert_id, - pdo_pgsql_fetch_error_func, - pdo_pgsql_get_attribute -}; - -static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */ -{ - pdo_pgsql_db_handle *H; - int ret = 0; - - H = pecalloc(1, sizeof(pdo_pgsql_db_handle), dbh->is_persistent); - dbh->driver_data = H; - - H->einfo.errcode = 0; - H->einfo.errmsg = NULL; - - H->server = PQconnectdb(dbh->data_source); - - if (PQstatus(H->server) != CONNECTION_OK) { - pdo_pgsql_error(dbh, PGRES_FATAL_ERROR); - goto cleanup; - } - - H->attached = 1; - H->pgoid = -1; - - dbh->methods = &pgsql_methods; - dbh->alloc_own_columns = 1; - dbh->supports_placeholders = PDO_PLACEHOLDER_NONE; - dbh->max_escaped_char_length = 2; - - ret = 1; - -cleanup: - if (!ret) { - pgsql_handle_closer(dbh TSRMLS_CC); - } - - return ret; -} -/* }}} */ - -pdo_driver_t pdo_pgsql_driver = { - PDO_DRIVER_HEADER(pgsql), - pdo_pgsql_handle_factory -}; - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo_pgsql/pgsql_statement.c b/ext/pdo_pgsql/pgsql_statement.c deleted file mode 100644 index 8808e91ef770..000000000000 --- a/ext/pdo_pgsql/pgsql_statement.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Edin Kadribasic | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "pdo/php_pdo.h" -#include "pdo/php_pdo_driver.h" -#include "php_pdo_pgsql.h" -#include "php_pdo_pgsql_int.h" - - -static int pgsql_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC) -{ - pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data; - int i; - - if (S->result) { - /* free the resource */ - PQclear(S->result); - S->result = NULL; - } - if(S->cols) { - efree(S->cols); - S->cols = NULL; - } - efree(S); - return 1; -} - -static int pgsql_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC) -{ - pdo_dbh_t *dbh = stmt->dbh; - pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data; - pdo_pgsql_db_handle *H = S->H; - ExecStatusType status; - - if (stmt->executed) { - /* ensure that we free any previous unfetched results */ - if(S->result) { - PQclear(S->result); - S->result = NULL; - } - } - - S->result = PQexec(H->server, stmt->active_query_string); - status = PQresultStatus(S->result); - - if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) { - pdo_pgsql_error_stmt(stmt, status); - return 0; - } - - if(!stmt->executed) { - stmt->column_count = (int) PQnfields(S->result); - S->cols = ecalloc(stmt->column_count, sizeof(pdo_pgsql_column)); - } - - - if (status == PGRES_COMMAND_OK) { - stmt->row_count = (long)atoi(PQcmdTuples(S->result)); - } else { - stmt->row_count = (long)PQntuples(S->result); - } - - return 1; -} - -static int pgsql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param, - enum pdo_param_event event_type TSRMLS_DC) -{ - return 1; -} - -static int pgsql_stmt_fetch(pdo_stmt_t *stmt TSRMLS_DC) -{ - pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data; - - if (S->current_row < stmt->row_count) { - S->current_row++; - return 1; - } else { - return 0; - } -} - -static int pgsql_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC) -{ - pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data; - struct pdo_column_data *cols = stmt->columns; - - if (!S->result) { - return 0; - } - - cols[colno].name = estrdup(PQfname(S->result, colno)); - cols[colno].namelen = strlen(cols[colno].name); - cols[colno].maxlen = PQfsize(S->result, colno); - cols[colno].precision = PQfmod(S->result, colno); - cols[colno].param_type = PDO_PARAM_STR; - - return 1; -} - -static int pgsql_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, unsigned long *len TSRMLS_DC) -{ - pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data; - - if (!S->result) { - return 0; - } - - /* We have already increased count by 1 in pgsql_stmt_fetch() */ - *ptr = PQgetvalue(S->result, S->current_row - 1, colno); - *len = PQgetlength(S->result, S->current_row - 1, colno); - - return 1; -} - -struct pdo_stmt_methods pgsql_stmt_methods = { - pgsql_stmt_dtor, - pgsql_stmt_execute, - pgsql_stmt_fetch, - pgsql_stmt_describe, - pgsql_stmt_get_col, - pgsql_stmt_param_hook -}; - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo_pgsql/php_pdo_pgsql.h b/ext/pdo_pgsql/php_pdo_pgsql.h deleted file mode 100644 index bcfd2bb2cd69..000000000000 --- a/ext/pdo_pgsql/php_pdo_pgsql.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Edin Kadribasic | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifndef PHP_PDO_PGSQL_H -#define PHP_PDO_PGSQL_H - -#if HAVE_PDO_PGSQL - -#include - -extern zend_module_entry pdo_pgsql_module_entry; -#define phpext_pdo_pgsql_ptr &pdo_pgsql_module_entry - -#ifdef PHP_WIN32 -#define PHP_PDO_PGSQL_API __declspec(dllexport) -#else -#define PHP_PDO_PGSQL_API -#endif - -#ifdef ZTS -#include "TSRM.h" -#endif - -PHP_MINIT_FUNCTION(pdo_pgsql); -PHP_MSHUTDOWN_FUNCTION(pdo_pgsql); -PHP_RINIT_FUNCTION(pdo_pgsql); -PHP_RSHUTDOWN_FUNCTION(pdo_pgsql); -PHP_MINFO_FUNCTION(pdo_pgsql); - -#endif /* HAVE_PDO_PGSQL */ -#endif /* PHP_PDO_PGSQL_H */ - - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pdo_pgsql/php_pdo_pgsql_int.h b/ext/pdo_pgsql/php_pdo_pgsql_int.h deleted file mode 100644 index 27d84277b979..000000000000 --- a/ext/pdo_pgsql/php_pdo_pgsql_int.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Edin Kadribasic | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifndef PHP_PDO_PGSQL_INT_H -#define PHP_PDO_PGSQL_INT_H - -#if HAVE_PDO_PGSQL - -#include - -typedef struct { - const char *file; - int line; - unsigned int errcode; - char *errmsg; -} pdo_pgsql_error_info; - -/* stuff we use in a pgsql database handle */ -typedef struct { - PGconn *server; - unsigned attached:1; - unsigned _reserved:31; - pdo_pgsql_error_info einfo; - Oid pgoid; -} pdo_pgsql_db_handle; - -typedef struct { - char *def; -} pdo_pgsql_column; - -typedef struct { - pdo_pgsql_db_handle *H; - PGresult *result; - int current_row; - pdo_pgsql_column *cols; -} pdo_pgsql_stmt; - -typedef struct { - char *repr; - long repr_len; - int pgsql_type; - void *thing; /* for LOBS, REFCURSORS etc. */ -} pdo_pgsql_bound_param; - -extern pdo_driver_t pdo_pgsql_driver; - -extern int _pdo_pgsql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, int errcode, const char *file, int line TSRMLS_DC); -#define pdo_pgsql_error(d,e) _pdo_pgsql_error(d, NULL, e, __FILE__, __LINE__ TSRMLS_CC) -#define pdo_pgsql_error_stmt(s,e) _pdo_pgsql_error(s->dbh, s, e, __FILE__, __LINE__ TSRMLS_CC) - -extern struct pdo_stmt_methods pgsql_stmt_methods; - -#endif /* HAVE_PDO_PGSQL */ -#endif /* PHP_PDO_PGSQL_INT_H */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/pgsql/config.m4 b/ext/pgsql/config.m4 index b6ebfb1a5796..544776abc99b 100644 --- a/ext/pgsql/config.m4 +++ b/ext/pgsql/config.m4 @@ -2,7 +2,7 @@ dnl dnl $Id$ dnl -AC_DEFUN(PHP_PGSQL_CHECK_FUNCTIONS,[ +AC_DEFUN([PHP_PGSQL_CHECK_FUNCTIONS],[ ]) PHP_ARG_WITH(pgsql,for PostgreSQL support, @@ -76,7 +76,7 @@ if test "$PHP_PGSQL" != "no"; then AC_CHECK_LIB(pq, PQparameterStatus,AC_DEFINE(HAVE_PQPARAMETERSTATUS,1,[PostgreSQL 7.4 or later])) AC_CHECK_LIB(pq, PQprotocolVersion,AC_DEFINE(HAVE_PQPROTOCOLVERSION,1,[PostgreSQL 7.4 or later])) AC_CHECK_LIB(pq, PQtransactionStatus,AC_DEFINE(HAVE_PGTRANSACTIONSTATUS,1,[PostgreSQL 7.4 or later])) - AC_CHECK_LIB(pq, pg_encoding_to_char,AC_DEFINE(HAVE_PGSQL_WITH_MULTIBYTE_SUPPORT,1,[Whether libpq is compiled with --enable-multibye])) + AC_CHECK_LIB(pq, pg_encoding_to_char,AC_DEFINE(HAVE_PGSQL_WITH_MULTIBYTE_SUPPORT,1,[Whether libpq is compiled with --enable-multibyte])) LIBS=$old_LIBS LDFLAGS=$old_LDFLAGS diff --git a/ext/pgsql/config.w32 b/ext/pgsql/config.w32 index c66959d30215..30477ad459f6 100644 --- a/ext/pgsql/config.w32 +++ b/ext/pgsql/config.w32 @@ -8,7 +8,7 @@ if (PHP_PGSQL != "no") { CHECK_HEADER_ADD_INCLUDE("libpq-fe.h", "CFLAGS_PGSQL", PHP_PHP_BUILD + "\\include\\pgsql;" + PHP_PGSQL)) { EXTENSION("pgsql", "pgsql.c"); AC_DEFINE('HAVE_PGSQL', 1, 'Have PostgreSQL library'); - ADD_FLAG("CFLAGS_PGSQL", "/D HAVE_PQCMDTUPLES /D HAVE_PQCLIENTENCODING /D HAVE_PQESCAPE /D HAVE_PG_CONFIG_H /D PGSQL_EXPORTS"); + ADD_FLAG("CFLAGS_PGSQL", "/D HAVE_PG_CONFIG_H /D PGSQL_EXPORTS /D HAVE_PQSETNONBLOCKING /D HAVE_PQCMDTUPLES /D HAVE_PQCLIENTENCODING /D HAVE_PQESCAPE /D HAVE_PQPARAMETERSTATUS /D HAVE_PGTRANSACTIONSTATUS"); } else { WARNING("pgsql not enabled; libraries and headers not found"); } diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 414e2050ecd9..a69f1f035bc9 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -105,7 +105,9 @@ function_entry pgsql_functions[] = { PHP_FE(pg_fetch_array, NULL) PHP_FE(pg_fetch_object, NULL) PHP_FE(pg_fetch_all, NULL) +#if HAVE_PQCMDTUPLES PHP_FE(pg_affected_rows,NULL) +#endif PHP_FE(pg_get_result, NULL) PHP_FE(pg_result_seek, NULL) PHP_FE(pg_result_status,NULL) @@ -166,7 +168,9 @@ function_entry pgsql_functions[] = { /* aliases for downwards compatibility */ PHP_FALIAS(pg_exec, pg_query, NULL) PHP_FALIAS(pg_getlastoid, pg_last_oid, NULL) +#if HAVE_PQCMDTUPLES PHP_FALIAS(pg_cmdtuples, pg_affected_rows, NULL) +#endif PHP_FALIAS(pg_errormessage, pg_last_error, NULL) PHP_FALIAS(pg_numrows, pg_num_rows, NULL) PHP_FALIAS(pg_numfields, pg_num_fields, NULL) @@ -1156,6 +1160,7 @@ PHP_FUNCTION(pg_num_fields) } /* }}} */ +#if HAVE_PQCMDTUPLES /* {{{ proto int pg_affected_rows(resource result) Returns the number of affected tuples */ PHP_FUNCTION(pg_affected_rows) @@ -1163,6 +1168,7 @@ PHP_FUNCTION(pg_affected_rows) php_pgsql_get_result_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_CMD_TUPLES); } /* }}} */ +#endif /* {{{ proto string pg_last_notice(resource connection) Returns the last notice set by the backend */ @@ -2744,6 +2750,7 @@ PHP_FUNCTION(pg_copy_from) zval **tmp; char *table_name, *pg_delim = NULL, *pg_null_as = NULL; int table_name_len, pg_delim_len, pg_null_as_len; + int pg_null_as_free = 0; char *query; char *query_template = "COPY \"\" FROM STDIN DELIMITERS ':' WITH NULL AS ''"; HashPosition pos; @@ -2763,6 +2770,7 @@ PHP_FUNCTION(pg_copy_from) } if (!pg_null_as) { pg_null_as = safe_estrdup("\\\\N"); + pg_null_as_free = 1; } ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink); @@ -2775,7 +2783,9 @@ PHP_FUNCTION(pg_copy_from) } pgsql_result = PQexec(pgsql, query); - efree(pg_null_as); + if (pg_null_as_free) { + efree(pg_null_as); + } efree(query); if (pgsql_result) { @@ -3268,6 +3278,11 @@ PHP_FUNCTION(pg_get_notify) } ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink); + + if (!(result_type & PGSQL_BOTH)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid result type"); + RETURN_FALSE; + } PQconsumeInput(pgsql); pgsql_notify = PQnotifies(pgsql); @@ -3276,11 +3291,11 @@ PHP_FUNCTION(pg_get_notify) RETURN_FALSE; } array_init(return_value); - if (result_type & (PGSQL_NUM|PGSQL_BOTH)) { + if (result_type & PGSQL_NUM) { add_index_string(return_value, 0, pgsql_notify->relname, 1); add_index_long(return_value, 1, pgsql_notify->be_pid); } - if (result_type & (PGSQL_ASSOC|PGSQL_BOTH)) { + if (result_type & PGSQL_ASSOC) { add_assoc_string(return_value, "message", pgsql_notify->relname, 1); add_assoc_long(return_value, "pid", pgsql_notify->be_pid); } diff --git a/ext/pgsql/php_pgsql.h b/ext/pgsql/php_pgsql.h index f25acc9072b9..ceb9a732996a 100644 --- a/ext/pgsql/php_pgsql.h +++ b/ext/pgsql/php_pgsql.h @@ -86,7 +86,9 @@ PHP_FUNCTION(pg_fetch_object); PHP_FUNCTION(pg_fetch_result); PHP_FUNCTION(pg_fetch_row); PHP_FUNCTION(pg_fetch_all); +#if HAVE_PQCMDTUPLES PHP_FUNCTION(pg_affected_rows); +#endif PHP_FUNCTION(pg_get_result); PHP_FUNCTION(pg_result_seek); PHP_FUNCTION(pg_result_status); diff --git a/ext/posix/config.m4 b/ext/posix/config.m4 index fc3767e98b51..9bd6fdb5c5b0 100644 --- a/ext/posix/config.m4 +++ b/ext/posix/config.m4 @@ -9,5 +9,7 @@ if test "$PHP_POSIX" = "yes"; then AC_DEFINE(HAVE_POSIX, 1, [whether to include POSIX-like functions]) PHP_NEW_EXTENSION(posix, posix.c, $ext_shared) - AC_CHECK_FUNCS(seteuid setegid setsid getsid setpgid getpgid ctermid mkfifo getrlimit) + AC_CHECK_HEADERS(sys/mkdev.h) + + AC_CHECK_FUNCS(seteuid setegid setsid getsid setpgid getpgid ctermid mkfifo mknod getrlimit getlogin getgroups) fi diff --git a/ext/posix/php_posix.h b/ext/posix/php_posix.h index 1970c2dab91f..4defff806e9c 100644 --- a/ext/posix/php_posix.h +++ b/ext/posix/php_posix.h @@ -54,8 +54,12 @@ PHP_FUNCTION(posix_seteuid); #ifdef HAVE_SETEGID PHP_FUNCTION(posix_setegid); #endif +#ifdef HAVE_GETGROUPS PHP_FUNCTION(posix_getgroups); +#endif +#ifdef HAVE_GETLOGIN PHP_FUNCTION(posix_getlogin); +#endif /* POSIX.1, 4.3 */ PHP_FUNCTION(posix_getpgrp); diff --git a/ext/posix/posix.c b/ext/posix/posix.c index 107c38d26abf..a116afa33720 100644 --- a/ext/posix/posix.c +++ b/ext/posix/posix.c @@ -44,6 +44,9 @@ #include #include #include +#if HAVE_SYS_MKDEV_H +# include +#endif ZEND_DECLARE_MODULE_GLOBALS(posix) @@ -70,8 +73,12 @@ function_entry posix_functions[] = { #ifdef HAVE_SETEGID PHP_FE(posix_setegid, NULL) #endif +#ifdef HAVE_GETGROUPS PHP_FE(posix_getgroups, NULL) +#endif +#ifdef HAVE_GETLOGIN PHP_FE(posix_getlogin, NULL) +#endif /* POSIX.1, 4.3 */ PHP_FE(posix_getpgrp, NULL) @@ -180,7 +187,7 @@ ZEND_GET_MODULE(posix) #define PHP_POSIX_SINGLE_ARG_FUNC(func_name) \ long val; \ - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &val) == FAILURE) return; \ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &val) == FAILURE) RETURN_FALSE; \ if (func_name(val) < 0) { \ POSIX_G(last_error) = errno; \ RETURN_FALSE; \ @@ -194,8 +201,9 @@ PHP_FUNCTION(posix_kill) { long pid, sig; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &pid, &sig) == FAILURE) - return; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &pid, &sig) == FAILURE) { + RETURN_FALSE; + } if (kill(pid, sig) < 0) { POSIX_G(last_error) = errno; @@ -292,6 +300,7 @@ PHP_FUNCTION(posix_setegid) /* {{{ proto array posix_getgroups(void) Get supplementary group id's (POSIX.1, 4.2.3) */ +#ifdef HAVE_GETGROUPS PHP_FUNCTION(posix_getgroups) { gid_t gidlist[NGROUPS_MAX]; @@ -311,10 +320,12 @@ PHP_FUNCTION(posix_getgroups) add_next_index_long(return_value, gidlist[i]); } } +#endif /* }}} */ /* {{{ proto string posix_getlogin(void) Get user name (POSIX.1, 4.2.4) */ +#ifdef HAVE_GETLOGIN PHP_FUNCTION(posix_getlogin) { char *p; @@ -328,6 +339,7 @@ PHP_FUNCTION(posix_getlogin) RETURN_STRING(p, 1); } +#endif /* }}} */ /* {{{ proto int posix_getpgrp(void) @@ -354,8 +366,9 @@ PHP_FUNCTION(posix_setpgid) { long pid, pgid; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &pid, &pgid) == FAILURE) - return; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &pid, &pgid) == FAILURE) { + RETURN_FALSE; + } if (setpgid(pid, pgid) < 0) { POSIX_G(last_error) = errno; @@ -371,7 +384,16 @@ PHP_FUNCTION(posix_setpgid) #ifdef HAVE_GETPGID PHP_FUNCTION(posix_getpgid) { - PHP_POSIX_SINGLE_ARG_FUNC(getpgid); + long val; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &val) == FAILURE) { + RETURN_FALSE; + } + + if ((val = getpgid(val)) < 0) { + POSIX_G(last_error) = errno; + RETURN_FALSE; + } + RETURN_LONG(val); } #endif /* }}} */ @@ -381,7 +403,16 @@ PHP_FUNCTION(posix_getpgid) #ifdef HAVE_GETSID PHP_FUNCTION(posix_getsid) { - PHP_POSIX_SINGLE_ARG_FUNC(getsid); + long val; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &val) == FAILURE) { + RETURN_FALSE; + } + + if ((val = getsid(val)) < 0) { + POSIX_G(last_error) = errno; + RETURN_FALSE; + } + RETURN_LONG(val); } #endif /* }}} */ @@ -495,8 +526,9 @@ PHP_FUNCTION(posix_ttyname) char *p; int fd; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &z_fd) == FAILURE) - return; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &z_fd) == FAILURE) { + RETURN_FALSE; + } switch (Z_TYPE_P(z_fd)) { case IS_RESOURCE: @@ -525,8 +557,9 @@ PHP_FUNCTION(posix_isatty) zval *z_fd; int fd; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &z_fd) == FAILURE) - return; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &z_fd) == FAILURE) { + RETURN_FALSE; + } switch (Z_TYPE_P(z_fd)) { case IS_RESOURCE: @@ -591,8 +624,9 @@ PHP_FUNCTION(posix_mkfifo) long mode; int result; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &path, &path_len, &mode) == FAILURE) - return; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &path, &path_len, &mode) == FAILURE) { + RETURN_FALSE; + } if (PG(safe_mode) && (!php_checkuid(path, NULL, CHECKUID_ALLOW_ONLY_DIR))) { RETURN_FALSE; @@ -656,8 +690,9 @@ PHP_FUNCTION(posix_getgrnam) struct group *g; int name_len; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) - return; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) { + RETURN_FALSE; + } if (NULL == (g = getgrnam(name))) { POSIX_G(last_error) = errno; @@ -680,8 +715,9 @@ PHP_FUNCTION(posix_getgrgid) long gid; struct group *g; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &gid) == FAILURE) - return; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &gid) == FAILURE) { + RETURN_FALSE; + } if (NULL == (g = getgrgid(gid))) { POSIX_G(last_error) = errno; @@ -721,9 +757,9 @@ PHP_FUNCTION(posix_getpwnam) char *name; int name_len; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) - return; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) { + RETURN_FALSE; + } if (NULL == (pw = getpwnam(name))) { POSIX_G(last_error) = errno; RETURN_FALSE; @@ -746,8 +782,9 @@ PHP_FUNCTION(posix_getpwuid) long uid; struct passwd *pw; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &uid) == FAILURE) - return; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &uid) == FAILURE) { + RETURN_FALSE; + } if (NULL == (pw = getpwuid(uid))) { POSIX_G(last_error) = errno; @@ -895,8 +932,9 @@ PHP_FUNCTION(posix_strerror) { long error; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &error) == FAILURE) - return; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &error) == FAILURE) { + RETURN_FALSE; + } RETURN_STRING(strerror(error), 1); } diff --git a/ext/pspell/config.m4 b/ext/pspell/config.m4 index 955ddbf7706b..28be70dd206f 100644 --- a/ext/pspell/config.m4 +++ b/ext/pspell/config.m4 @@ -29,8 +29,17 @@ if test "$PHP_PSPELL" != "no"; then PSPELL_LIBDIR=$PSPELL_DIR/lib - AC_DEFINE(HAVE_PSPELL,1,[ ]) - PHP_SUBST(PSPELL_SHARED_LIBADD) PHP_ADD_LIBRARY_WITH_PATH(pspell, $PSPELL_LIBDIR, PSPELL_SHARED_LIBADD) + + dnl Add -laspell to LIBS if it exists + PHP_CHECK_LIBRARY(aspell,new_aspell_config, + [ + PHP_ADD_LIBRARY_WITH_PATH(aspell, $PSPELL_LIBDIR, PSPELL_SHARED_LIBADD) + ], [], [ + -L$PSPELL_LIBDIR + ]) + PHP_ADD_INCLUDE($PSPELL_INCDIR) + PHP_SUBST(PSPELL_SHARED_LIBADD) + AC_DEFINE(HAVE_PSPELL,1,[ ]) fi diff --git a/ext/pspell/tests/01pspell_basic.phpt b/ext/pspell/tests/01pspell_basic.phpt index 107690e08808..37676d087e87 100644 --- a/ext/pspell/tests/01pspell_basic.phpt +++ b/ext/pspell/tests/01pspell_basic.phpt @@ -4,7 +4,7 @@ pspell basic tests (warning: may fail with pspell/aspell < GNU Aspell 0.50.3) --FILE-- diff --git a/ext/readline/readline.c b/ext/readline/readline.c index 44a0808165da..9fbfb1a643de 100644 --- a/ext/readline/readline.c +++ b/ext/readline/readline.c @@ -154,13 +154,13 @@ PHP_FUNCTION(readline_info) add_assoc_long(return_value,"done",rl_done); add_assoc_long(return_value,"pending_input",rl_pending_input); add_assoc_string(return_value,"prompt",SAFE_STRING(rl_prompt),1); - add_assoc_string(return_value,"terminal_name",SAFE_STRING(rl_terminal_name),1); + add_assoc_string(return_value,"terminal_name",(char *)SAFE_STRING(rl_terminal_name),1); #endif #if HAVE_ERASE_EMPTY_LINE add_assoc_long(return_value,"erase_empty_line",rl_erase_empty_line); #endif - add_assoc_string(return_value,"library_version",SAFE_STRING(rl_library_version),1); - add_assoc_string(return_value,"readline_name",SAFE_STRING(rl_readline_name),1); + add_assoc_string(return_value,"library_version",(char *)SAFE_STRING(rl_library_version),1); + add_assoc_string(return_value,"readline_name",(char *)SAFE_STRING(rl_readline_name),1); } else { convert_to_string_ex(what); @@ -196,7 +196,7 @@ PHP_FUNCTION(readline_info) } else if (! strcasecmp(Z_STRVAL_PP(what),"prompt")) { RETVAL_STRING(SAFE_STRING(rl_prompt),1); } else if (! strcasecmp(Z_STRVAL_PP(what),"terminal_name")) { - RETVAL_STRING(SAFE_STRING(rl_terminal_name),1); + RETVAL_STRING((char *)SAFE_STRING(rl_terminal_name),1); #endif #if HAVE_ERASE_EMPTY_LINE } else if (! strcasecmp(Z_STRVAL_PP(what),"erase_empty_line")) { @@ -208,9 +208,9 @@ PHP_FUNCTION(readline_info) RETVAL_LONG(oldval); #endif } else if (! strcasecmp(Z_STRVAL_PP(what),"library_version")) { - RETVAL_STRING(SAFE_STRING(rl_library_version),1); + RETVAL_STRING((char *)SAFE_STRING(rl_library_version),1); } else if (! strcasecmp(Z_STRVAL_PP(what),"readline_name")) { - oldstr = rl_readline_name; + oldstr = (char *)rl_readline_name; if (ac == 2) { /* XXX if (rl_readline_name) free(rl_readline_name); */ convert_to_string_ex(value); @@ -393,7 +393,13 @@ static char **_readline_completion_cb(char *text, int start, int end) if (call_user_function(CG(function_table), NULL, params[0], &_readline_array, 3, params+1 TSRMLS_CC) == SUCCESS) { if (Z_TYPE(_readline_array) == IS_ARRAY) { - matches = completion_matches(text,_readline_command_generator); + if (zend_hash_num_elements(Z_ARRVAL(_readline_array))) { + matches = completion_matches(text,_readline_command_generator); + } else { + matches = malloc(sizeof(char *) * 2); + matches[0] = strdup(""); + matches[1] = '\0'; + } } } diff --git a/ext/recode/config9.m4 b/ext/recode/config9.m4 index 1ee6a6d3f0b3..2065f6c6e905 100644 --- a/ext/recode/config9.m4 +++ b/ext/recode/config9.m4 @@ -6,7 +6,6 @@ dnl Check for extensions with which Recode can not work if test "$PHP_RECODE" != "no"; then test "$PHP_IMAP" != "no" && recode_conflict="$recode_conflict imap" test "$PHP_MYSQL" != "no" && recode_conflict="$recode_conflict mysql" - test "$PHP_YAZ" != "no" && recode_conflict="$recode_conflict yaz" if test -n "$recode_conflict"; then AC_MSG_ERROR([recode extension can not be configured together with:$recode_conflict]) diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 81cde4791ed7..145b579b4f19 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -145,8 +145,10 @@ typedef struct _property_reference { /* Struct for parameters */ typedef struct _parameter_reference { - int offset; + zend_uint offset; + zend_uint required; struct _zend_arg_info *arg_info; + zend_function *fptr; } parameter_reference; /* Struct for reflection objects */ @@ -155,6 +157,7 @@ typedef struct { void *ptr; unsigned int free_ptr:1; zval *obj; + zend_class_entry *ce; } reflection_object; static zend_object_handlers reflection_object_handlers; @@ -213,6 +216,7 @@ static void reflection_objects_clone(void *object, void **object_clone TSRMLS_DC static zend_object_value reflection_objects_new(zend_class_entry *class_type TSRMLS_DC) { + zval tmp; zend_object_value retval; reflection_object *intern; @@ -226,6 +230,7 @@ static zend_object_value reflection_objects_new(zend_class_entry *class_type TSR ALLOC_HASHTABLE(intern->zo.properties); zend_hash_init(intern->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0); + zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); retval.handle = zend_objects_store_put(intern, NULL, reflection_free_objects_storage, reflection_objects_clone TSRMLS_CC); retval.handlers = &reflection_object_handlers; return retval; @@ -252,7 +257,7 @@ static void _extension_string(string *str, zend_module_entry *module, char *inde /* {{{ _class_string */ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *indent TSRMLS_DC) { - int count, count_static_props = 0, count_static_funcs = 0; + int count, count_static_props = 0, count_static_funcs = 0, count_shadow_props = 0; string sub_indent; string_init(&sub_indent); @@ -344,7 +349,9 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos); while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) { - if (prop->flags & ZEND_ACC_STATIC) { + if(prop->flags & ZEND_ACC_SHADOW) { + count_shadow_props++; + } else if (prop->flags & ZEND_ACC_STATIC) { count_static_props++; } zend_hash_move_forward_ex(&ce->properties_info, &pos); @@ -360,9 +367,10 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos); while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) { - if (prop->flags & ZEND_ACC_STATIC) { + if ((prop->flags & ZEND_ACC_STATIC) && !(prop->flags & ZEND_ACC_SHADOW)) { _property_string(str, prop, NULL, sub_indent.string TSRMLS_CC); } + zend_hash_move_forward_ex(&ce->properties_info, &pos); } } @@ -410,7 +418,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in /* Default/Implicit properties */ if (&ce->properties_info) { - count = zend_hash_num_elements(&ce->properties_info) - count_static_props; + count = zend_hash_num_elements(&ce->properties_info) - count_static_props - count_shadow_props; string_printf(str, "\n%s - Properties [%d] {\n", indent, count); if (count > 0) { HashPosition pos; @@ -419,7 +427,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos); while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) { - if (!(prop->flags & ZEND_ACC_STATIC)) { + if (!(prop->flags & (ZEND_ACC_STATIC|ZEND_ACC_SHADOW))) { _property_string(str, prop, NULL, sub_indent.string TSRMLS_CC); } zend_hash_move_forward_ex(&ce->properties_info, &pos); @@ -501,9 +509,14 @@ static void _const_string(string *str, char *name, zval *value, char *indent TSR /* }}} */ /* {{{ _parameter_string */ -static void _parameter_string(string *str, struct _zend_arg_info *arg_info, int offset, char* indent TSRMLS_DC) +static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg_info *arg_info, zend_uint offset, zend_uint required, char* indent TSRMLS_DC) { string_printf(str, "Parameter #%d [ ", offset); + if (offset >= required) { + string_printf(str, " "); + } else { + string_printf(str, " "); + } if (arg_info->class_name) { string_printf(str, "%s ", arg_info->class_name); if (arg_info->allow_null) { @@ -518,6 +531,32 @@ static void _parameter_string(string *str, struct _zend_arg_info *arg_info, int } else { string_printf(str, "$param%d", offset); } + if (fptr->type == ZEND_USER_FUNCTION && offset >= required) { + zend_op *precv = &((zend_op_array*)fptr)->opcodes[offset*2 + 1]; + if (precv->opcode == ZEND_RECV_INIT && precv->op2.op_type != IS_UNUSED) { + zval *zv, zv_copy; + int use_copy; + string_write(str, " = ", sizeof(" = ")-1); + zv_copy = precv->op2.u.constant; + zv = &zv_copy; + zval_update_constant(&zv, (void*)1 TSRMLS_CC); + if (Z_TYPE_P(zv) == IS_NULL) { + string_write(str, "NULL", sizeof("NULL")-1); + } else if (Z_TYPE_P(zv) == IS_STRING) { + string_write(str, "'", sizeof("'")-1); + string_write(str, Z_STRVAL_P(zv), MIN(Z_STRLEN_P(zv), 15)); + if (Z_STRLEN_P(zv) > 15) { + string_write(str, "...", sizeof("...")-1); + } + string_write(str, "'", sizeof("'")-1); + } else { + zend_make_printable_zval(zv, &zv_copy, &use_copy); + string_write(str, Z_STRVAL(zv_copy), Z_STRLEN(zv_copy)); + zval_dtor(&zv_copy); + } + zval_ptr_dtor(&zv); + } + } string_write(str, " ]", sizeof(" ]")-1); } /* }}} */ @@ -525,8 +564,8 @@ static void _parameter_string(string *str, struct _zend_arg_info *arg_info, int /* {{{ _function_parameter_string */ static void _function_parameter_string(string *str, zend_function *fptr, char* indent TSRMLS_DC) { - zend_uint i; struct _zend_arg_info *arg_info = fptr->common.arg_info; + zend_uint i, required = fptr->common.required_num_args; if (!arg_info) { return; @@ -536,7 +575,7 @@ static void _function_parameter_string(string *str, zend_function *fptr, char* i string_printf(str, "%s- Parameters [%d] {\n", indent, fptr->common.num_args); for (i = 0; i < fptr->common.num_args; i++) { string_printf(str, "%s ", indent); - _parameter_string(str, arg_info, i, indent TSRMLS_CC); + _parameter_string(str, fptr, arg_info, i, required, indent TSRMLS_CC); string_write(str, "\n", sizeof("\n")-1); arg_info++; } @@ -586,6 +625,9 @@ static void _function_string(string *str, zend_function *fptr, char* indent TSRM case ZEND_ACC_PROTECTED: string_printf(str, "protected "); break; + default: + string_printf(str, " "); + break; } string_printf(str, fptr->common.scope ? "method " : "function "); @@ -779,8 +821,8 @@ static void _function_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask) } /* }}} */ -/* {{{ reflection_class_factory */ -static void reflection_class_factory(zend_class_entry *ce, zval *object TSRMLS_DC) +/* {{{ zend_reflection_class_factory */ +ZEND_API void zend_reflection_class_factory(zend_class_entry *ce, zval *object TSRMLS_DC) { reflection_object *intern; zval *name; @@ -791,6 +833,7 @@ static void reflection_class_factory(zend_class_entry *ce, zval *object TSRMLS_D intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC); intern->ptr = ce; intern->free_ptr = 0; + intern->ce = ce; zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); } /* }}} */ @@ -818,12 +861,13 @@ static void reflection_extension_factory(zval *object, char *name_str TSRMLS_DC) ZVAL_STRINGL(name, module->name, name_len, 1); intern->ptr = module; intern->free_ptr = 0; + intern->ce = NULL; zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); } /* }}} */ /* {{{ reflection_parameter_factory */ -static void reflection_parameter_factory(struct _zend_arg_info *arg_info, int offset, zval *object TSRMLS_DC) +static void reflection_parameter_factory(zend_function *fptr, struct _zend_arg_info *arg_info, zend_uint offset, zend_uint required, zval *object TSRMLS_DC) { reflection_object *intern; parameter_reference *reference; @@ -840,8 +884,11 @@ static void reflection_parameter_factory(struct _zend_arg_info *arg_info, int of reference = (parameter_reference*) emalloc(sizeof(parameter_reference)); reference->arg_info = arg_info; reference->offset = offset; + reference->required = required; + reference->fptr = fptr; intern->ptr = reference; intern->free_ptr = 1; + intern->ce = fptr->common.scope; zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); } /* }}} */ @@ -859,6 +906,7 @@ static void reflection_function_factory(zend_function *function, zval *object TS intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC); intern->ptr = function; intern->free_ptr = 0; + intern->ce = NULL; zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); } /* }}} */ @@ -878,6 +926,7 @@ static void reflection_method_factory(zend_class_entry *ce, zend_function *metho intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC); intern->ptr = method; intern->free_ptr = 0; + intern->ce = ce; zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL); } @@ -923,6 +972,7 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info reference->prop = prop; intern->ptr = reference; intern->free_ptr = 1; + intern->ce = ce; zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL); } @@ -1051,7 +1101,7 @@ ZEND_METHOD(reflection, export) zval_ptr_dtor(&fname); if (result == FAILURE) { - _DO_THROW("Invokation of method __toString() failed"); + _DO_THROW("Invocation of method __toString() failed"); /* Returns from this function */ } @@ -1084,32 +1134,32 @@ ZEND_METHOD(reflection, getModifierNames) array_init(return_value); if (modifiers & (ZEND_ACC_ABSTRACT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) { - add_next_index_stringl(return_value, "abstract", sizeof("abstract"), 1); + add_next_index_stringl(return_value, "abstract", sizeof("abstract")-1, 1); } if (modifiers & (ZEND_ACC_FINAL | ZEND_ACC_FINAL_CLASS)) { - add_next_index_stringl(return_value, "final", sizeof("final"), 1); + add_next_index_stringl(return_value, "final", sizeof("final")-1, 1); } /* These are mutually exclusive */ switch (modifiers & ZEND_ACC_PPP_MASK) { case ZEND_ACC_PUBLIC: - add_next_index_stringl(return_value, "public", sizeof("public"), 1); + add_next_index_stringl(return_value, "public", sizeof("public")-1, 1); break; case ZEND_ACC_PRIVATE: - add_next_index_stringl(return_value, "private", sizeof("private"), 1); + add_next_index_stringl(return_value, "private", sizeof("private")-1, 1); break; case ZEND_ACC_PROTECTED: - add_next_index_stringl(return_value, "protected", sizeof("protected"), 1); + add_next_index_stringl(return_value, "protected", sizeof("protected")-1, 1); break; } if (modifiers & ZEND_ACC_STATIC) { - add_next_index_stringl(return_value, "static", sizeof("static"), 1); + add_next_index_stringl(return_value, "static", sizeof("static")-1, 1); } } /* }}} */ -/* {{{ proto public static mixed ReflectionFunction::export(string name, [, bool return]) throws ReflectionException +/* {{{ proto public static mixed ReflectionFunction::export(string name [, bool return]) throws ReflectionException Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */ ZEND_METHOD(reflection_function, export) { @@ -1152,6 +1202,7 @@ ZEND_METHOD(reflection_function, __construct) zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); intern->ptr = fptr; intern->free_ptr = 0; + intern->ce = NULL; } /* }}} */ @@ -1283,7 +1334,8 @@ ZEND_METHOD(reflection_function, getStaticVariables) /* Return an empty array in case no static variables exist */ array_init(return_value); - if (fptr->op_array.static_variables != NULL) { + if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.static_variables != NULL) { + zend_hash_apply_with_argument(fptr->op_array.static_variables, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC); zend_hash_copy(Z_ARRVAL_P(return_value), fptr->op_array.static_variables, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *)); } } @@ -1332,7 +1384,7 @@ ZEND_METHOD(reflection_function, invoke) if (result == FAILURE) { zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, - "Invokation of method %s() failed", fptr->common.function_name); + "Invocation of method %s() failed", fptr->common.function_name); return; } @@ -1356,13 +1408,41 @@ ZEND_METHOD(reflection_function, returnsReference) } /* }}} */ +/* {{{ proto public bool ReflectionFunction::getNumberOfParameters() + Gets the number of required parameters */ +ZEND_METHOD(reflection_function, getNumberOfParameters) +{ + reflection_object *intern; + zend_function *fptr; + + METHOD_NOTSTATIC; + GET_REFLECTION_OBJECT_PTR(fptr); + + RETURN_LONG(fptr->common.num_args); +} +/* }}} */ + +/* {{{ proto public bool ReflectionFunction::getNumberOfRequiredParameters() + Gets the number of required parameters */ +ZEND_METHOD(reflection_function, getNumberOfRequiredParameters) +{ + reflection_object *intern; + zend_function *fptr; + + METHOD_NOTSTATIC; + GET_REFLECTION_OBJECT_PTR(fptr); + + RETURN_LONG(fptr->common.required_num_args); +} +/* }}} */ + /* {{{ proto public ReflectionParameter[] Reflection_Function::getParameters() Returns an array of parameter objects for this function */ ZEND_METHOD(reflection_function, getParameters) { reflection_object *intern; zend_function *fptr; - int i; + zend_uint i; struct _zend_arg_info *arg_info; METHOD_NOTSTATIC; @@ -1375,7 +1455,7 @@ ZEND_METHOD(reflection_function, getParameters) zval *parameter; ALLOC_ZVAL(parameter); - reflection_parameter_factory(arg_info, i, parameter TSRMLS_CC); + reflection_parameter_factory(fptr, arg_info, i, fptr->common.required_num_args, parameter TSRMLS_CC); add_next_index_zval(return_value, parameter); arg_info++; @@ -1383,7 +1463,7 @@ ZEND_METHOD(reflection_function, getParameters) } /* }}} */ -/* {{{ proto public static mixed ReflectionParameter::export(mixed function, mixed parameter, [, bool return]) throws ReflectionException +/* {{{ proto public static mixed ReflectionParameter::export(mixed function, mixed parameter [, bool return]) throws ReflectionException Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */ ZEND_METHOD(reflection_parameter, export) { @@ -1403,6 +1483,7 @@ ZEND_METHOD(reflection_parameter, __construct) zend_function *fptr; struct _zend_arg_info *arg_info; int position; + zend_class_entry *ce = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &reference, ¶meter) == FAILURE) { return; @@ -1435,7 +1516,6 @@ ZEND_METHOD(reflection_parameter, __construct) case IS_ARRAY: { zval **classref; zval **method; - zend_class_entry *ce; zend_class_entry **pce; char *lcname; @@ -1479,12 +1559,12 @@ ZEND_METHOD(reflection_parameter, __construct) arg_info = fptr->common.arg_info; if (Z_TYPE_P(parameter) == IS_LONG) { position= Z_LVAL_P(parameter); - if (position < 0 || position >= fptr->common.num_args) { + if (position < 0 || (zend_uint)position >= fptr->common.num_args) { _DO_THROW("The parameter specified by its offset could not be found"); /* returns out of this function */ } } else { - int i; + zend_uint i; position= -1; convert_to_string_ex(¶meter); @@ -1510,9 +1590,12 @@ ZEND_METHOD(reflection_parameter, __construct) ref = (parameter_reference*) emalloc(sizeof(parameter_reference)); ref->arg_info = &arg_info[position]; - ref->offset = position; + ref->offset = (zend_uint)position; + ref->required = fptr->common.required_num_args; + ref->fptr = fptr; intern->ptr = ref; intern->free_ptr = 1; + intern->ce = ce; } /* }}} */ @@ -1527,7 +1610,7 @@ ZEND_METHOD(reflection_parameter, __toString) METHOD_NOTSTATIC_NUMPARAMS(0); GET_REFLECTION_OBJECT_PTR(param); string_init(&str); - _parameter_string(&str, param->arg_info, param->offset, "" TSRMLS_CC); + _parameter_string(&str, param->fptr, param->arg_info, param->offset, param->required, "" TSRMLS_CC); RETURN_STRINGL(str.string, str.len - 1, 0); } /* }}} */ @@ -1541,7 +1624,7 @@ ZEND_METHOD(reflection_parameter, getName) } /* }}} */ -/* {{{ proto public ReflectionClass Reflection_Parameter::getClass() +/* {{{ proto public ReflectionClass ReflectionParameter::getClass() Returns this parameters's class hint or NULL if there is none */ ZEND_METHOD(reflection_parameter, getClass) { @@ -1564,7 +1647,7 @@ ZEND_METHOD(reflection_parameter, getClass) return; } free_alloca(lcname); - reflection_class_factory(*pce, return_value TSRMLS_CC); + zend_reflection_class_factory(*pce, return_value TSRMLS_CC); } } /* }}} */ @@ -1597,7 +1680,81 @@ ZEND_METHOD(reflection_parameter, isPassedByReference) } /* }}} */ -/* {{{ proto public static mixed ReflectionMethod::export(mixed class, string name, [, bool return]) throws ReflectionException +/* {{{ proto public bool ReflectionParameter::isOptional() + Returns whether this parameter is an optional parameter */ +ZEND_METHOD(reflection_parameter, isOptional) +{ + reflection_object *intern; + parameter_reference *param; + + METHOD_NOTSTATIC_NUMPARAMS(0); + GET_REFLECTION_OBJECT_PTR(param); + + RETVAL_BOOL(param->offset >= param->required); +} +/* }}} */ + +/* {{{ proto public bool ReflectionParameter::isDefaultValueAvailable() + Returns whether the default value of this parameter is available */ +ZEND_METHOD(reflection_parameter, isDefaultValueAvailable) +{ + reflection_object *intern; + parameter_reference *param; + zend_op *precv; + + METHOD_NOTSTATIC_NUMPARAMS(0); + GET_REFLECTION_OBJECT_PTR(param); + + if (param->fptr->type != ZEND_USER_FUNCTION) + { + RETURN_FALSE; + } + if (param->offset < param->required) { + RETURN_FALSE; + } + precv = &((zend_op_array*)param->fptr)->opcodes[param->offset*2 + 1]; + if (precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) { + RETURN_FALSE; + } + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto public bool ReflectionParameter::getDefaultValue() + Returns the default value of this parameter or throws an exception */ +ZEND_METHOD(reflection_parameter, getDefaultValue) +{ + reflection_object *intern; + parameter_reference *param; + zend_op *precv; + zval *zv, zv_copy; + + METHOD_NOTSTATIC_NUMPARAMS(0); + GET_REFLECTION_OBJECT_PTR(param); + + if (param->fptr->type != ZEND_USER_FUNCTION) + { + zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Cannot determine default value for internal functions"); + return; + } + if (param->offset < param->required) { + zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Parameter is not optional"); + return; + } + precv = &((zend_op_array*)param->fptr)->opcodes[param->offset*2 + 1]; + if (precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) { + zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Internal error"); + return; + } + + zv_copy = precv->op2.u.constant; + zv = &zv_copy; + zval_update_constant(&zv, (void*)0 TSRMLS_CC); + RETURN_ZVAL(zv, 1, 1); +} +/* }}} */ + +/* {{{ proto public static mixed ReflectionMethod::export(mixed class, string name [, bool return]) throws ReflectionException Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */ ZEND_METHOD(reflection_method, export) { @@ -1669,6 +1826,7 @@ ZEND_METHOD(reflection_method, __construct) zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); intern->ptr = mptr; intern->free_ptr = 0; + intern->ce = ce; } /* }}} */ @@ -1689,7 +1847,7 @@ ZEND_METHOD(reflection_method, __toString) /* }}} */ /* {{{ proto public mixed ReflectionMethod::invoke(mixed object, mixed* args) - Invokes the function. Pass a */ + Invokes the method. */ ZEND_METHOD(reflection_method, invoke) { zval *retval_ptr; @@ -1706,7 +1864,7 @@ ZEND_METHOD(reflection_method, invoke) METHOD_NOTSTATIC; if (argc < 1) { - zend_error(E_WARNING, "%s expects at least one parameter, none given", get_active_function_name(TSRMLS_C)); + zend_error(E_WARNING, "Invoke() expects at least one parameter, none given"); RETURN_FALSE; } @@ -1716,11 +1874,11 @@ ZEND_METHOD(reflection_method, invoke) (mptr->common.fn_flags & ZEND_ACC_ABSTRACT)) { if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) { zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, - "Trying to invoke abstract method %s::%s", + "Trying to invoke abstract method %s::%s()", mptr->common.scope->name, mptr->common.function_name); } else { zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, - "Trying to invoke %s method %s::%s from scope %s", + "Trying to invoke %s method %s::%s() from scope %s", mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private", mptr->common.scope->name, mptr->common.function_name, Z_OBJCE_P(getThis())->name); @@ -1781,7 +1939,7 @@ ZEND_METHOD(reflection_method, invoke) if (result == FAILURE) { zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, - "Invokation of method %s::%s() failed", mptr->common.scope->name, mptr->common.function_name); + "Invocation of method %s::%s() failed", mptr->common.scope->name, mptr->common.function_name); return; } @@ -1848,7 +2006,10 @@ ZEND_METHOD(reflection_method, isConstructor) METHOD_NOTSTATIC_NUMPARAMS(0); GET_REFLECTION_OBJECT_PTR(mptr); - RETURN_BOOL(mptr->common.scope->constructor == mptr); + /* we need to check if the ctor is the ctor of the class level we we + * looking at since we might be looking at an inherited old style ctor + * defined in base class. */ + RETURN_BOOL(mptr->common.fn_flags & ZEND_ACC_CTOR && intern->ce->constructor && intern->ce->constructor->common.scope == mptr->common.scope); } /* }}} */ @@ -1861,7 +2022,7 @@ ZEND_METHOD(reflection_method, isDestructor) METHOD_NOTSTATIC_NUMPARAMS(0); GET_REFLECTION_OBJECT_PTR(mptr); - RETURN_BOOL(mptr->common.scope->destructor == mptr); + RETURN_BOOL(mptr->common.fn_flags & ZEND_ACC_DTOR); } /* }}} */ @@ -1879,7 +2040,7 @@ ZEND_METHOD(reflection_method, getModifiers) } /* }}} */ -/* {{{ proto public ReflectionClass Reflection_Method::getDeclaringClass() +/* {{{ proto public ReflectionClass ReflectionMethod::getDeclaringClass() Get the declaring class */ ZEND_METHOD(reflection_method, getDeclaringClass) { @@ -1889,11 +2050,11 @@ ZEND_METHOD(reflection_method, getDeclaringClass) METHOD_NOTSTATIC; GET_REFLECTION_OBJECT_PTR(mptr); - reflection_class_factory(mptr->common.scope, return_value TSRMLS_CC); + zend_reflection_class_factory(mptr->common.scope, return_value TSRMLS_CC); } /* }}} */ -/* {{{ proto public static mixed ReflectionClass::export(mixed argument, [, bool return]) throws ReflectionException +/* {{{ proto public static mixed ReflectionClass::export(mixed argument [, bool return]) throws ReflectionException Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */ ZEND_METHOD(reflection_class, export) { @@ -1970,6 +2131,9 @@ ZEND_METHOD(reflection_class, getStaticProperties) METHOD_NOTSTATIC_NUMPARAMS(0); GET_REFLECTION_OBJECT_PTR(ce); + + zend_update_class_constants(ce TSRMLS_CC); + array_init(return_value); zend_hash_copy(Z_ARRVAL_P(return_value), ce->static_members, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *)); } @@ -1987,6 +2151,8 @@ ZEND_METHOD(reflection_class, getDefaultProperties) GET_REFLECTION_OBJECT_PTR(ce); array_init(return_value); + zend_update_class_constants(ce TSRMLS_CC); + count = zend_hash_num_elements(&ce->default_properties); if (count > 0) { HashPosition pos; @@ -2134,7 +2300,7 @@ ZEND_METHOD(reflection_class, getDocComment) } /* }}} */ -/* {{{ proto public ReflectionMethod Reflection_Class::getConstructor() +/* {{{ proto public ReflectionMethod ReflectionClass::getConstructor() Returns the class' constructor if there is one, NULL otherwise */ ZEND_METHOD(reflection_class, getConstructor) { @@ -2152,14 +2318,14 @@ ZEND_METHOD(reflection_class, getConstructor) } /* }}} */ -/* {{{ proto public ReflectionMethod Reflection_Class::getMethod(string name) - Returns the class' method specified by it's name */ +/* {{{ proto public ReflectionMethod ReflectionClass::getMethod(string name) throws ReflectionException + Returns the class' method specified by its name */ ZEND_METHOD(reflection_class, getMethod) { reflection_object *intern; zend_class_entry *ce; zend_function *mptr; - char *name; + char *name, *lc_name; int name_len; METHOD_NOTSTATIC; @@ -2168,11 +2334,15 @@ ZEND_METHOD(reflection_class, getMethod) } GET_REFLECTION_OBJECT_PTR(ce); - zend_str_tolower(name, name_len); - if (zend_hash_find(&ce->function_table, name, name_len + 1, (void**) &mptr) == SUCCESS) { + lc_name = zend_str_tolower_dup(name, name_len); + if (zend_hash_find(&ce->function_table, lc_name, name_len + 1, (void**) &mptr) == SUCCESS) { reflection_method_factory(ce, mptr, return_value TSRMLS_CC); + efree(lc_name); } else { - RETURN_NULL(); + efree(lc_name); + zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, + "Method %s does not exist", name); + return; } } /* }}} */ @@ -2195,7 +2365,7 @@ static int _addmethod(zend_function *mptr, int num_args, va_list args, zend_hash } /* }}} */ -/* {{{ proto public ReflectionMethod[] Reflection_Class::getMethods() +/* {{{ proto public ReflectionMethod[] ReflectionClass::getMethods() Returns an array of this class' methods */ ZEND_METHOD(reflection_class, getMethods) { @@ -2221,8 +2391,8 @@ ZEND_METHOD(reflection_class, getMethods) } /* }}} */ -/* {{{ proto public ReflectionProperty Reflection_Class::getProperty(string name) - Returns the class' property specified by it's name */ +/* {{{ proto public ReflectionProperty ReflectionClass::getProperty(string name) throws ReflectionException + Returns the class' property specified by its name */ ZEND_METHOD(reflection_class, getProperty) { reflection_object *intern; @@ -2237,10 +2407,12 @@ ZEND_METHOD(reflection_class, getProperty) } GET_REFLECTION_OBJECT_PTR(ce); - if (zend_hash_find(&ce->properties_info, name, name_len + 1, (void**) &property_info) == SUCCESS) { + if (zend_hash_find(&ce->properties_info, name, name_len + 1, (void**) &property_info) == SUCCESS && (property_info->flags & ZEND_ACC_SHADOW) == 0) { reflection_property_factory(ce, property_info, return_value TSRMLS_CC); } else { - RETURN_NULL(); + zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, + "Property %s does not exist", name); + return; } } /* }}} */ @@ -2253,6 +2425,10 @@ static int _addproperty(zend_property_info *pptr, int num_args, va_list args, ze zval *retval = va_arg(args, zval*); long filter = va_arg(args, long); + if (pptr->flags & ZEND_ACC_SHADOW) { + return 0; + } + if (pptr->flags & filter) { TSRMLS_FETCH(); ALLOC_ZVAL(property); @@ -2263,7 +2439,7 @@ static int _addproperty(zend_property_info *pptr, int num_args, va_list args, ze } /* }}} */ -/* {{{ proto public ReflectionProperty[] Reflection_Class::getProperties() +/* {{{ proto public ReflectionProperty[] ReflectionClass::getProperties() Returns an array of this class' properties */ ZEND_METHOD(reflection_class, getProperties) { @@ -2300,6 +2476,7 @@ ZEND_METHOD(reflection_class, getConstants) METHOD_NOTSTATIC_NUMPARAMS(0); GET_REFLECTION_OBJECT_PTR(ce); array_init(return_value); + zend_hash_apply_with_argument(&ce->constants_table, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC); zend_hash_copy(Z_ARRVAL_P(return_value), &ce->constants_table, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *)); } /* }}} */ @@ -2320,6 +2497,7 @@ ZEND_METHOD(reflection_class, getConstant) } GET_REFLECTION_OBJECT_PTR(ce); + zend_hash_apply_with_argument(&ce->constants_table, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC); if (zend_hash_find(&ce->constants_table, name, name_len + 1, (void **) &value) == FAILURE) { RETURN_FALSE; } @@ -2349,7 +2527,7 @@ ZEND_METHOD(reflection_class, isInstantiable) METHOD_NOTSTATIC_NUMPARAMS(0); GET_REFLECTION_OBJECT_PTR(ce); - if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_ABSTRACT)) { + if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) { RETURN_FALSE; } @@ -2383,7 +2561,7 @@ ZEND_METHOD(reflection_class, isFinal) Returns whether this class is abstract */ ZEND_METHOD(reflection_class, isAbstract) { - _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_IMPLICIT_ABSTRACT_CLASS); + _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS); } /* }}} */ @@ -2467,7 +2645,7 @@ ZEND_METHOD(reflection_class, newInstance) if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) { efree(params); zval_ptr_dtor(&retval_ptr); - zend_error(E_WARNING, "Invokation of %s's constructor failed", ce->name); + zend_error(E_WARNING, "Invocation of %s's constructor failed", ce->name); RETURN_NULL(); } if (retval_ptr) { @@ -2478,7 +2656,7 @@ ZEND_METHOD(reflection_class, newInstance) } /* }}} */ -/* {{{ proto public ReflectionClass[] Reflection_Class::getInterfaces() +/* {{{ proto public ReflectionClass[] ReflectionClass::getInterfaces() Returns an array of interfaces this class implements */ ZEND_METHOD(reflection_class, getInterfaces) { @@ -2497,14 +2675,14 @@ ZEND_METHOD(reflection_class, getInterfaces) for (i=0; i < ce->num_interfaces; i++) { zval *interface; ALLOC_ZVAL(interface); - reflection_class_factory(ce->interfaces[i], interface TSRMLS_CC); + zend_reflection_class_factory(ce->interfaces[i], interface TSRMLS_CC); add_next_index_zval(return_value, interface); } } } /* }}} */ -/* {{{ proto public ReflectionClass Reflection_Class::getParentClass() +/* {{{ proto public ReflectionClass ReflectionClass::getParentClass() Returns the class' parent class, or, if none exists, FALSE */ ZEND_METHOD(reflection_class, getParentClass) { @@ -2515,14 +2693,14 @@ ZEND_METHOD(reflection_class, getParentClass) GET_REFLECTION_OBJECT_PTR(ce); if (ce->parent) { - reflection_class_factory(ce->parent, return_value TSRMLS_CC); + zend_reflection_class_factory(ce->parent, return_value TSRMLS_CC); } else { RETURN_FALSE; } } /* }}} */ -/* {{{ proto public bool ReflectionClass::isSubclassOf(string|reflection_class class) +/* {{{ proto public bool ReflectionClass::isSubclassOf(string|ReflectionClass class) Returns whether this class is a subclass of another class */ ZEND_METHOD(reflection_class, isSubclassOf) { @@ -2541,7 +2719,7 @@ ZEND_METHOD(reflection_class, isSubclassOf) case IS_STRING: if (zend_lookup_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), &pce TSRMLS_CC) == FAILURE) { zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, - "Interface %s doesn't exist", Z_STRVAL_P(class_name)); + "Interface %s does not exist", Z_STRVAL_P(class_name)); return; } class_ce = *pce; @@ -2559,7 +2737,7 @@ ZEND_METHOD(reflection_class, isSubclassOf) /* no break */ default: zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, - "Parameter one must either be a string or a Reflection_Class object"); + "Parameter one must either be a string or a ReflectionClass object"); return; } @@ -2568,7 +2746,7 @@ ZEND_METHOD(reflection_class, isSubclassOf) } /* }}} */ -/* {{{ proto public bool ReflectionClass::implementsInterface(string|reflection_class interface_name) +/* {{{ proto public bool ReflectionClass::implementsInterface(string|ReflectionClass interface_name) Returns whether this class is a subclass of another class */ ZEND_METHOD(reflection_class, implementsInterface) { @@ -2587,7 +2765,7 @@ ZEND_METHOD(reflection_class, implementsInterface) case IS_STRING: if (zend_lookup_class(Z_STRVAL_P(interface), Z_STRLEN_P(interface), &pce TSRMLS_CC) == FAILURE) { zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, - "Interface %s doesn't exist", Z_STRVAL_P(interface)); + "Interface %s does not exist", Z_STRVAL_P(interface)); return; } interface_ce = *pce; @@ -2605,7 +2783,7 @@ ZEND_METHOD(reflection_class, implementsInterface) /* no break */ default: zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, - "Parameter one must either be a string or a Reflection_Class object"); + "Parameter one must either be a string or a ReflectionClass object"); return; } @@ -2632,7 +2810,7 @@ ZEND_METHOD(reflection_class, isIterateable) } /* }}} */ -/* {{{ proto public ReflectionExtension|NULL Reflection_Class::getExtension() +/* {{{ proto public ReflectionExtension|NULL ReflectionClass::getExtension() Returns NULL or the extension the class belongs to */ ZEND_METHOD(reflection_class, getExtension) { @@ -2666,7 +2844,7 @@ ZEND_METHOD(reflection_class, getExtensionName) } /* }}} */ -/* {{{ proto public static mixed ReflectionObject::export(mixed argument, [, bool return]) throws ReflectionException +/* {{{ proto public static mixed ReflectionObject::export(mixed argument [, bool return]) throws ReflectionException Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */ ZEND_METHOD(reflection_object, export) { @@ -2682,7 +2860,7 @@ ZEND_METHOD(reflection_object, __construct) } /* }}} */ -/* {{{ proto public static mixed ReflectionProperty::export(mixed class, string name, [, bool return]) throws ReflectionException +/* {{{ proto public static mixed ReflectionProperty::export(mixed class, string name [, bool return]) throws ReflectionException Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */ ZEND_METHOD(reflection_property, export) { @@ -2695,7 +2873,7 @@ ZEND_METHOD(reflection_property, export) ZEND_METHOD(reflection_property, __construct) { zval *propname, *classname; - char *name_str; + char *name_str, *class_name, *prop_name; int name_len; zval *object; reflection_object *intern; @@ -2734,7 +2912,7 @@ ZEND_METHOD(reflection_property, __construct) /* returns out of this function */ } - if (zend_hash_find(&ce->properties_info, name_str, name_len + 1, (void **) &property_info) == FAILURE) { + if (zend_hash_find(&ce->properties_info, name_str, name_len + 1, (void **) &property_info) == FAILURE || (property_info->flags & ZEND_ACC_SHADOW)) { zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Property %s::$%s does not exist", ce->name, name_str); return; @@ -2760,8 +2938,9 @@ ZEND_METHOD(reflection_property, __construct) ZVAL_STRINGL(classname, ce->name, ce->name_length, 1); zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL); + zend_unmangle_property_name(property_info->name, &class_name, &prop_name); MAKE_STD_ZVAL(propname); - ZVAL_STRING(propname, property_info->name, 1); + ZVAL_STRING(propname, prop_name, 1); zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &propname, sizeof(zval *), NULL); reference = (property_reference*) emalloc(sizeof(property_reference)); @@ -2769,6 +2948,7 @@ ZEND_METHOD(reflection_property, __construct) reference->prop = property_info; intern->ptr = reference; intern->free_ptr = 1; + intern->ce = ce; } /* }}} */ @@ -2861,7 +3041,7 @@ ZEND_METHOD(reflection_property, getModifiers) } /* }}} */ -/* {{{ proto public mixed ReflectionProperty::getValue(stdclass object) +/* {{{ proto public mixed ReflectionProperty::getValue([stdclass object]) Returns this property's value */ ZEND_METHOD(reflection_property, getValue) { @@ -2878,16 +3058,16 @@ ZEND_METHOD(reflection_property, getValue) /* Returns from this function */ } - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &object) == FAILURE) { - return; - } - if ((ref->prop->flags & ZEND_ACC_STATIC)) { - if (zend_hash_quick_find(Z_OBJCE_P(object)->static_members, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) { + zend_update_class_constants(intern->ce TSRMLS_CC); + if (zend_hash_quick_find(intern->ce->static_members, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) { zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name); /* Bails out */ } } else { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &object) == FAILURE) { + return; + } if (zend_hash_quick_find(Z_OBJPROP_P(object), ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) { zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name); /* Bails out */ @@ -2899,7 +3079,7 @@ ZEND_METHOD(reflection_property, getValue) } /* }}} */ -/* {{{ proto public void ReflectionProperty::setValue(stdclass object, mixed value) +/* {{{ proto public void ReflectionProperty::setValue([stdclass object,] mixed value) Sets this property's value */ ZEND_METHOD(reflection_property, setValue) { @@ -2909,38 +3089,48 @@ ZEND_METHOD(reflection_property, setValue) zval *object; zval *value; int setter_done = 0; + zval *tmp; + HashTable *prop_table; METHOD_NOTSTATIC; GET_REFLECTION_OBJECT_PTR(ref); - if (ref->prop->flags & ~ZEND_ACC_PUBLIC) { + if (ref->prop->flags & ~(ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)) { _DO_THROW("Cannot access non-public member"); /* Returns from this function */ } - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "oz", &object, &value) == FAILURE) { - return; - } - - if (zend_hash_quick_find(Z_OBJPROP_P(object), ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &variable_ptr) == SUCCESS) { - if (*variable_ptr == value) { - setter_done = 1; - } else { - if (PZVAL_IS_REF(*variable_ptr)) { - zval_dtor(*variable_ptr); - (*variable_ptr)->type = value->type; - (*variable_ptr)->value = value->value; - if (value->refcount > 0) { - zval_copy_ctor(*variable_ptr); - } - setter_done = 1; + if ((ref->prop->flags & ZEND_ACC_STATIC)) { + if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &tmp, &value) == FAILURE) { + return; } } + prop_table = intern->ce->static_members; } else { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "oz", &object, &value) == FAILURE) { + return; + } + prop_table = Z_OBJPROP_P(object); + } + + if (zend_hash_quick_find(prop_table, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &variable_ptr) == FAILURE) { zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name); /* Bails out */ } - + if (*variable_ptr == value) { + setter_done = 1; + } else { + if (PZVAL_IS_REF(*variable_ptr)) { + zval_dtor(*variable_ptr); + (*variable_ptr)->type = value->type; + (*variable_ptr)->value = value->value; + if (value->refcount > 0) { + zval_copy_ctor(*variable_ptr); + } + setter_done = 1; + } + } if (!setter_done) { zval **foo; @@ -2948,12 +3138,12 @@ ZEND_METHOD(reflection_property, setValue) if (PZVAL_IS_REF(value)) { SEPARATE_ZVAL(&value); } - zend_hash_quick_update(Z_OBJPROP_P(object), ref->prop->name, ref->prop->name_length+1, ref->prop->h, &value, sizeof(zval *), (void **) &foo); + zend_hash_quick_update(prop_table, ref->prop->name, ref->prop->name_length+1, ref->prop->h, &value, sizeof(zval *), (void **) &foo); } } /* }}} */ -/* {{{ proto public ReflectionClass Reflection_Property::getDeclaringClass() +/* {{{ proto public ReflectionClass ReflectionProperty::getDeclaringClass() Get the declaring class */ ZEND_METHOD(reflection_property, getDeclaringClass) { @@ -2963,10 +3153,10 @@ ZEND_METHOD(reflection_property, getDeclaringClass) METHOD_NOTSTATIC_NUMPARAMS(0); GET_REFLECTION_OBJECT_PTR(ref); - reflection_class_factory(ref->ce, return_value TSRMLS_CC); + zend_reflection_class_factory(ref->ce, return_value TSRMLS_CC); } -/* {{{ proto public static mixed ReflectionExtension::export(string name, [, bool return]) throws ReflectionException +/* {{{ proto public static mixed ReflectionExtension::export(string name [, bool return]) throws ReflectionException Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */ ZEND_METHOD(reflection_extension, export) { @@ -3009,6 +3199,7 @@ ZEND_METHOD(reflection_extension, __construct) zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); intern->ptr = module; intern->free_ptr = 0; + intern->ce = NULL; } /* }}} */ @@ -3056,7 +3247,7 @@ ZEND_METHOD(reflection_extension, getVersion) } /* }}} */ -/* {{{ proto public ReflectionFunction[] Reflection_Extension::getFunctions() +/* {{{ proto public ReflectionFunction[] ReflectionExtension::getFunctions() Returns an array of this extension's fuctions */ ZEND_METHOD(reflection_extension, getFunctions) { @@ -3081,7 +3272,7 @@ ZEND_METHOD(reflection_extension, getFunctions) ALLOC_ZVAL(function); reflection_function_factory(fptr, function TSRMLS_CC); - add_next_index_zval(return_value, function); + add_assoc_zval_ex(return_value, func->fname, strlen(func->fname)+1, function); func++; } } @@ -3162,10 +3353,10 @@ static int add_extension_class(zend_class_entry **pce, int num_args, va_list arg TSRMLS_FETCH(); if (add_reflection_class) { ALLOC_ZVAL(zclass); - reflection_class_factory(*pce, zclass TSRMLS_CC); + zend_reflection_class_factory(*pce, zclass TSRMLS_CC); add_assoc_zval_ex(class_array, (*pce)->name, (*pce)->name_length + 1, zclass); } else { - add_next_index_stringl(class_array, (*pce)->name, (*pce)->name_length + 1, 1); + add_next_index_stringl(class_array, (*pce)->name, (*pce)->name_length, 1); } } return ZEND_HASH_APPLY_KEEP; @@ -3173,7 +3364,7 @@ static int add_extension_class(zend_class_entry **pce, int num_args, va_list arg /* }}} */ /* {{{ proto public ReflectionClass[] ReflectionExtension::getClasses() - Returns an array containing Reflection_Class objects for all classes of this extension */ + Returns an array containing ReflectionClass objects for all classes of this extension */ ZEND_METHOD(reflection_extension, getClasses) { reflection_object *intern; @@ -3235,6 +3426,8 @@ static zend_function_entry reflection_function_functions[] = { ZEND_ME(reflection_function, invoke, NULL, 0) ZEND_ME(reflection_function, returnsReference, NULL, 0) ZEND_ME(reflection_function, getParameters, NULL, 0) + ZEND_ME(reflection_function, getNumberOfParameters, NULL, 0) + ZEND_ME(reflection_function, getNumberOfRequiredParameters, NULL, 0) {NULL, NULL, NULL} }; @@ -3327,6 +3520,9 @@ static zend_function_entry reflection_parameter_functions[] = { ZEND_ME(reflection_parameter, isPassedByReference, NULL, 0) ZEND_ME(reflection_parameter, getClass, NULL, 0) ZEND_ME(reflection_parameter, allowsNull, NULL, 0) + ZEND_ME(reflection_parameter, isOptional, NULL, 0) + ZEND_ME(reflection_parameter, isDefaultValueAvailable, NULL, 0) + ZEND_ME(reflection_parameter, getDefaultValue, NULL, 0) {NULL, NULL, NULL} }; @@ -3346,12 +3542,33 @@ static zend_function_entry reflection_extension_functions[] = { }; /* }}} */ +static zend_object_handlers *zend_std_obj_handlers; + +/* {{{ _reflection_write_property */ +static void _reflection_write_property(zval *object, zval *member, zval *value TSRMLS_DC) +{ + if (Z_TYPE_P(member) == IS_STRING + && zend_hash_exists(&Z_OBJCE_P(object)->default_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1) + && (!strcmp(Z_STRVAL_P(member), "name") || !strcmp(Z_STRVAL_P(member), "class"))) + { + zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, + "Cannot set read-only property %s::$%s", Z_OBJCE_P(object)->name, Z_STRVAL_P(member)); + } + else + { + zend_std_obj_handlers->write_property(object, member, value TSRMLS_CC); + } +} +/* }}} */ + /* {{{ zend_register_reflection_api */ ZEND_API void zend_register_reflection_api(TSRMLS_D) { zend_class_entry _reflection_entry; + zend_std_obj_handlers = zend_get_std_object_handlers(); memcpy(&reflection_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); reflection_object_handlers.clone_obj = NULL; + reflection_object_handlers.write_property = _reflection_write_property; INIT_CLASS_ENTRY(_reflection_entry, "ReflectionException", reflection_exception_functions); reflection_exception_ptr = zend_register_internal_class_ex(&_reflection_entry, zend_exception_get_default(), NULL TSRMLS_CC); @@ -3367,20 +3584,25 @@ ZEND_API void zend_register_reflection_api(TSRMLS_D) { _reflection_entry.create_object = reflection_objects_new; reflection_function_ptr = zend_register_internal_class(&_reflection_entry TSRMLS_CC); reflection_register_implement(reflection_function_ptr, reflector_ptr TSRMLS_CC); + zend_declare_property_string(reflection_function_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC); INIT_CLASS_ENTRY(_reflection_entry, "ReflectionParameter", reflection_parameter_functions); _reflection_entry.create_object = reflection_objects_new; reflection_parameter_ptr = zend_register_internal_class(&_reflection_entry TSRMLS_CC); reflection_register_implement(reflection_parameter_ptr, reflector_ptr TSRMLS_CC); + zend_declare_property_string(reflection_parameter_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC); INIT_CLASS_ENTRY(_reflection_entry, "ReflectionMethod", reflection_method_functions); _reflection_entry.create_object = reflection_objects_new; reflection_method_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_function_ptr, NULL TSRMLS_CC); + zend_declare_property_string(reflection_method_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_string(reflection_method_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC); INIT_CLASS_ENTRY(_reflection_entry, "ReflectionClass", reflection_class_functions); _reflection_entry.create_object = reflection_objects_new; reflection_class_ptr = zend_register_internal_class(&_reflection_entry TSRMLS_CC); reflection_register_implement(reflection_class_ptr, reflector_ptr TSRMLS_CC); + zend_declare_property_string(reflection_class_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC); INIT_CLASS_ENTRY(_reflection_entry, "ReflectionObject", reflection_object_functions); _reflection_entry.create_object = reflection_objects_new; @@ -3390,11 +3612,14 @@ ZEND_API void zend_register_reflection_api(TSRMLS_D) { _reflection_entry.create_object = reflection_objects_new; reflection_property_ptr = zend_register_internal_class(&_reflection_entry TSRMLS_CC); reflection_register_implement(reflection_property_ptr, reflector_ptr TSRMLS_CC); + zend_declare_property_string(reflection_property_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_string(reflection_property_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC); INIT_CLASS_ENTRY(_reflection_entry, "ReflectionExtension", reflection_extension_functions); _reflection_entry.create_object = reflection_objects_new; reflection_extension_ptr = zend_register_internal_class(&_reflection_entry TSRMLS_CC); reflection_register_implement(reflection_extension_ptr, reflector_ptr TSRMLS_CC); + zend_declare_property_string(reflection_extension_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC); /* Property modifiers */ REGISTER_MAIN_LONG_CONSTANT("P_STATIC", ZEND_ACC_STATIC, CONST_PERSISTENT|CONST_CS); diff --git a/ext/reflection/tests/001.phpt b/ext/reflection/tests/001.phpt new file mode 100755 index 000000000000..f68afc950e3e --- /dev/null +++ b/ext/reflection/tests/001.phpt @@ -0,0 +1,89 @@ +--TEST-- +Reflection inheritance +--FILE-- +getMethods() as $m) + { + $res[] = $m->class . '::' . $m->name; + } + return $res; + } +} + +$r = new ReflectionClassEx('ReflectionClassEx'); + +$exp = array ( + 'UMLClass::__clone', + 'UMLClass::export', + 'UMLClass::__construct', + 'UMLClass::__toString', + 'UMLClass::getName', + 'UMLClass::isInternal', + 'UMLClass::isUserDefined', + 'UMLClass::isInstantiable', + 'UMLClass::getFileName', + 'UMLClass::getStartLine', + 'UMLClass::getEndLine', + 'UMLClass::getDocComment', + 'UMLClass::getConstructor', + 'UMLClass::getMethod', + 'UMLClass::getMethods', + 'UMLClass::getProperty', + 'UMLClass::getProperties', + 'UMLClass::getConstants', + 'UMLClass::getConstant', + 'UMLClass::getInterfaces', + 'UMLClass::isInterface', + 'UMLClass::isAbstract', + 'UMLClass::isFinal', + 'UMLClass::getModifiers', + 'UMLClass::isInstance', + 'UMLClass::newInstance', + 'UMLClass::getParentClass', + 'UMLClass::isSubclassOf', + 'UMLClass::getStaticProperties', + 'UMLClass::getDefaultProperties', + 'UMLClass::isIterateable', + 'UMLClass::implementsInterface', + 'UMLClass::getExtension', + 'UMLClass::getExtensionName'); + +$miss = array(); + +$res = $r->getMethodNames(); + +foreach($exp as $m) +{ + if (!in_array($m, $exp)) + { + $miss[] = $m; + } +} + +var_dump($miss); + +$props = array_keys(get_class_vars('ReflectionClassEx')); +sort($props); +var_dump($props); +var_dump($r->name); +?> +===DONE=== +--EXPECT-- +array(0) { +} +array(2) { + [0]=> + string(3) "bla" + [1]=> + string(4) "name" +} +string(17) "ReflectionClassEx" +===DONE=== diff --git a/ext/reflection/tests/002.phpt b/ext/reflection/tests/002.phpt new file mode 100755 index 000000000000..195aeb23e7d9 --- /dev/null +++ b/ext/reflection/tests/002.phpt @@ -0,0 +1,63 @@ +--TEST-- +Reflection properties are read only +--FILE-- +class); +var_dump($r->name); +var_dump($r->foo); +@var_dump($r->bar); + +try +{ + $r->class = 'bullshit'; +} +catch(ReflectionException $e) +{ + echo $e->getMessage() . "\n"; +} +try +{ +$r->name = 'bullshit'; +} +catch(ReflectionException $e) +{ + echo $e->getMessage() . "\n"; +} + +$r->foo = 'bar'; +$r->bar = 'baz'; + +var_dump($r->class); +var_dump($r->name); +var_dump($r->foo); +var_dump($r->bar); + +?> +===DONE=== +--EXPECTF-- +ReflectionMethodEx::__construct +string(18) "ReflectionMethodEx" +string(7) "getName" +string(3) "xyz" +NULL +Cannot set read-only property ReflectionMethodEx::$class +Cannot set read-only property ReflectionMethodEx::$name +string(18) "ReflectionMethodEx" +string(7) "getName" +string(3) "bar" +string(3) "baz" +===DONE=== diff --git a/ext/reflection/tests/003.phpt b/ext/reflection/tests/003.phpt new file mode 100755 index 000000000000..660389255907 --- /dev/null +++ b/ext/reflection/tests/003.phpt @@ -0,0 +1,31 @@ +--TEST-- +invoke() with base class method +--FILE-- +invoke($o); + +?> +===DONE=== +--EXPECT-- +Foo::Test +===DONE=== diff --git a/ext/reflection/tests/invoke.phpt b/ext/reflection/tests/004.phpt similarity index 94% rename from ext/reflection/tests/invoke.phpt rename to ext/reflection/tests/004.phpt index a79b0e0b0610..c5a243be6faf 100755 --- a/ext/reflection/tests/invoke.phpt +++ b/ext/reflection/tests/004.phpt @@ -1,5 +1,5 @@ --TEST-- -invoke with non object or null value +invoke() with non object or null value --FILE-- getDocComment())); + +foreach($r->getMethods() as $m) +{ + var_dump(strip_doc_comment($m->getDocComment())); +} + +?> +===DONE=== +--EXPECT-- +string(19) "Comment for class A" +string(15) "Method A::bla()" +bool(false) +bool(false) +string(22) "* Comment for A::baz()" +===DONE=== diff --git a/ext/reflection/tests/bug29828.phpt b/ext/reflection/tests/bug29828.phpt new file mode 100755 index 000000000000..b82be39f981a --- /dev/null +++ b/ext/reflection/tests/bug29828.phpt @@ -0,0 +1,35 @@ +--TEST-- +Bug #29828 (Interfaces no longer work) +--FILE-- +getMethods())); +var_dump($r->getMethod('bla')->isConstructor()); +var_dump($r->getMethod('bla')->isAbstract()); + +$o=new BlaMore; +$o->bla(); + +?> +===DONE=== +--EXPECT-- +int(1) +bool(false) +bool(false) +Hello +===DONE=== diff --git a/ext/reflection/tests/bug30146.phpt b/ext/reflection/tests/bug30146.phpt new file mode 100755 index 000000000000..4f48985dcc34 --- /dev/null +++ b/ext/reflection/tests/bug30146.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #30146 (ReflectionProperty->getValue() requires instance for static property) +--FILE-- +getValue(null)); + +$r->setValue(NULL, 2); +var_dump($r->getValue()); + +$r->setValue(3); +var_dump($r->getValue()); +?> +===DONE=== +--EXPECT-- +int(1) +int(2) +int(3) +===DONE=== \ No newline at end of file diff --git a/ext/reflection/tests/bug30148.phpt b/ext/reflection/tests/bug30148.phpt new file mode 100755 index 000000000000..c3bfd0611f93 --- /dev/null +++ b/ext/reflection/tests/bug30148.phpt @@ -0,0 +1,35 @@ +--TEST-- +Bug #30148 (ReflectionMethod->isConstructor() fails for inherited classes) +--FILE-- +isConstructor()); +var_dump($b->isConstructor()); +var_dump($c->isConstructor()); +var_dump($d->isConstructor()); +var_dump($e->isConstructor()); +?> +===DONE=== +--EXPECT-- +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +===DONE=== \ No newline at end of file diff --git a/ext/reflection/tests/bug30209.phpt b/ext/reflection/tests/bug30209.phpt new file mode 100755 index 000000000000..6705c6704d7c --- /dev/null +++ b/ext/reflection/tests/bug30209.phpt @@ -0,0 +1,31 @@ +--TEST-- +Bug #30209 (ReflectionClass::getMethod() lowercases attribute) +--FILE-- +name); + $method = $class->getMethod($this->name); + var_dump($this->name); + } + + catch (Exception $e) {} + } +} + +$foo = new Foo; +$foo->testBAR(); +?> +===DONE=== +--EXPECTF-- +string(7) "testBAR" +string(7) "testBAR" +===DONE=== diff --git a/ext/reflection/tests/bug30856.phpt b/ext/reflection/tests/bug30856.phpt new file mode 100755 index 000000000000..296326338848 --- /dev/null +++ b/ext/reflection/tests/bug30856.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #30856 (ReflectionClass::getStaticProperties segfaults) +--FILE-- +getStaticProperties()); +?> +===DONE=== +--EXPECT-- +array(1) { + ["a"]=> + string(4) "test" +} +===DONE=== diff --git a/ext/reflection/tests/bug30961.phpt b/ext/reflection/tests/bug30961.phpt new file mode 100755 index 000000000000..78067471d4d1 --- /dev/null +++ b/ext/reflection/tests/bug30961.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #30961 (Wrong linenumber in ReflectionClass getStartLine()) +--FILE-- +getStartLine() . "\n"; + echo $ref2->getStartLine() . "\n"; +?> +--EXPECT-- +2 +6 diff --git a/ext/reflection/tests/bug31651.phpt b/ext/reflection/tests/bug31651.phpt new file mode 100755 index 000000000000..60bee14e9f69 --- /dev/null +++ b/ext/reflection/tests/bug31651.phpt @@ -0,0 +1,24 @@ +--TEST-- +Bug #31651 (ReflectionClass::getDefaultProperties segfaults with arrays.) +--FILE-- + 1); +} + +$ref = new ReflectionClass('Test'); + +print_r($ref->getDefaultProperties()); + +?> +--EXPECT-- +Array +( + [a] => Array + ( + [a] => 1 + ) + +) diff --git a/ext/reflection/tests/bug32981.phpt b/ext/reflection/tests/bug32981.phpt new file mode 100755 index 000000000000..1f89ca682b6e --- /dev/null +++ b/ext/reflection/tests/bug32981.phpt @@ -0,0 +1,34 @@ +--TEST-- +Bug #32981 (ReflectionMethod::getStaticVariables() causes apache2.0.54 seg fault) +--FILE-- +getMethods() as $method) +{ + var_dump($method->getName()); + $arr_static_vars[] = $method->getStaticVariables(); +} + +var_dump($arr_static_vars); + +?> +===DONE=== +--EXPECT-- +string(4) "test" +array(1) { + [0]=> + array(1) { + ["enabled"]=> + bool(true) + } +} +===DONE=== diff --git a/ext/reflection/tests/parameters_001.phpt b/ext/reflection/tests/parameters_001.phpt new file mode 100755 index 000000000000..fb22a22a95b7 --- /dev/null +++ b/ext/reflection/tests/parameters_001.phpt @@ -0,0 +1,46 @@ +--TEST-- +Check for parameter being optional +--SKIPIF-- + +--FILE-- +getNumberOfParameters()); +var_dump($f->getNumberOfRequiredParameters()); + +$p = new ReflectionParameter(array('Test', 'func'), 'x'); +var_dump($p->isOptional()); + +$p = new ReflectionParameter(array('Test', 'func'), 'y'); +var_dump($p->isOptional()); + +try { + $p = new ReflectionParameter(array('Test', 'func'), 'z'); + var_dump($p->isOptional()); +} +catch (Exception $e) { + var_dump($e->getMessage()); +} + +?> +===DONE=== +--EXPECT-- +int(2) +int(1) +bool(false) +bool(true) +string(54) "The parameter specified by its name could not be found" +===DONE=== diff --git a/ext/session/mod_files.c b/ext/session/mod_files.c index 15cd5d77475e..e6d0edfcabb8 100644 --- a/ext/session/mod_files.c +++ b/ext/session/mod_files.c @@ -166,8 +166,11 @@ static void ps_files_open(ps_files *data, const char *key TSRMLS_DC) flock(data->fd, LOCK_EX); #ifdef F_SETFD - if (fcntl(data->fd, F_SETFD, 1)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "fcntl(%d, F_SETFD, 1) failed: %s (%d)", data->fd, strerror(errno), errno); +#ifndef FD_CLOEXEC +#define FD_CLOEXEC 1 +#endif + if (fcntl(data->fd, F_SETFD, FD_CLOEXEC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "fcntl(%d, F_SETFD, FD_CLOEXEC) failed: %s (%d)", data->fd, strerror(errno), errno); } #endif } else { @@ -216,7 +219,11 @@ static int ps_files_cleanup_dir(const char *dirname, int maxlifetime TSRMLS_DC) buf[dirname_len + entry_len + 1] = '\0'; /* check whether its last access was more than maxlifet ago */ if (VCWD_STAT(buf, &sbuf) == 0 && +#ifdef NETWARE + (now - sbuf.st_mtime.tv_sec) > maxlifetime) { +#else (now - sbuf.st_mtime) > maxlifetime) { +#endif VCWD_UNLINK(buf); nrdels++; } diff --git a/ext/session/mod_files.h b/ext/session/mod_files.h index c185a03b0339..e460ca5014f2 100644 --- a/ext/session/mod_files.h +++ b/ext/session/mod_files.h @@ -16,6 +16,8 @@ +----------------------------------------------------------------------+ */ +/* $Id$ */ + #ifndef MOD_FILES_H #define MOD_FILES_H diff --git a/ext/session/mod_mm.h b/ext/session/mod_mm.h index 47c46acf1a71..fc221794ded2 100644 --- a/ext/session/mod_mm.h +++ b/ext/session/mod_mm.h @@ -16,6 +16,8 @@ +----------------------------------------------------------------------+ */ +/* $Id$ */ + #ifndef MOD_MM_H #define MOD_MM_H diff --git a/ext/session/mod_user.h b/ext/session/mod_user.h index 79e28a3941f0..cb5d18744eaa 100644 --- a/ext/session/mod_user.h +++ b/ext/session/mod_user.h @@ -16,6 +16,8 @@ +----------------------------------------------------------------------+ */ +/* $Id$ */ + #ifndef MOD_USER_H #define MOD_USER_H diff --git a/ext/session/php_session.h b/ext/session/php_session.h index 19ce366f2656..90f25e8dc29d 100644 --- a/ext/session/php_session.h +++ b/ext/session/php_session.h @@ -16,6 +16,8 @@ +----------------------------------------------------------------------+ */ +/* $Id$ */ + #ifndef PHP_SESSION_H #define PHP_SESSION_H diff --git a/ext/session/session.c b/ext/session/session.c index 135a732253ac..f6fdb6302cb1 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -131,13 +131,27 @@ static PHP_INI_MH(OnUpdateSerializer) return SUCCESS; } +static PHP_INI_MH(OnUpdateSaveDir) { + /* Only do the safemode/open_basedir check at runtime */ + if(stage == PHP_INI_STAGE_RUNTIME) { + if (PG(safe_mode) && (!php_checkuid(new_value, NULL, CHECKUID_ALLOW_ONLY_DIR))) { + return FAILURE; + } + + if (php_check_open_basedir(new_value TSRMLS_CC)) { + return FAILURE; + } + } + OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); + return SUCCESS; +} /* {{{ PHP_INI */ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("session.bug_compat_42", "1", PHP_INI_ALL, OnUpdateBool, bug_compat, php_ps_globals, ps_globals) STD_PHP_INI_BOOLEAN("session.bug_compat_warn", "1", PHP_INI_ALL, OnUpdateBool, bug_compat_warn, php_ps_globals, ps_globals) - STD_PHP_INI_ENTRY("session.save_path", "", PHP_INI_ALL, OnUpdateString, save_path, php_ps_globals, ps_globals) + STD_PHP_INI_ENTRY("session.save_path", "", PHP_INI_ALL, OnUpdateSaveDir,save_path, php_ps_globals, ps_globals) STD_PHP_INI_ENTRY("session.name", "PHPSESSID", PHP_INI_ALL, OnUpdateString, session_name, php_ps_globals, ps_globals) PHP_INI_ENTRY("session.save_handler", "files", PHP_INI_ALL, OnUpdateSaveHandler) STD_PHP_INI_BOOLEAN("session.auto_start", "0", PHP_INI_ALL, OnUpdateBool, auto_start, php_ps_globals, ps_globals) @@ -169,6 +183,7 @@ PS_SERIALIZER_FUNCS(php); PS_SERIALIZER_FUNCS(php_binary); #define MAX_SERIALIZERS 10 +#define PREDEFINED_SERIALIZERS 2 static ps_serializer ps_serializers[MAX_SERIALIZERS + 1] = { PS_SERIALIZER_ENTRY(php), @@ -176,6 +191,7 @@ static ps_serializer ps_serializers[MAX_SERIALIZERS + 1] = { }; #define MAX_MODULES 10 +#define PREDEFINED_MODULES 2 static ps_module *ps_modules[MAX_MODULES + 1] = { ps_files_ptr, @@ -423,8 +439,8 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) p += namelen + 1; if (has_value) { - MAKE_STD_ZVAL(current); - if (php_var_unserialize(¤t, &p, endptr, &var_hash TSRMLS_CC)) { + ALLOC_INIT_ZVAL(current); + if (php_var_unserialize(¤t, (const unsigned char**)&p, endptr, &var_hash TSRMLS_CC)) { php_set_session_var(name, namelen, current, &var_hash TSRMLS_CC); } zval_ptr_dtor(¤t); @@ -451,6 +467,11 @@ PS_SERIALIZER_ENCODE_FUNC(php) PS_ENCODE_LOOP( smart_str_appendl(&buf, key, (unsigned char) key_length); + if (memchr(key, PS_DELIMITER, key_length)) { + PHP_VAR_SERIALIZE_DESTROY(var_hash); + smart_str_free(&buf); + return FAILURE; + } smart_str_appendc(&buf, PS_DELIMITER); php_var_serialize(&buf, struc, &var_hash TSRMLS_CC); @@ -499,7 +520,7 @@ PS_SERIALIZER_DECODE_FUNC(php) if (has_value) { ALLOC_INIT_ZVAL(current); - if (php_var_unserialize(¤t, &q, endptr, &var_hash TSRMLS_CC)) { + if (php_var_unserialize(¤t, (const unsigned char**)&q, endptr, &var_hash TSRMLS_CC)) { php_set_session_var(name, namelen, current, &var_hash TSRMLS_CC); } zval_ptr_dtor(¤t); @@ -529,8 +550,13 @@ static void php_session_track_init(TSRMLS_D) array_init(session_vars); PS(http_session_vars) = session_vars; - ZEND_SET_GLOBAL_VAR_WITH_LENGTH("HTTP_SESSION_VARS", sizeof("HTTP_SESSION_VARS"), PS(http_session_vars), 2, 1); - ZEND_SET_GLOBAL_VAR_WITH_LENGTH("_SESSION", sizeof("_SESSION"), PS(http_session_vars), 2, 1); + if (PG(register_long_arrays)) { + ZEND_SET_GLOBAL_VAR_WITH_LENGTH("HTTP_SESSION_VARS", sizeof("HTTP_SESSION_VARS"), PS(http_session_vars), 2, 1); + ZEND_SET_GLOBAL_VAR_WITH_LENGTH("_SESSION", sizeof("_SESSION"), PS(http_session_vars), 2, 1); + } + else { + ZEND_SET_GLOBAL_VAR_WITH_LENGTH("_SESSION", sizeof("_SESSION"), PS(http_session_vars), 1, 0); + } } static char *php_session_encode(int *newlen TSRMLS_DC) @@ -538,7 +564,11 @@ static char *php_session_encode(int *newlen TSRMLS_DC) char *ret = NULL; IF_SESSION_VARS() { - if (PS(serializer)->encode(&ret, newlen TSRMLS_CC) == FAILURE) + if (!PS(serializer)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown session.serialize_handler. Failed to encode session object."); + ret = NULL; + } + else if (PS(serializer)->encode(&ret, newlen TSRMLS_CC) == FAILURE) ret = NULL; } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot encode non-existent session."); @@ -549,6 +579,10 @@ static char *php_session_encode(int *newlen TSRMLS_DC) static void php_session_decode(const char *val, int vallen TSRMLS_DC) { + if (!PS(serializer)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown session.serialize_handler. Failed to decode session object."); + return; + } if (PS(serializer)->decode(val, vallen TSRMLS_CC) == FAILURE) { php_session_destroy(TSRMLS_C); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to decode session object. Session has been destroyed."); @@ -858,7 +892,11 @@ static void last_modified(TSRMLS_D) #define LAST_MODIFIED "Last-Modified: " memcpy(buf, LAST_MODIFIED, sizeof(LAST_MODIFIED) - 1); +#ifdef NETWARE + strcpy_gmt(buf + sizeof(LAST_MODIFIED) - 1, &(sb.st_mtime.tv_sec)); +#else strcpy_gmt(buf + sizeof(LAST_MODIFIED) - 1, &sb.st_mtime); +#endif ADD_HEADER(buf); } } @@ -1082,6 +1120,21 @@ PHPAPI void php_session_start(TSRMLS_D) PS(define_sid) = 1; PS(send_cookie) = 1; if (PS(session_status) != php_session_none) { + + if (PS(session_status) == php_session_disabled) { + char *value; + + value = zend_ini_string("session.save_handler", sizeof("session.save_handler"), 0); + + if (value) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot find save handler %s", value); + } + else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot find unknown save handler"); + } + return; + } + php_error(E_NOTICE, "A session had already been started - ignoring session_start()"); return; } @@ -1095,7 +1148,7 @@ PHPAPI void php_session_start(TSRMLS_D) */ if (!PS(id)) { - if (zend_hash_find(&EG(symbol_table), "_COOKIE", + if (PS(use_cookies) && zend_hash_find(&EG(symbol_table), "_COOKIE", sizeof("_COOKIE"), (void **) &data) == SUCCESS && Z_TYPE_PP(data) == IS_ARRAY && zend_hash_find(Z_ARRVAL_PP(data), PS(session_name), @@ -1304,11 +1357,19 @@ PHP_FUNCTION(session_module_name) } PS(mod_data) = NULL; - RETVAL_STRING(safe_estrdup(PS(mod)->s_name), 0); - + if (PS(mod) && PS(mod)->s_name) { + RETVAL_STRING(safe_estrdup(PS(mod)->s_name), 0); + } else { + RETVAL_EMPTY_STRING(); + } + zend_alter_ini_entry("session.save_handler", sizeof("session.save_handler"), Z_STRVAL_PP(p_name), Z_STRLEN_PP(p_name), PHP_INI_USER, PHP_INI_STAGE_RUNTIME); } else { - RETURN_STRING(safe_estrdup(PS(mod)->s_name), 0); + if (PS(mod) && PS(mod)->s_name) { + RETURN_STRING(safe_estrdup(PS(mod)->s_name), 0); + } else { + RETURN_EMPTY_STRING(); + } } } /* }}} */ @@ -1320,12 +1381,22 @@ PHP_FUNCTION(session_set_save_handler) zval **args[6]; int i; ps_user *mdata; + char *name; if (ZEND_NUM_ARGS() != 6 || zend_get_parameters_array_ex(6, args) == FAILURE) WRONG_PARAM_COUNT; if (PS(session_status) != php_session_none) RETURN_FALSE; + + for (i = 0; i < 6; i++) { + if (!zend_is_callable(*args[i], 0, &name)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument %d is not a valid callback", i+1); + efree(name); + RETURN_FALSE; + } + efree(name); + } zend_alter_ini_entry("session.save_handler", sizeof("session.save_handler"), "user", sizeof("user")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); @@ -1490,8 +1561,14 @@ PHP_FUNCTION(session_register) WRONG_PARAM_COUNT; } - if (PS(session_status) == php_session_none) + if (PS(session_status) == php_session_none || PS(session_status) == php_session_disabled) { php_session_start(TSRMLS_C); + } + + if (PS(session_status) == php_session_disabled) { + efree(args); + RETURN_FALSE; + } for (i = 0; i < argc; i++) { if (Z_TYPE_PP(args[i]) == IS_ARRAY) @@ -1768,6 +1845,9 @@ PHP_MSHUTDOWN_FUNCTION(session) PHP_MSHUTDOWN(ps_mm) (SHUTDOWN_FUNC_ARGS_PASSTHRU); #endif + ps_serializers[PREDEFINED_SERIALIZERS].name = NULL; + ps_modules[PREDEFINED_MODULES] = NULL; + return SUCCESS; } diff --git a/ext/session/tests/007.phpt b/ext/session/tests/007.phpt index 7e13ab27e34d..a37b1db8f897 100644 --- a/ext/session/tests/007.phpt +++ b/ext/session/tests/007.phpt @@ -8,6 +8,7 @@ session.cache_limiter= register_globals=1 session.bug_compat_42=1 session.serialize_handler=php +register_long_arrays=1 --FILE-- +--FILE-- + +--EXPECTF-- + +Warning: session_set_save_handler(): Argument 1 is not a valid callback in %sbug31454.php on line %d +Done diff --git a/ext/shmop/shmop.c b/ext/shmop/shmop.c index 78d9e1b9735e..eec73d157303 100644 --- a/ext/shmop/shmop.c +++ b/ext/shmop/shmop.c @@ -316,7 +316,7 @@ PHP_FUNCTION(shmop_write) RETURN_FALSE; } - if (offset > shmop->size) { + if (offset < 0 || offset > shmop->size) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "offset out of range"); RETURN_FALSE; } diff --git a/ext/shmop/tests/001.phpt b/ext/shmop/tests/001.phpt index 1a1b926308d0..fc293c82ec83 100644 --- a/ext/shmop/tests/001.phpt +++ b/ext/shmop/tests/001.phpt @@ -3,7 +3,7 @@ shmop extension test --SKIPIF-- --FILE-- diff --git a/ext/simplexml/config.m4 b/ext/simplexml/config.m4 index 9fa9c455edc2..f1c635868274 100644 --- a/ext/simplexml/config.m4 +++ b/ext/simplexml/config.m4 @@ -1,15 +1,19 @@ dnl $Id$ dnl config.m4 for extension simplexml -PHP_ARG_ENABLE(simplexml, whether to enable simplexml support, -[ --disable-simplexml Disable simplexml support], yes) +PHP_ARG_ENABLE(simplexml, whether to enable SimpleXML support, +[ --disable-simplexml Disable SimpleXML support], yes) if test -z "$PHP_LIBXML_DIR"; then PHP_ARG_WITH(libxml-dir, libxml2 install dir, [ --with-libxml-dir=DIR SimpleXML: libxml2 install prefix], no, no) fi -if test "$PHP_SIMPLEXML" != "no" && test "$PHP_LIBXML" != "no"; then +if test "$PHP_SIMPLEXML" != "no"; then + + if test "$PHP_LIBXML" = "no"; then + AC_MSG_ERROR([SimpleXML extension requires LIBXML extension, add --enable-libxml]) + fi PHP_SETUP_LIBXML(SIMPLEXML_SHARED_LIBADD, [ AC_DEFINE(HAVE_SIMPLEXML,1,[ ]) diff --git a/ext/simplexml/php_simplexml_exports.h b/ext/simplexml/php_simplexml_exports.h index 6d6e7b8baf54..445605fdf5e6 100755 --- a/ext/simplexml/php_simplexml_exports.h +++ b/ext/simplexml/php_simplexml_exports.h @@ -35,7 +35,7 @@ __n = (__s)->node->node; \ } else { \ __n = NULL; \ - php_error(E_WARNING, "Node no longer exists"); \ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Node no longer exists"); \ } \ } diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index b2af53d21018..45d45f863f46 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -92,7 +92,7 @@ static void _node_as_zval(php_sxe_object *sxe, xmlNodePtr node, zval *value, int __n = (__s)->node->node; \ } else { \ __n = NULL; \ - php_error(E_WARNING, "Node no longer exists"); \ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Node no longer exists"); \ } \ } @@ -272,7 +272,7 @@ static zval * sxe_dimension_read(zval *object, zval *offset, int type TSRMLS_DC) /* {{{ change_node_zval() */ static void -change_node_zval(xmlNodePtr node, zval *value) +change_node_zval(xmlNodePtr node, zval *value TSRMLS_DC) { zval value_copy; @@ -295,7 +295,7 @@ change_node_zval(xmlNodePtr node, zval *value) } break; default: - php_error(E_WARNING, "It is not possible to assign complex types to nodes"); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "It is not possible to assign complex types to nodes"); break; } } @@ -418,9 +418,9 @@ static void sxe_prop_dim_write(zval *object, zval *member, zval *value, zend_boo xmlUnlinkNode(tempnode); php_libxml_node_free_resource((xmlNodePtr) tempnode TSRMLS_CC); } - change_node_zval(newnode, value); + change_node_zval(newnode, value TSRMLS_CC); } else if (counter > 1) { - php_error(E_WARNING, "Cannot assign to an array of nodes (duplicate subnodes or attr detected)\n"); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot assign to an array of nodes (duplicate subnodes or attr detected)\n"); } else { if (attribs) { switch (Z_TYPE_P(value)) { @@ -433,7 +433,7 @@ static void sxe_prop_dim_write(zval *object, zval *member, zval *value, zend_boo newnode = (xmlNodePtr)xmlNewProp(node, name, Z_STRVAL_P(value)); break; default: - php_error(E_WARNING, "It is not yet possible to assign complex types to attributes"); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "It is not yet possible to assign complex types to attributes"); } } } @@ -764,8 +764,8 @@ sxe_objects_compare(zval *object1, zval *object2 TSRMLS_DC) } /* }}} */ -/* {{{ xpath() - */ +/* {{{ array SimpleXMLElement::xpath(string path) + Runs XPath query on the XML data */ SXE_METHOD(xpath) { php_sxe_object *sxe; @@ -845,8 +845,8 @@ SXE_METHOD(xpath) } /* }}} */ -/* {{{ proto asXML([string filename]) - */ +/* {{{ proto string SimpleXMLElement::asXML([string filename]) + Return a well-formed XML string based on SimpleXML element */ SXE_METHOD(asXML) { php_sxe_object *sxe; @@ -918,8 +918,8 @@ SXE_METHOD(asXML) } /* }}} */ -/* {{{ simplexml_children() - */ +/* {{{ proto object SimpleXMLElement::children() + Finds children of given node */ SXE_METHOD(children) { php_sxe_object *sxe; @@ -940,8 +940,8 @@ SXE_METHOD(children) } /* }}} */ -/* {{{ simplexml_attributes() - */ +/* {{{ proto array SimpleXMLElement::attributes([string ns]) + Identifies an element's attributes */ SXE_METHOD(attributes) { php_sxe_object *sxe; @@ -1081,6 +1081,37 @@ static zend_object_handlers sxe_object_handlers = { NULL }; +static zend_object_handlers sxe_ze1_object_handlers = { + ZEND_OBJECTS_STORE_HANDLERS, + sxe_property_read, + sxe_property_write, + sxe_dimension_read, + sxe_dimension_write, + NULL, + sxe_get_value, /* get */ + NULL, + sxe_property_exists, + sxe_property_delete, + sxe_dimension_exists, + sxe_dimension_delete, + sxe_properties_get, + NULL, /* zend_get_std_object_handlers()->get_method,*/ + NULL, /* zend_get_std_object_handlers()->call_method,*/ + NULL, /* zend_get_std_object_handlers()->get_constructor, */ + NULL, /* zend_get_std_object_handlers()->get_class_entry,*/ + NULL, /* zend_get_std_object_handlers()->get_class_name,*/ + sxe_objects_compare, + sxe_object_cast, + NULL +}; + +static zend_object_value sxe_object_ze1_clone(zval *zobject TSRMLS_DC) +{ + php_error(E_ERROR, "Cannot clone object of class %s due to 'zend.ze1_compatibility_mode'", Z_OBJCE_P(zobject)->name); + /* Return zobject->value.obj just to satisfy compiler */ + return zobject->value.obj; +} + /* {{{ sxe_object_clone() */ static void @@ -1186,7 +1217,11 @@ php_sxe_register_object(php_sxe_object *intern TSRMLS_DC) zend_object_value rv; rv.handle = zend_objects_store_put(intern, sxe_object_dtor, (zend_objects_free_object_storage_t)sxe_object_free_storage, sxe_object_clone TSRMLS_CC); + if (EG(ze1_compatibility_mode)) { + rv.handlers = (zend_object_handlers *) &sxe_ze1_object_handlers; + } else { rv.handlers = (zend_object_handlers *) &sxe_object_handlers; + } return rv; } @@ -1280,6 +1315,9 @@ PHP_FUNCTION(simplexml_load_string) } /* }}} */ + +/* {{{ proto SimpleXMLElement::__construct() + SimpleXMLElement constructor */ SXE_METHOD(__construct) { php_sxe_object *sxe = php_sxe_fetch_object(getThis() TSRMLS_CC); @@ -1304,6 +1342,8 @@ SXE_METHOD(__construct) php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, docp TSRMLS_CC); php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement(docp), NULL TSRMLS_CC); } +/* }}} */ + typedef struct { zend_object_iterator intern; @@ -1540,7 +1580,7 @@ PHP_FUNCTION(simplexml_import_dom) if (nodep) { if (nodep->doc == NULL) { - php_error(E_WARNING, "Imported Node must have associated Document"); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Imported Node must have associated Document"); RETURN_NULL(); } if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) { @@ -1565,7 +1605,7 @@ PHP_FUNCTION(simplexml_import_dom) return_value->type = IS_OBJECT; return_value->value.obj = php_sxe_register_object(sxe TSRMLS_CC); } else { - php_error(E_WARNING, "Invalid Nodetype to import"); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Nodetype to import"); RETVAL_NULL(); } } @@ -1625,6 +1665,12 @@ PHP_MINIT_FUNCTION(simplexml) sxe_object_handlers.get_class_entry = zend_get_std_object_handlers()->get_class_entry; sxe_object_handlers.get_class_name = zend_get_std_object_handlers()->get_class_name; + sxe_ze1_object_handlers.get_method = zend_get_std_object_handlers()->get_method; + sxe_ze1_object_handlers.get_constructor = zend_get_std_object_handlers()->get_constructor; + sxe_ze1_object_handlers.get_class_entry = zend_get_std_object_handlers()->get_class_entry; + sxe_ze1_object_handlers.get_class_name = zend_get_std_object_handlers()->get_class_name; + sxe_ze1_object_handlers.clone_obj = sxe_object_ze1_clone; + #if HAVE_SPL && !defined(COMPILE_DL_SPL) if (zend_get_module_started("spl") == SUCCESS) { PHP_MINIT(spl_sxe)(INIT_FUNC_ARGS_PASSTHRU); diff --git a/ext/snmp/php_snmp.h b/ext/snmp/php_snmp.h index e923ca11a380..dac11ff9f0cc 100644 --- a/ext/snmp/php_snmp.h +++ b/ext/snmp/php_snmp.h @@ -39,6 +39,7 @@ extern zend_module_entry snmp_module_entry; #endif PHP_MINIT_FUNCTION(snmp); +PHP_MSHUTDOWN_FUNCTION(snmp); PHP_MINFO_FUNCTION(snmp); PHP_FUNCTION(snmpget); @@ -51,6 +52,12 @@ PHP_FUNCTION(snmp_set_enum_print); PHP_FUNCTION(snmp_set_oid_numeric_print); PHP_FUNCTION(snmpset); +PHP_FUNCTION(snmp2_get); +PHP_FUNCTION(snmp2_getnext); +PHP_FUNCTION(snmp2_walk); +PHP_FUNCTION(snmp2_real_walk); +PHP_FUNCTION(snmp2_set); + PHP_FUNCTION(snmp3_get); PHP_FUNCTION(snmp3_getnext); PHP_FUNCTION(snmp3_walk); diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c index 2100008a2e8f..171d4252213c 100644 --- a/ext/snmp/snmp.c +++ b/ext/snmp/snmp.c @@ -40,19 +40,13 @@ #include "win32/time.h" #elif defined(NETWARE) #ifdef USE_WINSOCK -/*#include */ #include #else #include #endif #include -/*#include */ -#ifdef NEW_LIBC #include #else -#include "netware/time_nw.h" -#endif -#else #include #include #include @@ -133,6 +127,12 @@ function_entry snmp_functions[] = { #endif PHP_FE(snmpset, NULL) + PHP_FE(snmp2_get, NULL) + PHP_FE(snmp2_getnext, NULL) + PHP_FE(snmp2_walk, NULL) + PHP_FE(snmp2_real_walk, NULL) + PHP_FE(snmp2_set, NULL) + PHP_FE(snmp3_get, NULL) PHP_FE(snmp3_getnext, NULL) PHP_FE(snmp3_walk, NULL) @@ -153,7 +153,7 @@ zend_module_entry snmp_module_entry = { "snmp", snmp_functions, PHP_MINIT(snmp), - NULL, + PHP_MSHUTDOWN(snmp), NULL, NULL, PHP_MINFO(snmp), @@ -182,6 +182,11 @@ PHP_MINIT_FUNCTION(snmp) { init_snmp("snmpapp"); +#ifdef NETSNMP_DS_LIB_DONT_PERSIST_STATE + /* Prevent update of the snmpapp.conf file */ + netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PERSIST_STATE, 1); +#endif + ZEND_INIT_MODULE_GLOBALS(snmp, php_snmp_init_globals, NULL); REGISTER_LONG_CONSTANT("SNMP_VALUE_LIBRARY", SNMP_VALUE_LIBRARY, CONST_CS | CONST_PERSISTENT); @@ -205,6 +210,16 @@ PHP_MINIT_FUNCTION(snmp) } /* }}} */ +/* {{{ PHP_MSHUTDOWN_FUNCTION + */ +PHP_MSHUTDOWN_FUNCTION(snmp) +{ + snmp_shutdown("snmpapp"); + + return SUCCESS; +} +/* }}} */ + /* {{{ PHP_MINFO_FUNCTION */ PHP_MINFO_FUNCTION(snmp) @@ -314,7 +329,7 @@ static void php_snmp_getvalue(struct variable_list *vars, zval *snmpval TSRMLS_D /* {{{ php_snmp_internal * -* Generic SNMP object fetcher (for both v3 and v1) +* Generic SNMP object fetcher (for all SNMP versions) * * st=1 snmpget() - query an agent and return a single value. * st=2 snmpget() - query an agent and return the next single value. @@ -336,9 +351,9 @@ static void php_snmp_internal(INTERNAL_FUNCTION_PARAMETERS, int st, struct snmp_pdu *pdu=NULL, *response; struct variable_list *vars; oid name[MAX_NAME_LEN]; - int name_length; + size_t name_length; oid root[MAX_NAME_LEN]; - int rootlen = 0; + size_t rootlen = 0; int gotroot = 0; int status, count; char buf[2048]; @@ -431,6 +446,7 @@ static void php_snmp_internal(INTERNAL_FUNCTION_PARAMETERS, int st, if (st == 1) { *return_value = *snmpval; zval_copy_ctor(return_value); + zval_ptr_dtor(&snmpval); snmp_close(ss); return; } else if (st == 2) { @@ -514,7 +530,7 @@ static void php_snmp_internal(INTERNAL_FUNCTION_PARAMETERS, int st, /* {{{ php_snmp * -* Generic SNMPv1 handler +* Generic community based SNMP handler for version 1 and 2. * This function makes use of the internal SNMP object fetcher. * The object fetcher is shared with SNMPv3. * @@ -528,7 +544,7 @@ static void php_snmp_internal(INTERNAL_FUNCTION_PARAMETERS, int st, * st=11 snmpset() - query an agent and set a single value * */ -static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st) +static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version) { zval **a1, **a2, **a3, **a4, **a5, **a6, **a7; struct snmp_session session; @@ -590,7 +606,7 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st) session.peername = hostname; session.remote_port = remote_port; - session.version = SNMP_VERSION_1; + session.version = version; /* * FIXME: potential memory leak * This is a workaround for an "artifact" (Mike Slifcak) @@ -616,7 +632,7 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st) Fetch a SNMP object */ PHP_FUNCTION(snmpget) { - php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,1); + php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,1, SNMP_VERSION_1); } /* }}} */ @@ -624,7 +640,7 @@ PHP_FUNCTION(snmpget) Fetch a SNMP object */ PHP_FUNCTION(snmpgetnext) { - php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,2); + php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,2, SNMP_VERSION_1); } /* }}} */ @@ -632,7 +648,7 @@ PHP_FUNCTION(snmpgetnext) Return all objects under the specified object id */ PHP_FUNCTION(snmpwalk) { - php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,3); + php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,3, SNMP_VERSION_1); } /* }}} */ @@ -640,7 +656,7 @@ PHP_FUNCTION(snmpwalk) Return all objects including their respective object id withing the specified one */ PHP_FUNCTION(snmprealwalk) { - php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,4); + php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,4, SNMP_VERSION_1); } /* }}} */ @@ -718,7 +734,7 @@ PHP_FUNCTION(snmp_set_oid_numeric_print) Set the value of a SNMP object */ PHP_FUNCTION(snmpset) { - php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,11); + php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,11, SNMP_VERSION_1); } /* }}} */ @@ -787,7 +803,24 @@ static int netsnmp_session_set_sec_protocol(struct snmp_session *s, char *prot T s->securityPrivProtoLen = OIDSIZE(usmDESPrivProtocol); return (0); #ifdef HAVE_AES - } else if (!strcasecmp(prot, "AES128")) { + } else if (!strcasecmp(prot, "AES128") +#ifdef SNMP_VALIDATE_ERR +/* +* In Net-SNMP before 5.2, the following symbols exist: +* usmAES128PrivProtocol, usmAES192PrivProtocol, usmAES256PrivProtocol +* In an effort to be more standards-compliant, 5.2 removed the last two. +* As of 5.2, the symbols are: +* usmAESPrivProtocol, usmAES128PrivProtocol +* +* As we want this extension to compile on both versions, we use the latter +* symbol on purpose, as it's defined to be the same as the former. +*/ + || !strcasecmp(prot, "AES")) { + s->securityPrivProto = usmAES128PrivProtocol; + s->securityPrivProtoLen = OIDSIZE(usmAES128PrivProtocol); + return (0); +#else + ) { s->securityPrivProto = usmAES128PrivProtocol; s->securityPrivProtoLen = OIDSIZE(usmAES128PrivProtocol); return (0); @@ -799,6 +832,7 @@ static int netsnmp_session_set_sec_protocol(struct snmp_session *s, char *prot T s->securityPrivProto = usmAES256PrivProtocol; s->securityPrivProtoLen = OIDSIZE(usmAES256PrivProtocol); return (0); +#endif #endif } else if (strlen(prot)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid privacy protocol: %s", prot); @@ -819,7 +853,7 @@ static int netsnmp_session_gen_auth_key(struct snmp_session *s, char *pass TSRML s->securityAuthKeyLen = USM_AUTH_KU_LEN; if (s->securityAuthProto == NULL) { /* get .conf set default */ - oid *def = get_default_authtype(&(s->securityAuthProtoLen)); + const oid *def = get_default_authtype(&(s->securityAuthProtoLen)); s->securityAuthProto = snmp_duplicate_objid(def, s->securityAuthProtoLen); } if (s->securityAuthProto == NULL) { @@ -848,7 +882,7 @@ static int netsnmp_session_gen_sec_key(struct snmp_session *s, u_char *pass TSRM s->securityPrivKeyLen = USM_PRIV_KU_LEN; if (s->securityPrivProto == NULL) { /* get .conf set default */ - oid *def = get_default_privtype(&(s->securityPrivProtoLen)); + const oid *def = get_default_privtype(&(s->securityPrivProtoLen)); s->securityPrivProto = snmp_duplicate_objid(def, s->securityPrivProtoLen); } if (s->securityPrivProto == NULL) { @@ -869,6 +903,45 @@ static int netsnmp_session_gen_sec_key(struct snmp_session *s, u_char *pass TSRM } /* }}} */ +/* {{{ proto string snmp2_get(string host, string community, string object_id [, int timeout [, int retries]]) + Fetch a SNMP object */ +PHP_FUNCTION(snmp2_get) +{ + php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,1, SNMP_VERSION_2c); +} +/* }}} */ + +/* {{{ proto string snmp2_getnext(string host, string community, string object_id [, int timeout [, int retries]]) + Fetch a SNMP object */ +PHP_FUNCTION(snmp2_getnext) +{ + php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,2, SNMP_VERSION_2c); +} +/* }}} */ + +/* {{{ proto array snmp2_walk(string host, string community, string object_id [, int timeout [, int retries]]) + Return all objects under the specified object id */ +PHP_FUNCTION(snmp2_walk) +{ + php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,3, SNMP_VERSION_2c); +} +/* }}} */ + +/* {{{ proto array snmp2_real_walk(string host, string community, string object_id [, int timeout [, int retries]]) + Return all objects including their respective object id withing the specified one */ +PHP_FUNCTION(snmp2_real_walk) +{ + php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,4, SNMP_VERSION_2c); +} +/* }}} */ + +/* {{{ proto int snmp2_set(string host, string community, string object_id, string type, mixed value [, int timeout [, int retries]]) + Set the value of a SNMP object */ +PHP_FUNCTION(snmp2_set) +{ + php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,11, SNMP_VERSION_2c); +} +/* }}} */ /* {{{ proto void php_snmpv3(INTERNAL_FUNCTION_PARAMETERS, int st) * diff --git a/ext/soap/EXPERIMENTAL b/ext/soap/EXPERIMENTAL deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/ext/soap/config.m4 b/ext/soap/config.m4 index 73d2b1e67360..d4c1a0da9c55 100644 --- a/ext/soap/config.m4 +++ b/ext/soap/config.m4 @@ -1,15 +1,20 @@ dnl $Id$ dnl config.m4 for extension soap -PHP_ARG_ENABLE(soap, whether to enable soap support, +PHP_ARG_ENABLE(soap, whether to enable SOAP support, [ --enable-soap Include SOAP support.]) if test -z "$PHP_LIBXML_DIR"; then PHP_ARG_WITH(libxml-dir, libxml2 install dir, - [ --with-libxml-dir=DIR XML: libxml2 install prefix], no, no) + [ --with-libxml-dir=DIR SOAP: libxml2 install prefix], no, no) fi -if test "$PHP_SOAP" != "no" && test "$PHP_LIBXML" != "no"; then +if test "$PHP_SOAP" != "no"; then + + if test "$PHP_LIBXML" = "no"; then + AC_MSG_ERROR([SOAP extension requires LIBXML extension, add --enable-libxml]) + fi + PHP_SETUP_LIBXML(SOAP_SHARED_LIBADD, [ AC_DEFINE(HAVE_SOAP,1,[ ]) PHP_NEW_EXTENSION(soap, soap.c php_encoding.c php_http.c php_packet_soap.c php_schema.c php_sdl.c php_xml.c, $ext_shared) diff --git a/ext/soap/interop/client_round2_interop.php b/ext/soap/interop/client_round2_interop.php index a8a3fad81037..588ee9288891 100644 --- a/ext/soap/interop/client_round2_interop.php +++ b/ext/soap/interop/client_round2_interop.php @@ -94,7 +94,7 @@ function _fetchEndpoints(&$soapclient, $test) { $this->_getEndpoints($test, 1); // retreive endpoints from the endpoint server - $endpointArray = $soapclient->__call("GetEndpointInfo",array("groupName"=>$test),array('soapaction'=>"http://soapinterop.org/",'uri'=>"http://soapinterop.org/")); + $endpointArray = $soapclient->__soapCall("GetEndpointInfo",array("groupName"=>$test),array('soapaction'=>"http://soapinterop.org/",'uri'=>"http://soapinterop.org/")); if (is_soap_fault($endpointArray) || PEAR::isError($endpointArray)) { if ($this->html) print "
";
             print $soapclient->wire."\n";
@@ -428,9 +428,9 @@ function doEndpointMethod(&$endpoint_info, &$soap_test) {
             $return = eval('return $soap->'.$soap_test->method_name.'('.$args.');');
         } else {
           if ($soap_test->headers || $soap_test->headers_expect) {
-            $return = $soap->__call($soap_test->method_name,$soap_test->method_params,array('soapaction'=>$soapaction,'uri'=>$namespace), $soap_test->headers, $result_headers);
+            $return = $soap->__soapCall($soap_test->method_name,$soap_test->method_params,array('soapaction'=>$soapaction,'uri'=>$namespace), $soap_test->headers, $result_headers);
           } else {
-            $return = $soap->__call($soap_test->method_name,$soap_test->method_params,array('soapaction'=>$soapaction,'uri'=>$namespace));
+            $return = $soap->__soapCall($soap_test->method_name,$soap_test->method_params,array('soapaction'=>$soapaction,'uri'=>$namespace));
           }
         }
 } catch (SoapFault $ex) {
diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c
index 7174eb9f167b..1d0778aac85f 100644
--- a/ext/soap/php_encoding.c
+++ b/ext/soap/php_encoding.c
@@ -22,20 +22,22 @@
 #include 
 
 #include "php_soap.h"
+#include "ext/libxml/php_libxml.h"
+#include 
+#include "zend_strtod.h"
 
 /* zval type decode */
 static zval *to_zval_double(encodeTypePtr type, xmlNodePtr data);
 static zval *to_zval_long(encodeTypePtr type, xmlNodePtr data);
-static zval *to_zval_ulong(encodeTypePtr type, xmlNodePtr data);
 static zval *to_zval_bool(encodeTypePtr type, xmlNodePtr data);
 static zval *to_zval_string(encodeTypePtr type, xmlNodePtr data);
 static zval *to_zval_stringr(encodeTypePtr type, xmlNodePtr data);
 static zval *to_zval_stringc(encodeTypePtr type, xmlNodePtr data);
+static zval *to_zval_stringb(encodeTypePtr type, xmlNodePtr data);
 static zval *to_zval_map(encodeTypePtr type, xmlNodePtr data);
 static zval *to_zval_null(encodeTypePtr type, xmlNodePtr data);
 
 static xmlNodePtr to_xml_long(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
-static xmlNodePtr to_xml_ulong(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
 static xmlNodePtr to_xml_double(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
 static xmlNodePtr to_xml_bool(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
 
@@ -71,17 +73,18 @@ static zval *to_zval_array(encodeTypePtr type, xmlNodePtr data);
 static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
 static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
 
+static zval *to_zval_any(encodeTypePtr type, xmlNodePtr data);
+static xmlNodePtr to_xml_any(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
+
 /* Try and guess for non-wsdl clients and servers */
 static zval *guess_zval_convert(encodeTypePtr type, xmlNodePtr data);
 static xmlNodePtr guess_xml_convert(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
 
 static int is_map(zval *array);
-static void get_array_type(xmlNodePtr node, zval *array, smart_str *out_type TSRMLS_DC);
+static encodePtr get_array_type(xmlNodePtr node, zval *array, smart_str *out_type TSRMLS_DC);
 
 static xmlNodePtr check_and_resolve_href(xmlNodePtr data);
 
-static encodePtr get_conversion(int encode);
-
 static void get_type_str(xmlNodePtr node, const char* ns, const char* type, smart_str* ret);
 static void set_ns_and_type_ex(xmlNodePtr node, char *ns, char *type);
 
@@ -145,8 +148,8 @@ encode defaultEncoding[] = {
 	{{XSD_GMONTH, XSD_GMONTH_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gmonth},
 	{{XSD_DURATION, XSD_DURATION_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_duration},
 
-	{{XSD_HEXBINARY, XSD_HEXBINARY_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_stringl},
-	{{XSD_BASE64BINARY, XSD_BASE64BINARY_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_stringl},
+	{{XSD_HEXBINARY, XSD_HEXBINARY_STRING, XSD_NAMESPACE, NULL}, to_zval_stringb, to_xml_stringl},
+	{{XSD_BASE64BINARY, XSD_BASE64BINARY_STRING, XSD_NAMESPACE, NULL}, to_zval_stringb, to_xml_stringl},
 
 	{{XSD_LONG, XSD_LONG_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
 	{{XSD_INT, XSD_INT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
@@ -159,7 +162,8 @@ encode defaultEncoding[] = {
 	{{XSD_UNSIGNEDBYTE, XSD_UNSIGNEDBYTE_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
 	{{XSD_UNSIGNEDSHORT, XSD_UNSIGNEDSHORT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
 	{{XSD_UNSIGNEDINT, XSD_UNSIGNEDINT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
-	{{XSD_UNSIGNEDLONG, XSD_UNSIGNEDLONG_STRING, XSD_NAMESPACE, NULL}, to_zval_ulong, to_xml_ulong},
+	{{XSD_UNSIGNEDLONG, XSD_UNSIGNEDLONG_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
+	{{XSD_INTEGER, XSD_INTEGER_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
 
 	{{XSD_ANYTYPE, XSD_ANYTYPE_STRING, XSD_NAMESPACE, NULL}, guess_zval_convert, guess_xml_convert},
 	{{XSD_UR_TYPE, XSD_UR_TYPE_STRING, XSD_NAMESPACE, NULL}, guess_zval_convert, guess_xml_convert},
@@ -199,6 +203,8 @@ encode defaultEncoding[] = {
 	{{XSD_BYTE, XSD_BYTE_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_long},
 	{{XSD_1999_TIMEINSTANT, XSD_1999_TIMEINSTANT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
 
+	{{XSD_ANYXML, "", "", NULL}, to_zval_any, to_xml_any},
+
 	{{END_KNOWN_TYPES, NULL, NULL, NULL}, guess_zval_convert, guess_xml_convert}
 };
 
@@ -254,7 +260,7 @@ xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style, xmlNodePtr par
 			soap_error0(E_ERROR, "Encoding: SoapVar hasn't 'enc_type' propery");
 		}
 
-		if (SOAP_GLOBAL(sdl) && encode == NULL) {
+		if (SOAP_GLOBAL(sdl)) {
 			if (zend_hash_find(ht, "enc_stype", sizeof("enc_stype"), (void **)&zstype) == SUCCESS) {
 				if (zend_hash_find(ht, "enc_ns", sizeof("enc_ns"), (void **)&zns) == SUCCESS) {
 				  enc = get_encoder(SOAP_GLOBAL(sdl), Z_STRVAL_PP(zns), Z_STRVAL_PP(zstype));
@@ -266,6 +272,9 @@ xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style, xmlNodePtr par
 		if (enc == NULL) {
 			enc = get_conversion(Z_LVAL_P(*ztype));
 		}
+		if (enc == NULL) {
+			enc = encode;
+		}
 
 		if (zend_hash_find(ht, "enc_value", sizeof("enc_value"), (void **)&zdata) == FAILURE) {
 			node = master_to_xml(enc, NULL, style, parent);
@@ -273,7 +282,7 @@ xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style, xmlNodePtr par
 			node = master_to_xml(enc, *zdata, style, parent);
 		}
 
-		if (style == SOAP_ENCODED || (SOAP_GLOBAL(sdl) && encode == NULL)) {
+		if (style == SOAP_ENCODED || (SOAP_GLOBAL(sdl) && encode != enc)) {
 			if (zend_hash_find(ht, "enc_stype", sizeof("enc_stype"), (void **)&zstype) == SUCCESS) {
 				if (style == SOAP_LITERAL) {
 					encode_add_ns(node, XSI_NAMESPACE);
@@ -310,15 +319,10 @@ xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style, xmlNodePtr par
 	return node;
 }
 
-zval *master_to_zval(encodePtr encode, xmlNodePtr data)
+static zval *master_to_zval_int(encodePtr encode, xmlNodePtr data)
 {
 	zval *ret = NULL;
-	TSRMLS_FETCH();
 
-	if (encode == NULL) {
-		encode = get_conversion(UNKNOWN_TYPE);
-	}
-	data = check_and_resolve_href(data);
 	if (encode->to_zval_before) {
 		data = encode->to_zval_before(&encode->details, data, 0);
 	}
@@ -331,6 +335,41 @@ zval *master_to_zval(encodePtr encode, xmlNodePtr data)
 	return ret;
 }
 
+zval *master_to_zval(encodePtr encode, xmlNodePtr data)
+{
+	TSRMLS_FETCH();
+	data = check_and_resolve_href(data);
+
+	if (encode == NULL) {
+		encode = get_conversion(UNKNOWN_TYPE);
+	} else {
+	  /* Use xsi:type if it is defined */
+		xmlAttrPtr type_attr = get_attribute_ex(data->properties,"type", XSI_NAMESPACE);
+
+		if (type_attr != NULL) {
+			encodePtr  enc = get_encoder_from_prefix(SOAP_GLOBAL(sdl), data, type_attr->children->content);
+
+			if (enc != NULL && enc != encode) {
+			  encodePtr tmp = enc;
+			  while (tmp &&
+			         tmp->details.sdl_type != NULL &&
+			         tmp->details.sdl_type->kind != XSD_TYPEKIND_COMPLEX) {
+			    if (enc == tmp->details.sdl_type->encode ||
+			        tmp == tmp->details.sdl_type->encode) {
+			    	enc = NULL;
+			    	break;
+			    }
+			    tmp = tmp->details.sdl_type->encode;
+			  }
+			  if (enc != NULL) {
+			    encode = enc;
+			  }
+			}
+		}
+	}
+	return master_to_zval_int(encode, data);
+}
+
 #ifdef HAVE_PHP_DOMXML
 zval *to_xml_before_user(encodeTypePtr type, zval *data)
 {
@@ -460,7 +499,23 @@ static zval *to_zval_string(encodeTypePtr type, xmlNodePtr data)
 	FIND_XML_NULL(data, ret);
 	if (data && data->children) {
 		if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
-			ZVAL_STRING(ret, data->children->content, 1);
+			TSRMLS_FETCH();
+
+			if (SOAP_GLOBAL(encoding) != NULL) {
+				xmlBufferPtr in  = xmlBufferCreateStatic(data->children->content, strlen(data->children->content));
+				xmlBufferPtr out = xmlBufferCreate();
+				int n = xmlCharEncOutFunc(SOAP_GLOBAL(encoding), out, in);
+
+				if (n >= 0) {
+					ZVAL_STRING(ret, (char*)xmlBufferContent(out), 1);
+				} else {
+					ZVAL_STRING(ret, data->children->content, 1);
+				}
+				xmlBufferFree(out);
+				xmlBufferFree(in);
+			} else {
+				ZVAL_STRING(ret, data->children->content, 1);
+			}
 		} else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
 			ZVAL_STRING(ret, data->children->content, 1);
 		} else {
@@ -479,8 +534,24 @@ static zval *to_zval_stringr(encodeTypePtr type, xmlNodePtr data)
 	FIND_XML_NULL(data, ret);
 	if (data && data->children) {
 		if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
+			TSRMLS_FETCH();
+
 			whiteSpace_replace(data->children->content);
-			ZVAL_STRING(ret, data->children->content, 1);
+			if (SOAP_GLOBAL(encoding) != NULL) {
+				xmlBufferPtr in  = xmlBufferCreateStatic(data->children->content, strlen(data->children->content));
+				xmlBufferPtr out = xmlBufferCreate();
+				int n = xmlCharEncOutFunc(SOAP_GLOBAL(encoding), out, in);
+
+				if (n >= 0) {
+					ZVAL_STRING(ret, (char*)xmlBufferContent(out), 1);
+				} else {
+					ZVAL_STRING(ret, data->children->content, 1);
+				}
+				xmlBufferFree(out);
+				xmlBufferFree(in);
+			} else {
+				ZVAL_STRING(ret, data->children->content, 1);
+			}
 		} else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
 			ZVAL_STRING(ret, data->children->content, 1);
 		} else {
@@ -493,6 +564,42 @@ static zval *to_zval_stringr(encodeTypePtr type, xmlNodePtr data)
 }
 
 static zval *to_zval_stringc(encodeTypePtr type, xmlNodePtr data)
+{
+	zval *ret;
+	MAKE_STD_ZVAL(ret);
+	FIND_XML_NULL(data, ret);
+	if (data && data->children) {
+		if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
+			TSRMLS_FETCH();
+
+			whiteSpace_collapse(data->children->content);
+			if (SOAP_GLOBAL(encoding) != NULL) {
+				xmlBufferPtr in  = xmlBufferCreateStatic(data->children->content, strlen(data->children->content));
+				xmlBufferPtr out = xmlBufferCreate();
+				int n = xmlCharEncOutFunc(SOAP_GLOBAL(encoding), out, in);
+
+				if (n >= 0) {
+					ZVAL_STRING(ret, (char*)xmlBufferContent(out), 1);
+				} else {
+					ZVAL_STRING(ret, data->children->content, 1);
+				}
+				xmlBufferFree(out);
+				xmlBufferFree(in);
+			} else {
+				ZVAL_STRING(ret, data->children->content, 1);
+			}
+		} else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
+			ZVAL_STRING(ret, data->children->content, 1);
+		} else {
+			soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
+		}
+	} else {
+		ZVAL_EMPTY_STRING(ret);
+	}
+	return ret;
+}
+
+static zval *to_zval_stringb(encodeTypePtr type, xmlNodePtr data)
 {
 	zval *ret;
 	MAKE_STD_ZVAL(ret);
@@ -534,6 +641,24 @@ static xmlNodePtr to_xml_string(encodeTypePtr type, zval *data, int style, xmlNo
 		zval_dtor(&tmp);
 	}
 
+	if (SOAP_GLOBAL(encoding) != NULL) {
+		xmlBufferPtr in  = xmlBufferCreateStatic(str, new_len);
+		xmlBufferPtr out = xmlBufferCreate();
+		int n = xmlCharEncInFunc(SOAP_GLOBAL(encoding), out, in);
+
+		if (n >= 0) {
+			efree(str);
+			str = estrdup(xmlBufferContent(out));
+			new_len = n;
+		} else if (!php_libxml_xmlCheckUTF8(str)) {
+			soap_error1(E_ERROR,  "Encoding: string '%s' is not a valid utf-8 string", str);
+		}
+		xmlBufferFree(out);
+		xmlBufferFree(in);
+	} else if (!php_libxml_xmlCheckUTF8(str)) {
+		soap_error1(E_ERROR,  "Encoding: string '%s' is not a valid utf-8 string", str);
+	}
+
 	xmlNodeSetContentLen(ret, str, new_len);
 	efree(str);
 
@@ -593,32 +718,13 @@ static zval *to_zval_long(encodeTypePtr type, xmlNodePtr data)
 	MAKE_STD_ZVAL(ret);
 	FIND_XML_NULL(data, ret);
 
-	if (data && data->children) {
-		if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
-			whiteSpace_collapse(data->children->content);
-			ZVAL_LONG(ret, atol(data->children->content));
-		} else {
-			soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
-		}
-	} else {
-		ZVAL_NULL(ret);
-	}
-	return ret;
-}
-
-static zval *to_zval_ulong(encodeTypePtr type, xmlNodePtr data)
-{
-	zval *ret;
-	MAKE_STD_ZVAL(ret);
-	FIND_XML_NULL(data, ret);
-
 	if (data && data->children) {
 		if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
 			whiteSpace_collapse(data->children->content);
 			errno = 0;
 			ret->value.lval = strtol(data->children->content, NULL, 0);
 			if (errno == ERANGE) { /* overflow */
-				ret->value.dval = strtod(data->children->content, NULL);
+				ret->value.dval = zend_strtod(data->children->content, NULL);
 				ret->type = IS_DOUBLE;
 			} else {
 				ret->type = IS_LONG;
@@ -633,30 +739,6 @@ static zval *to_zval_ulong(encodeTypePtr type, xmlNodePtr data)
 }
 
 static xmlNodePtr to_xml_long(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
-{
-	xmlNodePtr ret;
-	zval tmp;
-
-	ret = xmlNewNode(NULL,"BOGUS");
-	xmlAddChild(parent, ret);
-	FIND_ZVAL_NULL(data, ret, style);
-
-	tmp = *data;
-	zval_copy_ctor(&tmp);
-	if (Z_TYPE(tmp) != IS_LONG) {
-		convert_to_long(&tmp);
-	}
-	convert_to_string(&tmp);
-	xmlNodeSetContentLen(ret, Z_STRVAL(tmp), Z_STRLEN(tmp));
-	zval_dtor(&tmp);
-
-	if (style == SOAP_ENCODED) {
-		set_ns_and_type(ret, type);
-	}
-	return ret;
-}
-
-static xmlNodePtr to_xml_ulong(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
 {
 	xmlNodePtr ret;
 
@@ -665,8 +747,9 @@ static xmlNodePtr to_xml_ulong(encodeTypePtr type, zval *data, int style, xmlNod
 	FIND_ZVAL_NULL(data, ret, style);
 
 	if (Z_TYPE_P(data) == IS_DOUBLE) {
-		char s[16];
-		sprintf(s, "%0.0f",Z_DVAL_P(data));
+		char s[256];
+
+		sprintf(s, "%0.0f",floor(Z_DVAL_P(data)));
 		xmlNodeSetContent(ret, s);
 	} else {
 		zval tmp = *data;
@@ -752,9 +835,9 @@ static xmlNodePtr to_xml_bool(encodeTypePtr type, zval *data, int style, xmlNode
 	}
 
 	if (data->value.lval == 1) {
-		xmlNodeSetContent(ret, "1");
+		xmlNodeSetContent(ret, "true");
 	} else {
-		xmlNodeSetContent(ret, "0");
+		xmlNodeSetContent(ret, "false");
 	}
 
 	if (data == &tmp) {
@@ -788,6 +871,105 @@ static xmlNodePtr to_xml_null(encodeTypePtr type, zval *data, int style, xmlNode
 	return ret;
 }
 
+static void set_zval_property(zval* object, char* name, zval* val TSRMLS_DC)
+{
+	zend_class_entry *old_scope;
+
+	old_scope = EG(scope);
+	EG(scope) = Z_OBJCE_P(object);
+#ifdef ZEND_ENGINE_2
+	val->refcount--;
+#endif
+	add_property_zval(object, name, val);
+	EG(scope) = old_scope;
+}
+
+static zval* get_zval_property(zval* object, char* name TSRMLS_DC)
+{
+	if (Z_TYPE_P(object) == IS_OBJECT) {
+		zval member;
+		zval *data;
+		zend_class_entry *old_scope;
+
+		ZVAL_STRING(&member, name, 0);
+		old_scope = EG(scope);
+	  EG(scope) = Z_OBJCE_P(object);
+		data = Z_OBJ_HT_P(object)->read_property(object, &member, BP_VAR_IS TSRMLS_CC);
+		EG(scope) = old_scope;
+		if (data == EG(uninitialized_zval_ptr)) {
+			return NULL;
+		}
+		return data;
+	} else if (Z_TYPE_P(object) == IS_ARRAY) {
+		zval **data_ptr;
+
+		if (zend_hash_find(Z_ARRVAL_P(object), name, strlen(name)+1, (void**)&data_ptr) == SUCCESS) {
+		  return *data_ptr;
+		}
+	}
+  return NULL;
+}
+
+static void unset_zval_property(zval* object, char* name TSRMLS_DC)
+{
+	if (Z_TYPE_P(object) == IS_OBJECT) {
+		zval member;
+		zend_class_entry *old_scope;
+
+		ZVAL_STRING(&member, name, 0);
+		old_scope = EG(scope);
+	  EG(scope) = Z_OBJCE_P(object);
+		Z_OBJ_HT_P(object)->unset_property(object, &member TSRMLS_CC);
+		EG(scope) = old_scope;
+	} else if (Z_TYPE_P(object) == IS_ARRAY) {
+		zend_hash_del(Z_ARRVAL_P(object), name, strlen(name)+1);
+	}
+}
+
+static void model_to_zval_any(zval *ret, xmlNodePtr node TSRMLS_DC)
+{
+	zval* any = NULL;
+
+	while (node != NULL) {
+		if (get_zval_property(ret, (char*)node->name TSRMLS_CC) == NULL) {
+			zval* val = master_to_zval(get_conversion(XSD_ANYXML), node);
+			if (get_attribute_ex(node->properties,"type", XSI_NAMESPACE) == NULL &&
+			    Z_TYPE_P(val) == IS_STRING) {
+				while (node->next != NULL &&
+				       get_zval_property(ret, (char*)node->next->name TSRMLS_CC) == NULL &&
+				       get_attribute_ex(node->next->properties,"type", XSI_NAMESPACE) == NULL) {
+					zval* val2 = master_to_zval(get_conversion(XSD_ANYXML), node->next);
+					if (Z_TYPE_P(val2) != IS_STRING) {
+						break;
+					}
+					add_string_to_string(val, val, val2);
+					zval_ptr_dtor(&val2);
+				  node = node->next;
+				}
+			}
+			if (any == NULL) {
+				any = val;
+			} else {
+				if (Z_TYPE_P(any) != IS_ARRAY) {
+			    /* Convert into array */
+			    zval *arr;
+
+			    MAKE_STD_ZVAL(arr);
+			    array_init(arr);
+				  add_next_index_zval(arr, any);
+				  any = arr;
+			  }
+			  /* Add array element */
+			  add_next_index_zval(any, val);
+			}
+		}
+		node = node->next;
+	}
+	if (any) {
+		set_zval_property(ret, "any", any TSRMLS_CC);
+	}
+}
+
 static void model_to_zval_object(zval *ret, sdlContentModelPtr model, xmlNodePtr data, sdlPtr sdl TSRMLS_DC)
 {
 	switch (model->kind) {
@@ -844,24 +1026,29 @@ static void model_to_zval_object(zval *ret, sdlContentModelPtr model, xmlNodePtr
 						} while ((node = get_node(node->next, model->u.element->name)) != NULL);
 						val = array;
 					}
-#ifdef ZEND_ENGINE_2
-					val->refcount--;
-#endif
-					add_property_zval(ret, model->u.element->name, val);
+					set_zval_property(ret, model->u.element->name, val TSRMLS_CC);
 				}
 			}
 			break;
-		case XSD_CONTENT_SEQUENCE:
 		case XSD_CONTENT_ALL:
+		case XSD_CONTENT_SEQUENCE:
 		case XSD_CONTENT_CHOICE: {
 			sdlContentModelPtr *tmp;
 			HashPosition pos;
+			sdlContentModelPtr any = NULL;
 
 			zend_hash_internal_pointer_reset_ex(model->u.content, &pos);
 			while (zend_hash_get_current_data_ex(model->u.content, (void**)&tmp, &pos) == SUCCESS) {
-				model_to_zval_object(ret, *tmp, data, sdl TSRMLS_CC);
+				if ((*tmp)->kind == XSD_CONTENT_ANY) {
+					any = *tmp;
+				} else {
+					model_to_zval_object(ret, *tmp, data, sdl TSRMLS_CC);
+				}
 				zend_hash_move_forward_ex(model->u.content, &pos);
 			}
+			if (any) {
+				model_to_zval_any(ret, data->children TSRMLS_CC);
+			}
 			break;
 		}
 		case XSD_CONTENT_GROUP:
@@ -879,8 +1066,20 @@ static zval *to_zval_object(encodeTypePtr type, xmlNodePtr data)
 	xmlNodePtr trav;
 	sdlPtr sdl;
 	sdlTypePtr sdlType = type->sdl_type;
+	zend_class_entry *ce = ZEND_STANDARD_CLASS_DEF_PTR;
+	zend_bool redo_any = 0;
 	TSRMLS_FETCH();
 
+	if (SOAP_GLOBAL(class_map) && type->type_str) {
+		zval             **classname;
+		zend_class_entry  *tmp;
+
+		if (zend_hash_find(SOAP_GLOBAL(class_map), type->type_str, strlen(type->type_str)+1, (void**)&classname) == SUCCESS &&
+		    Z_TYPE_PP(classname) == IS_STRING &&
+		    (tmp = zend_fetch_class(Z_STRVAL_PP(classname), Z_STRLEN_PP(classname), ZEND_FETCH_CLASS_AUTO TSRMLS_CC)) != NULL) {
+			ce = tmp;
+		}
+	}
 	sdl = SOAP_GLOBAL(sdl);
 	if (sdlType) {
 		if (sdlType->kind == XSD_TYPEKIND_RESTRICTION &&
@@ -899,16 +1098,13 @@ static zval *to_zval_object(encodeTypePtr type, xmlNodePtr data)
 
 				MAKE_STD_ZVAL(ret);
 
-				object_init(ret);
-				base = master_to_zval(enc, data);
-#ifdef ZEND_ENGINE_2
-				base->refcount--;
-#endif
-				add_property_zval(ret, "_", base);
+				object_init_ex(ret, ce);
+				base = master_to_zval_int(enc, data);
+				set_zval_property(ret, "_", base TSRMLS_CC);
 			} else {
 				MAKE_STD_ZVAL(ret);
 				FIND_XML_NULL(data, ret);
-				object_init(ret);
+				object_init_ex(ret, ce);
 			}
 		} else if (sdlType->kind == XSD_TYPEKIND_EXTENSION &&
 		           sdlType->encode &&
@@ -917,27 +1113,31 @@ static zval *to_zval_object(encodeTypePtr type, xmlNodePtr data)
 			    sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_SIMPLE &&
 			    sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_LIST &&
 			    sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
-				ret = master_to_zval(sdlType->encode, data);
+				ret = master_to_zval_int(sdlType->encode, data);
 				FIND_XML_NULL(data, ret);
+				if (get_zval_property(ret, "any" TSRMLS_CC) != NULL) {
+				  unset_zval_property(ret, "any" TSRMLS_CC);
+					redo_any = 1;
+			  }
 			} else {
 				zval *base;
 
 				MAKE_STD_ZVAL(ret);
 
-				object_init(ret);
-				base = master_to_zval(sdlType->encode, data);
-#ifdef ZEND_ENGINE_2
-				base->refcount--;
-#endif
-				add_property_zval(ret, "_", base);
+				object_init_ex(ret, ce);
+				base = master_to_zval_int(sdlType->encode, data);
+				set_zval_property(ret, "_", base TSRMLS_CC);
 			}
 		} else {
 			MAKE_STD_ZVAL(ret);
 			FIND_XML_NULL(data, ret);
-			object_init(ret);
+			object_init_ex(ret, ce);
 		}
 		if (sdlType->model) {
 			model_to_zval_object(ret, sdlType->model, data, sdl TSRMLS_CC);
+			if (redo_any && get_zval_property(ret, "any" TSRMLS_CC) == NULL) {
+				model_to_zval_any(ret, data->children TSRMLS_CC);				
+		  }
 		}
 		if (sdlType->attributes) {
 			sdlAttributePtr *attr;
@@ -967,10 +1167,7 @@ static zval *to_zval_object(encodeTypePtr type, xmlNodePtr data)
 						xmlNodeSetContent(dummy, str_val);
 						data = master_to_zval((*attr)->encode, dummy);
 						xmlFreeNode(dummy);
-#ifdef ZEND_ENGINE_2
-						data->refcount--;
-#endif
-						add_property_zval(ret, (*attr)->name, data);
+						set_zval_property(ret, (*attr)->name, data TSRMLS_CC);
 					}
 				}
 				zend_hash_move_forward_ex(sdlType->attributes, &pos);
@@ -980,19 +1177,36 @@ static zval *to_zval_object(encodeTypePtr type, xmlNodePtr data)
 
 		MAKE_STD_ZVAL(ret);
 		FIND_XML_NULL(data, ret);
-		object_init(ret);
+		object_init_ex(ret, ce);
 
 		trav = data->children;
 
 		while (trav != NULL) {
 			if (trav->type == XML_ELEMENT_NODE) {
-				zval *tmpVal;
+				zval  *tmpVal;
+				zval *prop;
 
 				tmpVal = master_to_zval(NULL, trav);
-#ifdef ZEND_ENGINE_2
-				tmpVal->refcount--;
-#endif
-				add_property_zval(ret, (char *)trav->name, tmpVal);
+
+				prop = get_zval_property(ret, (char*)trav->name TSRMLS_CC);
+				if (!prop) {
+          set_zval_property(ret, (char*)trav->name, tmpVal TSRMLS_CC);
+				} else {
+				  /* Property already exist - make array */
+				  if (Z_TYPE_P(prop) != IS_ARRAY) {
+				    /* Convert into array */
+				    zval *arr;
+
+				    MAKE_STD_ZVAL(arr);
+				    array_init(arr);
+				    prop->refcount++;
+					  add_next_index_zval(arr, prop);
+	          set_zval_property(ret, (char*)trav->name, arr TSRMLS_CC);
+					  prop = arr;
+				  }
+				  /* Add array element */
+				  add_next_index_zval(prop, tmpVal);
+				}
 			}
 			trav = trav->next;
 		}
@@ -1000,18 +1214,19 @@ static zval *to_zval_object(encodeTypePtr type, xmlNodePtr data)
 	return ret;
 }
 
-static int model_to_xml_object(xmlNodePtr node, sdlContentModelPtr model, HashTable *prop, int style, int strict)
+static int model_to_xml_object(xmlNodePtr node, sdlContentModelPtr model, zval *object, int style, int strict TSRMLS_DC)
 {
 	switch (model->kind) {
 		case XSD_CONTENT_ELEMENT: {
-			zval **data;
+			zval *data;
 			xmlNodePtr property;
 			encodePtr enc;
 
-			if (zend_hash_find(prop, model->u.element->name, strlen(model->u.element->name)+1, (void**)&data) == SUCCESS) {
+			data = get_zval_property(object, model->u.element->name TSRMLS_CC);
+			if (data) {
 				enc = model->u.element->encode;
-				if ((model->max_occurs == -1 || model->max_occurs > 1) && Z_TYPE_PP(data) == IS_ARRAY) {
-					HashTable *ht = Z_ARRVAL_PP(data);
+				if ((model->max_occurs == -1 || model->max_occurs > 1) && Z_TYPE_P(data) == IS_ARRAY) {
+					HashTable *ht = Z_ARRVAL_P(data);
 					zval **val;
 
 					zend_hash_internal_pointer_reset(ht);
@@ -1040,7 +1255,7 @@ static int model_to_xml_object(xmlNodePtr node, sdlContentModelPtr model, HashTa
 						zend_hash_move_forward(ht);
 					}
 				} else {
-					if (Z_TYPE_PP(data) == IS_NULL && model->u.element->nillable) {
+					if (Z_TYPE_P(data) == IS_NULL && model->u.element->nillable) {
 						property = xmlNewNode(NULL,"BOGUS");
 						xmlAddChild(node, property);
 						if (style == SOAP_ENCODED) {
@@ -1050,19 +1265,31 @@ static int model_to_xml_object(xmlNodePtr node, sdlContentModelPtr model, HashTa
 							xmlSetNsProp(property, xsi, "nil", "1");
 						}
 					} else {
-						property = master_to_xml(enc, *data, style, node);
+						property = master_to_xml(enc, data, style, node);
 						if (property->children && property->children->content &&
 						    model->u.element->fixed && strcmp(model->u.element->fixed,property->children->content) != 0) {
 							soap_error3(E_ERROR, "Encoding: Element '%s' has fixed value '%s' (value '%s' is not allowed)", model->u.element->name, model->u.element->fixed, property->children->content);
 						}
 					}
 					xmlNodeSetName(property, model->u.element->name);
-					if (style == SOAP_LITERAL && model->u.element->namens) {
+					if (style == SOAP_LITERAL &&
+					    model->u.element->namens &&
+					    model->u.element->form == XSD_FORM_QUALIFIED) {
 						xmlNsPtr nsp = encode_add_ns(property, model->u.element->namens);
 						xmlSetNs(property, nsp);
 					}
 				}
 				return 1;
+			} else if (strict && model->u.element->nillable) {
+				property = xmlNewNode(NULL,model->u.element->name);
+				xmlAddChild(node, property);
+				if (style == SOAP_ENCODED) {
+					xmlSetProp(property, "xsi:nil", "1");
+				} else {
+					xmlNsPtr xsi = encode_add_ns(property,XSI_NAMESPACE);
+					xmlSetNsProp(property, xsi, "nil", "1");
+				}
+				return 1;
 			} else if (model->min_occurs == 0) {
 				return 2;
 			} else {
@@ -1073,6 +1300,37 @@ static int model_to_xml_object(xmlNodePtr node, sdlContentModelPtr model, HashTa
 			}
 			break;
 		}
+		case XSD_CONTENT_ANY: {
+			zval *data;
+			xmlNodePtr property;
+			encodePtr enc;
+
+			data = get_zval_property(object, "any" TSRMLS_CC);
+			if (data) {
+				enc = get_conversion(XSD_ANYXML);
+				if ((model->max_occurs == -1 || model->max_occurs > 1) && Z_TYPE_P(data) == IS_ARRAY) {
+					HashTable *ht = Z_ARRVAL_P(data);
+					zval **val;
+
+					zend_hash_internal_pointer_reset(ht);
+					while (zend_hash_get_current_data(ht,(void**)&val) == SUCCESS) {
+						property = master_to_xml(enc, *val, style, node);
+						zend_hash_move_forward(ht);
+					}
+				} else {
+					property = master_to_xml(enc, data, style, node);
+				}
+				return 1;
+			} else if (model->min_occurs == 0) {
+				return 2;
+			} else {
+				if (strict) {
+					soap_error0(E_ERROR,  "Encoding: object hasn't 'any' property");
+				}
+				return 0;
+			}
+			break;
+		}
 		case XSD_CONTENT_SEQUENCE:
 		case XSD_CONTENT_ALL: {
 			sdlContentModelPtr *tmp;
@@ -1080,7 +1338,7 @@ static int model_to_xml_object(xmlNodePtr node, sdlContentModelPtr model, HashTa
 
 			zend_hash_internal_pointer_reset_ex(model->u.content, &pos);
 			while (zend_hash_get_current_data_ex(model->u.content, (void**)&tmp, &pos) == SUCCESS) {
-				if (!model_to_xml_object(node, *tmp, prop, style, model->min_occurs > 0)) {
+				if (!model_to_xml_object(node, *tmp, object, style, model->min_occurs > 0 TSRMLS_CC)) {
 					return 0;
 				}
 				zend_hash_move_forward_ex(model->u.content, &pos);
@@ -1094,7 +1352,7 @@ static int model_to_xml_object(xmlNodePtr node, sdlContentModelPtr model, HashTa
 
 			zend_hash_internal_pointer_reset_ex(model->u.content, &pos);
 			while (zend_hash_get_current_data_ex(model->u.content, (void**)&tmp, &pos) == SUCCESS) {
-				int tmp_ret = model_to_xml_object(node, *tmp, prop, style, 0);
+				int tmp_ret = model_to_xml_object(node, *tmp, object, style, 0 TSRMLS_CC);
 				if (tmp_ret == 1) {
 					return 1;
 				} else if (tmp_ret != 0) {
@@ -1105,7 +1363,7 @@ static int model_to_xml_object(xmlNodePtr node, sdlContentModelPtr model, HashTa
 			return ret;
 		}
 		case XSD_CONTENT_GROUP: {
-			return model_to_xml_object(node, model->u.group->model, prop, style, model->min_occurs > 0);
+			return model_to_xml_object(node, model->u.group->model, object, style, model->min_occurs > 0 TSRMLS_CC);
 		}
 		default:
 		  break;
@@ -1181,9 +1439,9 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo
 				enc = enc->details.sdl_type->encode;
 			}
 			if (enc) {
-				zval **tmp;
-				if (prop && zend_hash_find(prop, "_", sizeof("_"), (void**)&tmp) == SUCCESS) {
-					xmlParam = master_to_xml(enc, *tmp, style, parent);
+				zval *tmp = get_zval_property(data, "_" TSRMLS_CC);
+				if (tmp) {
+					xmlParam = master_to_xml(enc, tmp, style, parent);
 				} else if (prop == NULL) {
 					xmlParam = master_to_xml(enc, data, style, parent);
 				} else {
@@ -1202,10 +1460,10 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo
 			    sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
 				xmlParam = master_to_xml(sdlType->encode, data, style, parent);
 			} else {
-				zval **tmp;
+				zval *tmp = get_zval_property(data, "_" TSRMLS_CC);
 
-				if (prop && zend_hash_find(prop, "_", sizeof("_"), (void**)&tmp) == SUCCESS) {
-					xmlParam = master_to_xml(sdlType->encode, *tmp, style, parent);
+				if (tmp) {
+					xmlParam = master_to_xml(sdlType->encode, tmp, style, parent);
 				} else if (prop == NULL) {
 					xmlParam = master_to_xml(sdlType->encode, data, style, parent);
 				} else {
@@ -1252,25 +1510,37 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo
 					zend_hash_move_forward(prop);
 				}
 			} else if (sdlType->model) {
-				model_to_xml_object(xmlParam, sdlType->model, prop, style, 1);
+				model_to_xml_object(xmlParam, sdlType->model, data, style, 1 TSRMLS_CC);
 			}
 			if (sdlType->attributes) {
 				sdlAttributePtr *attr;
-				zval **data;
+				zval *zattr;
 				HashPosition pos;
 
 				zend_hash_internal_pointer_reset_ex(sdlType->attributes, &pos);
 				while (zend_hash_get_current_data_ex(sdlType->attributes, (void**)&attr, &pos) == SUCCESS) {
 					if ((*attr)->name) {
-						if (zend_hash_find(prop, (*attr)->name, strlen((*attr)->name)+1, (void**)&data) == SUCCESS) {
+						zattr = get_zval_property(data, (*attr)->name TSRMLS_CC);
+						if (zattr) {
 							xmlNodePtr dummy;
 
-							dummy = master_to_xml((*attr)->encode, *data, SOAP_LITERAL, xmlParam);
+							dummy = master_to_xml((*attr)->encode, zattr, SOAP_LITERAL, xmlParam);
 							if (dummy->children && dummy->children->content) {
 								if ((*attr)->fixed && strcmp((*attr)->fixed,dummy->children->content) != 0) {
 									soap_error3(E_ERROR, "Encoding: Attribute '%s' has fixed value '%s' (value '%s' is not allowed)", (*attr)->name, (*attr)->fixed, dummy->children->content);
 								}
-								xmlSetProp(xmlParam, (*attr)->name, dummy->children->content);
+								/* we need to handle xml: namespace specially, since it is
+								   an implicit schema. Otherwise, use form.
+								*/
+								if ((*attr)->namens &&
+								    (!strncmp((*attr)->namens, XML_NAMESPACE, sizeof(XML_NAMESPACE)) || 
+								     (*attr)->form == XSD_FORM_QUALIFIED)) {
+									xmlNsPtr nsp = encode_add_ns(xmlParam, (*attr)->namens);
+
+									xmlSetNsProp(xmlParam, nsp, (*attr)->name, dummy->children->content);
+								} else {
+									xmlSetProp(xmlParam, (*attr)->name, dummy->children->content);
+								}
 							}
 							xmlUnlinkNode(dummy);
 							xmlFreeNode(dummy);
@@ -1311,7 +1581,18 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo
 				property = master_to_xml(get_conversion((*zprop)->type), (*zprop), style, xmlParam);
 
 				if (key_type == HASH_KEY_IS_STRING) {
-					xmlNodeSetName(property, str_key);
+			  	char *prop_name;
+
+					if (Z_TYPE_P(data) == IS_OBJECT) {
+						char *class_name;
+
+						zend_unmangle_property_name(str_key, &class_name, &prop_name);
+					} else {
+						prop_name = str_key;
+					}
+					if (prop_name) {
+						xmlNodeSetName(property, prop_name);
+					}
 				}
 				zend_hash_move_forward(prop);
 			}
@@ -1327,7 +1608,6 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo
 static xmlNodePtr guess_array_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
 {
 	encodePtr enc = NULL;
-	TSRMLS_FETCH();
 
 	if (data && Z_TYPE_P(data) == IS_ARRAY) {
 		if (is_map(data)) {
@@ -1460,7 +1740,6 @@ static void add_xml_array_elements(xmlNodePtr xmlParam,
 
 	 			if (zdata) {
 	 				if (enc == NULL) {
-						TSRMLS_FETCH();
  						xparam = master_to_xml(get_conversion((*zdata)->type), (*zdata), style, xmlParam);
  					} else {
  						xparam = master_to_xml(enc, (*zdata), style, xmlParam);
@@ -1649,8 +1928,7 @@ static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNod
 				enc = elementType->encode;
 				get_type_str(xmlParam, elementType->encode->details.ns, elementType->encode->details.type_str, &array_type);
 			} else {
-				get_array_type(xmlParam, data, &array_type TSRMLS_CC);
-				enc = get_encoder_ex(SOAP_GLOBAL(sdl), array_type.c, array_type.len);
+				enc = get_array_type(xmlParam, data, &array_type TSRMLS_CC);
 			}
 		} else if (sdl_type && sdl_type->elements &&
 		           zend_hash_num_elements(sdl_type->elements) == 1 &&
@@ -1669,8 +1947,7 @@ static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNod
 			dims[0] = i;
 		} else {
 
-			get_array_type(xmlParam, data, &array_type TSRMLS_CC);
-			enc = get_encoder_ex(SOAP_GLOBAL(sdl), array_type.c, array_type.len);
+			enc = get_array_type(xmlParam, data, &array_type TSRMLS_CC);
 			smart_str_append_long(&array_size, i);
 			dims = safe_emalloc(sizeof(int), dimension, 0);
 			dims[0] = i;
@@ -1930,7 +2207,6 @@ static xmlNodePtr to_xml_map(encodeTypePtr type, zval *data, int style, xmlNodeP
 {
 	xmlNodePtr xmlParam;
 	int i;
-	TSRMLS_FETCH();
 
 	xmlParam = xmlNewNode(NULL,"BOGUS");
 	xmlAddChild(parent, xmlParam);
@@ -1988,7 +2264,6 @@ static zval *to_zval_map(encodeTypePtr type, xmlNodePtr data)
 {
 	zval *ret, *key, *value;
 	xmlNodePtr trav, item, xmlKey, xmlValue;
-	TSRMLS_FETCH();
 
 	MAKE_STD_ZVAL(ret);
 	FIND_XML_NULL(data, ret);
@@ -2033,7 +2308,6 @@ static xmlNodePtr guess_xml_convert(encodeTypePtr type, zval *data, int style, x
 {
 	encodePtr  enc;
 	xmlNodePtr ret;
-	TSRMLS_FETCH();
 
 	if (data) {
 		enc = get_conversion(data->type);
@@ -2069,12 +2343,16 @@ static zval *guess_zval_convert(encodeTypePtr type, xmlNodePtr data)
 		if (tmpattr != NULL) {
 		  type_name = tmpattr->children->content;
 			enc = get_encoder_from_prefix(SOAP_GLOBAL(sdl), data, tmpattr->children->content);
+			if (enc && type == &enc->details) {
+				enc = NULL;
+			}
 			if (enc != NULL) {
 			  encodePtr tmp = enc;
 			  while (tmp &&
 			         tmp->details.sdl_type != NULL &&
 			         tmp->details.sdl_type->kind != XSD_TYPEKIND_COMPLEX) {
-			    if (tmp == enc) {
+			    if (enc == tmp->details.sdl_type->encode ||
+			        tmp == tmp->details.sdl_type->encode) {
 			    	enc = NULL;
 			    	break;
 			    }
@@ -2105,7 +2383,7 @@ static zval *guess_zval_convert(encodeTypePtr type, xmlNodePtr data)
 			}
 		}
 	}
-	ret = master_to_zval(enc, data);
+	ret = master_to_zval_int(enc, data);
 	if (SOAP_GLOBAL(sdl) && type_name && enc->details.sdl_type) {
 		zval* soapvar;
 		char *ns, *cptype;
@@ -2140,7 +2418,7 @@ static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *forma
 	int max_reallocs = 5;
 	size_t buf_len=64, real_len;
 	char *buf;
-	char tzbuf[6];
+	char tzbuf[8];
 
 	xmlNodePtr xmlParam;
 
@@ -2162,19 +2440,19 @@ static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *forma
 
 		/* Time zone support */
 #ifdef HAVE_TM_GMTOFF
-		sprintf(tzbuf, "%c%02d%02d", (ta->tm_gmtoff < 0) ? '-' : '+', abs(ta->tm_gmtoff / 3600), abs( (ta->tm_gmtoff % 3600) / 60 ));
+		sprintf(tzbuf, "%c%02d:%02d", (ta->tm_gmtoff < 0) ? '-' : '+', abs(ta->tm_gmtoff / 3600), abs( (ta->tm_gmtoff % 3600) / 60 ));
 #else
 # ifdef __CYGWIN__
-		sprintf(tzbuf, "%c%02d%02d", ((ta->tm_isdst ? _timezone - 3600:_timezone)>0)?'-':'+', abs((ta->tm_isdst ? _timezone - 3600 : _timezone) / 3600), abs(((ta->tm_isdst ? _timezone - 3600 : _timezone) % 3600) / 60));
+		sprintf(tzbuf, "%c%02d:%02d", ((ta->tm_isdst ? _timezone - 3600:_timezone)>0)?'-':'+', abs((ta->tm_isdst ? _timezone - 3600 : _timezone) / 3600), abs(((ta->tm_isdst ? _timezone - 3600 : _timezone) % 3600) / 60));
 # else
-		sprintf(tzbuf, "%c%02d%02d", ((ta->tm_isdst ? timezone - 3600:timezone)>0)?'-':'+', abs((ta->tm_isdst ? timezone - 3600 : timezone) / 3600), abs(((ta->tm_isdst ? timezone - 3600 : timezone) % 3600) / 60));
+		sprintf(tzbuf, "%c%02d:%02d", ((ta->tm_isdst ? timezone - 3600:timezone)>0)?'-':'+', abs((ta->tm_isdst ? timezone - 3600 : timezone) / 3600), abs(((ta->tm_isdst ? timezone - 3600 : timezone) % 3600) / 60));
 # endif
 #endif
-		if (strcmp(tzbuf,"+0000") == 0) {
+		if (strcmp(tzbuf,"+00:00") == 0) {
 		  strcpy(tzbuf,"Z");
 		  real_len++;
 		} else {
-			real_len += 5;
+			real_len += 6;
 		}
 		if (real_len >= buf_len) {
 			buf = (char *) erealloc(buf, real_len+1);
@@ -2345,11 +2623,47 @@ static xmlNodePtr to_xml_union(encodeTypePtr enc, zval *data, int style, xmlNode
 	return to_xml_list(enc,data,style, parent);
 }
 
+static zval *to_zval_any(encodeTypePtr type, xmlNodePtr data)
+{
+	xmlBufferPtr buf;
+	zval *ret;
+
+	buf = xmlBufferCreate();
+	xmlNodeDump(buf, NULL, data, 0, 0);
+	MAKE_STD_ZVAL(ret);
+	ZVAL_STRING(ret, (char*)xmlBufferContent(buf), 1);
+	xmlBufferFree(buf);
+	return ret;
+}
+
+static xmlNodePtr to_xml_any(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
+{	
+	xmlNodePtr ret;
+
+	if (Z_TYPE_P(data) == IS_STRING) {
+		ret = xmlNewTextLen(Z_STRVAL_P(data), Z_STRLEN_P(data));
+	} else {
+		zval tmp = *data;
+
+		zval_copy_ctor(&tmp);
+		convert_to_string(&tmp);
+		ret = xmlNewTextLen(Z_STRVAL_P(data), Z_STRLEN_P(data));
+		zval_dtor(&tmp);
+	}
+	ret->name = xmlStringTextNoenc;
+	xmlAddChild(parent, ret);
+
+	return ret;
+}
+
 zval *sdl_guess_convert_zval(encodeTypePtr enc, xmlNodePtr data)
 {
 	sdlTypePtr type;
 
 	type = enc->sdl_type;
+	if (type == NULL) {
+		return guess_zval_convert(enc, data);
+	}
 /*FIXME: restriction support
 	if (type && type->restrictions &&
 	    data &&  data->children && data->children->content) {
@@ -2382,7 +2696,7 @@ zval *sdl_guess_convert_zval(encodeTypePtr enc, xmlNodePtr data)
 	switch (type->kind) {
 		case XSD_TYPEKIND_SIMPLE:
 			if (type->encode && enc != &type->encode->details) {
-				return master_to_zval(type->encode, data);
+				return master_to_zval_int(type->encode, data);
 			} else {
 				return guess_zval_convert(enc, data);
 			}
@@ -2413,6 +2727,13 @@ xmlNodePtr sdl_guess_convert_xml(encodeTypePtr enc, zval *data, int style, xmlNo
 
 	type = enc->sdl_type;
 
+	if (type == NULL) {
+		ret = guess_xml_convert(enc, data, style, parent);
+		if (style == SOAP_ENCODED) {
+			set_ns_and_type(ret, enc);
+		}
+		return ret;
+	}
 /*FIXME: restriction support
 	if (type) {
 		if (type->restrictions && Z_TYPE_P(data) == IS_STRING) {
@@ -2566,7 +2887,7 @@ void encode_reset_ns()
 	SOAP_GLOBAL(cur_uniq_ns) = 0;
 }
 
-static encodePtr get_conversion(int encode)
+encodePtr get_conversion(int encode)
 {
 	encodePtr *enc = NULL;
 	TSRMLS_FETCH();
@@ -2611,19 +2932,21 @@ static int is_map(zval *array)
 	return FALSE;
 }
 
-static void get_array_type(xmlNodePtr node, zval *array, smart_str *type TSRMLS_DC)
+static encodePtr get_array_type(xmlNodePtr node, zval *array, smart_str *type TSRMLS_DC)
 {
-	HashTable *ht = HASH_OF(array);
+	HashTable *ht;
 	int i, count, cur_type, prev_type, different;
 	zval **tmp;
 	char *prev_stype = NULL, *cur_stype = NULL, *prev_ns = NULL, *cur_ns = NULL;
 
 	if (!array || Z_TYPE_P(array) != IS_ARRAY) {
 		smart_str_appendl(type, "xsd:anyType", 11);
+		return get_conversion(XSD_ANYTYPE);
 	}
 
 	different = FALSE;
 	cur_type = prev_type = 0;
+	ht = HASH_OF(array);
 	count = zend_hash_num_elements(ht);
 
 	zend_hash_internal_pointer_reset(ht);
@@ -2680,20 +3003,33 @@ static void get_array_type(xmlNodePtr node, zval *array, smart_str *type TSRMLS_
 
 	if (different || count == 0) {
 		smart_str_appendl(type, "xsd:anyType", 11);
+		return get_conversion(XSD_ANYTYPE);		
 	} else {
+		encodePtr enc;
+
 		if (cur_stype != NULL) {
+			smart_str array_type = {0};
+
 			if (cur_ns) {
 				xmlNsPtr ns = encode_add_ns(node,cur_ns);
-				smart_str_appends(type,ns->prefix);
-				smart_str_appendc(type,':');
+
+				smart_str_appends(type, ns->prefix);
+				smart_str_appendc(type, ':');
+				smart_str_appends(&array_type, cur_ns);
+				smart_str_appendc(&array_type, ':');
 			}
-			smart_str_appends(type,cur_stype);
+			smart_str_appends(type, cur_stype);
 			smart_str_0(type);
-		} else {
-			encodePtr enc;
+			smart_str_appends(&array_type, cur_stype);
+			smart_str_0(&array_type);
 
+			enc = get_encoder_ex(SOAP_GLOBAL(sdl), array_type.c, array_type.len);
+			smart_str_free(&array_type);
+			return enc;
+		} else {
 			enc = get_conversion(cur_type);
 			get_type_str(node, enc->details.ns, enc->details.type_str, type);
+			return enc;
 		}
 	}
 }
diff --git a/ext/soap/php_encoding.h b/ext/soap/php_encoding.h
index 4d7f75d117d5..d291e5befe0b 100644
--- a/ext/soap/php_encoding.h
+++ b/ext/soap/php_encoding.h
@@ -43,6 +43,8 @@
 #define XSD_NS_PREFIX "xsd"
 #define XSI_NAMESPACE "http://www.w3.org/2001/XMLSchema-instance"
 #define XSI_NS_PREFIX "xsi"
+#define XML_NAMESPACE "http://www.w3.org/XML/1998/namespace"
+#define XML_NS_PREFIX "xml"
 
 #define XSD_STRING 101
 #define XSD_STRING_STRING "string"
@@ -137,6 +139,8 @@
 #define XSD_UR_TYPE 146
 #define XSD_UR_TYPE_STRING "ur-type"
 
+#define XSD_ANYXML 147
+
 #define APACHE_NAMESPACE "http://xml.apache.org/xml-soap"
 #define APACHE_MAP 200
 #define APACHE_MAP_STRING "Map"
@@ -212,6 +216,8 @@ zval *sdl_guess_convert_zval(encodeTypePtr enc, xmlNodePtr data);
 void encode_reset_ns();
 xmlNsPtr encode_add_ns(xmlNodePtr node, const char* ns);
 
+encodePtr get_conversion(int encode);
+
 void delete_encoder(void *handle);
 
 extern encode defaultEncoding[];
diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c
index b4f9c2351a56..000ce4408f32 100644
--- a/ext/soap/php_http.c
+++ b/ext/soap/php_http.c
@@ -21,9 +21,10 @@
 
 #include "php_soap.h"
 #include "ext/standard/base64.h"
+#include "ext/standard/md5.h"
 
 static char *get_http_header_value(char *headers, char *type);
-static int get_http_body(php_stream *socketd, char *headers,  char **response, int *out_size TSRMLS_DC);
+static int get_http_body(php_stream *socketd, int close, char *headers,  char **response, int *out_size TSRMLS_DC);
 static int get_http_headers(php_stream *socketd,char **response, int *out_size TSRMLS_DC);
 
 #define smart_str_append_const(str, const) \
@@ -32,21 +33,19 @@ static int get_http_headers(php_stream *socketd,char **response, int *out_size T
 static int stream_alive(php_stream *stream  TSRMLS_DC)
 {
 	int socket;
-	fd_set rfds;
-	struct timeval tv;
 	char buf;
 
+	/* maybe better to use:
+	 * php_stream_set_option(stream, PHP_STREAM_OPTION_CHECK_LIVENESS, 0, NULL)
+	 * here instead */
+
 	if (stream == NULL || stream->eof || php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT, (void**)&socket, 0) != SUCCESS) {
 		return FALSE;
 	}
 	if (socket == -1) {
 		return FALSE;
 	} else {
-		FD_ZERO(&rfds);
-		FD_SET(socket, &rfds);
-		tv.tv_sec = 0;
-		tv.tv_usec = 0;
-		if (select(socket + 1, &rfds, NULL, NULL, &tv) > 0 && FD_ISSET(socket, &rfds)) {
+		if (php_pollfd_for_ms(socket, PHP_POLLREADABLE, 0) > 0) {
 			if (0 == recv(socket, &buf, sizeof(buf), MSG_PEEK) && php_socket_errno() != EAGAIN) {
 				return FALSE;
 			}
@@ -56,7 +55,7 @@ static int stream_alive(php_stream *stream  TSRMLS_DC)
 }
 
 /* Proxy HTTP Authentication */
-static void proxy_authentication(zval* this_ptr, smart_str* soap_headers TSRMLS_DC)
+void proxy_authentication(zval* this_ptr, smart_str* soap_headers TSRMLS_DC)
 {
 	zval **login, **password;
 
@@ -80,17 +79,46 @@ static void proxy_authentication(zval* this_ptr, smart_str* soap_headers TSRMLS_
 	}
 }
 
+/* HTTP Authentication */
+void basic_authentication(zval* this_ptr, smart_str* soap_headers TSRMLS_DC)
+{
+	zval **login, **password;
+
+	if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_login", sizeof("_login"), (void **)&login) == SUCCESS &&
+			!zend_hash_exists(Z_OBJPROP_P(this_ptr), "_digest", sizeof("_digest"))) {
+		char* buf;
+		int len;
+		smart_str auth = {0};
+
+		smart_str_appendl(&auth, Z_STRVAL_PP(login), Z_STRLEN_PP(login));
+		smart_str_appendc(&auth, ':');
+		if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_password", sizeof("_password"), (void **)&password) == SUCCESS) {
+			smart_str_appendl(&auth, Z_STRVAL_PP(password), Z_STRLEN_PP(password));
+		}
+		smart_str_0(&auth);
+		buf = php_base64_encode(auth.c, auth.len, &len);
+		smart_str_append_const(soap_headers, "Authorization: Basic ");
+		smart_str_appendl(soap_headers, buf, len);
+		smart_str_append_const(soap_headers, "\r\n");
+		efree(buf);
+		smart_str_free(&auth);
+	}
+}
+
 static php_stream* http_connect(zval* this_ptr, php_url *phpurl, int use_ssl, int *use_proxy TSRMLS_DC)
 {
 	php_stream *stream;
-	zval **proxy_host, **proxy_port;
+	zval **proxy_host, **proxy_port, **tmp;
 	char *host;
 #ifdef ZEND_ENGINE_2
+	php_stream_context *context = NULL;
 	char *name;
 	long namelen;
 #endif
 	int port;
 	int old_error_reporting;
+	struct timeval tv;
+	struct timeval *timeout = NULL;
 
 	if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_proxy_host", sizeof("_proxy_host"), (void **) &proxy_host) == SUCCESS &&
 	    Z_TYPE_PP(proxy_host) == IS_STRING &&
@@ -103,21 +131,41 @@ static php_stream* http_connect(zval* this_ptr, php_url *phpurl, int use_ssl, in
 		host = phpurl->host;
 		port = phpurl->port;
 	}
+	if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_connection_timeout", sizeof("_connection_timeout"), (void **) &tmp) == SUCCESS &&
+	    Z_TYPE_PP(tmp) == IS_LONG && Z_LVAL_PP(tmp) > 0) {
+	  tv.tv_sec = Z_LVAL_PP(tmp);
+	  tv.tv_usec = 0;
+		timeout = &tv;
+	}
 
 	old_error_reporting = EG(error_reporting);
 	EG(error_reporting) &= ~(E_WARNING|E_NOTICE|E_USER_WARNING|E_USER_NOTICE);
 
 #ifdef ZEND_ENGINE_2
 	namelen = spprintf(&name, 0, "%s://%s:%d", (use_ssl && !*use_proxy)? "ssl" : "tcp", host, port);
+	if (use_ssl) {
+		zval **tmp;
+
+		if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_local_cert", sizeof("_local_cert"), (void **) &tmp) == SUCCESS &&
+		    Z_TYPE_PP(tmp) == IS_STRING) {
+			context = php_stream_context_alloc();
+			php_stream_context_set_option(context, "ssl", "local_cert", *tmp);
+			if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_passphrase", sizeof("_passphrase"), (void **) &tmp) == SUCCESS &&
+			    Z_TYPE_PP(tmp) == IS_STRING) {
+				php_stream_context_set_option(context, "ssl", "passphrase", *tmp);
+			}
+		}
+	}
 	stream = php_stream_xport_create(name, namelen,
 		ENFORCE_SAFE_MODE | REPORT_ERRORS,
 		STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT,
 		NULL /*persistent_id*/,
-		NULL /*timeout*/,
-		NULL, NULL, NULL);
+		timeout,
+		context,
+		NULL, NULL);
 	efree(name);
 #else
-	stream = php_stream_sock_open_host(host, port, SOCK_STREAM, NULL, NULL);
+	stream = php_stream_sock_open_host(host, port, SOCK_STREAM, timeout, NULL);
 #endif
 
 	/* SSL & proxy */
@@ -186,13 +234,13 @@ static int in_domain(const char *host, const char *domain)
   }
 }
 
-int make_http_soap_request(zval  *this_ptr, 
+int make_http_soap_request(zval  *this_ptr,
                            char  *buf,
                            int    buf_size,
-                           char  *location, 
-                           char  *soapaction, 
+                           char  *location,
+                           char  *soapaction,
                            int    soap_version,
-                           char **buffer, 
+                           char **buffer,
                            int   *buffer_len TSRMLS_DC)
 {
 	char *request;
@@ -206,8 +254,9 @@ int make_http_soap_request(zval  *this_ptr,
 	char *http_headers, *http_body, *content_type, *http_version, *cookie_itt;
 	int http_header_size, http_body_size, http_close;
 	char *connection;
-	int http_1_1 = 0;
-	int http_status = 0;
+	int http_1_1;
+	int http_status;
+	int content_type_xml = 0;
 	char *content_encoding;
 
 	if (this_ptr == NULL || Z_TYPE_P(this_ptr) != IS_OBJECT) {
@@ -273,7 +322,7 @@ int make_http_soap_request(zval  *this_ptr,
 		phpurl = php_url_parse(location);
 	}
 
-try_again:	
+try_again:
 	if (phpurl == NULL || phpurl->host == NULL) {
 	  if (phpurl != NULL) {php_url_free(phpurl);}
 		if (request != buf) {efree(request);}
@@ -382,6 +431,10 @@ int make_http_soap_request(zval  *this_ptr,
 		smart_str_append_const(&soap_headers, " HTTP/1.1\r\n"
 			"Host: ");
 		smart_str_appends(&soap_headers, phpurl->host);
+		if (phpurl->port != (use_ssl?443:80)) {
+			smart_str_appendc(&soap_headers, ':');
+			smart_str_append_unsigned(&soap_headers, phpurl->port);
+		}
 		smart_str_append_const(&soap_headers, "\r\n"
 			"Connection: Keep-Alive\r\n"
 /*
@@ -390,14 +443,15 @@ int make_http_soap_request(zval  *this_ptr,
 */
 			"User-Agent: PHP SOAP 0.1\r\n");
 		if (soap_version == SOAP_1_2) {
-			smart_str_append_const(&soap_headers,"Content-Type: application/soap+xml; charset=\"utf-8");
+			smart_str_append_const(&soap_headers,"Content-Type: application/soap+xml; charset=utf-8");
 			if (soapaction) {
-				smart_str_append_const(&soap_headers,"\"; action=\"");
+				smart_str_append_const(&soap_headers,"; action=\"");
 				smart_str_appends(&soap_headers, soapaction);
+				smart_str_append_const(&soap_headers,"\"");
 			}
-			smart_str_append_const(&soap_headers,"\"\r\n");
+			smart_str_append_const(&soap_headers,"\r\n");
 		} else {
-			smart_str_append_const(&soap_headers,"Content-Type: text/xml; charset=\"utf-8\"\r\n");
+			smart_str_append_const(&soap_headers,"Content-Type: text/xml; charset=utf-8\r\n");
 			if (soapaction) {
 				smart_str_append_const(&soap_headers, "SOAPAction: \"");
 				smart_str_appends(&soap_headers, soapaction);
@@ -409,23 +463,164 @@ int make_http_soap_request(zval  *this_ptr,
 		smart_str_append_const(&soap_headers, "\r\n");
 
 		/* HTTP Authentication */
-		if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_login", sizeof("_login"), (void **)&login) == SUCCESS) {
-			char* buf;
-			int len;
-
-			smart_str auth = {0};
-			smart_str_appendl(&auth, Z_STRVAL_PP(login), Z_STRLEN_PP(login));
-			smart_str_appendc(&auth, ':');
-			if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_password", sizeof("_password"), (void **)&password) == SUCCESS) {
-				smart_str_appendl(&auth, Z_STRVAL_PP(password), Z_STRLEN_PP(password));
+		if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_login", sizeof("_login"), (void **)&login) == SUCCESS &&
+		    Z_TYPE_PP(login) == IS_STRING) {
+			zval **digest;
+
+			if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_digest", sizeof("_digest"), (void **)&digest) == SUCCESS) {
+				if (Z_TYPE_PP(digest) == IS_ARRAY) {
+					char          HA1[33], HA2[33], response[33], cnonce[33], nc[9];
+					PHP_MD5_CTX   md5ctx;
+					unsigned char hash[16];
+
+					PHP_MD5Init(&md5ctx);
+					sprintf(cnonce, "%d", rand());
+					PHP_MD5Update(&md5ctx, cnonce, strlen(cnonce));
+					PHP_MD5Final(hash, &md5ctx);
+					make_digest(cnonce, hash);
+
+					if (zend_hash_find(Z_ARRVAL_PP(digest), "nc", sizeof("nc"), (void **)&tmp) == SUCCESS &&
+					    Z_TYPE_PP(tmp) == IS_LONG) {
+						Z_LVAL_PP(tmp)++;
+						sprintf(nc, "%08ld", Z_LVAL_PP(tmp));
+					} else {
+						add_assoc_long(*digest, "nc", 1);
+						strcpy(nc, "00000001");
+					}
+
+					PHP_MD5Init(&md5ctx);
+					PHP_MD5Update(&md5ctx, Z_STRVAL_PP(login), Z_STRLEN_PP(login));
+					PHP_MD5Update(&md5ctx, ":", 1);
+					if (zend_hash_find(Z_ARRVAL_PP(digest), "realm", sizeof("realm"), (void **)&tmp) == SUCCESS &&
+					    Z_TYPE_PP(tmp) == IS_STRING) {
+						PHP_MD5Update(&md5ctx, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
+					}
+					PHP_MD5Update(&md5ctx, ":", 1);
+					if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_password", sizeof("_password"), (void **)&password) == SUCCESS &&
+					    Z_TYPE_PP(password) == IS_STRING) {
+						PHP_MD5Update(&md5ctx, Z_STRVAL_PP(password), Z_STRLEN_PP(password));
+					}
+					PHP_MD5Final(hash, &md5ctx);
+					make_digest(HA1, hash);
+					if (zend_hash_find(Z_ARRVAL_PP(digest), "algorithm", sizeof("algorithm"), (void **)&tmp) == SUCCESS &&
+					    Z_TYPE_PP(tmp) == IS_STRING &&
+					    Z_STRLEN_PP(tmp) == sizeof("md5-sess")-1 &&
+					    stricmp(Z_STRVAL_PP(tmp), "md5-sess") == 0) {
+						PHP_MD5Init(&md5ctx);
+						PHP_MD5Update(&md5ctx, HA1, 32);
+						PHP_MD5Update(&md5ctx, ":", 1);
+						if (zend_hash_find(Z_ARRVAL_PP(digest), "nonce", sizeof("nonce"), (void **)&tmp) == SUCCESS &&
+						    Z_TYPE_PP(tmp) == IS_STRING) {
+							PHP_MD5Update(&md5ctx, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
+						}
+						PHP_MD5Update(&md5ctx, ":", 1);
+						PHP_MD5Update(&md5ctx, cnonce, 8);
+						PHP_MD5Final(hash, &md5ctx);
+						make_digest(HA1, hash);
+					}
+
+					PHP_MD5Init(&md5ctx);
+					PHP_MD5Update(&md5ctx, "POST:", sizeof("POST:")-1);
+					if (phpurl->path) {
+						PHP_MD5Update(&md5ctx, phpurl->path, strlen(phpurl->path));
+					}
+					if (phpurl->query) {
+						PHP_MD5Update(&md5ctx, "?", 1);
+						PHP_MD5Update(&md5ctx, phpurl->query, strlen(phpurl->query));
+					}
+
+					/* TODO: Support for qop="auth-int" */
+/*
+					if (zend_hash_find(Z_ARRVAL_PP(digest), "qop", sizeof("qop"), (void **)&tmp) == SUCCESS &&
+					    Z_TYPE_PP(tmp) == IS_STRING &&
+					    Z_STRLEN_PP(tmp) == sizeof("auth-int")-1 &&
+					    stricmp(Z_STRVAL_PP(tmp), "auth-int") == 0) {
+						PHP_MD5Update(&md5ctx, ":", 1);
+						PHP_MD5Update(&md5ctx, HEntity, HASHHEXLEN);
+					}
+*/
+					PHP_MD5Final(hash, &md5ctx);
+					make_digest(HA2, hash);
+
+					PHP_MD5Init(&md5ctx);
+					PHP_MD5Update(&md5ctx, HA1, 32);
+					PHP_MD5Update(&md5ctx, ":", 1);
+					if (zend_hash_find(Z_ARRVAL_PP(digest), "nonce", sizeof("nonce"), (void **)&tmp) == SUCCESS &&
+					    Z_TYPE_PP(tmp) == IS_STRING) {
+						PHP_MD5Update(&md5ctx, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
+					}
+					PHP_MD5Update(&md5ctx, ":", 1);
+					if (zend_hash_find(Z_ARRVAL_PP(digest), "qop", sizeof("qop"), (void **)&tmp) == SUCCESS &&
+					    Z_TYPE_PP(tmp) == IS_STRING) {
+						PHP_MD5Update(&md5ctx, nc, 8);
+						PHP_MD5Update(&md5ctx, ":", 1);
+						PHP_MD5Update(&md5ctx, cnonce, 8);
+						PHP_MD5Update(&md5ctx, ":", 1);
+						/* TODO: Support for qop="auth-int" */
+						PHP_MD5Update(&md5ctx, "auth", sizeof("auth")-1);
+						PHP_MD5Update(&md5ctx, ":", 1);
+					}
+					PHP_MD5Update(&md5ctx, HA2, 32);
+					PHP_MD5Final(hash, &md5ctx);
+					make_digest(response, hash);
+	
+					smart_str_append_const(&soap_headers, "Authorization: Digest username=\"");
+					smart_str_appendl(&soap_headers, Z_STRVAL_PP(login), Z_STRLEN_PP(login));
+					if (zend_hash_find(Z_ARRVAL_PP(digest), "realm", sizeof("realm"), (void **)&tmp) == SUCCESS &&
+					    Z_TYPE_PP(tmp) == IS_STRING) {
+						smart_str_append_const(&soap_headers, "\", realm=\"");
+						smart_str_appendl(&soap_headers, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
+					}
+					if (zend_hash_find(Z_ARRVAL_PP(digest), "nonce", sizeof("nonce"), (void **)&tmp) == SUCCESS &&
+					    Z_TYPE_PP(tmp) == IS_STRING) {
+						smart_str_append_const(&soap_headers, "\", nonce=\"");
+						smart_str_appendl(&soap_headers, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
+					}
+					smart_str_append_const(&soap_headers, "\", uri=\"");
+					if (phpurl->path) {
+						smart_str_appends(&soap_headers, phpurl->path);
+					}
+					if (phpurl->query) {
+						smart_str_appendc(&soap_headers, '?');
+						smart_str_appends(&soap_headers, phpurl->query);
+					}
+					if (zend_hash_find(Z_ARRVAL_PP(digest), "qop", sizeof("qop"), (void **)&tmp) == SUCCESS &&
+					    Z_TYPE_PP(tmp) == IS_STRING) {
+					/* TODO: Support for qop="auth-int" */
+						smart_str_append_const(&soap_headers, "\", qop=\"auth");
+						smart_str_append_const(&soap_headers, "\", nc=\"");
+						smart_str_appendl(&soap_headers, nc, 8);
+						smart_str_append_const(&soap_headers, "\", cnonce=\"");
+						smart_str_appendl(&soap_headers, cnonce, 8);
+					}
+					smart_str_append_const(&soap_headers, "\", response=\"");
+					smart_str_appendl(&soap_headers, response, 32);
+					if (zend_hash_find(Z_ARRVAL_PP(digest), "opaque", sizeof("opaque"), (void **)&tmp) == SUCCESS &&
+					    Z_TYPE_PP(tmp) == IS_STRING) {
+						smart_str_append_const(&soap_headers, "\", opaque=\"");
+						smart_str_appendl(&soap_headers, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
+					}
+					smart_str_append_const(&soap_headers, "\"\r\n");
+				}
+			} else {
+				char* buf;
+				int len;
+
+				smart_str auth = {0};
+				smart_str_appendl(&auth, Z_STRVAL_PP(login), Z_STRLEN_PP(login));
+				smart_str_appendc(&auth, ':');
+				if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_password", sizeof("_password"), (void **)&password) == SUCCESS &&
+				    Z_TYPE_PP(password) == IS_STRING) {
+					smart_str_appendl(&auth, Z_STRVAL_PP(password), Z_STRLEN_PP(password));
+				}
+				smart_str_0(&auth);
+				buf = php_base64_encode(auth.c, auth.len, &len);
+				smart_str_append_const(&soap_headers, "Authorization: Basic ");
+				smart_str_appendl(&soap_headers, buf, len);
+				smart_str_append_const(&soap_headers, "\r\n");
+				efree(buf);
+				smart_str_free(&auth);
 			}
-			smart_str_0(&auth);
-			buf = php_base64_encode(auth.c, auth.len, &len);
-			smart_str_append_const(&soap_headers, "Authorization: Basic ");
-			smart_str_appendl(&soap_headers, buf, len);
-			smart_str_append_const(&soap_headers, "\r\n");
-			efree(buf);
-			smart_str_free(&auth);
 		}
 
 		/* Proxy HTTP Authentication */
@@ -453,10 +648,10 @@ int make_http_soap_request(zval  *this_ptr,
 						if (zend_hash_index_find(Z_ARRVAL_PP(data), 0, (void**)&value) == SUCCESS &&
 						    Z_TYPE_PP(value) == IS_STRING) {
 						  zval **tmp;
-						  if (zend_hash_index_find(Z_ARRVAL_PP(data), 1, (void**)&tmp) == SUCCESS &&
-						      strncmp(phpurl->path?phpurl->path:"/",Z_STRVAL_PP(tmp),Z_STRLEN_PP(tmp)) == 0 &&
-						      zend_hash_index_find(Z_ARRVAL_PP(data), 2, (void**)&tmp) == SUCCESS &&
-						      in_domain(phpurl->host,Z_STRVAL_PP(tmp)) &&
+						  if ((zend_hash_index_find(Z_ARRVAL_PP(data), 1, (void**)&tmp) == FAILURE ||
+						       strncmp(phpurl->path?phpurl->path:"/",Z_STRVAL_PP(tmp),Z_STRLEN_PP(tmp)) == 0) &&
+						      (zend_hash_index_find(Z_ARRVAL_PP(data), 2, (void**)&tmp) == FAILURE ||
+						       in_domain(phpurl->host,Z_STRVAL_PP(tmp))) &&
 						      (use_ssl || zend_hash_index_find(Z_ARRVAL_PP(data), 3, (void**)&tmp) == FAILURE)) {
 								smart_str_appendl(&soap_headers, key, strlen(key));
 								smart_str_appendc(&soap_headers, '=');
@@ -494,111 +689,46 @@ int make_http_soap_request(zval  *this_ptr,
 
 	}
 
-	if (!get_http_headers(stream, &http_headers, &http_header_size TSRMLS_CC)) {
-		if (request != buf) {efree(request);}
-		php_stream_close(stream);
-		zend_hash_del(Z_OBJPROP_P(this_ptr), "httpsocket", sizeof("httpsocket"));
-		zend_hash_del(Z_OBJPROP_P(this_ptr), "_use_proxy", sizeof("_use_proxy"));
-		add_soap_fault(this_ptr, "HTTP", "Error Fetching http headers", NULL, NULL TSRMLS_CC);
-		return FALSE;
-	}
-
-	if (zend_hash_find(Z_OBJPROP_P(this_ptr), "trace", sizeof("trace"), (void **) &trace) == SUCCESS &&
-	    Z_LVAL_PP(trace) > 0) {
-		add_property_stringl(this_ptr, "__last_response_headers", http_headers, http_header_size, 1);
-	}
-
-	/* Check to see what HTTP status was sent */
-	http_version = get_http_header_value(http_headers,"HTTP/");
-	if (http_version) {
-		char *tmp;
-
-		tmp = strstr(http_version," ");
-
-		if (tmp != NULL) {
-			tmp++;
-			http_status = atoi(tmp);
+	do {
+		if (!get_http_headers(stream, &http_headers, &http_header_size TSRMLS_CC)) {
+			if (http_headers) {efree(http_headers);}
+			if (request != buf) {efree(request);}
+			php_stream_close(stream);
+			zend_hash_del(Z_OBJPROP_P(this_ptr), "httpsocket", sizeof("httpsocket"));
+			zend_hash_del(Z_OBJPROP_P(this_ptr), "_use_proxy", sizeof("_use_proxy"));
+			add_soap_fault(this_ptr, "HTTP", "Error Fetching http headers", NULL, NULL TSRMLS_CC);
+			return FALSE;
 		}
 
-		/* Process HTTP status codes */
-		if (http_status >= 200 && http_status < 300) {
-		} else if (http_status >= 300 && http_status < 400) {
-			char *loc;
+		if (zend_hash_find(Z_OBJPROP_P(this_ptr), "trace", sizeof("trace"), (void **) &trace) == SUCCESS &&
+		    Z_LVAL_PP(trace) > 0) {
+			add_property_stringl(this_ptr, "__last_response_headers", http_headers, http_header_size, 1);
+		}
 
-			if ((loc = get_http_header_value(http_headers,"Location: ")) != NULL) {
-			  php_url *new_url  = php_url_parse(loc);
-			  char *body;
-			  int body_size;
+		/* Check to see what HTTP status was sent */
+		http_1_1 = 0;
+		http_status = 0;
+		http_version = get_http_header_value(http_headers,"HTTP/");
+		if (http_version) {
+			char *tmp;
 
-				if (new_url != NULL) {
-					if (get_http_body(stream, http_headers, &body, &body_size TSRMLS_CC)) {
-						efree(body);
-					} else {
-						php_stream_close(stream);
-						zend_hash_del(Z_OBJPROP_P(this_ptr), "httpsocket", sizeof("httpsocket"));
-						stream = NULL;
-					}
-					efree(http_version);
-					efree(http_headers);
-					efree(loc);
-					if (new_url->scheme == NULL && new_url->path != NULL) {						
-					  new_url->scheme = estrdup(phpurl->scheme);
-					  new_url->host = estrdup(phpurl->host);
-					  new_url->port = phpurl->port;
-						if (new_url->path && new_url->path[0] != '/') {
-						  char *t = phpurl->path?phpurl->path:"/";
-						  char *p = strrchr(t, '/');
-						  char *s = emalloc((p - t) + strlen(new_url->path) + 2);
-
-						  strncpy(s, t, (p - t) + 1);
-						  s[(p - t) + 1] = 0;
-						  strcat(s, new_url->path);
-						  efree(new_url->path);
-						  new_url->path = s;
-						} 
-					}
-					phpurl = new_url;
-					goto try_again;
-				}
+			if (!strncmp(http_version,"1.1", 3)) {
+				http_1_1 = 1;
 			}
-/*
-		} else if (http_status == 400) {
-			add_soap_fault(this_ptr, "HTTP", "Bad Request", NULL, NULL TSRMLS_CC);
-		} else if (http_status == 401) {
-			add_soap_fault(this_ptr, "HTTP", "Unauthorized Request", NULL, NULL TSRMLS_CC);
-		} else if (http_status == 405) {
-			add_soap_fault(this_ptr, "HTTP", "Method not allowed", NULL, NULL TSRMLS_CC);
-		} else if (http_status == 415) {
-			add_soap_fault(this_ptr, "HTTP", "Unsupported Media Type", NULL, NULL TSRMLS_CC);
-		} else if (http_status >= 400 && http_status < 500) {
-			add_soap_fault(this_ptr, "HTTP", "Client Error", NULL, NULL TSRMLS_CC);
-		} else if (http_status == 500) {
-			add_soap_fault(this_ptr, "HTTP", "Internal Server Error", NULL, NULL TSRMLS_CC);
-		} else if (http_status >= 500 && http_status < 600) {
-			add_soap_fault(this_ptr, "HTTP", "Server Error", NULL, NULL TSRMLS_CC);
-		} else {
-			add_soap_fault(this_ptr, "HTTP", "Unsupported HTTP status code", NULL, NULL TSRMLS_CC);
-*/
-		}
 
-		/* Try and get headers again */
-		if (http_status == 100) {
-			efree(http_headers);
-			if (!get_http_headers(stream, &http_headers, &http_header_size TSRMLS_CC)) {
-				if (request != buf) {efree(request);}
-				php_stream_close(stream);
-				zend_hash_del(Z_OBJPROP_P(this_ptr), "httpsocket", sizeof("httpsocket"));
-				zend_hash_del(Z_OBJPROP_P(this_ptr), "_use_proxy", sizeof("_use_proxy"));
-				add_soap_fault(this_ptr, "HTTP", "Error Fetching http headers", NULL, NULL TSRMLS_CC);
-				return FALSE;
+			tmp = strstr(http_version," ");
+			if (tmp != NULL) {
+				tmp++;
+				http_status = atoi(tmp);
 			}
-		}
+			efree(http_version);
 
-		if (strncmp(http_version,"1.1", 3)) {
-			http_1_1 = 1;
+			/* Try and get headers again */
+			if (http_status == 100) {
+				efree(http_headers);
+			}
 		}
-		efree(http_version);
-	}
+	} while (http_status == 100);
 
 	/* Grab and send back every cookie */
 
@@ -682,7 +812,7 @@ int make_http_soap_request(zval  *this_ptr,
 		efree(cookie);
 	}
 
-	if (!get_http_body(stream, http_headers, &http_body, &http_body_size TSRMLS_CC)) {
+	if (!get_http_body(stream, !http_1_1, http_headers, &http_body, &http_body_size TSRMLS_CC)) {
 		if (request != buf) {efree(request);}
 		php_stream_close(stream);
 		efree(http_headers);
@@ -725,6 +855,127 @@ int make_http_soap_request(zval  *this_ptr,
 		zend_hash_del(Z_OBJPROP_P(this_ptr), "_use_proxy", sizeof("_use_proxy"));
 	}
 
+	/* Process HTTP status codes */
+	if (http_status >= 300 && http_status < 400) {
+		char *loc;
+
+		if ((loc = get_http_header_value(http_headers,"Location: ")) != NULL) {
+			php_url *new_url  = php_url_parse(loc);
+			char *body;
+			int body_size;
+
+			if (new_url != NULL) {
+				if (get_http_body(stream, !http_1_1, http_headers, &body, &body_size TSRMLS_CC)) {
+					efree(body);
+				} else {
+					php_stream_close(stream);
+					zend_hash_del(Z_OBJPROP_P(this_ptr), "httpsocket", sizeof("httpsocket"));
+					stream = NULL;
+				}
+				efree(http_headers);
+				efree(http_body);
+				efree(loc);
+				if (new_url->scheme == NULL && new_url->path != NULL) {
+					new_url->scheme = estrdup(phpurl->scheme);
+					new_url->host = estrdup(phpurl->host);
+					new_url->port = phpurl->port;
+					if (new_url->path && new_url->path[0] != '/') {
+						char *t = phpurl->path?phpurl->path:"/";
+						char *p = strrchr(t, '/');
+						char *s = emalloc((p - t) + strlen(new_url->path) + 2);
+
+						strncpy(s, t, (p - t) + 1);
+						s[(p - t) + 1] = 0;
+						strcat(s, new_url->path);
+						efree(new_url->path);
+						new_url->path = s;
+					}
+				}
+				phpurl = new_url;
+
+				goto try_again;
+			}
+		}
+	} else if (http_status == 401) {
+		/* Digest authentication */
+		zval **digest, **login, **password;
+		char *auth = get_http_header_value(http_headers, "WWW-Authenticate: ");
+
+		if (auth &&
+				strstr(auth, "Digest") == auth &&
+		    (zend_hash_find(Z_OBJPROP_P(this_ptr), "_digest", sizeof("_digest"), (void **)&digest) == FAILURE ||
+		     Z_TYPE_PP(digest) != IS_ARRAY) &&
+		    zend_hash_find(Z_OBJPROP_P(this_ptr), "_login", sizeof("_login"), (void **)&login) == SUCCESS &&
+		    Z_TYPE_PP(login) == IS_STRING &&
+		    zend_hash_find(Z_OBJPROP_P(this_ptr), "_password", sizeof("_password"), (void **)&password) == SUCCESS &&
+		    Z_TYPE_PP(password) == IS_STRING) {
+			char *s;
+			zval *digest = NULL;
+
+			s = auth + sizeof("Digest")-1;
+			while (*s != '\0') {
+				char *name, *val;
+				while (*s == ' ') ++s;
+				name = s;
+				while (*s != '\0' && *s != '=') ++s;
+				if (*s == '=') {
+					*s = '\0';
+					++s;
+					if (*s == '"') {
+						++s;
+						val = s;
+						while (*s != '\0' && *s != '"') ++s;
+					} else {
+						val = s;
+						while (*s != '\0' && *s != ' ' && *s != ',') ++s;
+					}
+					if (*s != '\0') {
+						if (*s != ',') {
+							*s = '\0';
+							++s;
+							while (*s != '\0' && *s != ',') ++s;
+							if (*s != '\0') ++s;
+						} else {
+							*s = '\0';
+							++s;
+						}
+					}
+					if (digest == NULL) {
+						ALLOC_INIT_ZVAL(digest);
+						array_init(digest);
+					}
+					add_assoc_string(digest, name, val ,1);
+				}
+			}
+
+			if (digest != NULL) {
+				php_url *new_url  = emalloc(sizeof(php_url));
+
+#ifdef ZEND_ENGINE_2
+				digest->refcount--;
+#endif
+				add_property_zval_ex(this_ptr, "_digest", sizeof("_digest"), digest TSRMLS_CC);
+
+				*new_url = *phpurl;
+				if (phpurl->scheme) phpurl->scheme = estrdup(phpurl->scheme);
+				if (phpurl->user) phpurl->user = estrdup(phpurl->user);
+				if (phpurl->pass) phpurl->pass = estrdup(phpurl->pass);
+				if (phpurl->host) phpurl->host = estrdup(phpurl->host);
+				if (phpurl->path) phpurl->path = estrdup(phpurl->path);
+				if (phpurl->query) phpurl->query = estrdup(phpurl->query);
+				if (phpurl->fragment) phpurl->fragment = estrdup(phpurl->fragment);
+				phpurl = new_url;
+
+				efree(auth);
+				efree(http_headers);
+				efree(http_body);
+
+				goto try_again;
+			}
+		}
+		if (auth) efree(auth);
+	}
+
 	/* Check and see if the server even sent a xml document */
 	content_type = get_http_header_value(http_headers,"Content-Type: ");
 	if (content_type) {
@@ -738,6 +989,7 @@ int make_http_soap_request(zval  *this_ptr,
 		}
 		if (strncmp(content_type, "text/xml", cmplen) == 0 ||
 		    strncmp(content_type, "application/soap+xml", cmplen) == 0) {
+			content_type_xml = 1;
 /*
 			if (strncmp(http_body, "= 400) {
+		int error = 0;
+
+		if (*buffer_len == 0) {
+			error = 1;
+		} else if (*buffer_len > 0) {
+			if (!content_type_xml) {
+				char *s = *buffer;
+
+				while (*s != '\0' && *s < ' ') {
+					s++;
+				}
+				if (strncmp(s, "= 400 && http_status < 500) {
+				add_soap_fault(this_ptr, "HTTP", "Client Error", NULL, NULL TSRMLS_CC);
+			} else if (http_status == 500) {
+				add_soap_fault(this_ptr, "HTTP", "Internal Server Error", NULL, NULL TSRMLS_CC);
+			} else if (http_status >= 500 && http_status < 600) {
+				add_soap_fault(this_ptr, "HTTP", "Server Error", NULL, NULL TSRMLS_CC);
+			} else {
+				add_soap_fault(this_ptr, "HTTP", "Unsupported HTTP status code", NULL, NULL TSRMLS_CC);
+			}
+			return FALSE;
+		}
+	}
+
 	return TRUE;
 }
 
@@ -840,25 +1134,35 @@ static char *get_http_header_value(char *headers, char *type)
 	return NULL;
 }
 
-static int get_http_body(php_stream *stream, char *headers,  char **response, int *out_size TSRMLS_DC)
+static int get_http_body(php_stream *stream, int close, char *headers,  char **response, int *out_size TSRMLS_DC)
 {
 	char *header, *http_buf = NULL;
-	int header_close = 0, header_chunked = 0, header_length = 0, http_buf_size = 0;
+	int header_close = close, header_chunked = 0, header_length = 0, http_buf_size = 0;
 
-	header = get_http_header_value(headers, "Connection: ");
-	if (header) {
-		if(!strcmp(header, "close")) header_close = 1;
-		efree(header);
+	if (!close) {
+		header = get_http_header_value(headers, "Connection: ");
+		if (header) {
+			if(!strncasecmp(header, "close", sizeof("close")-1)) header_close = 1;
+			efree(header);
+		}
 	}
 	header = get_http_header_value(headers, "Transfer-Encoding: ");
 	if (header) {
-		if(!strcmp(header, "chunked")) header_chunked = 1;
+		if(!strncasecmp(header, "chunked", sizeof("chunked")-1)) header_chunked = 1;
 		efree(header);
 	}
 	header = get_http_header_value(headers, "Content-Length: ");
 	if (header) {
 		header_length = atoi(header);
 		efree(header);
+		if (!header_length && !header_chunked) {
+			/* Empty response */
+			http_buf = emalloc(1);
+			http_buf[0] = '\0';
+			(*response) = http_buf;
+			(*out_size) = 0;
+			return TRUE;
+		}
 	}
 
 	if (header_chunked) {
diff --git a/ext/soap/php_http.h b/ext/soap/php_http.h
index fc055a144ad2..55f8ddcf473a 100644
--- a/ext/soap/php_http.h
+++ b/ext/soap/php_http.h
@@ -31,4 +31,6 @@ int make_http_soap_request(zval  *this_ptr,
                            char **response, 
                            int   *response_len TSRMLS_DC);
 
+void proxy_authentication(zval* this_ptr, smart_str* soap_headers TSRMLS_DC);
+void basic_authentication(zval* this_ptr, smart_str* soap_headers TSRMLS_DC);
 #endif
diff --git a/ext/soap/php_packet_soap.c b/ext/soap/php_packet_soap.c
index b78fdee888bf..fbf476611b22 100644
--- a/ext/soap/php_packet_soap.c
+++ b/ext/soap/php_packet_soap.c
@@ -34,6 +34,11 @@ int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunction
 
 	ZVAL_NULL(return_value);
 
+	/* Response for one-way opearation */
+	if (buffer_size == 0) {
+		return TRUE;
+	}
+
 	/* Parse XML packet */
 	response = soap_xmlParseMemory(buffer, buffer_size);
 
@@ -222,6 +227,11 @@ int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunction
 			}
 		}
 		add_soap_fault(this_ptr, faultcode, faultstring, faultactor, details TSRMLS_CC);
+#ifdef ZEND_ENGINE_2
+		if (details) {
+			details->refcount--;
+		}
+#endif
 		xmlFreeDoc(response);
 		return FALSE;
 	}
@@ -250,8 +260,16 @@ int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunction
 				while (zend_hash_get_current_data(fn->responseParameters, (void **)&h_param) == SUCCESS) {
 					param = (*h_param);
 					if (fnb->style == SOAP_DOCUMENT) {
-						name = param->encode->details.type_str;
-						ns = param->encode->details.ns;
+						if (param->element) {
+							name = param->element->name;
+							ns = param->element->namens;
+/*
+							name = param->encode->details.type_str;
+							ns = param->encode->details.ns;
+*/
+						} else {
+							name = param->paramName;
+						}
 					} else {
 						name = fn->responseName;
 						/* ns = ? */
@@ -263,6 +281,9 @@ int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunction
 						cur = get_node(resp, name);
 						/* TODO: produce warning invalid ns */
 					}
+					if (!cur && fnb->style == SOAP_RPC) {
+					  cur = resp;
+					}
 					if (cur) {
 						if (fnb->style == SOAP_DOCUMENT) {
 							val = cur;
diff --git a/ext/soap/php_schema.c b/ext/soap/php_schema.c
index a1d7ed8514b2..10119a45de35 100644
--- a/ext/soap/php_schema.c
+++ b/ext/soap/php_schema.c
@@ -88,20 +88,10 @@ static encodePtr create_encoder(sdlPtr sdl, sdlTypePtr cur_type, const char *ns,
 
 static encodePtr get_create_encoder(sdlPtr sdl, sdlTypePtr cur_type, const char *ns, const char *type)
 {
-	encodePtr enc = NULL;
-	smart_str nscat = {0};
-
-	smart_str_appends(&nscat, ns);
-	smart_str_appendc(&nscat, ':');
-	smart_str_appends(&nscat, type);
-	smart_str_0(&nscat);
-
-	enc = get_encoder_ex(sdl, nscat.c, nscat.len);
+	encodePtr enc = get_encoder(sdl, ns, type);
 	if (enc == NULL) {
 		enc = create_encoder(sdl, cur_type, ns, type);
 	}
-
-	smart_str_free(&nscat);
 	return enc;
 }
 
@@ -135,7 +125,6 @@ static void schema_load_file(sdlCtx *ctx, xmlAttrPtr ns, xmlChar *location, xmlA
 			new_tns = get_attribute(schema->properties, "targetNamespace");
 			if (new_tns == NULL) {
 				if (tns != NULL) {
-					xmlFreeDoc(doc);
 					xmlSetProp(schema, "targetNamespace", tns->children->content);
 				}
 			} else if (tns != NULL && strcmp(tns->children->content,new_tns->children->content) != 0) {
@@ -1302,9 +1291,44 @@ static int schema_sequence(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr seqType, sdlTy
 	return TRUE;
 }
 
-static int schema_any(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr extType, sdlTypePtr cur_type, sdlContentModelPtr model)
+/*
+
+  Content: (annotation?)
+
+*/
+static int schema_any(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr anyType, sdlTypePtr cur_type, sdlContentModelPtr model)
 {
-	/* TODO:  support */
+	if (model != NULL) {
+		sdlContentModelPtr newModel;
+		xmlAttrPtr attr;
+
+		newModel = emalloc(sizeof(sdlContentModel));
+		newModel->kind = XSD_CONTENT_ANY;
+		newModel->min_occurs = 1;
+		newModel->max_occurs = 1;
+
+		attr = get_attribute(anyType->properties, "minOccurs");
+		if (attr) {
+			newModel->min_occurs = atoi(attr->children->content);
+		}
+
+		attr = get_attribute(anyType->properties, "maxOccurs");
+		if (attr) {
+			if (!strncmp(attr->children->content, "unbounded", sizeof("unbounded"))) {
+				newModel->max_occurs = -1;
+			} else {
+				newModel->max_occurs = atoi(attr->children->content);
+			}
+		}
+
+		zend_hash_next_index_insert(model->u.content, &newModel, sizeof(sdlContentModelPtr), NULL);
+	}
 	return TRUE;
 }
 
@@ -1363,7 +1387,6 @@ static int schema_complexType(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr compType, s
 {
 	xmlNodePtr trav;
 	xmlAttrPtr attrs, name, ns;
-	TSRMLS_FETCH();
 
 	attrs = compType->properties;
 	ns = get_attribute(attrs, "targetNamespace");
@@ -1631,6 +1654,39 @@ static int schema_element(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr element, sdlTyp
 		cur_type->def = estrdup(attr->children->content);
 	}
 
+	/* form */
+	attr = get_attribute(attrs, "form");
+	if (attr) {
+		if (strncmp(attr->children->content,"qualified",sizeof("qualified")) == 0) {
+		  cur_type->form = XSD_FORM_QUALIFIED;
+		} else if (strncmp(attr->children->content,"unqualified",sizeof("unqualified")) == 0) {
+		  cur_type->form = XSD_FORM_UNQUALIFIED;
+		} else {
+		  cur_type->form = XSD_FORM_DEFAULT;
+		}
+	} else {
+	  cur_type->form = XSD_FORM_DEFAULT;
+	}
+	if (cur_type->form == XSD_FORM_DEFAULT) {
+ 		xmlNodePtr parent = element->parent;
+ 		while (parent) {
+			if (node_is_equal_ex(parent, "schema", SCHEMA_NAMESPACE)) {
+				xmlAttrPtr def;
+				def = get_attribute(parent->properties, "elementFormDefault");
+				if(def == NULL || strncmp(def->children->content, "qualified", sizeof("qualified"))) {
+					cur_type->form = XSD_FORM_UNQUALIFIED;
+				} else {
+					cur_type->form = XSD_FORM_QUALIFIED;
+				}
+				break;
+			}
+			parent = parent->parent;
+  	}
+		if (parent == NULL) {
+			cur_type->form = XSD_FORM_UNQUALIFIED;
+		}	
+	}
+
 	/* type = QName */
 	type = get_attribute(attrs, "type");
 	if (type) {
@@ -1729,6 +1785,7 @@ static int schema_attribute(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrType, sdl
 			if (nsptr != NULL) {
 				smart_str_appends(&key, nsptr->href);
 				smart_str_appendc(&key, ':');
+				newAttr->namens = estrdup(nsptr->href);
 			}
 			smart_str_appends(&key, attr_name);
 			smart_str_0(&key);
@@ -1745,6 +1802,7 @@ static int schema_attribute(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrType, sdl
 			if (ns != NULL) {
 				smart_str_appends(&key, ns->children->content);
 				smart_str_appendc(&key, ':');
+				newAttr->namens = estrdup(ns->children->content);
 			}
 			smart_str_appends(&key, name->children->content);
 			smart_str_0(&key);
@@ -1855,7 +1913,25 @@ static int schema_attribute(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrType, sdl
 		}
 		attr = attr->next;
 	}
-
+	if (newAttr->form == XSD_FORM_DEFAULT) {
+ 		xmlNodePtr parent = attrType->parent;
+ 		while (parent) {
+			if (node_is_equal_ex(parent, "schema", SCHEMA_NAMESPACE)) {
+				xmlAttrPtr def;
+				def = get_attribute(parent->properties, "attributeFormDefault");
+				if(def == NULL || strncmp(def->children->content, "qualified", sizeof("qualified"))) {
+					newAttr->form = XSD_FORM_UNQUALIFIED;
+				} else {
+					newAttr->form = XSD_FORM_QUALIFIED;
+				}
+				break;
+			}
+			parent = parent->parent;
+  	}
+		if (parent == NULL) {
+			newAttr->form = XSD_FORM_UNQUALIFIED;
+		}	
+	}
 	trav = attrType->children;
 	if (trav != NULL && node_is_equal(trav, "annotation")) {
 		/* TODO:  support */
@@ -2014,6 +2090,9 @@ static void schema_attribute_fixup(sdlCtx *ctx, sdlAttributePtr attr)
 				if ((*tmp)->name != NULL && attr->name == NULL) {
 					attr->name = estrdup((*tmp)->name);
 				}
+				if ((*tmp)->namens != NULL && attr->namens == NULL) {
+					attr->namens = estrdup((*tmp)->namens);
+				}
 				if ((*tmp)->def != NULL && attr->def == NULL) {
 					attr->def = estrdup((*tmp)->def);
 				}
@@ -2071,6 +2150,7 @@ static void schema_attributegroup_fixup(sdlCtx *ctx, sdlAttributePtr attr, HashT
 							memcpy(newAttr, *tmp_attr, sizeof(sdlAttribute));
 							if (newAttr->def) {newAttr->def = estrdup(newAttr->def);}
 							if (newAttr->fixed) {newAttr->fixed = estrdup(newAttr->fixed);}
+							if (newAttr->namens) {newAttr->namens = estrdup(newAttr->namens);}
 							if (newAttr->name) {newAttr->name = estrdup(newAttr->name);}
 							if (newAttr->extraAttributes) {
 							  xmlNodePtr node;
@@ -2152,6 +2232,9 @@ static void schema_type_fixup(sdlCtx *ctx, sdlTypePtr type)
 				if ((*tmp)->def) {
 				  type->def = estrdup((*tmp)->def);
 				}
+				type->form = (*tmp)->form;
+			} else if (strcmp(type->ref, SCHEMA_NAMESPACE ":schema") == 0) {
+				type->encode = get_conversion(XSD_ANYXML);
 			} else {
 				soap_error0(E_ERROR, "Parsing Schema: unresolved element 'ref' attribute");
 			}
@@ -2253,6 +2336,8 @@ void delete_model(void *handle)
 		case XSD_CONTENT_GROUP_REF:
 			efree(tmp->u.group_ref);
 			break;
+		default:
+			break;
 	}
 	efree(tmp);
 }
@@ -2330,6 +2415,9 @@ void delete_attribute(void *attribute)
 	if (attr->name) {
 		efree(attr->name);
 	}
+	if (attr->namens) {
+		efree(attr->namens);
+	}
 	if (attr->ref) {
 		efree(attr->ref);
 	}
diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c
index 9865e02cdc39..229aed785c7b 100644
--- a/ext/soap/php_sdl.c
+++ b/ext/soap/php_sdl.c
@@ -20,6 +20,7 @@
 /* $Id$ */
 
 #include "php_soap.h"
+#include "ext/libxml/php_libxml.h"
 #include "libxml/uri.h"
 
 #include "ext/standard/md5.h"
@@ -49,21 +50,10 @@ encodePtr get_encoder_from_prefix(sdlPtr sdl, xmlNodePtr node, const char *type)
 	parse_namespace(type, &cptype, &ns);
 	nsptr = xmlSearchNs(node->doc, node, ns);
 	if (nsptr != NULL) {
-		int ns_len = strlen(nsptr->href);
-		int type_len = strlen(cptype);
-		int len = ns_len + type_len + 1;
-		char *nscat = emalloc(len + 1);
-
-		memcpy(nscat, nsptr->href, ns_len);
-		nscat[ns_len] = ':';
-		memcpy(nscat+ns_len+1, cptype, type_len);
-		nscat[len] = '\0';
-
-		enc = get_encoder_ex(sdl, nscat, len);
+		enc = get_encoder(sdl, nsptr->href, cptype);
 		if (enc == NULL) {
-			enc = get_encoder_ex(sdl, type, type_len);
+			enc = get_encoder_ex(sdl, cptype, strlen(cptype));
 		}
-		efree(nscat);
 	} else {
 		enc = get_encoder_ex(sdl, type, strlen(type));
 	}
@@ -75,7 +65,6 @@ encodePtr get_encoder_from_prefix(sdlPtr sdl, xmlNodePtr node, const char *type)
 static sdlTypePtr get_element(sdlPtr sdl, xmlNodePtr node, const char *type)
 {
 	sdlTypePtr ret = NULL;
-	TSRMLS_FETCH();
 
 	if (sdl->elements) {
 		xmlNsPtr nsptr;
@@ -128,8 +117,24 @@ encodePtr get_encoder(sdlPtr sdl, const char *ns, const char *type)
 	nscat[len] = '\0';
 
 	enc = get_encoder_ex(sdl, nscat, len);
-
 	efree(nscat);
+
+	if (enc == NULL &&
+	    ((ns_len == sizeof(SOAP_1_1_ENC_NAMESPACE)-1 &&
+	      memcmp(ns, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)-1) == 0) ||
+	     (ns_len == sizeof(SOAP_1_2_ENC_NAMESPACE)-1 &&
+	      memcmp(ns, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)-1) == 0))) {
+		ns_len = sizeof(XSD_NAMESPACE)-1;
+		len = ns_len + type_len + 1;
+		nscat = emalloc(len + 1);
+		memcpy(nscat, XSD_NAMESPACE, sizeof(XSD_NAMESPACE)-1);
+		nscat[ns_len] = ':';
+		memcpy(nscat+ns_len+1, type, type_len);
+		nscat[len] = '\0';
+
+		enc = get_encoder_ex(sdl, nscat, len);
+		efree(nscat);
+	}
 	return enc;
 }
 
@@ -195,7 +200,7 @@ static int is_wsdl_element(xmlNodePtr node)
 	return 1;
 }
 
-static void load_wsdl_ex(char *struri, sdlCtx *ctx, int include)
+static void load_wsdl_ex(zval *this_ptr, char *struri, sdlCtx *ctx, int include TSRMLS_DC)
 {
 	sdlPtr tmpsdl = ctx->sdl;
 	xmlDocPtr wsdl;
@@ -205,9 +210,9 @@ static void load_wsdl_ex(char *struri, sdlCtx *ctx, int include)
 	if (zend_hash_exists(&ctx->docs, struri, strlen(struri)+1)) {
 		return;
 	}
-
+	
 	wsdl = soap_xmlParseFile(struri);
-
+	
 	if (!wsdl) {
 		soap_error1(E_ERROR, "Parsing WSDL: Couldn't load from '%s'", struri);
 	}
@@ -265,7 +270,7 @@ static void load_wsdl_ex(char *struri, sdlCtx *ctx, int include)
 					uri = xmlBuildURI(tmp->children->content, base);
 					xmlFree(base);
 				}
-				load_wsdl_ex(uri, ctx, 1);
+				load_wsdl_ex(this_ptr, uri, ctx, 1 TSRMLS_CC);
 				xmlFree(uri);
 			}
 
@@ -390,6 +395,10 @@ static sdlSoapBindingFunctionHeaderPtr wsdl_soap_binding_header(sdlCtx* ctx, xml
 					h->ns = estrdup(h->element->namens);
 				}
 			}
+			if (h->element->name) {
+				efree(h->name);
+				h->name = estrdup(h->element->name);
+			}
 		}
 	}
 	if (!fault) {
@@ -447,8 +456,43 @@ static void wsdl_soap_binding_body(sdlCtx* ctx, xmlNodePtr node, char* wsdl_soap
 
 			tmp = get_attribute(body->properties, "parts");
 			if (tmp) {
-				whiteSpace_collapse(tmp->children->content);
-				binding->parts = estrdup(tmp->children->content);
+				HashTable    ht;
+				char *parts = tmp->children->content;
+
+				/* Delete all parts those are not in the "parts" attribute */
+				zend_hash_init(&ht, 0, NULL, delete_parameter, 0);
+				while (*parts) {
+					HashPosition pos;
+					sdlParamPtr *param;
+					int found = 0;
+					char *end;
+
+					while (*parts == ' ') ++parts;
+					if (*parts == '\0') break;
+					end = strchr(parts, ' ');
+					if (end) *end = '\0';
+					zend_hash_internal_pointer_reset_ex(params, &pos);
+					while (zend_hash_get_current_data_ex(params, (void **)¶m, &pos) != FAILURE) {
+						if ((*param)->paramName &&
+						    strcmp(parts, (*param)->paramName) == 0) {
+					  	sdlParamPtr x_param;
+					  	x_param = emalloc(sizeof(sdlParam));
+					  	*x_param = **param;
+					  	(*param)->paramName = NULL;
+					  	zend_hash_next_index_insert(&ht, &x_param, sizeof(sdlParamPtr), NULL);
+					  	found = 1;
+					  	break;
+						}
+						zend_hash_move_forward_ex(params, &pos);
+					}
+					if (!found) {
+						soap_error1(E_ERROR, "Parsing WSDL: Missing part '%s' in ", parts);
+					}
+					parts += strlen(parts);
+					if (end) *end = ' ';
+				}
+				zend_hash_destroy(params);
+				*params = ht;
 			}
 
 			if (binding->use == SOAP_ENCODED) {
@@ -558,7 +602,7 @@ static HashTable* wsdl_message(sdlCtx *ctx, char* message_name)
 	return parameters;
 }
 
-static sdlPtr load_wsdl(char *struri)
+static sdlPtr load_wsdl(zval *this_ptr, char *struri TSRMLS_DC)
 {
 	sdlCtx ctx;
 	int i,n;
@@ -575,7 +619,7 @@ static sdlPtr load_wsdl(char *struri)
 	zend_hash_init(&ctx.portTypes, 0, NULL, NULL, 0);
 	zend_hash_init(&ctx.services,  0, NULL, NULL, 0);
 
-	load_wsdl_ex(struri,&ctx, 0);
+	load_wsdl_ex(this_ptr, struri,&ctx, 0 TSRMLS_CC);
 	schema_pass2(&ctx);
 
 	n = zend_hash_num_elements(&ctx.services);
@@ -993,7 +1037,7 @@ static sdlPtr load_wsdl(char *struri)
 	return ctx.sdl;
 }
 
-#define WSDL_CACHE_VERSION 0x09
+#define WSDL_CACHE_VERSION 0x0e
 
 #define WSDL_CACHE_GET(ret,type,buf)   memcpy(&ret,*buf,sizeof(type)); *buf += sizeof(type);
 #define WSDL_CACHE_GET_INT(ret,buf)    ret = ((unsigned char)(*buf)[0])|((unsigned char)(*buf)[1]<<8)|((unsigned char)(*buf)[2]<<16)|((int)(*buf)[3]<<24); *buf += 4;
@@ -1042,6 +1086,7 @@ static void sdl_deserialize_attribute(sdlAttributePtr attr, encodePtr *encoders,
 	int i;
 
 	attr->name = sdl_deserialize_string(in);
+	attr->namens = sdl_deserialize_string(in);
 	attr->ref = sdl_deserialize_string(in);
 	attr->def = sdl_deserialize_string(in);
 	attr->fixed = sdl_deserialize_string(in);
@@ -1141,6 +1186,7 @@ static void sdl_deserialize_type(sdlTypePtr type, sdlTypePtr *types, encodePtr *
 	type->fixed = sdl_deserialize_string(in);
 	type->ref = sdl_deserialize_string(in);
 	WSDL_CACHE_GET_1(type->nillable, char, in);
+	WSDL_CACHE_GET_1(type->form, sdlForm, in);
 
 	WSDL_CACHE_GET_INT(i, in);
 	type->encode = encoders[i];
@@ -1240,7 +1286,6 @@ static void sdl_deserialize_soap_body(sdlSoapBindingFunctionBodyPtr body, encode
 		body->encodingStyle = SOAP_ENCODING_DEFAULT;
 	}
 	body->ns = sdl_deserialize_string(in);
-	body->parts = sdl_deserialize_string(in);
 	WSDL_CACHE_GET_INT(i, in);
 	if (i > 0) {
 		body->headers = emalloc(sizeof(HashTable));
@@ -1279,9 +1324,9 @@ static void sdl_deserialize_soap_body(sdlSoapBindingFunctionBodyPtr body, encode
 					tmp2->name = sdl_deserialize_string(in);
 					tmp2->ns = sdl_deserialize_string(in);
 					WSDL_CACHE_GET_INT(n, in);
-					tmp->encode = encoders[n];
+					tmp2->encode = encoders[n];
 					WSDL_CACHE_GET_INT(n, in);
-					tmp->element = types[n];
+					tmp2->element = types[n];
 					--j;
 				}
 			}
@@ -1317,7 +1362,7 @@ static sdlPtr get_sdl_from_cache(const char *fn, const char *uri, time_t t)
 	sdlPtr sdl;
 	time_t old_t;
 	int  i, num_groups, num_types, num_elements, num_encoders, num_bindings, num_func;
-	sdlFunctionPtr *functions;
+	sdlFunctionPtr *functions = NULL;
 	sdlBindingPtr *bindings;
 	sdlTypePtr *types;
 	encodePtr *encoders;
@@ -1459,14 +1504,12 @@ static sdlPtr get_sdl_from_cache(const char *fn, const char *uri, time_t t)
 			binding->name = sdl_deserialize_string(&in);
 			binding->location = sdl_deserialize_string(&in);
 			WSDL_CACHE_GET_1(binding->bindingType,sdlBindingType,&in);
-			if (binding->bindingType == BINDING_SOAP) {
-				if (*in != 0) {
-				  sdlSoapBindingPtr soap_binding = binding->bindingAttributes = emalloc(sizeof(sdlSoapBinding));
-					WSDL_CACHE_GET_1(soap_binding->style,sdlEncodingStyle,&in);
-					WSDL_CACHE_GET_1(soap_binding->transport,sdlTransport,&in);
-				} else {
-					WSDL_CACHE_SKIP(1,&in);
-				}
+			if (binding->bindingType == BINDING_SOAP && *in != 0) {
+			  sdlSoapBindingPtr soap_binding = binding->bindingAttributes = emalloc(sizeof(sdlSoapBinding));
+				WSDL_CACHE_GET_1(soap_binding->style,sdlEncodingStyle,&in);
+				WSDL_CACHE_GET_1(soap_binding->transport,sdlTransport,&in);
+			} else {
+				WSDL_CACHE_SKIP(1,&in);
 			}
 			bindings[i] = binding;
 		}
@@ -1475,23 +1518,23 @@ static sdlPtr get_sdl_from_cache(const char *fn, const char *uri, time_t t)
 	/* deserialize functions */
 	WSDL_CACHE_GET_INT(num_func, &in);
 	zend_hash_init(&sdl->functions, num_func, NULL, delete_function, 0);
-	functions = emalloc(num_func*sizeof(sdlFunctionPtr));
-	for (i = 0; i < num_func; i++) {
-		int binding_num, num_faults;
-		sdlFunctionPtr func = emalloc(sizeof(sdlFunction));
-		sdl_deserialize_key(&sdl->functions, func, &in);
-		func->functionName = sdl_deserialize_string(&in);
-		func->requestName = sdl_deserialize_string(&in);
-		func->responseName = sdl_deserialize_string(&in);
-
-		WSDL_CACHE_GET_INT(binding_num, &in);
-		if (binding_num == 0) {
-			func->binding = NULL;
-		} else {
-			func->binding = bindings[binding_num-1];
-		}
-		if (func->binding && func->binding->bindingType == BINDING_SOAP) {
-			if (*in != 0) {
+	if (num_func > 0) {
+		functions = emalloc(num_func*sizeof(sdlFunctionPtr));
+		for (i = 0; i < num_func; i++) {
+			int binding_num, num_faults;
+			sdlFunctionPtr func = emalloc(sizeof(sdlFunction));
+			sdl_deserialize_key(&sdl->functions, func, &in);
+			func->functionName = sdl_deserialize_string(&in);
+			func->requestName = sdl_deserialize_string(&in);
+			func->responseName = sdl_deserialize_string(&in);
+
+			WSDL_CACHE_GET_INT(binding_num, &in);
+			if (binding_num == 0) {
+				func->binding = NULL;
+			} else {
+				func->binding = bindings[binding_num-1];
+			}
+			if (func->binding && func->binding->bindingType == BINDING_SOAP && *in != 0) {
 				sdlSoapBindingFunctionPtr binding = func->bindingAttributes = emalloc(sizeof(sdlSoapBindingFunction));
 				memset(binding, 0, sizeof(sdlSoapBindingFunction));
 				WSDL_CACHE_GET_1(binding->style,sdlEncodingStyle,&in);
@@ -1502,43 +1545,43 @@ static sdlPtr get_sdl_from_cache(const char *fn, const char *uri, time_t t)
 				WSDL_CACHE_SKIP(1, &in);
 				func->bindingAttributes = NULL;
 			}
-		}
 
-		func->requestParameters = sdl_deserialize_parameters(encoders, types, &in);
-		func->responseParameters = sdl_deserialize_parameters(encoders, types, &in);
+			func->requestParameters = sdl_deserialize_parameters(encoders, types, &in);
+			func->responseParameters = sdl_deserialize_parameters(encoders, types, &in);
 
-		WSDL_CACHE_GET_INT(num_faults, &in);
-		if (num_faults > 0) {
-		  int j;
+			WSDL_CACHE_GET_INT(num_faults, &in);
+			if (num_faults > 0) {
+			  int j;
 
-			func->faults = emalloc(sizeof(HashTable));
-			zend_hash_init(func->faults, num_faults, NULL, delete_fault, 0);
+				func->faults = emalloc(sizeof(HashTable));
+				zend_hash_init(func->faults, num_faults, NULL, delete_fault, 0);
 
-			for (j = 0; j < num_faults; j++) {
-				sdlFaultPtr fault = emalloc(sizeof(sdlFault));
+				for (j = 0; j < num_faults; j++) {
+					sdlFaultPtr fault = emalloc(sizeof(sdlFault));
 
-				sdl_deserialize_key(func->faults, fault, &in);
-				fault->name =sdl_deserialize_string(&in);
-				fault->details =sdl_deserialize_parameters(encoders, types, &in);
-				if (*in != 0) {
-					sdlSoapBindingFunctionFaultPtr binding = fault->bindingAttributes = emalloc(sizeof(sdlSoapBindingFunctionFault));
-					memset(binding, 0, sizeof(sdlSoapBindingFunctionFault));
-					WSDL_CACHE_GET_1(binding->use,sdlEncodingUse,&in);
-					if (binding->use == SOAP_ENCODED) {
-						WSDL_CACHE_GET_1(binding->encodingStyle, sdlRpcEncodingStyle, &in);
+					sdl_deserialize_key(func->faults, fault, &in);
+					fault->name =sdl_deserialize_string(&in);
+					fault->details =sdl_deserialize_parameters(encoders, types, &in);
+					if (*in != 0) {
+						sdlSoapBindingFunctionFaultPtr binding = fault->bindingAttributes = emalloc(sizeof(sdlSoapBindingFunctionFault));
+						memset(binding, 0, sizeof(sdlSoapBindingFunctionFault));
+						WSDL_CACHE_GET_1(binding->use,sdlEncodingUse,&in);
+						if (binding->use == SOAP_ENCODED) {
+							WSDL_CACHE_GET_1(binding->encodingStyle, sdlRpcEncodingStyle, &in);
+						} else {
+							binding->encodingStyle = SOAP_ENCODING_DEFAULT;
+						}
+						binding->ns = sdl_deserialize_string(&in);
 					} else {
-						binding->encodingStyle = SOAP_ENCODING_DEFAULT;
+						WSDL_CACHE_SKIP(1, &in);
+						fault->bindingAttributes = NULL;
 					}
-					binding->ns = sdl_deserialize_string(&in);
-				} else {
-					WSDL_CACHE_SKIP(1, &in);
-					fault->bindingAttributes = NULL;
 				}
+			} else {
+				func->faults = NULL;
 			}
-		} else {
-			func->faults = NULL;
+			functions[i] = func;
 		}
-		functions[i] = func;
 	}
 
 	/* deserialize requests */
@@ -1555,7 +1598,9 @@ static sdlPtr get_sdl_from_cache(const char *fn, const char *uri, time_t t)
 		}
 	}
 
-	efree(functions);
+	if (functions) {
+		efree(functions);
+	}
 	efree(bindings);
 	efree(encoders);
 	efree(types);
@@ -1623,6 +1668,7 @@ static void sdl_serialize_attribute(sdlAttributePtr attr, HashTable *tmp_encoder
 	int i;
 
 	sdl_serialize_string(attr->name, out);
+	sdl_serialize_string(attr->namens, out);
 	sdl_serialize_string(attr->ref, out);
 	sdl_serialize_string(attr->def, out);
 	sdl_serialize_string(attr->fixed, out);
@@ -1715,6 +1761,7 @@ static void sdl_serialize_type(sdlTypePtr type, HashTable *tmp_encoders, HashTab
 	sdl_serialize_string(type->fixed, out);
 	sdl_serialize_string(type->ref, out);
 	WSDL_CACHE_PUT_1(type->nillable, out);
+	WSDL_CACHE_PUT_1(type->form, out);
 	sdl_serialize_encoder_ref(type->encode, tmp_encoders, out);
 
 	if (type->restrictions) {
@@ -1840,7 +1887,6 @@ static void sdl_serialize_soap_body(sdlSoapBindingFunctionBodyPtr body, HashTabl
 		WSDL_CACHE_PUT_1(body->encodingStyle, out);
 	}
 	sdl_serialize_string(body->ns, out);
-	sdl_serialize_string(body->parts, out);
 	if (body->headers) {
 		i = zend_hash_num_elements(body->headers);
 	} else {
@@ -2162,20 +2208,72 @@ static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr s
 	zend_hash_destroy(&tmp_types);
 }
 
-sdlPtr get_sdl(char *uri TSRMLS_DC)
+sdlPtr get_sdl(zval *this_ptr, char *uri TSRMLS_DC)
 {
 	sdlPtr sdl = NULL;
 	char* old_error_code = SOAP_GLOBAL(error_code);
+	int uri_len;
+	php_stream_context *context=NULL;
+	zval **proxy_host, **proxy_port, *orig_context, *new_context;
+	smart_str headers = {0};
+
+	if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_proxy_host", sizeof("_proxy_host"), (void **) &proxy_host) == SUCCESS &&
+	    Z_TYPE_PP(proxy_host) == IS_STRING &&
+	    zend_hash_find(Z_OBJPROP_P(this_ptr), "_proxy_port", sizeof("_proxy_port"), (void **) &proxy_port) == SUCCESS &&
+	    Z_TYPE_PP(proxy_port) == IS_LONG) {
+	    	zval str_port, *str_proxy;
+	    	smart_str proxy = {0};
+		str_port = **proxy_port;
+		zval_copy_ctor(&str_port);
+		convert_to_string(&str_port);
+		smart_str_appends(&proxy,"tcp://");
+		smart_str_appends(&proxy,Z_STRVAL_PP(proxy_host));
+		smart_str_appends(&proxy,":");
+		smart_str_appends(&proxy,Z_STRVAL(str_port));
+		zval_dtor(&str_port);
+		MAKE_STD_ZVAL(str_proxy);
+		ZVAL_STRING(str_proxy, proxy.c, 1);
+		smart_str_free(&proxy);
+		
+		context = php_stream_context_alloc();
+		php_stream_context_set_option(context, "http", "proxy", str_proxy);
+		zval_ptr_dtor(&str_proxy);
+
+		proxy_authentication(this_ptr, &headers TSRMLS_CC);
+	}
+
+	basic_authentication(this_ptr, &headers TSRMLS_CC);
+
+	if (headers.len > 0) {
+		zval *str_headers;
+
+		if (!context) {
+			context = php_stream_context_alloc();
+		}
+
+		smart_str_0(&headers);
+		MAKE_STD_ZVAL(str_headers);
+		ZVAL_STRING(str_headers, headers.c, 1);
+		php_stream_context_set_option(context, "http", "header", str_headers);
+		smart_str_free(&headers);
+		zval_ptr_dtor(&str_headers);
+	}
+
+	if (context) {
+		MAKE_STD_ZVAL(new_context);
+		php_stream_context_to_zval(context, new_context);
+		orig_context = php_libxml_switch_context(new_context TSRMLS_CC);
+	}
 
 	SOAP_GLOBAL(error_code) = "WSDL";
 
-	if (SOAP_GLOBAL(cache_enabled)) {
+	if (SOAP_GLOBAL(cache_enabled) && ((uri_len = strlen(uri)) < MAXPATHLEN)) {
 		char  fn[MAXPATHLEN];
 
-		if (strchr(uri,':') != NULL || IS_ABSOLUTE_PATH(uri,strlen(uri))) {
+		if (strchr(uri,':') != NULL || IS_ABSOLUTE_PATH(uri, uri_len)) {
 			strcpy(fn, uri);
 		} else if (VCWD_REALPATH(uri, fn) == NULL) {
-			sdl = load_wsdl(uri);
+			sdl = load_wsdl(this_ptr, uri TSRMLS_CC);
 		}
 		if (sdl == NULL) {
 			char* key;
@@ -2196,7 +2294,7 @@ sdlPtr get_sdl(char *uri TSRMLS_DC)
 			memcpy(key+len+sizeof("/wsdl-")-1,md5str,sizeof(md5str));
 
 			if ((sdl = get_sdl_from_cache(key, fn, t-SOAP_GLOBAL(cache_ttl))) == NULL) {
-				sdl = load_wsdl(fn);
+				sdl = load_wsdl(this_ptr, fn TSRMLS_CC);
 				if (sdl != NULL) {
 					add_sdl_to_cache(key, fn, t, sdl);
 				}
@@ -2204,9 +2302,16 @@ sdlPtr get_sdl(char *uri TSRMLS_DC)
 			efree(key);
 		}
 	} else {
-		sdl = load_wsdl(uri);
+		sdl = load_wsdl(this_ptr, uri TSRMLS_CC);
 	}
+
 	SOAP_GLOBAL(error_code) = old_error_code;
+
+	if (context) {
+		php_libxml_switch_context(orig_context TSRMLS_CC);
+		zval_ptr_dtor(&new_context);
+	}
+
 	return sdl;
 }
 
@@ -2274,9 +2379,6 @@ static void delete_sdl_soap_binding_function_body(sdlSoapBindingFunctionBody bod
 	if (body.ns) {
 		efree(body.ns);
 	}
-	if (body.parts) {
-		efree(body.parts);
-	}
 	if (body.headers) {
 		zend_hash_destroy(body.headers);
 		efree(body.headers);
diff --git a/ext/soap/php_sdl.h b/ext/soap/php_sdl.h
index 7b29c87ed85a..63f961ab7176 100644
--- a/ext/soap/php_sdl.h
+++ b/ext/soap/php_sdl.h
@@ -109,7 +109,6 @@ typedef struct _sdlSoapBindingFunctionFault {
 struct _sdlSoapBindingFunctionBody {
 	char                *ns;
 	sdlEncodingUse       use;
-	char                *parts;          /* not implemented yet */
 	sdlRpcEncodingStyle  encodingStyle;  /* not implemented yet */
 	HashTable           *headers;        /* array of sdlSoapBindingFunctionHeaderPtr */
 };
@@ -153,7 +152,8 @@ typedef enum _sdlContentKind {
 	XSD_CONTENT_ALL,
 	XSD_CONTENT_CHOICE,
 	XSD_CONTENT_GROUP_REF,
-	XSD_CONTENT_GROUP
+	XSD_CONTENT_GROUP,
+	XSD_CONTENT_ANY
 } sdlContentKind;
 
 
@@ -180,6 +180,19 @@ typedef enum _sdlTypeKind {
 	XSD_TYPEKIND_EXTENSION
 } sdlTypeKind;
 
+typedef enum _sdlUse {
+	XSD_USE_DEFAULT,
+	XSD_USE_OPTIONAL,
+	XSD_USE_PROHIBITED,
+	XSD_USE_REQUIRED
+} sdlUse;
+
+typedef enum _sdlForm {
+	XSD_FORM_DEFAULT,
+	XSD_FORM_QUALIFIED,
+	XSD_FORM_UNQUALIFIED
+} sdlForm;
+
 struct _sdlType {
 	sdlTypeKind         kind;
 	char               *name;
@@ -193,6 +206,7 @@ struct _sdlType {
 	char               *def;
 	char               *fixed;
 	char               *ref;
+	sdlForm             form;
 };
 
 struct _sdlParam {
@@ -219,19 +233,6 @@ struct _sdlFunction {
 	HashTable          *faults;             /* array of sdlFaultPtr */
 };
 
-typedef enum _sdlUse {
-	XSD_USE_DEFAULT,
-	XSD_USE_OPTIONAL,
-	XSD_USE_PROHIBITED,
-	XSD_USE_REQUIRED
-} sdlUse;
-
-typedef enum _sdlForm {
-	XSD_FORM_DEFAULT,
-	XSD_FORM_QUALIFIED,
-	XSD_FORM_UNQUALIFIED
-} sdlForm;
-
 typedef struct _sdlExtraAttribute {
 	char *ns;
 	char *val;
@@ -239,6 +240,7 @@ typedef struct _sdlExtraAttribute {
 
 struct _sdlAttribute {
 	char      *name;
+	char      *namens;
 	char      *ref;
 	char      *def;
 	char      *fixed;
@@ -248,7 +250,7 @@ struct _sdlAttribute {
 	encodePtr  encode;
 };
 
-sdlPtr get_sdl(char *uri TSRMLS_DC);
+sdlPtr get_sdl(zval *this_ptr, char *uri TSRMLS_DC);
 
 encodePtr get_encoder_from_prefix(sdlPtr sdl, xmlNodePtr data, const char *type);
 encodePtr get_encoder(sdlPtr sdl, const char *ns, const char *type);
diff --git a/ext/soap/php_soap.dsp b/ext/soap/php_soap.dsp
index ef0c09f29b92..4157c6332044 100644
--- a/ext/soap/php_soap.dsp
+++ b/ext/soap/php_soap.dsp
@@ -101,6 +101,10 @@ SOURCE=.\php_http.c
 # End Source File
 # Begin Source File
 
+SOURCE=.\php_packet_soap.c
+# End Source File
+# Begin Source File
+
 SOURCE=.\php_schema.c
 # End Source File
 # Begin Source File
@@ -129,6 +133,10 @@ SOURCE=.\php_http.h
 # End Source File
 # Begin Source File
 
+SOURCE=.\php_packet_soap.h
+# End Source File
+# Begin Source File
+
 SOURCE=.\php_schema.h
 # End Source File
 # Begin Source File
diff --git a/ext/soap/php_soap.h b/ext/soap/php_soap.h
index dfe1af553ea8..2d439010020a 100644
--- a/ext/soap/php_soap.h
+++ b/ext/soap/php_soap.h
@@ -115,6 +115,8 @@ struct _soapService {
 	int        type;
 	char      *actor;
 	char      *uri;
+	xmlCharEncodingHandlerPtr encoding;
+	HashTable *class_map;
 };
 
 #define SOAP_CLASS 1
@@ -144,6 +146,9 @@ struct _soapService {
 #define SOAP_COMPRESSION_GZIP    0x00
 #define SOAP_COMPRESSION_DEFLATE 0x10
 
+#define SOAP_AUTHENTICATION_BASIC   0
+#define SOAP_AUTHENTICATION_DIGEST  1
+
 ZEND_BEGIN_MODULE_GLOBALS(soap)
 	HashTable  defEncNs;     /* mapping of default namespaces to prefixes */
 	HashTable  defEnc;
@@ -158,6 +163,8 @@ ZEND_BEGIN_MODULE_GLOBALS(soap)
 	zend_bool  cache_enabled;
 	char*      cache_dir;
 	long       cache_ttl;
+	xmlCharEncodingHandlerPtr encoding;
+	HashTable *class_map;
 ZEND_END_MODULE_GLOBALS(soap)
 
 #ifdef PHP_WIN32
diff --git a/ext/soap/soap.c b/ext/soap/soap.c
index 1472658121ec..b32346da6f05 100644
--- a/ext/soap/soap.c
+++ b/ext/soap/soap.c
@@ -23,7 +23,9 @@
 #include "config.h"
 #endif
 #include "php_soap.h"
+#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
 #include "ext/session/php_session.h"
+#endif
 #ifdef ZEND_ENGINE_2
 #  include "zend_exceptions.h"
 #endif
@@ -48,7 +50,7 @@ static void function_to_string(sdlFunctionPtr function, smart_str *buf);
 static void type_to_string(sdlTypePtr type, smart_str *buf, int level);
 
 static void clear_soap_fault(zval *obj TSRMLS_DC);
-static void set_soap_fault(zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail, char *name TSRMLS_DC);
+static void set_soap_fault(zval *obj, char *fault_code_ns, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail, char *name TSRMLS_DC);
 static void soap_server_fault(char* code, char* string, char *actor, zval* details, char *name TSRMLS_DC);
 static void soap_server_fault_ex(sdlFunctionPtr function, zval* fault, soapHeader* hdr TSRMLS_DC);
 
@@ -92,6 +94,9 @@ static void soap_error_handler(int error_num, const char *error_filename, const
 	char* _old_error_code = SOAP_GLOBAL(error_code);\
 	zval* _old_error_object = SOAP_GLOBAL(error_object);\
 	int _old_soap_version = SOAP_GLOBAL(soap_version);\
+	zend_bool _old_in_compilation = CG(in_compilation); \
+	zend_bool _old_in_execution = EG(in_execution); \
+	zend_execute_data *_old_current_execute_data = EG(current_execute_data); \
 	int _bailout = 0;\
 	SOAP_GLOBAL(use_soap_error_handler) = 1;\
 	SOAP_GLOBAL(error_code) = "Client";\
@@ -100,6 +105,9 @@ static void soap_error_handler(int error_num, const char *error_filename, const
 
 #define SOAP_CLIENT_END_CODE() \
 	} zend_catch {\
+		CG(in_compilation) = _old_in_compilation; \
+		EG(in_execution) = _old_in_execution; \
+		EG(current_execute_data) = _old_current_execute_data; \
 		if (EG(exception) == NULL || \
 		    Z_TYPE_P(EG(exception)) != IS_OBJECT || \
 		    Z_OBJCE_P(EG(exception)) != soap_fault_class_entry) {\
@@ -170,6 +178,21 @@ ZEND_DECLARE_MODULE_GLOBALS(soap)
 
 static void (*old_error_handler)(int, const char *, const uint, const char*, va_list);
 
+#ifdef va_copy
+#define call_old_error_handler(error_num, error_filename, error_lineno, format, args) \
+{ \
+	va_list copy; \
+	va_copy(copy, args); \
+	old_error_handler(error_num, error_filename, error_lineno, format, copy); \
+	va_end(copy); \
+}
+#else
+#define call_old_error_handler(error_num, error_filename, error_lineno, format, args) \
+{ \
+	old_error_handler(error_num, error_filename, error_lineno, format, args); \
+}
+#endif
+
 #define PHP_SOAP_SERVER_CLASSNAME "SoapServer"
 #define PHP_SOAP_CLIENT_CLASSNAME "SoapClient"
 #define PHP_SOAP_VAR_CLASSNAME    "SoapVar"
@@ -235,6 +258,9 @@ PHP_METHOD(SoapClient, __getLastResponseHeaders);
 PHP_METHOD(SoapClient, __getFunctions);
 PHP_METHOD(SoapClient, __getTypes);
 PHP_METHOD(SoapClient, __doRequest);
+PHP_METHOD(SoapClient, __setCookie);
+PHP_METHOD(SoapClient, __setLocation);
+PHP_METHOD(SoapClient, __setSoapHeaders);
 
 /* SoapVar Functions */
 PHP_METHOD(SoapVar, SoapVar);
@@ -251,6 +277,12 @@ PHP_METHOD(SoapParam, SoapParam);
 /* SoapHeader Functions */
 PHP_METHOD(SoapHeader, SoapHeader);
 
+#ifdef ZEND_ENGINE_2
+#define SOAP_CTOR(class_name, func_name, arginfo, flags) ZEND_FENTRY(__construct, ZEND_FN(class_name##_##func_name), arginfo, flags)
+#else
+#define SOAP_CTOR(class_name, func_name, arginfo, flags) PHP_ME(class_name, func_name, arginfo, flags)
+#endif
+
 static zend_function_entry soap_functions[] = {
 #ifdef HAVE_PHP_DOMXML
 	PHP_FE(soap_encode_to_xml, NULL)
@@ -262,7 +294,7 @@ static zend_function_entry soap_functions[] = {
 };
 
 static zend_function_entry soap_fault_functions[] = {
-	PHP_ME(SoapFault, SoapFault, NULL, 0)
+	SOAP_CTOR(SoapFault, SoapFault, NULL, 0)
 #ifdef ZEND_ENGINE_2
 	PHP_ME(SoapFault, __toString, NULL, 0)
 #endif
@@ -270,7 +302,7 @@ static zend_function_entry soap_fault_functions[] = {
 };
 
 static zend_function_entry soap_server_functions[] = {
-	PHP_ME(SoapServer, SoapServer, NULL, 0)
+	SOAP_CTOR(SoapServer, SoapServer, NULL, 0)
 	PHP_ME(SoapServer, setPersistence, NULL, 0)
 	PHP_ME(SoapServer, setClass, NULL, 0)
 	PHP_ME(SoapServer, addFunction, NULL, 0)
@@ -287,17 +319,27 @@ static zend_function_entry soap_server_functions[] = {
 ZEND_BEGIN_ARG_INFO(__call_args, 0)
 	ZEND_ARG_PASS_INFO(0)
 	ZEND_ARG_PASS_INFO(0)
+ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO(__soap_call_args, 0)
+	ZEND_ARG_PASS_INFO(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()
 #else
-unsigned char __call_args[] = { 5, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
+unsigned char __call_args[] = { 2, BYREF_NONE, BYREF_NONE };
+unsigned char __soap_call_args[] = { 5, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
 #endif
 
 static zend_function_entry soap_client_functions[] = {
-	PHP_ME(SoapClient, SoapClient, NULL, 0)
+	SOAP_CTOR(SoapClient, SoapClient, NULL, 0)
 	PHP_ME(SoapClient, __call, __call_args, 0)
+#ifdef ZEND_ENGINE_2
+	ZEND_FENTRY(__soapCall, ZEND_FN(SoapClient___call), __soap_call_args, 0)
+#else
+	ZEND_NAMED_FE(__soapCall, ZEND_FN(SoapClient___call), __soap_call_args)
+#endif
 	PHP_ME(SoapClient, __getLastRequest, NULL, 0)
 	PHP_ME(SoapClient, __getLastResponse, NULL, 0)
 	PHP_ME(SoapClient, __getLastRequestHeaders, NULL, 0)
@@ -305,21 +347,24 @@ static zend_function_entry soap_client_functions[] = {
 	PHP_ME(SoapClient, __getFunctions, NULL, 0)
 	PHP_ME(SoapClient, __getTypes, NULL, 0)
 	PHP_ME(SoapClient, __doRequest, NULL, 0)
+	PHP_ME(SoapClient, __setCookie, NULL, 0)
+	PHP_ME(SoapClient, __setLocation, NULL, 0)
+	PHP_ME(SoapClient, __setSoapHeaders, NULL, 0)
 	{NULL, NULL, NULL}
 };
 
 static zend_function_entry soap_var_functions[] = {
-	PHP_ME(SoapVar, SoapVar, NULL, 0)
+	SOAP_CTOR(SoapVar, SoapVar, NULL, 0)
 	{NULL, NULL, NULL}
 };
 
 static zend_function_entry soap_param_functions[] = {
-	PHP_ME(SoapParam, SoapParam, NULL, 0)
+	SOAP_CTOR(SoapParam, SoapParam, NULL, 0)
 	{NULL, NULL, NULL}
 };
 
 static zend_function_entry soap_header_functions[] = {
-	PHP_ME(SoapHeader, SoapHeader, NULL, 0)
+	SOAP_CTOR(SoapHeader, SoapHeader, NULL, 0)
 	{NULL, NULL, NULL}
 };
 
@@ -361,7 +406,7 @@ PHP_INI_END()
 static void php_soap_init_globals(zend_soap_globals *soap_globals)
 {
 	int i;
-	long enc;
+	encodePtr enc;
 
 	zend_hash_init(&soap_globals->defEnc, 0, NULL, NULL, 1);
 	zend_hash_init(&soap_globals->defEncIndex, 0, NULL, NULL, 1);
@@ -369,7 +414,7 @@ static void php_soap_init_globals(zend_soap_globals *soap_globals)
 
 	i = 0;
 	do {
-		enc = (long)&defaultEncoding[i];
+		enc = &defaultEncoding[i];
 
 		/* If has a ns and a str_type then index it */
 		if (defaultEncoding[i].details.type_str) {
@@ -394,6 +439,7 @@ static void php_soap_init_globals(zend_soap_globals *soap_globals)
 	zend_hash_add(&soap_globals->defEncNs, XSD_1999_NAMESPACE, sizeof(XSD_1999_NAMESPACE), XSD_NS_PREFIX, sizeof(XSD_NS_PREFIX), NULL);
 	zend_hash_add(&soap_globals->defEncNs, XSD_NAMESPACE, sizeof(XSD_NAMESPACE), XSD_NS_PREFIX, sizeof(XSD_NS_PREFIX), NULL);
 	zend_hash_add(&soap_globals->defEncNs, XSI_NAMESPACE, sizeof(XSI_NAMESPACE), XSI_NS_PREFIX, sizeof(XSI_NS_PREFIX), NULL);
+	zend_hash_add(&soap_globals->defEncNs, XML_NAMESPACE, sizeof(XML_NAMESPACE), XML_NS_PREFIX, sizeof(XML_NS_PREFIX), NULL);
 	zend_hash_add(&soap_globals->defEncNs, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE), SOAP_1_1_ENC_NS_PREFIX, sizeof(SOAP_1_1_ENC_NS_PREFIX), NULL);
 	zend_hash_add(&soap_globals->defEncNs, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE), SOAP_1_2_ENC_NS_PREFIX, sizeof(SOAP_1_2_ENC_NS_PREFIX), NULL);
 
@@ -423,6 +469,8 @@ PHP_RINIT_FUNCTION(soap)
 	SOAP_GLOBAL(error_object) = NULL;
 	SOAP_GLOBAL(sdl) = NULL;
 	SOAP_GLOBAL(soap_version) = SOAP_1_1;
+	SOAP_GLOBAL(encoding) = NULL;
+	SOAP_GLOBAL(class_map) = NULL;
 	return SUCCESS;
 }
 
@@ -516,6 +564,9 @@ PHP_MINIT_FUNCTION(soap)
 	REGISTER_LONG_CONSTANT("SOAP_COMPRESSION_GZIP", SOAP_COMPRESSION_GZIP, CONST_CS | CONST_PERSISTENT);
 	REGISTER_LONG_CONSTANT("SOAP_COMPRESSION_DEFLATE", SOAP_COMPRESSION_DEFLATE, CONST_CS | CONST_PERSISTENT);
 
+	REGISTER_LONG_CONSTANT("SOAP_AUTHENTICATION_BASIC", SOAP_AUTHENTICATION_BASIC, CONST_CS | CONST_PERSISTENT);
+	REGISTER_LONG_CONSTANT("SOAP_AUTHENTICATION_DIGEST", SOAP_AUTHENTICATION_DIGEST, CONST_CS | CONST_PERSISTENT);
+
 	REGISTER_LONG_CONSTANT("UNKNOWN_TYPE", UNKNOWN_TYPE, CONST_CS | CONST_PERSISTENT);
 
 	REGISTER_LONG_CONSTANT("XSD_STRING", XSD_STRING, CONST_CS | CONST_PERSISTENT);
@@ -596,7 +647,7 @@ PHP_FUNCTION(soap_encode_to_xml)
 	int found, name_len;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &name, &name_len, &pzval) == FAILURE) {
-		php_error_docref(NULL TSRMLS_CC, E_ERROR, "wrong number of parameters");
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
 	}
 
 	enc = get_conversion(Z_TYPE_P(pzval));
@@ -612,7 +663,7 @@ PHP_FUNCTION(soap_encode_to_zval)
 	xmlNodePtr node;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &dom) == FAILURE) {
-		php_error_docref(NULL TSRMLS_CC, E_ERROR, "wrong number of parameters");
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
 	}
 
 	if (zend_hash_index_find(Z_OBJPROP_P(dom), 1, (void **)&addr) == FAILURE) {
@@ -633,7 +684,10 @@ PHP_METHOD(SoapParam, SoapParam)
 	int name_length;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs", &data, &name, &name_length) == FAILURE) {
-		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid arguments");
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
+	}
+	if (name_length == 0) {
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters. Invalid parameter name.");
 	}
 
 #ifndef ZEND_ENGINE_2
@@ -655,7 +709,13 @@ PHP_METHOD(SoapHeader, SoapHeader)
 	zend_bool must_understand = 0;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|zbz", &ns, &ns_len, &name, &name_len, &data, &must_understand, &actor) == FAILURE) {
-		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid arguments");
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
+	}
+	if (ns_len == 0) {
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters. Invalid namespace.");
+	}
+	if (name_len == 0) {
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters. Invalid header name.");
 	}
 
 	add_property_stringl(this_ptr, "namespace", ns, ns_len, 1);
@@ -668,12 +728,15 @@ PHP_METHOD(SoapHeader, SoapHeader)
 	}
 	add_property_bool(this_ptr, "mustUnderstand", must_understand);
 	if (actor == NULL) {
-	} else if (Z_TYPE_P(actor) == IS_LONG) {
+	} else if (Z_TYPE_P(actor) == IS_LONG &&
+	  (Z_LVAL_P(actor) == SOAP_ACTOR_NEXT ||
+	   Z_LVAL_P(actor) == SOAP_ACTOR_NONE ||
+	   Z_LVAL_P(actor) == SOAP_ACTOR_UNLIMATERECEIVER)) {
 		add_property_long(this_ptr, "actor", Z_LVAL_P(actor));
-	} else if (Z_TYPE_P(actor) == IS_STRING) {
+	} else if (Z_TYPE_P(actor) == IS_STRING && Z_STRLEN_P(actor) > 0) {
 		add_property_stringl(this_ptr, "actor", Z_STRVAL_P(actor), Z_STRLEN_P(actor), 1);
 	} else {
-		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid arguments");
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters. Invalid actor.");
 	}
 }
 
@@ -681,19 +744,46 @@ PHP_METHOD(SoapHeader, SoapHeader)
    SoapFault constructor */
 PHP_METHOD(SoapFault, SoapFault)
 {
-	char *fault_string = NULL, *fault_code = NULL, *fault_actor = NULL, *name = NULL;
+	char *fault_string = NULL, *fault_code = NULL, *fault_actor = NULL, *name = NULL, *fault_code_ns = NULL;
 	int fault_string_len, fault_code_len, fault_actor_len, name_len;
-	zval *details = NULL, *headerfault = NULL;
+	zval *code = NULL, *details = NULL, *headerfault = NULL;
 
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s!z!s!z",
-		&fault_code, &fault_code_len,
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs|s!z!s!z",
+		&code,
 		&fault_string, &fault_string_len,
 		&fault_actor, &fault_actor_len,
 		&details, &name, &name_len, &headerfault) == FAILURE) {
-		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid arguments");
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
+	}
+	if (Z_TYPE_P(code) == IS_NULL) {
+	} else if (Z_TYPE_P(code) == IS_STRING) {
+		fault_code = Z_STRVAL_P(code);
+		fault_code_len = Z_STRLEN_P(code);
+	} else if (Z_TYPE_P(code) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL_P(code)) == 2) {
+		zval **t_ns, **t_code;
+
+		zend_hash_internal_pointer_reset(Z_ARRVAL_P(code));
+		zend_hash_get_current_data(Z_ARRVAL_P(code), (void**)&t_ns);
+		zend_hash_move_forward(Z_ARRVAL_P(code));
+		zend_hash_get_current_data(Z_ARRVAL_P(code), (void**)&t_code);
+		if (Z_TYPE_PP(t_ns) == IS_STRING && Z_TYPE_PP(t_code) == IS_STRING) {
+		  fault_code_ns = Z_STRVAL_PP(t_ns);
+		  fault_code = Z_STRVAL_PP(t_code);
+		  fault_code_len = Z_STRLEN_PP(t_code);
+		} else {
+			php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters. Invalid fault code.");
+		}
+	} else  {
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters. Invalid fault code.");
+	}
+	if (fault_code != NULL && fault_code_len == 0) {
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters. Invalid fault code.");
+	}
+	if (name != NULL && name_len == 0) {
+		name = NULL;
 	}
 
-	set_soap_fault(this_ptr, fault_code, fault_string, fault_actor, details, name TSRMLS_CC);
+	set_soap_fault(this_ptr, fault_code_ns, fault_code, fault_string, fault_actor, details, name TSRMLS_CC);
 	if (headerfault != NULL) {
 		add_property_zval(this_ptr, "headerfault", headerfault);
 	}
@@ -751,7 +841,7 @@ PHP_METHOD(SoapVar, SoapVar)
 	int stype_len, ns_len, name_len, namens_len;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z!z|ssss", &data, &type, &stype, &stype_len, &ns, &ns_len, &name, &name_len, &namens, &namens_len) == FAILURE) {
-		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid arguments");
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
 	}
 
 	if (Z_TYPE_P(type) == IS_NULL) {
@@ -771,16 +861,16 @@ PHP_METHOD(SoapVar, SoapVar)
 		add_property_zval(this_ptr, "enc_value", data);
 	}
 
-	if (stype && strlen(stype) > 0) {
+	if (stype && stype_len > 0) {
 		add_property_stringl(this_ptr, "enc_stype", stype, stype_len, 1);
 	}
-	if (ns && strlen(ns) > 0) {
+	if (ns && ns_len > 0) {
 		add_property_stringl(this_ptr, "enc_ns", ns, ns_len, 1);
 	}
-	if (name && strlen(name) > 0) {
+	if (name && name_len > 0) {
 		add_property_stringl(this_ptr, "enc_name", name, name_len, 1);
 	}
-	if (namens && strlen(namens) > 0) {
+	if (namens && namens_len > 0) {
 		add_property_stringl(this_ptr, "enc_namens", namens, namens_len, 1);
 	}
 }
@@ -799,14 +889,14 @@ PHP_METHOD(SoapServer, SoapServer)
 	SOAP_SERVER_BEGIN_CODE();
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|a", &wsdl, &options) == FAILURE) {
-		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid arguments");
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
 	}
 
 	if (Z_TYPE_P(wsdl) == IS_STRING) {
 	} else if (Z_TYPE_P(wsdl) == IS_NULL) {
 		wsdl = NULL;
 	} else {
-		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid arguments");
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
 	}
 
 	service = emalloc(sizeof(soapService));
@@ -835,6 +925,28 @@ PHP_METHOD(SoapServer, SoapServer)
 		    Z_TYPE_PP(tmp) == IS_STRING) {
 			service->actor = estrndup(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
 		}
+
+		if (zend_hash_find(ht, "encoding", sizeof("encoding"), (void**)&tmp) == SUCCESS &&
+		    Z_TYPE_PP(tmp) == IS_STRING) {
+			xmlCharEncodingHandlerPtr encoding;
+		
+			encoding = xmlFindCharEncodingHandler(Z_STRVAL_PP(tmp));
+    	if (encoding == NULL) {
+				php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid arguments. Invalid 'encoding' option - '%s'.", Z_STRVAL_PP(tmp));
+	    } else {
+	      service->encoding = encoding;
+	    }
+		}
+
+		if (zend_hash_find(ht, "classmap", sizeof("classmap"), (void**)&tmp) == SUCCESS &&
+			Z_TYPE_PP(tmp) == IS_ARRAY) {
+			zval *ztmp;
+
+			ALLOC_HASHTABLE(service->class_map);
+			zend_hash_init(service->class_map, 0, NULL, ZVAL_PTR_DTOR, 0);
+			zend_hash_copy(service->class_map, (*tmp)->value.ht, (copy_ctor_func_t) zval_add_ref, (void *) &ztmp, sizeof(zval *));
+		}
+
 	} else if (wsdl == NULL) {
 		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid arguments. 'uri' option is required in nonWSDL mode.");
 	}
@@ -846,7 +958,7 @@ PHP_METHOD(SoapServer, SoapServer)
 	zend_hash_init(service->soap_functions.ft, 0, NULL, ZVAL_PTR_DTOR, 0);
 
 	if (wsdl) {
-		service->sdl = get_sdl(Z_STRVAL_P(wsdl) TSRMLS_CC);
+		service->sdl = get_sdl(this_ptr, Z_STRVAL_P(wsdl) TSRMLS_CC);
 		if (service->uri == NULL) {
 			if (service->sdl->target_ns) {
 				service->uri = estrdup(service->sdl->target_ns);
@@ -981,7 +1093,7 @@ PHP_FUNCTION(PHP_SOAP_SERVER_CLASS, map)
 		smart_str_free(&resloved_ns);
 	} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &type, &type_len, &class_name, &class_name_len, &type) == SUCCESS) {
 	} else {
-		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Wrong number of parameters");
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
 	}
 }
 #endif
@@ -1112,7 +1224,9 @@ PHP_METHOD(SoapServer, getFunctions)
 		HashPosition pos;
 		zend_hash_internal_pointer_reset_ex(ft, &pos);
 		while (zend_hash_get_current_data_ex(ft, (void **)&f, &pos) != FAILURE) {
-			add_next_index_string(return_value, f->common.function_name, 1);
+			if ((service->type != SOAP_CLASS) || (f->common.fn_flags & ZEND_ACC_PUBLIC)) {
+				add_next_index_string(return_value, f->common.function_name, 1);
+			}
 			zend_hash_move_forward_ex(ft, &pos);
 		}
 	}
@@ -1135,7 +1249,7 @@ PHP_METHOD(SoapServer, addFunction)
 	FETCH_THIS_SERVICE(service);
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &function_name) == FAILURE) {
-		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters passed");
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
 	}
 
 	/* TODO: could use zend_is_callable here */
@@ -1223,7 +1337,7 @@ PHP_METHOD(SoapServer, handle)
 	int soap_version, old_soap_version;
 	sdlPtr old_sdl = NULL;
 	soapServicePtr service;
-	xmlDocPtr doc_request, doc_return;
+	xmlDocPtr doc_request=NULL, doc_return;
 	zval function_name, **params, **raw_post, *soap_obj, retval, **server_vars;
 	char *fn_name, cont_len[30];
 	int num_params = 0, size, i, call_status = 0;
@@ -1233,13 +1347,15 @@ PHP_METHOD(SoapServer, handle)
 	sdlFunctionPtr function;
 	char *arg = NULL;
 	int arg_len;
+	xmlCharEncodingHandlerPtr old_encoding;
+	HashTable *old_class_map;
 
 	SOAP_SERVER_BEGIN_CODE();
 
 	FETCH_THIS_SERVICE(service);
 	SOAP_GLOBAL(soap_version) = service->version;
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &arg, &arg_len) == FAILURE) {
-		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters passed");
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
 	}
 	INIT_ZVAL(retval);
 
@@ -1262,7 +1378,7 @@ PHP_METHOD(SoapServer, handle)
 						INIT_ZVAL(readfile_ret);
 						MAKE_STD_ZVAL(param);
 
-						sapi_add_header("Content-Type: text/xml; charset=\"utf-8\"", sizeof("Content-Type: text/xml; charset=\"utf-8\""), 1);
+						sapi_add_header("Content-Type: text/xml; charset=utf-8", sizeof("Content-Type: text/xml; charset=utf-8")-1, 1);
 						ZVAL_STRING(param, service->sdl->source, 1);
 						ZVAL_STRING(&readfile, "readfile", 1);
 						if (call_user_function(EG(function_table), NULL, &readfile, &readfile_ret, 1, ¶m  TSRMLS_CC) == FAILURE) {
@@ -1278,7 +1394,7 @@ PHP_METHOD(SoapServer, handle)
 					} else {
 						soap_server_fault("Server", "WSDL generation is not supported yet", NULL, NULL, NULL TSRMLS_CC);
 /*
-						sapi_add_header("Content-Type: text/xml; charset=\"utf-8\"", sizeof("Content-Type: text/xml; charset=\"utf-8\""), 1);
+						sapi_add_header("Content-Type: text/xml; charset=utf-8", sizeof("Content-Type: text/xml; charset=utf-8"), 1);
 						PUTS("\nsdl;
+	old_encoding = SOAP_GLOBAL(encoding);
+	SOAP_GLOBAL(encoding) = service->encoding;
+	old_class_map = SOAP_GLOBAL(class_map);
+	SOAP_GLOBAL(class_map) = service->class_map;
 	old_soap_version = SOAP_GLOBAL(soap_version);
 	function = deserialize_function_call(service->sdl, doc_request, service->actor, &function_name, &num_params, ¶ms, &soap_version, &soap_headers TSRMLS_CC);
 	xmlFreeDoc(doc_request);
 
 	if (service->type == SOAP_CLASS) {
 		soap_obj = NULL;
-#if HAVE_PHP_SESSION
+#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
 		/* If persistent then set soap_obj from from the previous created session (if available) */
 		if (service->soap_class.persistance == SOAP_PERSISTENCE_SESSION) {
 			zval **tmp_soap;
@@ -1469,7 +1589,7 @@ PHP_METHOD(SoapServer, handle)
 				}
 				efree(class_name);
 			}
-#if HAVE_PHP_SESSION
+#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
 			/* If session then update session hash with new object */
 			if (service->soap_class.persistance == SOAP_PERSISTENCE_SESSION) {
 				zval **tmp_soap_pp;
@@ -1562,7 +1682,7 @@ PHP_METHOD(SoapServer, handle)
 	     zend_hash_exists(function_table, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)))) {
 		if (service->type == SOAP_CLASS) {
 			call_status = call_user_function(NULL, &soap_obj, &function_name, &retval, num_params, params TSRMLS_CC);
-#if HAVE_PHP_SESSION
+#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
 			if (service->soap_class.persistance != SOAP_PERSISTENCE_SESSION) {
 				zval_ptr_dtor(&soap_obj);
 			}
@@ -1615,28 +1735,35 @@ PHP_METHOD(SoapServer, handle)
 	/* Flush buffer */
 	php_end_ob_buffer(0, 0 TSRMLS_CC);
 
-	/* xmlDocDumpMemoryEnc(doc_return, &buf, &size, XML_CHAR_ENCODING_UTF8); */
-	xmlDocDumpMemory(doc_return, &buf, &size);
+	if (doc_return) {
+		/* xmlDocDumpMemoryEnc(doc_return, &buf, &size, XML_CHAR_ENCODING_UTF8); */
+		xmlDocDumpMemory(doc_return, &buf, &size);
 
-	if (size == 0) {
-		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Dump memory failed");
-	}
+		if (size == 0) {
+			php_error_docref(NULL TSRMLS_CC, E_ERROR, "Dump memory failed");
+		} 	
 
-	sprintf(cont_len, "Content-Length: %d", size);
-	sapi_add_header(cont_len, strlen(cont_len) + 1, 1);
-	if (soap_version == SOAP_1_2) {
-		sapi_add_header("Content-Type: application/soap+xml; charset=\"utf-8\"", sizeof("Content-Type: application/soap+xml; charset=\"utf-8\""), 1);
+		sprintf(cont_len, "Content-Length: %d", size);
+		sapi_add_header(cont_len, strlen(cont_len), 1);
+		if (soap_version == SOAP_1_2) {
+			sapi_add_header("Content-Type: application/soap+xml; charset=utf-8", sizeof("Content-Type: application/soap+xml; charset=utf-8")-1, 1);
+		} else {
+			sapi_add_header("Content-Type: text/xml; charset=utf-8", sizeof("Content-Type: text/xml; charset=utf-8")-1, 1);
+		}
+
+		xmlFreeDoc(doc_return);
+		php_write(buf, size TSRMLS_CC);
+		xmlFree(buf);
 	} else {
-		sapi_add_header("Content-Type: text/xml; charset=\"utf-8\"", sizeof("Content-Type: text/xml; charset=\"utf-8\""), 1);
+		sapi_add_header("HTTP/1.1 202 Accepted", sizeof("HTTP/1.1 202 Accepted")-1, 1);
+		sapi_add_header("Content-Length: 0", sizeof("Content-Length: 0")-1, 1);
 	}
 
-	xmlFreeDoc(doc_return);
-	php_write(buf, size TSRMLS_CC);
-	xmlFree(buf);
-
 fail:
 	SOAP_GLOBAL(soap_version) = old_soap_version;
+	SOAP_GLOBAL(encoding) = old_encoding;
 	SOAP_GLOBAL(sdl) = old_sdl;
+	SOAP_GLOBAL(class_map) = old_class_map;
 
 	/* Free soap headers */
 	zval_dtor(&retval);
@@ -1707,18 +1834,19 @@ static void soap_server_fault_ex(sdlFunctionPtr function, zval* fault, soapHeade
 	   Want to return HTTP 500 but apache wants to over write
 	   our fault code with their own handling... Figure this out later
 	*/
-	sapi_add_header("HTTP/1.1 500 Internal Service Error", sizeof("HTTP/1.1 500 Internal Service Error"), 1);
+	sapi_add_header("HTTP/1.1 500 Internal Service Error", sizeof("HTTP/1.1 500 Internal Service Error")-1, 1);
 	sprintf(cont_len,"Content-Length: %d", size);
-	sapi_add_header(cont_len, strlen(cont_len) + 1, 1);
+	sapi_add_header(cont_len, strlen(cont_len), 1);
 	if (soap_version == SOAP_1_2) {
-		sapi_add_header("Content-Type: application/soap+xml; charset=\"utf-8\"", sizeof("Content-Type: application/soap+xml; charset=\"utf-8\""), 1);
+		sapi_add_header("Content-Type: application/soap+xml; charset=utf-8", sizeof("Content-Type: application/soap+xml; charset=utf-8")-1, 1);
 	} else {
-		sapi_add_header("Content-Type: text/xml; charset=\"utf-8\"", sizeof("Content-Type: text/xml; charset=\"utf-8\""), 1);
+		sapi_add_header("Content-Type: text/xml; charset=utf-8", sizeof("Content-Type: text/xml; charset=utf-8")-1, 1);
 	}
 	php_write(buf, size TSRMLS_CC);
 
 	xmlFreeDoc(doc_return);
 	xmlFree(buf);
+	zend_clear_exception(TSRMLS_C);
 	zend_bailout();
 }
 
@@ -1728,77 +1856,146 @@ static void soap_server_fault(char* code, char* string, char *actor, zval* detai
 
 	INIT_ZVAL(ret);
 
-	set_soap_fault(&ret, code, string, actor, details, name TSRMLS_CC);
+	set_soap_fault(&ret, NULL, code, string, actor, details, name TSRMLS_CC);
 	/* TODO: Which function */
 	soap_server_fault_ex(NULL, &ret, NULL TSRMLS_CC);
 }
 
 static void soap_error_handler(int error_num, const char *error_filename, const uint error_lineno, const char *format, va_list args)
 {
+	zend_bool _old_in_compilation, _old_in_execution;
+	zend_execute_data *_old_current_execute_data;
 	TSRMLS_FETCH();
 
+	_old_in_compilation = CG(in_compilation);
+	_old_in_execution = EG(in_execution);
+	_old_current_execute_data = EG(current_execute_data);
+
 	if (!SOAP_GLOBAL(use_soap_error_handler)) {
-		old_error_handler(error_num, error_filename, error_lineno, format, args);
+		call_old_error_handler(error_num, error_filename, error_lineno, format, args);
 		return;
 	}
 
-	/*
-	  Trap all errors
-	  What do do with these warnings
-	    E_WARNING, E_NOTICE, E_CORE_WARNING, E_COMPILE_WARNING, E_USER_WARNING, E_USER_NOTICE
-	 */
-	if (error_num == E_USER_ERROR || error_num == E_COMPILE_ERROR || error_num == E_CORE_ERROR ||
-		error_num == E_ERROR || error_num == E_PARSE) {
-		char* code = SOAP_GLOBAL(error_code);
-		char buffer[1024];
-		int buffer_len;
-		zval outbuf, outbuflen;
-
-		INIT_ZVAL(outbuf);
-		INIT_ZVAL(outbuflen);
-
-		buffer_len = vsnprintf(buffer, sizeof(buffer)-1, format, args);
-		buffer[sizeof(buffer)-1]=0;
-		if (buffer_len > sizeof(buffer) - 1 || buffer_len < 0) {
-			buffer_len = sizeof(buffer) - 1;
-		}
-		if (SOAP_GLOBAL(error_object) &&
-		    Z_TYPE_P(SOAP_GLOBAL(error_object)) == IS_OBJECT &&
-		    Z_OBJCE_P(SOAP_GLOBAL(error_object)) == soap_class_entry) {
+	if (SOAP_GLOBAL(error_object) &&
+	    Z_TYPE_P(SOAP_GLOBAL(error_object)) == IS_OBJECT &&
+	    instanceof_function(Z_OBJCE_P(SOAP_GLOBAL(error_object)), soap_class_entry TSRMLS_CC)) {
 #ifdef ZEND_ENGINE_2
-			zval **tmp;
+		zval **tmp;
 
-			if (zend_hash_find(Z_OBJPROP_P(SOAP_GLOBAL(error_object)), "_exceptions", sizeof("_exceptions"), (void **) &tmp) != SUCCESS ||
-			    Z_TYPE_PP(tmp) != IS_BOOL || Z_LVAL_PP(tmp) != 0) {
-				zval *fault, *exception;
+		if ((error_num == E_USER_ERROR || 
+		     error_num == E_COMPILE_ERROR || 
+		     error_num == E_CORE_ERROR ||
+		     error_num == E_ERROR || 
+		     error_num == E_PARSE) &&
+		    (zend_hash_find(Z_OBJPROP_P(SOAP_GLOBAL(error_object)), "_exceptions", sizeof("_exceptions"), (void **) &tmp) != SUCCESS ||
+		     Z_TYPE_PP(tmp) != IS_BOOL || Z_LVAL_PP(tmp) != 0)) {
+			zval *fault, *exception;
+			char* code = SOAP_GLOBAL(error_code);
+			char buffer[1024];
+			int buffer_len;
+			zval outbuf, outbuflen;
+			va_list argcopy;
+			int old = PG(display_errors);
+
+			INIT_ZVAL(outbuf);
+			INIT_ZVAL(outbuflen);
+#ifdef va_copy
+			va_copy(argcopy, args);
+			buffer_len = vsnprintf(buffer, sizeof(buffer)-1, format, argcopy);
+			va_end(argcopy);
+#else
+			buffer_len = vsnprintf(buffer, sizeof(buffer)-1, format, args);
+#endif
+			buffer[sizeof(buffer)-1]=0;
+			if (buffer_len > sizeof(buffer) - 1 || buffer_len < 0) {
+				buffer_len = sizeof(buffer) - 1;
+			}
 
-				if (code == NULL) {
-					code = "Client";
-				}
-				fault = add_soap_fault(SOAP_GLOBAL(error_object), code, buffer, NULL, NULL TSRMLS_CC);
-				MAKE_STD_ZVAL(exception);
-				*exception = *fault;
-				zval_copy_ctor(exception);
-				INIT_PZVAL(exception);
-				zend_throw_exception_object(exception TSRMLS_CC);
-				zend_bailout();
-			} else {
-				old_error_handler(error_num, error_filename, error_lineno, format, args);
+			if (code == NULL) {
+				code = "Client";
 			}
+			fault = add_soap_fault(SOAP_GLOBAL(error_object), code, buffer, NULL, NULL TSRMLS_CC);
+			MAKE_STD_ZVAL(exception);
+			*exception = *fault;
+			zval_copy_ctor(exception);
+			INIT_PZVAL(exception);
+			zend_throw_exception_object(exception TSRMLS_CC);
+
+			PG(display_errors) = 0;
+			zend_try {
+				call_old_error_handler(error_num, error_filename, error_lineno, format, args);
+			} zend_catch {
+				CG(in_compilation) = _old_in_compilation;
+				EG(in_execution) = _old_in_execution;
+				EG(current_execute_data) = _old_current_execute_data;
+			} zend_end_try();
+			PG(display_errors) = old;
+			zend_bailout();
+		} else {
+			call_old_error_handler(error_num, error_filename, error_lineno, format, args);
+		}
 #else
-			old_error_handler(error_num, error_filename, error_lineno, format, args);
+		call_old_error_handler(error_num, error_filename, error_lineno, format, args);
 #endif
-		} else {
+	} else {
+		int old = PG(display_errors);
+		int fault = 0;
+		zval fault_obj;
+		va_list argcopy;
+
+		if (error_num == E_USER_ERROR || 
+		    error_num == E_COMPILE_ERROR || 
+		    error_num == E_CORE_ERROR ||
+		    error_num == E_ERROR || 
+		    error_num == E_PARSE) {
+
+			char* code = SOAP_GLOBAL(error_code);
+			char buffer[1024];
+			int buffer_len;
+			zval *outbuf = NULL;
+			zval outbuflen;
+
+			INIT_ZVAL(outbuflen);
+
+#ifdef va_copy
+			va_copy(argcopy, args);
+			buffer_len = vsnprintf(buffer, sizeof(buffer)-1, format, argcopy);
+			va_end(argcopy);
+#else
+			buffer_len = vsnprintf(buffer, sizeof(buffer)-1, format, args);
+#endif
+			buffer[sizeof(buffer)-1]=0;
+			if (buffer_len > sizeof(buffer) - 1 || buffer_len < 0) {
+				buffer_len = sizeof(buffer) - 1;
+			}
+
 			if (code == NULL) {
 				code = "Server";
 			}
 			/* Get output buffer and send as fault detials */
 			if (php_ob_get_length(&outbuflen TSRMLS_CC) != FAILURE && Z_LVAL(outbuflen) != 0) {
-				php_ob_get_buffer(&outbuf TSRMLS_CC);
+				ALLOC_INIT_ZVAL(outbuf);
+		    php_ob_get_buffer(outbuf TSRMLS_CC);
 			}
 			php_end_ob_buffer(0, 0 TSRMLS_CC);
 
-			soap_server_fault(code, buffer, NULL, &outbuf, NULL TSRMLS_CC);
+			INIT_ZVAL(fault_obj);
+			set_soap_fault(&fault_obj, NULL, code, buffer, NULL, outbuf, NULL TSRMLS_CC);
+			fault = 1;
+		}
+
+		PG(display_errors) = 0;
+		zend_try {
+			call_old_error_handler(error_num, error_filename, error_lineno, format, args);
+		} zend_catch {
+			CG(in_compilation) = _old_in_compilation;
+			EG(in_execution) = _old_in_execution;
+			EG(current_execute_data) = _old_current_execute_data;
+		} zend_end_try();
+		PG(display_errors) = old;
+
+		if (fault) {
+			soap_server_fault_ex(NULL, &fault_obj, NULL TSRMLS_CC);
 		}
 	}
 }
@@ -1839,13 +2036,13 @@ PHP_METHOD(SoapClient, SoapClient)
 	SOAP_CLIENT_BEGIN_CODE();
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|a", &wsdl, &options) == FAILURE) {
-		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters.");
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
 		return;
 	}
 
 	if (Z_TYPE_P(wsdl) == IS_STRING) {
 	} else if (Z_TYPE_P(wsdl) != IS_NULL ) {
-		php_error_docref(NULL TSRMLS_CC, E_ERROR, "$wsdl must be string or null.");
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "$wsdl must be string or null");
 		return;
 	} else {
 		wsdl = NULL;
@@ -1856,19 +2053,11 @@ PHP_METHOD(SoapClient, SoapClient)
 
 		if (wsdl == NULL) {
 			/* Fetching non-WSDL mode options */
-			if (zend_hash_find(ht, "location", sizeof("location"), (void**)&tmp) == SUCCESS &&
-			    Z_TYPE_PP(tmp) == IS_STRING) {
-				add_property_stringl(this_ptr, "location", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
-			} else {
-				php_error_docref(NULL TSRMLS_CC, E_ERROR, "'location' option is requred in nonWSDL mode.");
-				return;
-			}
-
 			if (zend_hash_find(ht, "uri", sizeof("uri"), (void**)&tmp) == SUCCESS &&
 			    Z_TYPE_PP(tmp) == IS_STRING) {
 				add_property_stringl(this_ptr, "uri", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
 			} else {
-				php_error_docref(NULL TSRMLS_CC, E_ERROR, "'uri' option is requred in nonWSDL mode.");
+				php_error_docref(NULL TSRMLS_CC, E_ERROR, "'uri' option is requred in nonWSDL mode");
 				return;
 			}
 
@@ -1885,6 +2074,14 @@ PHP_METHOD(SoapClient, SoapClient)
 			}
 		}
 
+		if (zend_hash_find(ht, "location", sizeof("location"), (void**)&tmp) == SUCCESS &&
+		    Z_TYPE_PP(tmp) == IS_STRING) {
+			add_property_stringl(this_ptr, "location", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
+		} else if (wsdl == NULL) {
+			php_error_docref(NULL TSRMLS_CC, E_ERROR, "'location' option is requred in nonWSDL mode");
+			return;
+		}
+
 		if (zend_hash_find(ht, "soap_version", sizeof("soap_version"), (void**)&tmp) == SUCCESS) {
 			if (Z_TYPE_PP(tmp) == IS_LONG ||
 			    (Z_LVAL_PP(tmp) == SOAP_1_1 && Z_LVAL_PP(tmp) == SOAP_1_2)) {
@@ -1898,6 +2095,11 @@ PHP_METHOD(SoapClient, SoapClient)
 			    Z_TYPE_PP(tmp) == IS_STRING) {
 				add_property_stringl(this_ptr, "_password", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
 			}
+			if (zend_hash_find(ht, "authentication", sizeof("authentication"), (void**)&tmp) == SUCCESS &&
+			    Z_TYPE_PP(tmp) == IS_LONG &&
+			    Z_LVAL_PP(tmp) == SOAP_AUTHENTICATION_DIGEST) {
+				add_property_null(this_ptr, "_digest");
+			}
 		}
 		if (zend_hash_find(ht, "proxy_host", sizeof("proxy_host"), (void**)&tmp) == SUCCESS &&
 		    Z_TYPE_PP(tmp) == IS_STRING) {
@@ -1915,6 +2117,14 @@ PHP_METHOD(SoapClient, SoapClient)
 				}
 			}
 		}
+		if (zend_hash_find(ht, "local_cert", sizeof("local_cert"), (void**)&tmp) == SUCCESS &&
+		    Z_TYPE_PP(tmp) == IS_STRING) {
+			add_property_stringl(this_ptr, "_local_cert", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
+			if (zend_hash_find(ht, "passphrase", sizeof("passphrase"), (void**)&tmp) == SUCCESS &&
+			    Z_TYPE_PP(tmp) == IS_STRING) {
+				add_property_stringl(this_ptr, "_passphrase", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
+			}
+		}
 		if (zend_hash_find(ht, "trace", sizeof("trace"), (void**)&tmp) == SUCCESS &&
 		    (Z_TYPE_PP(tmp) == IS_BOOL || Z_TYPE_PP(tmp) == IS_LONG) &&
 				Z_LVAL_PP(tmp) == 1) {
@@ -1936,8 +2146,37 @@ PHP_METHOD(SoapClient, SoapClient)
 	      zend_hash_exists(EG(function_table), "gzencode", sizeof("gzencode"))) {
 			add_property_long(this_ptr, "compression", Z_LVAL_PP(tmp));
 		}
+		if (zend_hash_find(ht, "encoding", sizeof("encoding"), (void**)&tmp) == SUCCESS &&
+		    Z_TYPE_PP(tmp) == IS_STRING) {
+			xmlCharEncodingHandlerPtr encoding;
+		
+			encoding = xmlFindCharEncodingHandler(Z_STRVAL_PP(tmp));
+    	if (encoding == NULL) {
+				php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid 'encoding' option - '%s'", Z_STRVAL_PP(tmp));
+	    } else {
+		    xmlCharEncCloseFunc(encoding);
+				add_property_stringl(this_ptr, "_encoding", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);			
+			}
+		}
+		if (zend_hash_find(ht, "classmap", sizeof("classmap"), (void**)&tmp) == SUCCESS &&
+			Z_TYPE_PP(tmp) == IS_ARRAY) {
+			zval *class_map;
+
+			MAKE_STD_ZVAL(class_map);
+			*class_map = **tmp;
+			zval_copy_ctor(class_map);
+#ifdef ZEND_ENGINE_2
+			class_map->refcount--;
+#endif
+			add_property_zval(this_ptr, "_classmap", class_map);
+		}
+
+		if (zend_hash_find(ht, "connection_timeout", sizeof("connection_timeout"), (void**)&tmp) == SUCCESS &&
+		    Z_TYPE_PP(tmp) == IS_LONG && Z_LVAL_PP(tmp) > 0) {
+			add_property_long(this_ptr, "_connection_timeout", Z_LVAL_PP(tmp));
+		}
 	} else if (wsdl == NULL) {
-		php_error_docref(NULL TSRMLS_CC, E_ERROR, "'location' and 'uri' options are requred in nonWSDL mode.");
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "'location' and 'uri' options are requred in nonWSDL mode");
 		return;
 	}
 
@@ -1950,7 +2189,7 @@ PHP_METHOD(SoapClient, SoapClient)
 		old_soap_version = SOAP_GLOBAL(soap_version);
 		SOAP_GLOBAL(soap_version) = soap_version;
 
-		sdl = get_sdl(Z_STRVAL_P(wsdl) TSRMLS_CC);
+		sdl = get_sdl(this_ptr, Z_STRVAL_P(wsdl) TSRMLS_CC);
 		ret = zend_list_insert(sdl, le_sdl);
 
 		add_property_resource(this_ptr, "sdl", ret);
@@ -1993,10 +2232,18 @@ static int do_request(zval *this_ptr, xmlDoc *request, char *location, char *act
 	ZVAL_STRINGL(params[0], buf, buf_size, 0);
 	INIT_ZVAL(param1);
 	params[1] = ¶m1;
-	ZVAL_STRING(params[1], location, 0);
+	if (location == NULL) {
+		ZVAL_NULL(params[1]);
+	} else {
+		ZVAL_STRING(params[1], location, 0);
+	}
 	INIT_ZVAL(param2);
 	params[2] = ¶m2;
-	ZVAL_STRING(params[2], action, 0);
+	if (action == NULL) {
+		ZVAL_NULL(params[2]);
+	} else {
+		ZVAL_STRING(params[2], action, 0);
+	}
 	INIT_ZVAL(param3);
 	params[3] = ¶m3;
 	ZVAL_LONG(params[3], version);
@@ -2005,6 +2252,9 @@ static int do_request(zval *this_ptr, xmlDoc *request, char *location, char *act
 		add_soap_fault(this_ptr, "Client", "SoapSlient::__doRequest() failed", NULL, NULL TSRMLS_CC);
 		ret = FALSE;
 	} else if (Z_TYPE_P(response) != IS_STRING) {
+		if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__soap_fault", sizeof("__soap_fault"), (void **) &fault) == FAILURE) {
+			add_soap_fault(this_ptr, "Client", "SoapSlient::__doRequest() returned non string value", NULL, NULL TSRMLS_CC);
+		}
 		ret = FALSE;
 	} else if (zend_hash_find(Z_OBJPROP_P(this_ptr), "trace", sizeof("trace"), (void **) &trace) == SUCCESS &&
 	    Z_LVAL_PP(trace) > 0) {
@@ -2023,6 +2273,7 @@ static void do_soap_call(zval* this_ptr,
                          int arg_count,
                          zval** real_args,
                          zval* return_value,
+                         char* location,
                          char* soap_action,
                          char* call_uri,
                          HashTable* soap_headers,
@@ -2035,11 +2286,11 @@ static void do_soap_call(zval* this_ptr,
  	sdlPtr old_sdl = NULL;
  	sdlFunctionPtr fn;
 	xmlDocPtr request = NULL;
-	char *buffer;
-	int len;
 	int ret = FALSE;
 	int soap_version;
 	zval response;
+	xmlCharEncodingHandlerPtr old_encoding;
+	HashTable *old_class_map;
 
 	SOAP_CLIENT_BEGIN_CODE();
 
@@ -2055,6 +2306,13 @@ static void do_soap_call(zval* this_ptr,
 		soap_version = SOAP_1_1;
 	}
 
+	if (location == NULL) {
+		if (zend_hash_find(Z_OBJPROP_P(this_ptr), "location", sizeof("location"),(void **) &tmp) == SUCCESS &&
+		    Z_TYPE_PP(tmp) == IS_STRING) {
+		  location = Z_STRVAL_PP(tmp);
+		}
+	}
+
 	if (FIND_SDL_PROPERTY(this_ptr,tmp) != FAILURE) {
 		FETCH_SDL_RES(sdl,tmp);
 	}
@@ -2064,17 +2322,35 @@ static void do_soap_call(zval* this_ptr,
 	SOAP_GLOBAL(soap_version) = soap_version;
 	old_sdl = SOAP_GLOBAL(sdl);
 	SOAP_GLOBAL(sdl) = sdl;
+	old_encoding = SOAP_GLOBAL(encoding);
+	if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_encoding", sizeof("_encoding"), (void **) &tmp) == SUCCESS &&
+	    Z_TYPE_PP(tmp) == IS_STRING) {
+		SOAP_GLOBAL(encoding) = xmlFindCharEncodingHandler(Z_STRVAL_PP(tmp));
+	} else {
+		SOAP_GLOBAL(encoding) = NULL;
+	}
+	old_class_map = SOAP_GLOBAL(class_map);
+	if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_classmap", sizeof("_classmap"), (void **) &tmp) == SUCCESS &&
+	    Z_TYPE_PP(tmp) == IS_ARRAY) {
+		SOAP_GLOBAL(class_map) = (*tmp)->value.ht;
+	} else {
+		SOAP_GLOBAL(class_map) = NULL;
+	}
+
  	if (sdl != NULL) {
  		fn = get_function(sdl, function);
  		if (fn != NULL) {
 			sdlBindingPtr binding = fn->binding;
+			if (location == NULL) {
+				location = binding->location;
+			}
 			if (binding->bindingType == BINDING_SOAP) {
 				sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)fn->bindingAttributes;
  				request = serialize_function_call(this_ptr, fn, NULL, fnb->input.ns, real_args, arg_count, soap_version, soap_headers TSRMLS_CC);
- 				ret = do_request(this_ptr, request, binding->location, fnb->soapAction, soap_version, &response TSRMLS_CC);
+ 				ret = do_request(this_ptr, request, location, fnb->soapAction, soap_version, &response TSRMLS_CC);
  			}	else {
  				request = serialize_function_call(this_ptr, fn, NULL, sdl->target_ns, real_args, arg_count, soap_version, soap_headers TSRMLS_CC);
- 				ret = do_request(this_ptr, request, binding->location, NULL, soap_version, &response TSRMLS_CC);
+ 				ret = do_request(this_ptr, request, location, NULL, soap_version, &response TSRMLS_CC);
  			}
 
 			xmlFreeDoc(request);
@@ -2095,12 +2371,12 @@ static void do_soap_call(zval* this_ptr,
 			smart_str_free(&error);
 		}
 	} else {
-		zval **uri, **location;
+		zval **uri;
 		smart_str action = {0};
 
 		if (zend_hash_find(Z_OBJPROP_P(this_ptr), "uri", sizeof("uri"), (void *)&uri) == FAILURE) {
 			add_soap_fault(this_ptr, "Client", "Error finding \"uri\" property", NULL, NULL TSRMLS_CC);
-		} else if (zend_hash_find(Z_OBJPROP_P(this_ptr), "location", sizeof("location"),(void **) &location) == FAILURE) {
+		} else if (location == NULL) {
 			add_soap_fault(this_ptr, "Client", "Error could not find \"location\" property", NULL, NULL TSRMLS_CC);
 		} else {
 			if (call_uri == NULL) {
@@ -2117,7 +2393,7 @@ static void do_soap_call(zval* this_ptr,
 			}
 			smart_str_0(&action);
 
-			ret = do_request(this_ptr, request, Z_STRVAL_PP(location), action.c, soap_version, &response TSRMLS_CC);
+			ret = do_request(this_ptr, request, location, action.c, soap_version, &response TSRMLS_CC);
 
 	 		smart_str_free(&action);
 			xmlFreeDoc(request);
@@ -2160,37 +2436,61 @@ static void do_soap_call(zval* this_ptr,
 		zend_throw_exception_object(exception TSRMLS_CC);
 	}
 #endif
+  if (SOAP_GLOBAL(encoding) != NULL) {
+		xmlCharEncCloseFunc(SOAP_GLOBAL(encoding));
+  }
+  SOAP_GLOBAL(class_map) = old_class_map;
+	SOAP_GLOBAL(encoding) = old_encoding;
 	SOAP_GLOBAL(sdl) = old_sdl;
 	SOAP_CLIENT_END_CODE();
 }
 
+static void verify_soap_headers_array(HashTable *ht TSRMLS_DC)
+{
+	zval **tmp;
+
+	zend_hash_internal_pointer_reset(ht);
+	while (zend_hash_get_current_data(ht, (void**)&tmp) == SUCCESS) {
+		if (Z_TYPE_PP(tmp) != IS_OBJECT ||
+		    Z_OBJCE_PP(tmp) != soap_header_class_entry) {
+			php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid SOAP header");
+		}
+		zend_hash_move_forward(ht);
+	}
+}
+
 
 /* {{{ proto mixed SoapClient::__call ( string function_name [, array arguments [, array options [, array input_headers [, array output_headers]]]])
    Calls a SOAP function */
 PHP_METHOD(SoapClient, __call)
 {
-	char *function, *soap_action = NULL, *uri = NULL;
+	char *function, *location=NULL, *soap_action = NULL, *uri = NULL;
 	int function_len, i = 0;
 	HashTable* soap_headers = NULL;
 	zval *options = NULL;
 	zval *headers = NULL;
 	zval *output_headers = NULL;
 	zval *args;
-	zval **real_args;
+	zval **real_args = NULL;
 	zval **param;
 	int arg_count;
+	zval **tmp;
+	zend_bool free_soap_headers;
 
 	HashPosition pos;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|zzz",
 		&function, &function_len, &args, &options, &headers, &output_headers) == FAILURE) {
-		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid arguments");
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
 	}
 
 	if (options) {
 		if (Z_TYPE_P(options) == IS_ARRAY) {
 			HashTable *ht = Z_ARRVAL_P(options);
-			zval **tmp;
+			if (zend_hash_find(ht, "location", sizeof("location"), (void**)&tmp) == SUCCESS &&
+			    Z_TYPE_PP(tmp) == IS_STRING) {
+				location = Z_STRVAL_PP(tmp);
+			}
 
 			if (zend_hash_find(ht, "soapaction", sizeof("soapaction"), (void**)&tmp) == SUCCESS &&
 			    Z_TYPE_PP(tmp) == IS_STRING) {
@@ -2202,49 +2502,69 @@ PHP_METHOD(SoapClient, __call)
 				soap_action = Z_STRVAL_PP(tmp);
 			}
 		} else if (Z_TYPE_P(options) != IS_NULL) {
-			php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid arguments");
+			php_error_docref(NULL TSRMLS_CC, E_ERROR, "first parameter must be string or null");
 		}
 	}
 
 	if (headers == NULL || Z_TYPE_P(headers) == IS_NULL) {
 	} else if (Z_TYPE_P(headers) == IS_ARRAY) {
-		zval** tmp;
-
 		soap_headers = Z_ARRVAL_P(headers);
-		zend_hash_internal_pointer_reset(soap_headers);
-		while (zend_hash_get_current_data(soap_headers, (void**)&tmp) == SUCCESS) {
-			if (Z_TYPE_PP(tmp) != IS_OBJECT ||
-			    Z_OBJCE_PP(tmp) != soap_header_class_entry) {
-				php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid arguments");
-			}
-			zend_hash_move_forward(soap_headers);
-		}
+		verify_soap_headers_array(soap_headers TSRMLS_CC);
+		free_soap_headers = 0;
 	} else if (Z_TYPE_P(headers) == IS_OBJECT &&
 	           Z_OBJCE_P(headers) == soap_header_class_entry) {
-	  soap_headers = emalloc(sizeof(HashTable));
-		zend_hash_init(soap_headers, 0, NULL, NULL/*ZVAL_PTR_DTOR*/, 0);
+	    soap_headers = emalloc(sizeof(HashTable));
+		zend_hash_init(soap_headers, 0, NULL, ZVAL_PTR_DTOR, 0);
 		zend_hash_next_index_insert(soap_headers, &headers, sizeof(zval*), NULL);
-	  headers = NULL;
+		ZVAL_ADDREF(headers);
+		free_soap_headers = 1;
 	} else{
-		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid arguments");
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid SOAP header");
+	}
+
+	/* Add default headers */
+	if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__default_headers", sizeof("__default_headers"), (void **) &tmp)==SUCCESS) {
+		HashTable *default_headers = Z_ARRVAL_P(*tmp);
+		if (soap_headers) {
+			if (!free_soap_headers) {
+				HashTable *tmp =  emalloc(sizeof(HashTable));
+				zend_hash_init(tmp, 0, NULL, ZVAL_PTR_DTOR, 0);
+				zend_hash_copy(tmp, soap_headers, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
+				soap_headers = tmp;
+				free_soap_headers = 1;
+			}
+			zend_hash_internal_pointer_reset(default_headers);
+			while (zend_hash_get_current_data(default_headers, (void**)&tmp) == SUCCESS) {
+				ZVAL_ADDREF(*tmp);
+				zend_hash_next_index_insert(soap_headers, tmp, sizeof(zval *), NULL);
+				zend_hash_move_forward(default_headers);
+			}
+		} else {
+			soap_headers = Z_ARRVAL_P(*tmp);
+			free_soap_headers = 0;
+		}
 	}
-
+	
 	arg_count = zend_hash_num_elements(Z_ARRVAL_P(args));
 
-	real_args = safe_emalloc(sizeof(zval *), arg_count, 0);
-	for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(args), &pos);
-		zend_hash_get_current_data_ex(Z_ARRVAL_P(args), (void **) ¶m, &pos) == SUCCESS;
-		zend_hash_move_forward_ex(Z_ARRVAL_P(args), &pos)) {
-			/*zval_add_ref(param);*/
-			real_args[i++] = *param;
+	if (arg_count > 0) {
+		real_args = safe_emalloc(sizeof(zval *), arg_count, 0);
+		for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(args), &pos);
+			zend_hash_get_current_data_ex(Z_ARRVAL_P(args), (void **) ¶m, &pos) == SUCCESS;
+			zend_hash_move_forward_ex(Z_ARRVAL_P(args), &pos)) {
+				/*zval_add_ref(param);*/
+				real_args[i++] = *param;
+		}
 	}
 	if (output_headers) {
 		array_init(output_headers);
 	}
-	do_soap_call(this_ptr, function, function_len, arg_count, real_args, return_value, soap_action, uri, soap_headers, output_headers TSRMLS_CC);
-	efree(real_args);
+	do_soap_call(this_ptr, function, function_len, arg_count, real_args, return_value, location, soap_action, uri, soap_headers, output_headers TSRMLS_CC);
+	if (arg_count > 0) {
+		efree(real_args);
+	}
 
-	if (soap_headers && ! headers) {
+	if (soap_headers && free_soap_headers) {
 		zend_hash_destroy(soap_headers);
 		efree(soap_headers);
 	}
@@ -2375,7 +2695,7 @@ PHP_METHOD(SoapClient, __doRequest)
 	    &location, &location_size,
 	    &action, &action_size,
 	    &version) == FAILURE) {
-		php_error_docref(NULL TSRMLS_CC, E_ERROR, "wrong parameters");
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
 	}
 	if (make_http_soap_request(this_ptr, buf, buf_size, location, action, version,
 	    &Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value) TSRMLS_CC)) {
@@ -2386,6 +2706,115 @@ PHP_METHOD(SoapClient, __doRequest)
 }
 /* }}} */
 
+/* {{{ proto void SoapClient::__setCookie(string name [, strung value])
+   Sets cookie thet will sent with SOAP request.
+   The call to this function will effect all folowing calls of SOAP methods.
+   If value is not specified cookie is removed. */
+PHP_METHOD(SoapClient, __setCookie)
+{
+	char *name;
+	char *val = NULL;
+	int  name_len, val_len;
+	zval **cookies;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s",
+	    &name, &name_len, &val, &val_len) == FAILURE) {
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
+	  RETURN_NULL();
+	}
+
+	if (val == NULL) {
+		if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_cookies", sizeof("_cookies"), (void **)&cookies) == SUCCESS) {
+			zend_hash_del(Z_ARRVAL_PP(cookies), name, name_len+1);
+		}
+	} else {
+		zval *zcookie;
+
+		if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_cookies", sizeof("_cookies"), (void **)&cookies) == FAILURE) {
+			zval *tmp_cookies;
+
+			MAKE_STD_ZVAL(tmp_cookies);
+			array_init(tmp_cookies);
+			zend_hash_update(Z_OBJPROP_P(this_ptr), "_cookies", sizeof("_cookies"), &tmp_cookies, sizeof(zval *), (void **)&cookies);
+		}
+
+		ALLOC_INIT_ZVAL(zcookie);
+		array_init(zcookie);
+		add_index_stringl(zcookie, 0, val, val_len, 1);
+		add_assoc_zval_ex(*cookies, name, name_len+1, zcookie);
+	}
+}
+/* }}} */
+
+/* {{{ proto void SoapClient::__setSoapHeaders(array SoapHeaders)
+   Sets SOAP headers for subsequent calls (replaces any previous
+   values).
+   If no value is specified, all of the headers are removed. */
+PHP_METHOD(SoapClient, __setSoapHeaders)
+{
+	zval *headers;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z", &headers) == FAILURE) {
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
+	  RETURN_NULL();
+	}
+
+    if (headers == NULL || Z_TYPE_P(headers) == IS_NULL) {
+		zend_hash_del(Z_OBJPROP_P(this_ptr), "__default_headers", sizeof("__default_headers"));
+    } else if (Z_TYPE_P(headers) == IS_ARRAY || Z_TYPE_P(headers) == IS_OBJECT) {
+		zval *default_headers;
+
+		verify_soap_headers_array(Z_ARRVAL_P(headers) TSRMLS_CC);
+		if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__default_headers", sizeof("__default_headers"), (void **) &default_headers)==FAILURE) {
+			add_property_zval(this_ptr, "__default_headers", headers);
+		}
+    } else if (Z_TYPE_P(headers) == IS_OBJECT &&
+               Z_OBJCE_P(headers) == soap_header_class_entry) {
+		zval *default_headers;
+		ALLOC_INIT_ZVAL(default_headers);
+		array_init(default_headers);
+		add_next_index_zval(default_headers, headers);
+		add_property_zval(this_ptr, "__default_headers", default_headers);
+    } else{
+        php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid SOAP header");
+    }
+	RETURN_TRUE;
+}
+/* }}} */
+
+
+
+/* {{{ proto string SoapClient::__setLocation([string new_location])
+   Sets the location option (the endpoint URL that will be touched by the 
+   following SOAP requests).
+   If new_location is not specified or null then SoapClient will use endpoint
+   from WSDL file. 
+   The function returns old value of location options. */
+PHP_METHOD(SoapClient, __setLocation)
+{
+	char *location = NULL;
+	int  location_len;
+	zval **tmp;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s",
+	    &location, &location_len) == FAILURE) {
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
+	  RETURN_NULL();
+	}
+	if (zend_hash_find(Z_OBJPROP_P(this_ptr), "location", sizeof("location"),(void **) &tmp) == SUCCESS &&
+	    Z_TYPE_PP(tmp) == IS_STRING) {
+	  RETVAL_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
+	} else {
+	  RETVAL_NULL();
+	}
+	if (location && location_len) {
+		add_property_stringl(this_ptr, "location", location, location_len, 1);
+	} else {
+		zend_hash_del(Z_OBJPROP_P(this_ptr), "location", sizeof("location"));
+	}
+}
+/* }}} */
+
 #ifndef ZEND_ENGINE_2
 static void soap_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference)
 {
@@ -2403,9 +2832,18 @@ static void soap_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_proper
 	} else {
 		int arg_count = ZEND_NUM_ARGS();
 		zval **arguments = (zval **) safe_emalloc(sizeof(zval *), arg_count, 0);
+		zval **soap_headers_p
+		HashTable *soap_headers;
 
 		zend_get_parameters_array(ht, arg_count, arguments);
-		do_soap_call(this_ptr, function, Z_STRLEN(function_name->element) + 1, arg_count, arguments, return_value, NULL, NULL, NULL, NULL TSRMLS_CC);
+
+		if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__default_headers", sizeof("__default_properties"), (void **) soap_headers_p)==SUCCESS
+			&& Z_TYPE_P(soap_headers_p)==IS_ARRAY) {
+			soap_headers = Z_ARRVAL_P(soap_headers_p);
+		} else {
+			soap_headers = NULL;
+		}
+		do_soap_call(this_ptr, function, Z_STRLEN(function_name->element) + 1, arg_count, arguments, return_value, NULL, NULL, NULL, soap_headers, NULL TSRMLS_CC);
 		efree(arguments);
 	}
 	zval_dtor(&function_name->element);
@@ -2422,16 +2860,16 @@ static void clear_soap_fault(zval *obj TSRMLS_DC)
 zval* add_soap_fault(zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail TSRMLS_DC)
 {
 	zval *fault;
-	MAKE_STD_ZVAL(fault);
-	set_soap_fault(fault, fault_code, fault_string, fault_actor, fault_detail, NULL TSRMLS_CC);
+	ALLOC_INIT_ZVAL(fault);
+	set_soap_fault(fault, NULL, fault_code, fault_string, fault_actor, fault_detail, NULL TSRMLS_CC);
 #ifdef ZEND_ENGINE_2
-	fault->refcount--;  /*FIXME*/
+	fault->refcount--;
 #endif
 	add_property_zval(obj, "__soap_fault", fault);
 	return fault;
 }
 
-static void set_soap_fault(zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail, char *name TSRMLS_DC)
+static void set_soap_fault(zval *obj, char *fault_code_ns, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail, char *name TSRMLS_DC)
 {
 	if (Z_TYPE_P(obj) != IS_OBJECT) {
 		object_init_ex(obj, soap_fault_class_entry);
@@ -2441,38 +2879,36 @@ static void set_soap_fault(zval *obj, char *fault_code, char *fault_string, char
 	}
 	if (fault_code != NULL) {
 		int soap_version = SOAP_GLOBAL(soap_version);
-		smart_str code = {0};
-		if (soap_version == SOAP_1_1) {
-			if (strcmp(fault_code,"Client") == 0 ||
-			    strcmp(fault_code,"Server") == 0 ||
-			    strcmp(fault_code,"VersionMismatch") == 0 ||
-			    strcmp(fault_code,"MustUnderstand") == 0) {
-				smart_str_appendl(&code, SOAP_1_1_ENV_NS_PREFIX, sizeof(SOAP_1_1_ENV_NS_PREFIX)-1);
-				smart_str_appendc(&code, ':');
-			}
-			smart_str_appends(&code,fault_code);
-		} else if (soap_version == SOAP_1_2) {
-			if (strcmp(fault_code,"Client") == 0) {
-				smart_str_appendl(&code, SOAP_1_2_ENV_NS_PREFIX, sizeof(SOAP_1_2_ENV_NS_PREFIX)-1);
-				smart_str_appendc(&code, ':');
-				smart_str_appendl(&code,"Sender",sizeof("Sender")-1);
-			} else if (strcmp(fault_code,"Server") == 0) {
-				smart_str_appendl(&code, SOAP_1_2_ENV_NS_PREFIX, sizeof(SOAP_1_2_ENV_NS_PREFIX)-1);
-				smart_str_appendc(&code, ':');
-				smart_str_appendl(&code,"Receiver",sizeof("Receiver")-1);
-			} else if (strcmp(fault_code,"VersionMismatch") == 0 ||
-			           strcmp(fault_code,"MustUnderstand") == 0 ||
-			           strcmp(fault_code,"DataEncodingUnknown") == 0) {
-				smart_str_appendl(&code, SOAP_1_2_ENV_NS_PREFIX, sizeof(SOAP_1_2_ENV_NS_PREFIX)-1);
-				smart_str_appendc(&code, ':');
-				smart_str_appends(&code,fault_code);
-			} else {
-				smart_str_appends(&code,fault_code);
+
+		if (fault_code_ns) {
+			add_property_string(obj, "faultcode", fault_code, 1);
+			add_property_string(obj, "faultcodens", fault_code_ns, 1);
+		} else {
+			if (soap_version == SOAP_1_1) {
+				add_property_string(obj, "faultcode", fault_code, 1);
+				if (strcmp(fault_code,"Client") == 0 ||
+				    strcmp(fault_code,"Server") == 0 ||
+				    strcmp(fault_code,"VersionMismatch") == 0 ||
+			  	  strcmp(fault_code,"MustUnderstand") == 0) {
+					add_property_string(obj, "faultcodens", SOAP_1_1_ENV_NAMESPACE, 1);
+				}
+			} else if (soap_version == SOAP_1_2) {
+				if (strcmp(fault_code,"Client") == 0) {
+					add_property_string(obj, "faultcode", "Sender", 1);
+					add_property_string(obj, "faultcodens", SOAP_1_2_ENV_NAMESPACE, 1);
+				} else if (strcmp(fault_code,"Server") == 0) {
+					add_property_string(obj, "faultcode", "Receiver", 1);
+					add_property_string(obj, "faultcodens", SOAP_1_2_ENV_NAMESPACE, 1);
+				} else if (strcmp(fault_code,"VersionMismatch") == 0 ||
+				           strcmp(fault_code,"MustUnderstand") == 0 ||
+				           strcmp(fault_code,"DataEncodingUnknown") == 0) {
+					add_property_string(obj, "faultcode", fault_code, 1);
+					add_property_string(obj, "faultcodens", SOAP_1_2_ENV_NAMESPACE, 1);
+				} else {
+					add_property_string(obj, "faultcode", fault_code, 1);
+				}
 			}
 		}
-		smart_str_0(&code);
-		add_property_string(obj, "faultcode", code.c, 1);
-		smart_str_free(&code);
 	}
 	if (fault_actor != NULL) {
 		add_property_string(obj, "faultactor", fault_actor, 1);
@@ -2603,8 +3039,6 @@ static sdlFunctionPtr deserialize_function_call(sdlPtr sdl, xmlDocPtr request, c
 	xmlAttrPtr attr;
 	sdlFunctionPtr function;
 
-	ZVAL_EMPTY_STRING(function_name);
-
 	/* Get  element */
 	env = NULL;
 	trav = request->children;
@@ -2694,10 +3128,13 @@ static sdlFunctionPtr deserialize_function_call(sdlPtr sdl, xmlDocPtr request, c
 	trav = body->children;
 	while (trav != NULL) {
 		if (trav->type == XML_ELEMENT_NODE) {
+/*
 			if (func != NULL) {
 				soap_server_fault("Client", "looks like we got \"Body\" with several functions call", NULL, NULL, NULL TSRMLS_CC);
 			}
+*/
 			func = trav;
+			break; /* FIXME: the rest of body is ignored */
 		}
 		trav = trav->next;
 	}
@@ -2870,7 +3307,7 @@ static int serialize_response_call2(xmlNodePtr body, sdlFunctionPtr function, ch
 			ns = encode_add_ns(body, fnb->output.ns);
 			if (function->responseName) {
 				method = xmlNewChild(body, ns, function->responseName, NULL);
-			} else {
+			} else if (function->responseParameters) {
 				method = xmlNewChild(body, ns, function->functionName, NULL);
 			}
 		}
@@ -2927,13 +3364,12 @@ static int serialize_response_call2(xmlNodePtr body, sdlFunctionPtr function, ch
 
 		zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(ret), &pos);
 		while (zend_hash_get_current_data_ex(Z_ARRVAL_P(ret), (void **)&data, &pos) != FAILURE) {
-			char *param_name;
+			char *param_name = NULL;
 			int   param_name_len;
-			long  param_index;
+			long  param_index = i;
 
 			zend_hash_get_current_key_ex(Z_ARRVAL_P(ret), ¶m_name, ¶m_name_len, ¶m_index, 0, &pos);
 			parameter = get_param(function, param_name, param_index, TRUE);
-
 			if (style == SOAP_RPC) {
 				param = serialize_parameter(parameter, *data, i, param_name, use, method TSRMLS_CC);
 			} else {
@@ -2963,6 +3399,7 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
 	xmlNodePtr envelope = NULL, body, param;
 	xmlNsPtr ns = NULL;
 	int use = SOAP_LITERAL;
+	xmlNodePtr head = NULL;
 
 	encode_reset_ns();
 
@@ -2989,6 +3426,7 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
 		HashTable* prop;
 		zval **tmp;
 		sdlFaultPtr fault = NULL;
+		char *fault_ns = NULL;
 
 		prop = Z_OBJPROP_P(ret);
 
@@ -3053,6 +3491,9 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
 		body = xmlNewChild(envelope, ns, "Body", NULL);
 		param = xmlNewChild(body, ns, "Fault", NULL);
 
+		if (zend_hash_find(prop, "faultcodens", sizeof("faultcodens"), (void**)&tmp) == SUCCESS && Z_TYPE_PP(tmp) == IS_STRING) {
+			fault_ns = Z_STRVAL_PP(tmp);
+		}
 		use = SOAP_LITERAL;
 		if (zend_hash_find(prop, "_name", sizeof("_name"), (void**)&tmp) == SUCCESS && Z_TYPE_PP(tmp) == IS_STRING) {
 			sdlFaultPtr *tmp_fault;
@@ -3064,6 +3505,9 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
 				    fault->bindingAttributes) {
 					sdlSoapBindingFunctionFaultPtr fb = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
 					use = fb->use;
+					if (fault_ns == NULL) {
+						fault_ns = fb->ns;
+					}
 				}
 			}
 		} else if (function && function->faults &&
@@ -3077,6 +3521,23 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
 			    fault->bindingAttributes) {
 				sdlSoapBindingFunctionFaultPtr fb = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
 				use = fb->use;
+				if (fault_ns == NULL) {
+				  fault_ns = fb->ns;
+				}
+			}
+		}
+
+		if (fault_ns == NULL &&
+		    fault && 
+		    fault->details && 
+		    zend_hash_num_elements(fault->details) == 1) {
+			sdlParamPtr sparam;
+
+			zend_hash_internal_pointer_reset(fault->details);
+			zend_hash_get_current_data(fault->details, (void**)&sparam);
+			sparam = *(sdlParamPtr*)sparam;
+			if (sparam->element) {
+				fault_ns = sparam->element->namens;
 			}
 		}
 
@@ -3086,7 +3547,12 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
 				xmlNodePtr node = xmlNewNode(NULL, "faultcode");
 				char *str = php_escape_html_entities(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), &new_len, 0, 0, NULL TSRMLS_CC);
 				xmlAddChild(param, node);
-				xmlNodeSetContentLen(node, str, new_len);
+				if (fault_ns) {
+					xmlNsPtr nsptr = encode_add_ns(node, fault_ns);
+					xmlNodeSetContent(node, xmlBuildQName(str, nsptr->prefix, NULL, 0));
+				} else {	
+					xmlNodeSetContentLen(node, str, new_len);
+				}
 				efree(str);
 			}
 			if (zend_hash_find(prop, "faultstring", sizeof("faultstring"), (void**)&tmp) == SUCCESS) {
@@ -3112,7 +3578,12 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
 				xmlNodePtr node = xmlNewChild(param, ns, "Code", NULL);
 				char *str = php_escape_html_entities(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), &new_len, 0, 0, NULL TSRMLS_CC);
 				node = xmlNewChild(node, ns, "Value", NULL);
-				xmlNodeSetContentLen(node, str, new_len);
+				if (fault_ns) {
+					xmlNsPtr nsptr = encode_add_ns(node, fault_ns);
+					xmlNodeSetContent(node, xmlBuildQName(str, nsptr->prefix, NULL, 0));
+				} else {	
+					xmlNodeSetContentLen(node, str, new_len);
+				}
 				efree(str);
 			}
 			if (zend_hash_find(prop, "faultstring", sizeof("faultstring"), (void**)&tmp) == SUCCESS) {
@@ -3127,7 +3598,7 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
 		}
 		if (fault && fault->details && zend_hash_num_elements(fault->details) == 1) {
 			xmlNodePtr node;
-		  zval *detail = NULL;
+			zval *detail = NULL;
 			sdlParamPtr sparam;
 			xmlNodePtr x;
 
@@ -3141,6 +3612,15 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
 			zend_hash_internal_pointer_reset(fault->details);
 			zend_hash_get_current_data(fault->details, (void**)&sparam);
 			sparam = *(sdlParamPtr*)sparam;
+
+			if (detail &&
+			    Z_TYPE_P(detail) == IS_OBJECT &&
+			    sparam->element &&
+			    zend_hash_num_elements(Z_OBJPROP_P(detail)) == 1 &&
+			    zend_hash_find(Z_OBJPROP_P(detail), sparam->element->name, strlen(sparam->element->name)+1, (void**)&tmp) == SUCCESS) {
+				detail = *tmp;
+			}
+
 			x = serialize_parameter(sparam, detail, 1, NULL, use, node TSRMLS_CC);
 
 			if (function &&
@@ -3148,7 +3628,7 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
 			    function->binding->bindingType == BINDING_SOAP &&
 			    function->bindingAttributes) {
 				sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
-				if (fnb->style == SOAP_RPC) {
+				if (fnb->style == SOAP_RPC && !sparam->element) {
 				  if (fault->bindingAttributes) {
 						sdlSoapBindingFunctionFaultPtr fb = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
 						if (fb->ns) {
@@ -3174,7 +3654,6 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
 	} else {
 
 		if (headers) {
-			xmlNodePtr head;
 			soapHeader *h;
 
 			head = xmlNewChild(envelope, ns, "Header", NULL);
@@ -3267,6 +3746,11 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
 		}
 	}
 
+	if (function && function->responseName == NULL && 
+	    body->children == NULL && head == NULL) {
+		xmlFreeDoc(doc);
+		return NULL;
+	}
 	return doc;
 }
 
@@ -3554,6 +4038,16 @@ static sdlParamPtr get_param(sdlFunctionPtr function, char *param_name, int inde
 	if (param_name != NULL) {
 		if (zend_hash_find(ht, param_name, strlen(param_name), (void **)&tmp) != FAILURE) {
 			return *tmp;
+		} else {
+			HashPosition pos;
+		
+			zend_hash_internal_pointer_reset_ex(ht, &pos);
+			while (zend_hash_get_current_data_ex(ht, (void **)&tmp, &pos) != FAILURE) {
+				if ((*tmp)->paramName && strcmp(param_name, (*tmp)->paramName) == 0) {
+					return *tmp;
+				}
+				zend_hash_move_forward_ex(ht, &pos);
+			}
 		}
 	} else {
 		if (zend_hash_index_find(ht, index, (void **)&tmp) != FAILURE) {
@@ -3706,11 +4200,19 @@ static void function_to_string(sdlFunctionPtr function, smart_str *buf)
 
 static void model_to_string(sdlContentModelPtr model, smart_str *buf, int level)
 {
+	int i;
+
 	switch (model->kind) {
 		case XSD_CONTENT_ELEMENT:
 			type_to_string(model->u.element, buf, level);
 			smart_str_appendl(buf, ";\n", 2);
 			break;
+		case XSD_CONTENT_ANY:
+			for (i = 0;i < level;i++) {
+				smart_str_appendc(buf, ' ');
+			}
+			smart_str_appendl(buf, " any;\n", sizeof(" any;\n")-1);
+			break;
 		case XSD_CONTENT_SEQUENCE:
 		case XSD_CONTENT_ALL:
 		case XSD_CONTENT_CHOICE: {
@@ -3745,8 +4247,12 @@ static void type_to_string(sdlTypePtr type, smart_str *buf, int level)
 		case XSD_TYPEKIND_SIMPLE:
 		case XSD_TYPEKIND_LIST:
 		case XSD_TYPEKIND_UNION:
-			smart_str_appendl(buf, type->encode->details.type_str, strlen(type->encode->details.type_str));
-			smart_str_appendc(buf, ' ');
+			if (type->encode) {
+				smart_str_appendl(buf, type->encode->details.type_str, strlen(type->encode->details.type_str));
+				smart_str_appendc(buf, ' ');
+			} else {
+				smart_str_appendl(buf, "anyType ", sizeof("anyType ")-1);
+			}
 			smart_str_appendl(buf, type->name, strlen(type->name));
 			break;
 		case XSD_TYPEKIND_COMPLEX:
@@ -3771,7 +4277,7 @@ static void type_to_string(sdlTypePtr type, smart_str *buf, int level)
 						len = end-(*ext)->val;
 					}
 					if (len == 0) {
-						smart_str_appendl(buf, "anyType", 7);
+						smart_str_appendl(buf, "anyType", sizeof("anyType")-1);
 					} else {
 						smart_str_appendl(buf, (*ext)->val, len);
 					}
@@ -3902,5 +4408,12 @@ static void delete_service(void *data)
 	if (service->sdl) {
 		delete_sdl(service->sdl);
 	}
+	if (service->encoding) {
+		xmlCharEncCloseFunc(service->encoding);
+	}
+	if (service->class_map) {
+		zend_hash_destroy(service->class_map);
+		FREE_HASHTABLE(service->class_map);
+	}
 	efree(service);
 }
diff --git a/ext/soap/tests/bugs/bug28969.phpt b/ext/soap/tests/bugs/bug28969.phpt
new file mode 100644
index 000000000000..6634888eac18
--- /dev/null
+++ b/ext/soap/tests/bugs/bug28969.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Bug #28969 (Wrong data encoding of special characters)
+--SKIPIF--
+
+--FILE--
+server = new SoapServer($wsdl, $options);
+    $this->server->addFunction('test');
+  }
+
+  function __doRequest($request, $location, $action, $version) {
+    ob_start();
+    $this->server->handle($request);
+    $response = ob_get_contents();
+    ob_end_clean();
+    return $response;
+  }
+
+}
+
+$x = new LocalSoapClient(NULL,array('location'=>'test://', 
+                                    'uri'=>'http://testuri.org',
+                                    'encoding'=>'ISO-8859-1')); 
+var_dump($x->test());
+echo "ok\n";
+?>
+--EXPECT--
+string(3) "¦è¥"
+ok
diff --git a/ext/soap/tests/bugs/bug28985.phpt b/ext/soap/tests/bugs/bug28985.phpt
new file mode 100644
index 000000000000..291cce0cbb22
--- /dev/null
+++ b/ext/soap/tests/bugs/bug28985.phpt
@@ -0,0 +1,204 @@
+--TEST--
+Bug #28985 (__getTypes() returning nothing on complex WSDL)
+--SKIPIF--
+
+--FILE--
+1));
+var_dump($client->__getTypes());
+?>
+--EXPECT--
+array(42) {
+  [0]=>
+  string(100) "struct LoginMGDIS {
+ string iUserLogin;
+ string iUserId;
+ string iUserPassword;
+ string iProfilId;
+}"
+  [1]=>
+  string(29) "struct LoginMGDISResponse {
+}"
+  [2]=>
+  string(28) "struct GetIdentification {
+}"
+  [3]=>
+  string(77) "struct GetIdentificationResponse {
+ ArrayOfAnyType GetIdentificationResult;
+}"
+  [4]=>
+  string(43) "struct ArrayOfAnyType {
+ anyType anyType;
+}"
+  [5]=>
+  string(37) "struct RollbackCurrentTransaction {
+}"
+  [6]=>
+  string(45) "struct RollbackCurrentTransactionResponse {
+}"
+  [7]=>
+  string(68) "struct GetListeProfil {
+ string iUserLogin;
+ string iUserPassword;
+}"
+  [8]=>
+  string(86) "struct MGCodeLibelle {
+ string Code;
+ string Libelle;
+ boolean Defaut;
+ anyType Tag;
+}"
+  [9]=>
+  string(61) "struct ArrayOfMGCodeLibelle {
+ MGCodeLibelle MGCodeLibelle;
+}"
+  [10]=>
+  string(77) "struct GetListeProfilResponse {
+ ArrayOfMGCodeLibelle GetListeProfilResult;
+}"
+  [11]=>
+  string(41) "struct GetListeValCodif {
+ string Code;
+}"
+  [12]=>
+  string(43) "struct ArrayOfMGCodif {
+ MGCodif MGCodif;
+}"
+  [13]=>
+  string(18) "struct MGCodif {
+}"
+  [14]=>
+  string(75) "struct GetListeValCodifResponse {
+ ArrayOfMGCodif GetListeValCodifResult;
+}"
+  [15]=>
+  string(39) "struct TestPhpSoap {
+ MGCodif entree;
+}"
+  [16]=>
+  string(57) "struct TestPhpSoapResponse {
+ string TestPhpSoapResult;
+}"
+  [17]=>
+  string(50) "struct GetListeCodif {
+ boolean iGetListeValeur;
+}"
+  [18]=>
+  string(87) "struct MGCodifGrp {
+ string TypeCodif;
+ string LibCodif;
+ ArrayOfMGCodif ListeCodifs;
+}"
+  [19]=>
+  string(52) "struct ArrayOfMGCodifGrp {
+ MGCodifGrp MGCodifGrp;
+}"
+  [20]=>
+  string(72) "struct GetListeCodifResponse {
+ ArrayOfMGCodifGrp GetListeCodifResult;
+}"
+  [21]=>
+  string(57) "struct DroitCreation {
+ string iObjet;
+ string iProfil;
+}"
+  [22]=>
+  string(62) "struct DroitCreationResponse {
+ boolean DroitCreationResult;
+}"
+  [23]=>
+  string(74) "struct ListeDroitCreation {
+ ArrayOfString iListeObjet;
+ string iProfil;
+}"
+  [24]=>
+  string(40) "struct ArrayOfString {
+ string string;
+}"
+  [25]=>
+  string(79) "struct ListeDroitCreationResponse {
+ ArrayOfAnyType ListeDroitCreationResult;
+}"
+  [26]=>
+  string(87) "struct GetDroitsObjetProtege {
+ string iObjet;
+ string iProfil;
+ string iUtilisateur;
+}"
+  [27]=>
+  string(154) "struct MGDroitsObjetProtege {
+ string LbUti;
+ string LbProf;
+ string LbServ;
+ string LbDir;
+ boolean isProtected;
+ ArrayOfMGDroitAcces ListeDroitsAcces;
+}"
+  [28]=>
+  string(58) "struct ArrayOfMGDroitAcces {
+ MGDroitAcces MGDroitAcces;
+}"
+  [29]=>
+  string(104) "struct MGDroitAcces {
+ string IdProfil;
+ boolean Lecture;
+ boolean Modification;
+ boolean Suppression;
+}"
+  [30]=>
+  string(91) "struct GetDroitsObjetProtegeResponse {
+ MGDroitsObjetProtege GetDroitsObjetProtegeResult;
+}"
+  [31]=>
+  string(76) "struct GetPrivileges {
+ string iIdSupport;
+ int iIdForme;
+ string iProfil;
+}"
+  [32]=>
+  string(68) "struct GetPrivilegesResponse {
+ ArrayOfString GetPrivilegesResult;
+}"
+  [33]=>
+  string(46) "struct GetLibelleProfil {
+ string iIdProfil;
+}"
+  [34]=>
+  string(67) "struct GetLibelleProfilResponse {
+ string GetLibelleProfilResult;
+}"
+  [35]=>
+  string(91) "struct GetValeurRecherche {
+ string iChampSource;
+ string iTable;
+ string iOrderByClause;
+}"
+  [36]=>
+  string(78) "struct GetValeurRechercheResponse {
+ ArrayOfString GetValeurRechercheResult;
+}"
+  [37]=>
+  string(128) "struct GetValeurRechercheWithClauseWhere {
+ string iChampSource;
+ string iTable;
+ string iClauseWhere;
+ string iOrderByClause;
+}"
+  [38]=>
+  string(108) "struct GetValeurRechercheWithClauseWhereResponse {
+ ArrayOfString GetValeurRechercheWithClauseWhereResult;
+}"
+  [39]=>
+  string(27) "struct GetEnvironnement {
+}"
+  [40]=>
+  string(106) "struct MGEnvironnement {
+ string RepBureautique;
+ string RepBureautiqueImage;
+ string RepBureautiqueDoc;
+}"
+  [41]=>
+  string(76) "struct GetEnvironnementResponse {
+ MGEnvironnement GetEnvironnementResult;
+}"
+}
\ No newline at end of file
diff --git a/ext/soap/tests/bugs/bug28985.wsdl b/ext/soap/tests/bugs/bug28985.wsdl
new file mode 100644
index 000000000000..ee528818bbe2
--- /dev/null
+++ b/ext/soap/tests/bugs/bug28985.wsdl
@@ -0,0 +1,683 @@
+
+
+  
+    
+      
+        
+          
+            
+            
+            
+            
+          
+        
+      
+      
+        
+      
+      
+        
+      
+      
+        
+          
+            
+          
+        
+      
+      
+        
+          
+        
+      
+      
+        
+      
+      
+        
+      
+      
+        
+          
+            
+            
+          
+        
+      
+      
+        
+          
+          
+          
+          
+        
+      
+      
+        
+          
+        
+      
+      
+        
+          
+            
+          
+        
+      
+      
+        
+          
+            
+          
+        
+      
+      
+        
+          
+        
+      
+      
+        
+          
+        
+      
+      
+        
+          
+            
+          
+        
+      
+      
+        
+          
+            
+          
+        
+      
+      
+        
+          
+            
+          
+        
+      
+      
+        
+          
+            
+          
+        
+      
+      
+        
+          
+          
+          
+        
+      
+      
+        
+          
+        
+      
+      
+        
+          
+            
+          
+        
+      
+      
+        
+          
+            
+            
+          
+        
+      
+      
+        
+          
+            
+          
+        
+      
+      
+        
+          
+            
+            
+          
+        
+      
+      
+        
+          
+        
+      
+      
+        
+          
+            
+          
+        
+      
+      
+        
+          
+            
+            
+            
+          
+        
+      
+      
+        
+          
+          
+          
+          
+          
+          
+        
+      
+      
+        
+          
+        
+      
+      
+        
+          
+          
+          
+          
+        
+      
+      
+        
+          
+            
+          
+        
+      
+      
+        
+          
+            
+            
+            
+          
+        
+      
+      
+        
+          
+            
+          
+        
+      
+      
+        
+          
+            
+          
+        
+      
+      
+        
+          
+            
+          
+        
+      
+      
+        
+          
+            
+            
+            
+          
+        
+      
+      
+        
+          
+            
+          
+        
+      
+      
+        
+          
+            
+            
+            
+            
+          
+        
+      
+      
+        
+          
+            
+          
+        
+      
+      
+        
+      
+      
+        
+          
+          
+          
+        
+      
+      
+        
+          
+            
+          
+        
+      
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+      
+      
+    
+    
+      
+      
+    
+    
+      
+      
+    
+    
+      
+      
+    
+    
+      
+      
+    
+    
+      
+      
+    
+    
+      
+      
+    
+    
+      
+      
+    
+    
+      
+      
+    
+    
+      
+      
+    
+    
+      
+      
+    
+    
+      
+      
+    
+    
+      
+      
+    
+    
+      
+      
+    
+    
+      
+      
+    
+  
+  
+    
+    
+      
+      
+        
+      
+      
+        
+      
+    
+    
+      
+      
+        
+      
+      
+        
+      
+    
+    
+      
+      
+        
+      
+      
+        
+      
+    
+    
+      
+      
+        
+      
+      
+        
+      
+    
+    
+      
+      
+        
+      
+      
+        
+      
+    
+    
+      
+      
+        
+      
+      
+        
+      
+    
+    
+      
+      
+        
+      
+      
+        
+      
+    
+    
+      
+      
+        
+      
+      
+        
+      
+    
+    
+      
+      
+        
+      
+      
+        
+      
+    
+    
+      
+      
+        
+      
+      
+        
+      
+    
+    
+      
+      
+        
+      
+      
+        
+      
+    
+    
+      
+      
+        
+      
+      
+        
+      
+    
+    
+      
+      
+        
+      
+      
+        
+      
+    
+    
+      
+      
+        
+      
+      
+        
+      
+    
+    
+      
+      
+        
+      
+      
+        
+      
+    
+  
+  
+    
+      
+    
+  
+
diff --git a/ext/soap/tests/bugs/bug29061.phpt b/ext/soap/tests/bugs/bug29061.phpt
new file mode 100644
index 000000000000..0bf8917fa595
--- /dev/null
+++ b/ext/soap/tests/bugs/bug29061.phpt
@@ -0,0 +1,12 @@
+--TEST--
+Bug #29061 (soap extension segfaults)
+--SKIPIF--
+
+--FILE--
+0)); 
+$client->getQuote("ibm"); 
+echo "ok\n";
+?>
+--EXPECT--
+ok
\ No newline at end of file
diff --git a/ext/soap/tests/bugs/bug29061.wsdl b/ext/soap/tests/bugs/bug29061.wsdl
new file mode 100644
index 000000000000..fb4d9aa3b5a4
--- /dev/null
+++ b/ext/soap/tests/bugs/bug29061.wsdl
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ext/soap/tests/bugs/bug29109.phpt b/ext/soap/tests/bugs/bug29109.phpt
new file mode 100644
index 000000000000..91d3ea265fe9
--- /dev/null
+++ b/ext/soap/tests/bugs/bug29109.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Bug #29109 (Uncaught SoapFault exception: [WSDL] Out of memory)
+--SKIPIF--
+
+--FILE--
+__getFunctions()); 
+?>
+--EXPECT--
+array(3) {
+  [0]=>
+  string(53) "HelloWorldResponse HelloWorld(HelloWorld $parameters)"
+  [1]=>
+  string(19) "string HelloWorld()"
+  [2]=>
+  string(19) "string HelloWorld()"
+}
\ No newline at end of file
diff --git a/ext/soap/tests/bugs/bug29109.wsdl b/ext/soap/tests/bugs/bug29109.wsdl
new file mode 100644
index 000000000000..800cd2357dbf
--- /dev/null
+++ b/ext/soap/tests/bugs/bug29109.wsdl
@@ -0,0 +1,121 @@
+
+
+  
+    
+      
+        
+      
+      
+        
+          
+
+            
+          
+        
+      
+      
+    
+  
+  
+    
+
+  
+  
+    
+  
+  
+  
+    
+  
+  
+
+  
+    
+  
+  
+    
+      
+      
+    
+  
+
+  
+    
+      
+      
+    
+  
+  
+    
+      
+
+      
+    
+  
+  
+    
+    
+      
+      
+        
+
+      
+      
+        
+      
+    
+  
+  
+    
+    
+
+      
+      
+        
+      
+      
+        
+      
+    
+  
+
+  
+    
+    
+      
+      
+        
+      
+      
+        
+
+      
+    
+  
+  
+    
+      
+    
+    
+      
+
+    
+    
+      
+    
+  
+
diff --git a/ext/soap/tests/bugs/bug29236.phpt b/ext/soap/tests/bugs/bug29236.phpt
new file mode 100644
index 000000000000..4dbc302c171c
--- /dev/null
+++ b/ext/soap/tests/bugs/bug29236.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Bug #29236 (memory error when wsdl-cache is enabled)
+--SKIPIF--
+
+--FILE--
+__getFunctions()); 
+?>
+--EXPECT--
+array(4) {
+  [0]=>
+  string(59) "StartSessionResponse StartSession(StartSession $parameters)"
+  [1]=>
+  string(62) "VerifySessionResponse VerifySession(VerifySession $parameters)"
+  [2]=>
+  string(41) "LogoutResponse Logout(Logout $parameters)"
+  [3]=>
+  string(62) "GetSystemInfoResponse GetSystemInfo(GetSystemInfo $parameters)"
+}
diff --git a/ext/soap/tests/bugs/bug29236.wsdl b/ext/soap/tests/bugs/bug29236.wsdl
new file mode 100644
index 000000000000..d60a4871d428
--- /dev/null
+++ b/ext/soap/tests/bugs/bug29236.wsdl
@@ -0,0 +1,287 @@
+
+
+  
+    
+      
+        
+          
+            
+            
+          
+        
+      
+      
+        
+          
+            
+          
+        
+      
+      
+        
+          
+          
+        
+        
+        
+        
+      
+      
+        
+          
+          
+          
+          
+        
+        
+      
+      
+        
+          
+        
+      
+      
+        
+        
+      
+      
+        
+          
+        
+      
+      
+        
+        
+        
+      
+      
+        
+          
+          
+          
+          
+          
+          
+        
+      
+      
+        
+          
+          
+          
+          
+          
+          
+          
+          
+          
+        
+      
+      
+        
+          
+          
+          
+          
+          
+        
+      
+      
+        
+          
+        
+        
+      
+      
+        
+          
+        
+      
+      
+        
+        
+      
+      
+        
+          
+          
+          
+          
+        
+      
+      
+      
+        
+          
+          
+        
+      
+      
+        
+          
+            
+            
+            
+          
+        
+      
+      
+        
+          
+            
+          
+        
+      
+      
+        
+          
+            
+            
+          
+        
+      
+      
+        
+          
+            
+          
+        
+      
+      
+        
+      
+      
+        
+          
+            
+          
+        
+      
+      
+        
+          
+        
+      
+      
+        
+        
+      
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+      
+      
+    
+    
+      
+      
+    
+    
+      
+      
+    
+    
+      
+      
+    
+  
+  
+  
+  
+    
+    
+      
+      
+        
+        
+      
+      
+        
+      
+    
+    
+      
+      
+        
+        
+      
+      
+        
+      
+    
+    
+      
+      
+        
+        
+      
+      
+        
+      
+    
+    
+      
+      
+        
+        
+      
+      
+        
+      
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+      
+    
+    
+      
+    
+    
+      
+    
+  
+
\ No newline at end of file
diff --git a/ext/soap/tests/bugs/bug29795.phpt b/ext/soap/tests/bugs/bug29795.phpt
new file mode 100644
index 000000000000..52f8862fda12
--- /dev/null
+++ b/ext/soap/tests/bugs/bug29795.phpt
@@ -0,0 +1,32 @@
+--TEST--
+Bug #29795 (SegFault with Soap and Amazon's Web Services)
+--SKIPIF--
+
+--FILE--
+3995USD
+EOF;
+  }
+
+}
+
+$client = new LocalSoapClient(dirname(__FILE__)."/bug29795.wsdl",array("trace"=>1));
+$ar=$client->GetPrice();
+echo "o";
+$client = new LocalSoapClient(dirname(__FILE__)."/bug29795.wsdl",array("trace"=>1));
+$ar=$client->GetPrice();
+echo "k\n";
+?>
+--EXPECT--
+ok
diff --git a/ext/soap/tests/bugs/bug29795.wsdl b/ext/soap/tests/bugs/bug29795.wsdl
new file mode 100644
index 000000000000..5a4499da0d7c
--- /dev/null
+++ b/ext/soap/tests/bugs/bug29795.wsdl
@@ -0,0 +1,40 @@
+
+	
+		
+			
+				
+					
+					
+				
+			
+		
+	
+	
+	
+	
+		
+	
+	
+		
+			
+			
+		
+	
+	
+		
+		
+			
+			
+				
+			
+			
+				
+			
+		
+	
+	
+		
+			
+		
+	
+
diff --git a/ext/soap/tests/bugs/bug29830.phpt b/ext/soap/tests/bugs/bug29830.phpt
new file mode 100644
index 000000000000..dc090f82cc15
--- /dev/null
+++ b/ext/soap/tests/bugs/bug29830.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Bug #29844 (SoapServer::setClass() should not export non-public methods)
+--SKIPIF--
+
+--FILE--
+"test://"));
+$server->setClass('hello_world');
+$functions = $server->getFunctions();
+foreach($functions as $func) {
+  echo $func . "\n";
+}
+?>
+--EXPECT--
+hello
diff --git a/ext/soap/tests/bugs/bug29839.phpt b/ext/soap/tests/bugs/bug29839.phpt
new file mode 100644
index 000000000000..25b4512a72c2
--- /dev/null
+++ b/ext/soap/tests/bugs/bug29839.phpt
@@ -0,0 +1,41 @@
+--TEST--
+Bug #29839 incorrect convert (xml:lang to lang)
+--SKIPIF--
+
+--FILE--
+server = new SoapServer($wsdl, $options);
+    $this->server->addFunction('EchoString');
+  }
+
+  function __doRequest($request, $location, $action, $version) {
+    ob_start();
+    $this->server->handle($request);
+    $response = ob_get_contents();
+    ob_end_clean();
+    return $response;
+  }
+
+}
+
+$client = new LocalSoapClient(dirname(__FILE__)."/bug29839.wsdl", array("trace"=>1)); 
+$client->EchoString(array("value"=>"hello","lang"=>"en"));
+echo $client->__getLastRequest();
+echo $client->__getLastResponse();
+echo "ok\n";
+?>
+--EXPECT--
+
+hello
+
+hello
+ok
\ No newline at end of file
diff --git a/ext/soap/tests/bugs/bug29839.wsdl b/ext/soap/tests/bugs/bug29839.wsdl
new file mode 100644
index 000000000000..d8ccb9795476
--- /dev/null
+++ b/ext/soap/tests/bugs/bug29839.wsdl
@@ -0,0 +1,42 @@
+
+	
+		
+			
+			
+				
+					
+				
+				
+			
+		
+	
+	
+		
+	
+	
+		
+	
+	
+		
+			
+			
+		
+	
+	
+		
+		
+			
+			
+				
+			
+			
+				
+			
+		
+	
+	
+		
+			
+		
+	
+
diff --git a/ext/soap/tests/bugs/bug29844.phpt b/ext/soap/tests/bugs/bug29844.phpt
new file mode 100644
index 000000000000..bef8335709f4
--- /dev/null
+++ b/ext/soap/tests/bugs/bug29844.phpt
@@ -0,0 +1,36 @@
+--TEST--
+Bug #29844 (SOAP doesn't return the result of a valid SOAP request)
+--SKIPIF--
+
+--FILE--
+server = new SoapServer($wsdl, $options);
+    $this->server->setClass('hello_world');;
+  }
+
+  function __doRequest($request, $location, $action, $version) {
+    ob_start();
+    $this->server->handle($request);
+    $response = ob_get_contents();
+    ob_end_clean();
+    return $response;
+  }
+
+}
+
+$client = new LocalSoapClient(dirname(__FILE__)."/bug29844.wsdl", array("trace"=>1)); 
+var_dump($client->hello('davey'));
+?>
+--EXPECT--
+string(11) "Hello davey"
diff --git a/ext/soap/tests/bugs/bug29844.wsdl b/ext/soap/tests/bugs/bug29844.wsdl
new file mode 100644
index 000000000000..b45aa3666f9b
--- /dev/null
+++ b/ext/soap/tests/bugs/bug29844.wsdl
@@ -0,0 +1,66 @@
+
+
+  
+    
+      
+      
+      Say Hello to Somebody
+    
+    
+      
+      
+      Say Goodbye to Somebody
+    
+  
+  
+    
+    
+      
+        
+      
+      
+        
+      
+      
+    
+    
+    
+      
+        
+      
+      
+        
+      
+      
+    
+  
+  
+    
+      
+    
+  
+  
+    
+    Say Hello to Somebody
+  
+  
+    
+    The greeting
+  
+  
+    
+    Say Goodbye to Somebody
+  
+  
+    
+    The goodbye
+  
+
diff --git a/ext/soap/tests/bugs/bug30045.phpt b/ext/soap/tests/bugs/bug30045.phpt
new file mode 100644
index 000000000000..753faf17554e
--- /dev/null
+++ b/ext/soap/tests/bugs/bug30045.phpt
@@ -0,0 +1,171 @@
+--TEST--
+Bug #30045 (Cannot pass big integers (> 2147483647) in SOAP requests)
+--SKIPIF--
+
+--FILE--
+server = new SoapServer($wsdl, $options);
+    $this->server->addFunction('foo');
+  }
+
+  function __doRequest($request, $location, $action, $version) {
+    $xml = simplexml_load_string($request);
+    echo $xml->children("http://schemas.xmlsoap.org/soap/envelope/")->Body->children("http://test-uri")->children()->param1->asXML(),"\n";
+    unset($xml);
+
+    ob_start();
+    $this->server->handle($request);
+    $response = ob_get_contents();
+    ob_end_clean();
+
+    return $response;
+  }
+
+}
+
+$soap = new LocalSoapClient(NULL, array("uri"=>"http://test-uri", "location"=>"test://"));
+
+function test($type, $num) {
+  global $soap;
+  try {
+	  printf("  %0.0f\n    ", $num);  	
+	  $ret = $soap->foo($type, new SoapVar($num, $type));
+	  printf("    %0.0f\n", $num, $ret);
+	} catch (SoapFault $ex) {
+	  var_dump($ex);
+	}
+}
+/*
+echo "byte\n";
+//test(XSD_BYTE, -129);
+test(XSD_BYTE, -128);
+test(XSD_BYTE,  127);
+//test(XSD_BYTE,  128);
+
+echo "\nshort\n";
+//test(XSD_SHORT, -32769);
+test(XSD_SHORT, -32768);
+test(XSD_SHORT,  32767);
+//test(XSD_SHORT,  32768);
+
+echo "\nint\n";
+//test(XSD_INT, -2147483649);
+test(XSD_INT, -2147483648);
+test(XSD_INT,  2147483647);
+//test(XSD_INT,  2147483648);
+
+echo "\nlong\n";
+//test(XSD_LONG, -9223372036854775809);
+test(XSD_LONG, -9223372036854775808);
+test(XSD_LONG,  9223372036854775807);
+//test(XSD_LONG,  9223372036854775808);
+
+echo "\nunsignedByte\n";
+//test(XSD_UNSIGNEDBYTE, -1);
+test(XSD_UNSIGNEDBYTE,  0);
+test(XSD_UNSIGNEDBYTE,  255);
+//test(XSD_UNSIGNEDBYTE,  256);
+
+echo "\nunsignedShort\n";
+//test(XSD_UNSIGNEDSHORT, -1);
+test(XSD_UNSIGNEDSHORT,  0);
+test(XSD_UNSIGNEDSHORT,  65535);
+//test(XSD_UNSIGNEDSHORT,  65536);
+
+echo "\nunsignedInt\n";
+//test(XSD_UNSIGNEDINT, -1);
+test(XSD_UNSIGNEDINT,  0);
+test(XSD_UNSIGNEDINT,  4294967295);
+//test(XSD_UNSIGNEDINT,  4294967296);
+
+echo "\nunsignedLong\n";
+//test(XSD_UNSIGNEDLONG, -1);
+test(XSD_UNSIGNEDLONG,  0);
+test(XSD_UNSIGNEDLONG,  18446744073709551615);
+//test(XSD_UNSIGNEDLONG,  18446744073709551616);
+
+echo "\nnegativeInteger\n";
+test(XSD_NEGATIVEINTEGER, -18446744073709551616);
+test(XSD_NEGATIVEINTEGER, -1);
+//test(XSD_NEGATIVEINTEGER,  0);
+
+echo "\nnonPositiveInteger\n";
+test(XSD_NONPOSITIVEINTEGER, -18446744073709551616);
+test(XSD_NONPOSITIVEINTEGER,  0);
+//test(XSD_NONPOSITIVEINTEGER,  1);
+
+echo "\nnonNegativeInteger\n";
+//test(XSD_NONNEGATIVEINTEGER, -1);
+test(XSD_NONNEGATIVEINTEGER,  0);
+test(XSD_NONNEGATIVEINTEGER,  18446744073709551616);
+
+echo "\nPositiveInteger\n";
+//test(XSD_POSITIVEINTEGER,  0);
+test(XSD_POSITIVEINTEGER,  1);
+test(XSD_POSITIVEINTEGER,  18446744073709551616);
+
+echo "\ninteger\n";
+test(XSD_INTEGER, -18446744073709551616);
+test(XSD_INTEGER,  18446744073709551616);
+*/
+echo "long\n";
+test(XSD_LONG, 2147483647);
+test(XSD_LONG, 2147483648);
+test(XSD_LONG,  4294967296);
+test(XSD_LONG,  8589934592);
+test(XSD_LONG, 17179869184); 
+
+echo "\nunsignedLong\n";
+test(XSD_UNSIGNEDLONG,  2147483647);
+test(XSD_UNSIGNEDLONG,  2147483648);
+test(XSD_UNSIGNEDLONG,  4294967296);
+test(XSD_UNSIGNEDLONG,  8589934592);
+test(XSD_UNSIGNEDLONG, 17179869184);
+
+?>
+--EXPECT--
+long
+  2147483647
+    2147483647
+    2147483647
+  2147483648
+    2147483648
+    2147483648
+  4294967296
+    4294967296
+    4294967296
+  8589934592
+    8589934592
+    8589934592
+  17179869184
+    17179869184
+    17179869184
+
+unsignedLong
+  2147483647
+    2147483647
+    2147483647
+  2147483648
+    2147483648
+    2147483648
+  4294967296
+    4294967296
+    4294967296
+  8589934592
+    8589934592
+    8589934592
+  17179869184
+    17179869184
+    17179869184
diff --git a/ext/soap/tests/bugs/bug30106.phpt b/ext/soap/tests/bugs/bug30106.phpt
new file mode 100644
index 000000000000..dbc44f6f0d4b
--- /dev/null
+++ b/ext/soap/tests/bugs/bug30106.phpt
@@ -0,0 +1,72 @@
+--TEST--
+Bug #30106 SOAP cannot not parse 'ref' element. Causes Uncaught SoapFault exception.
+--SKIPIF--
+
+--FILE--
+array(
+	  "schema"=>"",
+	  "any"=>"Hello World!Bye World!"));
+}
+
+class LocalSoapClient extends SoapClient {
+  function __construct($wsdl, $options=array()) {
+    parent::__construct($wsdl, $options);
+    $this->server = new SoapServer($wsdl, $options);
+		$this->server->addFunction("getContinentList"); 
+  }
+
+  function __doRequest($request, $location, $action, $version) {
+  	echo $request;
+    ob_start();
+    $this->server->handle($request);
+    $response = ob_get_contents();
+    ob_end_clean();
+  	echo $response;
+    return $response;
+  }
+}
+
+$client = new LocalSoapClient(dirname(__FILE__)."/bug30106.wsdl");
+var_dump($client->__getFunctions());
+var_dump($client->__getTypes());
+$x = $client->getContinentList(array("AFFILIATE_ID"=>1,"PASSWORD"=>"x"));
+var_dump($x);
+?>
+--EXPECTF--
+array(1) {
+  [0]=>
+  string(71) "getContinentListResponse getContinentList(getContinentList $parameters)"
+}
+array(3) {
+  [0]=>
+  string(64) "struct getContinentList {
+ int AFFILIATE_ID;
+ string PASSWORD;
+}"
+  [1]=>
+  string(83) "struct getContinentListResponse {
+ getContinentListResult getContinentListResult;
+}"
+  [2]=>
+  string(66) "struct getContinentListResult {
+  schema;
+  any;
+}"
+}
+
+1x
+
+Hello World!Bye World!
+object(stdClass)#%d (1) {
+  ["getContinentListResult"]=>
+  object(stdClass)#%d (2) {
+    ["schema"]=>
+    string(65) ""
+    ["any"]=>
+    string(48) "Hello World!Bye World!"
+  }
+}
diff --git a/ext/soap/tests/bugs/bug30106.wsdl b/ext/soap/tests/bugs/bug30106.wsdl
new file mode 100644
index 000000000000..db1922da339d
--- /dev/null
+++ b/ext/soap/tests/bugs/bug30106.wsdl
@@ -0,0 +1,59 @@
+
+
+  
+    
+      
+      
+        
+          
+            
+            
+          
+        
+      
+      
+        
+          
+            
+              
+                
+                  
+                  
+                
+              
+            
+          
+        
+      
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+      
+      
+    
+  
+  
+    
+    
+      
+      
+        
+      
+      
+        
+      
+    
+  
+  
+    
+      
+    
+  
+
\ No newline at end of file
diff --git a/ext/soap/tests/bugs/bug30175.phpt b/ext/soap/tests/bugs/bug30175.phpt
new file mode 100644
index 000000000000..f5501ac9bdce
--- /dev/null
+++ b/ext/soap/tests/bugs/bug30175.phpt
@@ -0,0 +1,47 @@
+--TEST--
+Bug #30175 (SOAP results aren't parsed correctly)
+--SKIPIF--
+
+--INI--
+soap.wsdl_cache_enabled=0
+--FILE--
+
+
+
+
+blah blah some name field
+This is a description. more blah blah blah
+127.0.0.1
+
+
+
+EOF;
+  }
+
+}
+
+$client = new LocalSoapClient(dirname(__FILE__)."/bug30175.wsdl");
+var_dump($client->qwebGetHostInfo());
+?>
+--EXPECT--
+array(3) {
+  ["name"]=>
+  string(25) "blah blah some name field"
+  ["shortDescription"]=>
+  string(42) "This is a description. more blah blah blah"
+  ["ipAddress"]=>
+  string(9) "127.0.0.1"
+}
diff --git a/ext/soap/tests/bugs/bug30175.wsdl b/ext/soap/tests/bugs/bug30175.wsdl
new file mode 100644
index 000000000000..f4cae2554e41
--- /dev/null
+++ b/ext/soap/tests/bugs/bug30175.wsdl
@@ -0,0 +1,126 @@
+
+
+
+
+
+ 
+  
+  
+   
+    
+   
+  
+  
+   
+    
+     
+      
+     
+     
+    
+   
+  
+ 
+
+
+
+
+ 
+
+
+
+ 
+
+
+
+ 
+
+
+
+ 
+
+
+
+
+
+
+ 
+ 
+ 
+
+
+
+ 
+  Service definition of function ns1__qwebSquare
+  
+  
+ 
+ 
+  Service definition of function ns1__qwebStrlen
+  
+  
+ 
+ 
+  Service definition of function ns1__qwebGetHostInfo
+  
+  
+ 
+
+
+
+ 
+ 
+  
+  
+   
+  
+  
+   
+  
+ 
+ 
+  
+  
+   
+  
+  
+   
+  
+ 
+ 
+  
+  
+   
+  
+  
+   
+  
+ 
+
+
+
+ Demo Qweb SOAP interface
+ 
+  
+ 
+
+
+
diff --git a/ext/soap/tests/bugs/bug30799.phpt b/ext/soap/tests/bugs/bug30799.phpt
new file mode 100644
index 000000000000..9fa0b12f0ecb
--- /dev/null
+++ b/ext/soap/tests/bugs/bug30799.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Bug #30799 SoapServer doesn't handle private or protected properties 
+--SKIPIF--
+
+--FILE--
+"test://",
+                               "uri" => "test://",
+                               "exceptions" => 0,
+                               "trace" => 1 ));
+$x->test(new foo());
+echo $x->__getLastRequest();
+echo "ok\n";
+?>
+--EXPECT--
+
+abc
+ok
diff --git a/ext/soap/tests/bugs/bug30928.phpt b/ext/soap/tests/bugs/bug30928.phpt
new file mode 100644
index 000000000000..c7b497c0ed33
--- /dev/null
+++ b/ext/soap/tests/bugs/bug30928.phpt
@@ -0,0 +1,63 @@
+--TEST--
+Bug #30928 When Using WSDL, SoapServer doesn't handle private or protected properties 
+--SKIPIF--
+
+--FILE--
+server = new SoapServer($wsdl, $options);
+    $this->server->addFunction('test');
+  }
+
+  function __doRequest($request, $location, $action, $version) {
+    ob_start();
+    $this->server->handle($request);
+    $response = ob_get_contents();
+    ob_end_clean();
+    return $response;
+  }
+}
+
+$x = new LocalSoapClient(dirname(__FILE__)."/bug30928.wsdl", 
+                         array());
+var_dump($x->test(new foo()));
+
+$x = new LocalSoapClient(dirname(__FILE__)."/bug30928.wsdl", 
+                         array("classmap" => array('testType'=>'foo')));
+var_dump($x->test(new foo()));
+
+echo "ok\n";
+?>
+--EXPECTF--
+object(stdClass)#%d (3) {
+  ["a"]=>
+  string(1) "a"
+  ["b"]=>
+  string(1) "b"
+  ["c"]=>
+  string(1) "c"
+}
+object(foo)#%d (3) {
+  ["a"]=>
+  string(1) "a"
+  ["b:private"]=>
+  string(1) "b"
+  ["c:protected"]=>
+  string(1) "c"
+}
+ok
diff --git a/ext/soap/tests/bugs/bug30928.wsdl b/ext/soap/tests/bugs/bug30928.wsdl
new file mode 100644
index 000000000000..7ed34d31a211
--- /dev/null
+++ b/ext/soap/tests/bugs/bug30928.wsdl
@@ -0,0 +1,49 @@
+
+
+  
+  
+   
+   
+	 
+		
+			
+			
+		
+		
+	 
+  
+  
+  
+  	
+  
+	
+		
+			
+			
+		
+	
+	
+		
+		
+			
+			
+				
+			
+			
+				
+			
+		
+	
+	
+   
+      
+   
+ 
+
diff --git a/ext/soap/tests/bugs/bug30994.phpt b/ext/soap/tests/bugs/bug30994.phpt
new file mode 100644
index 000000000000..7e811bbbf9fd
--- /dev/null
+++ b/ext/soap/tests/bugs/bug30994.phpt
@@ -0,0 +1,47 @@
+--TEST--
+Bug #30994 SOAP server unable to handle request with references 
+--SKIPIF--
+
+--FILE--
+
+
+
+
+	
+		XXX
+		TASKTEST
+		
+	
+	
+	
+		
+	
+	
+	
+		ABCabc123
+		123456
+	
+	
+
+
+EOF;
+
+function bassCall() {
+  return "ok";
+}
+
+$x = new SoapServer(NULL, array("uri"=>"http://spock/kunta/kunta"));
+$x->addFunction("bassCall");
+$x->handle();
+?>
+--EXPECT--
+
+ok
diff --git a/ext/soap/tests/bugs/bug31422.phpt b/ext/soap/tests/bugs/bug31422.phpt
new file mode 100644
index 000000000000..fbad1cbd98d3
--- /dev/null
+++ b/ext/soap/tests/bugs/bug31422.phpt
@@ -0,0 +1,42 @@
+--TEST--
+Bug #31422 No Error-Logging on SoapServer-Side
+--SKIPIF--
+
+--INI--
+log_errors=1
+--FILE--
+"http://testuri.org"));
+$server->addfunction("Add");
+
+$HTTP_RAW_POST_DATA = <<
+
+  
+    
+      22
+      33
+    
+  
+
+EOF;
+
+$server->handle();
+echo "ok\n";
+?>
+--EXPECTF--
+PHP Warning:  fopen() expects at least 2 parameters, 0 given in %sbug31422.php on line %d
+PHP Fatal error:  Hello in %sbug31422.php on line %d
+
+SOAP-ENV:ServerHello
diff --git a/ext/soap/tests/bugs/bug31695.phpt b/ext/soap/tests/bugs/bug31695.phpt
new file mode 100644
index 000000000000..770f5b4b6d58
--- /dev/null
+++ b/ext/soap/tests/bugs/bug31695.phpt
@@ -0,0 +1,62 @@
+--TEST--
+Bug #31695 Cannot redefine endpoint when using WSDL
+--SKIPIF--
+
+--FILE--
+server = new SoapServer($wsdl, $options);
+		$this->server->addFunction("Test"); 
+  }
+
+  function __doRequest($request, $location, $action, $version) {
+  	echo "$location\n";
+    ob_start();
+    $this->server->handle($request);
+    $response = ob_get_contents();
+    ob_end_clean();
+    return $response;
+  }
+}
+
+$client = new LocalSoapClient(dirname(__FILE__)."/bug31695.wsdl");
+$client->Test("str");
+$client = new LocalSoapClient(dirname(__FILE__)."/bug31695.wsdl", array("location"=>"test://1"));
+$client->Test("str");
+$client->__soapCall("Test", 
+                    array("arg1"),
+                     array("location"=>"test://2"));
+$old = $client->__setLocation("test://3");
+echo "$old\n";
+$client->Test("str");
+$client->Test("str");
+$client->__setLocation($old);
+$client->Test("str");
+$old = $client->__setLocation();
+$client->Test("str");
+$client->__setLocation($old);
+$client->Test("str");
+$client->__setLocation(null);
+$client->Test("str");
+var_dump($client->__setLocation());
+?>
+--EXPECT--
+test://0
+test://1
+test://2
+test://1
+test://3
+test://3
+test://1
+test://0
+test://1
+test://0
+NULL
diff --git a/ext/soap/tests/bugs/bug31695.wsdl b/ext/soap/tests/bugs/bug31695.wsdl
new file mode 100644
index 000000000000..5785cb07702a
--- /dev/null
+++ b/ext/soap/tests/bugs/bug31695.wsdl
@@ -0,0 +1,47 @@
+
+
+
+  
+    
+  
+  
+    
+  
+
+  
+    
+      
+      
+    
+  
+
+  
+    
+    
+      
+      
+        
+      
+      
+        
+      
+    
+  
+
+  
+    
+      
+    
+  
+
+
diff --git a/ext/soap/tests/bugs/bug31755.phpt b/ext/soap/tests/bugs/bug31755.phpt
new file mode 100644
index 000000000000..e93e17daa67c
--- /dev/null
+++ b/ext/soap/tests/bugs/bug31755.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Bug #31422 No Error-Logging on SoapServer-Side
+--SKIPIF--
+
+--FILE--
+ 'http://localhost',
+'uri' => 'myNS', 'exceptions' => false, 'trace' => true));
+
+$header = new SOAPHeader(null, 'foo', 'bar');
+
+$response= $client->__call('function', array(), null, $header);
+
+print $client->__getLastRequest();
+?>
+--EXPECTF--
+Fatal error: SoapHeader::__construct(): Invalid parameters. Invalid namespace. in %sbug31755.php on line %d
diff --git a/ext/soap/tests/bugs/bug32776.phpt b/ext/soap/tests/bugs/bug32776.phpt
new file mode 100644
index 000000000000..b3c4ff0170f0
--- /dev/null
+++ b/ext/soap/tests/bugs/bug32776.phpt
@@ -0,0 +1,47 @@
+--TEST--
+Bug #32776 SOAP doesn't support one-way operations
+--SKIPIF--
+
+--FILE--
+server = new SoapServer($wsdl, $options);
+    $this->server->addFunction('test');
+  }
+
+  function __doRequest($request, $location, $action, $version) {
+    ob_start();
+    $this->server->handle($request);
+    $response = ob_get_contents();
+    ob_end_clean();
+    return $response;
+  }
+
+}
+
+$x = new LocalSoapClient(dirname(__FILE__)."/bug32776.wsdl",array("trace"=>true,"exceptions"=>false)); 
+var_dump($x->test("Hello"));
+var_dump($d);
+var_dump($x->__getLastRequest());
+var_dump($x->__getLastResponse());
+echo "ok\n";
+?>
+--EXPECT--
+NULL
+string(5) "Hello"
+string(459) "
+Hello
+"
+string(0) ""
+ok
diff --git a/ext/soap/tests/bugs/bug32776.wsdl b/ext/soap/tests/bugs/bug32776.wsdl
new file mode 100644
index 000000000000..733901849e0d
--- /dev/null
+++ b/ext/soap/tests/bugs/bug32776.wsdl
@@ -0,0 +1,47 @@
+
+
+
+  
+    
+      
+      
+    
+  
+
+  
+    
+  
+
+  
+    
+      
+    
+  
+
+  
+    
+    
+      
+      
+        
+      
+    
+  
+
+  
+    
+      
+    
+  
+
+
diff --git a/ext/soap/tests/bugs/bug32941.phpt b/ext/soap/tests/bugs/bug32941.phpt
new file mode 100755
index 000000000000..5fd17df18e06
--- /dev/null
+++ b/ext/soap/tests/bugs/bug32941.phpt
@@ -0,0 +1,41 @@
+--TEST--
+Bug #32941 (Sending structured exception kills a php)
+--SKIPIF--
+
+--FILE--
+
+
+	
+		
+			soapenv:Server.userException
+			service.EchoServiceException
+			
+				
+					105
+					string param
+				
+				steckovic
+			
+		
+	
+
+EOF;
+	}
+}
+
+ini_set("soap.wsdl_cache_enabled", 1);
+$client = new TestSoapClient(dirname(__FILE__).'/bug32941.wsdl', array("trace" => 1, 'exceptions' => 0));
+$ahoj = $client->echoString('exception');
+$client = new TestSoapClient(dirname(__FILE__).'/bug32941.wsdl', array("trace" => 1, 'exceptions' => 0));
+$ahoj = $client->echoString('exception');
+echo "ok\n";
+?>
+--EXPECT--
+ok
diff --git a/ext/soap/tests/bugs/bug32941.wsdl b/ext/soap/tests/bugs/bug32941.wsdl
new file mode 100755
index 000000000000..61fd13dcbc8b
--- /dev/null
+++ b/ext/soap/tests/bugs/bug32941.wsdl
@@ -0,0 +1,141 @@
+
+
+
+ 
+  
+   
+   
+    
+     
+     
+    
+   
+   
+    
+     
+     
+    
+   
+  
+ 
+
+   
+
+      
+
+   
+
+   
+
+      
+
+   
+
+   
+
+      
+
+   
+
+   
+
+      
+
+   
+
+   
+
+      
+
+   
+
+   
+
+      
+
+         
+
+         
+
+         
+
+      
+
+      
+
+         
+
+         
+
+         
+
+      
+
+   
+
+   
+
+      
+
+      
+
+         
+
+         
+
+            
+
+         
+
+         
+
+            
+
+         
+
+         
+
+            
+
+         
+
+      
+
+      
+
+         
+
+         
+
+            
+
+         
+
+         
+
+            
+
+         
+
+         
+
+            
+
+         
+
+      
+
+   
+
+   
+
+      
+
+         
+
+      
+
+   
+
+
diff --git a/ext/soap/tests/bugs/xml.xsd b/ext/soap/tests/bugs/xml.xsd
new file mode 100644
index 000000000000..abb844ac1201
--- /dev/null
+++ b/ext/soap/tests/bugs/xml.xsd
@@ -0,0 +1,34 @@
+
+
+
+
+ 
+  
+   In due course, we should install the relevant ISO 2- and 3-letter
+         codes as the enumerated possible values . . .
+  
+ 
+
+ 
+  
+   
+    
+    
+   
+  
+ 
+
+ 
+  
+   See http://www.w3.org/TR/xmlbase/ for
+                     information about this attribute.
+  
+ 
+
+ 
+  
+  
+  
+ 
+
+
diff --git a/ext/soap/tests/classmap.wsdl b/ext/soap/tests/classmap.wsdl
new file mode 100644
index 000000000000..7fcf596244fe
--- /dev/null
+++ b/ext/soap/tests/classmap.wsdl
@@ -0,0 +1,60 @@
+
+	
+		
+			
+				
+					
+					
+				
+			
+  
+	
+	
+		
+  
+	
+		
+  
+	
+		
+  
+	
+		
+  
+	
+		
+			
+			
+		
+		
+			
+			
+		
+	
+	
+		
+		
+			
+			
+				
+			
+			
+				
+			
+		
+		
+			
+			
+				
+			
+			
+				
+			
+		
+	
+	
+		
+			
+		
+	
+
diff --git a/ext/soap/tests/classmap001.phpt b/ext/soap/tests/classmap001.phpt
new file mode 100644
index 000000000000..1908ddd1ec33
--- /dev/null
+++ b/ext/soap/tests/classmap001.phpt
@@ -0,0 +1,50 @@
+--TEST--
+SOAP Classmap 1: SoapServer support for classmap
+--SKIPIF--
+
+--FILE--
+
+  
+ 
+  
+    Blaat
+    aap
+
+
+ 
+
+";	
+
+class test{
+	function dotest(book $book){
+		$classname=get_class($book);
+		return "Classname: ".$classname;
+	}	
+}
+
+class book{
+	public $a="a";
+	public $b="c";
+		
+}
+$options=Array(
+		'actor' =>'http://schema.nothing.com',
+		'classmap' => array('book'=>'book', 'wsdltype2'=>'classname2')
+		);
+
+$server = new SoapServer(dirname(__FILE__)."/classmap.wsdl",$options);
+$server->setClass("test");
+$server->handle();
+echo "ok\n";
+?>
+--EXPECT--
+
+Classname: book
+ok
diff --git a/ext/soap/tests/classmap002.phpt b/ext/soap/tests/classmap002.phpt
new file mode 100644
index 000000000000..e6f5af9913db
--- /dev/null
+++ b/ext/soap/tests/classmap002.phpt
@@ -0,0 +1,44 @@
+--TEST--
+SOAP Classmap 2: SoapClient support for classmap
+--SKIPIF--
+
+--FILE--
+
+
+
+  Blaat
+  aap
+
+
+EOF;
+	}	
+}
+
+class book{
+	public $a="a";
+	public $b="c";
+		
+}
+
+$options=Array(
+		'actor' =>'http://schema.nothing.com',
+		'classmap' => array('book'=>'book', 'wsdltype2'=>'classname2')
+		);
+
+$client = new TestSoapClient(dirname(__FILE__)."/classmap.wsdl",$options);
+$ret = $client->dotest2("???");
+var_dump($ret);
+echo "ok\n";
+?>
+--EXPECT--
+object(book)#2 (2) {
+  ["a"]=>
+  string(5) "Blaat"
+  ["b"]=>
+  string(3) "aap"
+}
+ok
diff --git a/ext/soap/tests/schema/schema030.phpt b/ext/soap/tests/schema/schema030.phpt
index f6e62d4106d6..e46861391614 100644
--- a/ext/soap/tests/schema/schema030.phpt
+++ b/ext/soap/tests/schema/schema030.phpt
@@ -16,10 +16,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("str"=>"str","int"=>123.5));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 123str
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["int"]=>
   int(123)
   ["str"]=>
diff --git a/ext/soap/tests/schema/schema031.phpt b/ext/soap/tests/schema/schema031.phpt
index f7d771257723..479abfee9d72 100644
--- a/ext/soap/tests/schema/schema031.phpt
+++ b/ext/soap/tests/schema/schema031.phpt
@@ -16,10 +16,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("str"=>"str","int"=>123.5));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 123str
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["int"]=>
   int(123)
   ["str"]=>
diff --git a/ext/soap/tests/schema/schema032.phpt b/ext/soap/tests/schema/schema032.phpt
index bde19cee7e86..47b4af121cb7 100644
--- a/ext/soap/tests/schema/schema032.phpt
+++ b/ext/soap/tests/schema/schema032.phpt
@@ -16,10 +16,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("int"=>123.5));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 123
-object(stdClass)#5 (1) {
+object(stdClass)#%d (1) {
   ["int"]=>
   int(123)
 }
diff --git a/ext/soap/tests/schema/schema033.phpt b/ext/soap/tests/schema/schema033.phpt
index 1c8341b71d62..b504bc077a3d 100644
--- a/ext/soap/tests/schema/schema033.phpt
+++ b/ext/soap/tests/schema/schema033.phpt
@@ -21,14 +21,14 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("int"=>123.5,"nest"=>array("int"=>123.5)));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 123123
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["int"]=>
   int(123)
   ["nest"]=>
-  object(stdClass)#6 (1) {
+  object(stdClass)#%d (1) {
     ["int"]=>
     int(123)
   }
diff --git a/ext/soap/tests/schema/schema034.phpt b/ext/soap/tests/schema/schema034.phpt
index 995b0485e589..a83d6ea84648 100644
--- a/ext/soap/tests/schema/schema034.phpt
+++ b/ext/soap/tests/schema/schema034.phpt
@@ -22,14 +22,14 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("int"=>123.5,"testType2"=>array("int"=>123.5)));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 123123
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["int"]=>
   int(123)
   ["testType2"]=>
-  object(stdClass)#6 (1) {
+  object(stdClass)#%d (1) {
     ["int"]=>
     int(123)
   }
diff --git a/ext/soap/tests/schema/schema035.phpt b/ext/soap/tests/schema/schema035.phpt
index da2c6410a64f..8974ed00c549 100644
--- a/ext/soap/tests/schema/schema035.phpt
+++ b/ext/soap/tests/schema/schema035.phpt
@@ -23,14 +23,14 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("int"=>123.5,"testType2"=>array("int"=>123.5)));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 123123
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["int"]=>
   int(123)
   ["testType2"]=>
-  object(stdClass)#6 (1) {
+  object(stdClass)#%d (1) {
     ["int"]=>
     int(123)
   }
diff --git a/ext/soap/tests/schema/schema036.phpt b/ext/soap/tests/schema/schema036.phpt
index bf25ec4b985b..9d6dac45343a 100644
--- a/ext/soap/tests/schema/schema036.phpt
+++ b/ext/soap/tests/schema/schema036.phpt
@@ -22,14 +22,14 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("int"=>123.5,"testType2"=>array("int"=>123.5)));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 123123
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["int"]=>
   int(123)
   ["testType2"]=>
-  object(stdClass)#6 (1) {
+  object(stdClass)#%d (1) {
     ["int"]=>
     int(123)
   }
diff --git a/ext/soap/tests/schema/schema037.phpt b/ext/soap/tests/schema/schema037.phpt
index b1437a1f9325..4e59981fc9a5 100644
--- a/ext/soap/tests/schema/schema037.phpt
+++ b/ext/soap/tests/schema/schema037.phpt
@@ -16,10 +16,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("str"=>"str","int"=>123.5));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 str
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["str"]=>
   string(3) "str"
   ["int"]=>
diff --git a/ext/soap/tests/schema/schema038.phpt b/ext/soap/tests/schema/schema038.phpt
index fec13324232f..2d37e89e0b53 100644
--- a/ext/soap/tests/schema/schema038.phpt
+++ b/ext/soap/tests/schema/schema038.phpt
@@ -17,10 +17,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("str"=>"str","int"=>123.5));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 str
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["str"]=>
   string(3) "str"
   ["int"]=>
diff --git a/ext/soap/tests/schema/schema039.phpt b/ext/soap/tests/schema/schema039.phpt
index f392022809ab..0b7ef5afc462 100644
--- a/ext/soap/tests/schema/schema039.phpt
+++ b/ext/soap/tests/schema/schema039.phpt
@@ -19,10 +19,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("str"=>"str","int"=>123.5));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 str
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["str"]=>
   string(3) "str"
   ["int"]=>
diff --git a/ext/soap/tests/schema/schema040.phpt b/ext/soap/tests/schema/schema040.phpt
index 85a1d5c8b254..f7ddc0454684 100644
--- a/ext/soap/tests/schema/schema040.phpt
+++ b/ext/soap/tests/schema/schema040.phpt
@@ -20,10 +20,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("str"=>"str","int"=>123.5));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 str
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["str"]=>
   string(3) "str"
   ["int"]=>
diff --git a/ext/soap/tests/schema/schema041.phpt b/ext/soap/tests/schema/schema041.phpt
index 13df8d7902aa..1264cf5c90d7 100644
--- a/ext/soap/tests/schema/schema041.phpt
+++ b/ext/soap/tests/schema/schema041.phpt
@@ -19,10 +19,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("str"=>"str","int"=>123.5));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 123str
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["int"]=>
   int(123)
   ["str"]=>
diff --git a/ext/soap/tests/schema/schema042.phpt b/ext/soap/tests/schema/schema042.phpt
index eab30592051e..a8aa8857d9bf 100644
--- a/ext/soap/tests/schema/schema042.phpt
+++ b/ext/soap/tests/schema/schema042.phpt
@@ -17,10 +17,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("_"=>123.5,"int"=>123.5));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 123
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["_"]=>
   int(123)
   ["int"]=>
diff --git a/ext/soap/tests/schema/schema043.phpt b/ext/soap/tests/schema/schema043.phpt
index b1977b6cb69f..08c29963634d 100644
--- a/ext/soap/tests/schema/schema043.phpt
+++ b/ext/soap/tests/schema/schema043.phpt
@@ -24,10 +24,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("_"=>123.5,"int"=>123.5,"int2"=>123.5));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 123
-object(stdClass)#5 (3) {
+object(stdClass)#%d (3) {
   ["_"]=>
   int(123)
   ["int"]=>
diff --git a/ext/soap/tests/schema/schema044.phpt b/ext/soap/tests/schema/schema044.phpt
index b5dbbe1e6638..8fc070551874 100644
--- a/ext/soap/tests/schema/schema044.phpt
+++ b/ext/soap/tests/schema/schema044.phpt
@@ -17,10 +17,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("_"=>123.5,"int"=>123.5));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 123
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["_"]=>
   int(123)
   ["int"]=>
diff --git a/ext/soap/tests/schema/schema045.phpt b/ext/soap/tests/schema/schema045.phpt
index 6410e1e0634e..346a929d85b5 100644
--- a/ext/soap/tests/schema/schema045.phpt
+++ b/ext/soap/tests/schema/schema045.phpt
@@ -24,10 +24,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("_"=>123.5,"int"=>123.5,"int2"=>123.5));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 123
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["_"]=>
   int(123)
   ["int2"]=>
diff --git a/ext/soap/tests/schema/schema046.phpt b/ext/soap/tests/schema/schema046.phpt
index 3d4695c494bc..3f9d03afadd7 100644
--- a/ext/soap/tests/schema/schema046.phpt
+++ b/ext/soap/tests/schema/schema046.phpt
@@ -24,10 +24,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("_"=>123.5,"int"=>123.5,"int2"=>123.5));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 123
-object(stdClass)#5 (3) {
+object(stdClass)#%d (3) {
   ["_"]=>
   int(123)
   ["int"]=>
diff --git a/ext/soap/tests/schema/schema047.phpt b/ext/soap/tests/schema/schema047.phpt
index 497f7ef5d078..1265cfd3a381 100644
--- a/ext/soap/tests/schema/schema047.phpt
+++ b/ext/soap/tests/schema/schema047.phpt
@@ -22,10 +22,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("_"=>123.5,"int"=>123.5,"int2"=>123.5));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 123
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["int"]=>
   int(123)
   ["int2"]=>
diff --git a/ext/soap/tests/schema/schema048.phpt b/ext/soap/tests/schema/schema048.phpt
index 0fc02e2e6640..98d4d4be4438 100644
--- a/ext/soap/tests/schema/schema048.phpt
+++ b/ext/soap/tests/schema/schema048.phpt
@@ -24,10 +24,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("_"=>123.5,"int"=>123.5,"int2"=>123.5));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 123
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["_"]=>
   int(123)
   ["int2"]=>
diff --git a/ext/soap/tests/schema/schema049.phpt b/ext/soap/tests/schema/schema049.phpt
index 4213ba0c8f06..78dc5681ea21 100644
--- a/ext/soap/tests/schema/schema049.phpt
+++ b/ext/soap/tests/schema/schema049.phpt
@@ -24,10 +24,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("_"=>123.5,"int"=>123.5,"int2"=>123.5));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 123
-object(stdClass)#5 (1) {
+object(stdClass)#%d (1) {
   ["int2"]=>
   int(123)
 }
diff --git a/ext/soap/tests/schema/schema050.phpt b/ext/soap/tests/schema/schema050.phpt
index 925edb133f34..6c735125b765 100644
--- a/ext/soap/tests/schema/schema050.phpt
+++ b/ext/soap/tests/schema/schema050.phpt
@@ -16,10 +16,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("int"=>123.5,"int2"=>123.5));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 123123
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["int"]=>
   int(123)
   ["int2"]=>
diff --git a/ext/soap/tests/schema/schema051.phpt b/ext/soap/tests/schema/schema051.phpt
index 582c78eaf491..9636399814a9 100644
--- a/ext/soap/tests/schema/schema051.phpt
+++ b/ext/soap/tests/schema/schema051.phpt
@@ -16,10 +16,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("int"=>123.5,"int2"=>array(123.5,456.7)));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 123123456
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["int"]=>
   int(123)
   ["int2"]=>
diff --git a/ext/soap/tests/schema/schema052.phpt b/ext/soap/tests/schema/schema052.phpt
index 59f6ff811f68..8e7121ae2d0a 100644
--- a/ext/soap/tests/schema/schema052.phpt
+++ b/ext/soap/tests/schema/schema052.phpt
@@ -16,10 +16,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("int"=>123.5,"int2"=>array(123.5)));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 123123
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["int"]=>
   int(123)
   ["int2"]=>
diff --git a/ext/soap/tests/schema/schema053.phpt b/ext/soap/tests/schema/schema053.phpt
index b88115ec2959..8893bf5df345 100644
--- a/ext/soap/tests/schema/schema053.phpt
+++ b/ext/soap/tests/schema/schema053.phpt
@@ -16,10 +16,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("int"=>123.5,"int2"=>array()));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 123
-object(stdClass)#5 (1) {
+object(stdClass)#%d (1) {
   ["int"]=>
   int(123)
 }
diff --git a/ext/soap/tests/schema/schema062.phpt b/ext/soap/tests/schema/schema062.phpt
index e95c2959c835..d4efc9a599f3 100644
--- a/ext/soap/tests/schema/schema062.phpt
+++ b/ext/soap/tests/schema/schema062.phpt
@@ -17,10 +17,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("_"=>NULL,"int"=>123.5));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["_"]=>
   NULL
   ["int"]=>
diff --git a/ext/soap/tests/schema/schema063.phpt b/ext/soap/tests/schema/schema063.phpt
index 4c88b5e03634..dd60422a27d2 100644
--- a/ext/soap/tests/schema/schema063.phpt
+++ b/ext/soap/tests/schema/schema063.phpt
@@ -9,8 +9,8 @@ $schema = '';
 test_schema($schema,'type="xsd:unsignedLong"',0xffffffff);
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 4294967295
-float(4294967295)
+%s(4294967295)
 ok
diff --git a/ext/soap/tests/schema/schema064.phpt b/ext/soap/tests/schema/schema064.phpt
index b2b5db7ee05e..53e1b257be90 100644
--- a/ext/soap/tests/schema/schema064.phpt
+++ b/ext/soap/tests/schema/schema064.phpt
@@ -33,10 +33,10 @@ test_schema($schema,'type="tns:testType"',array(
 ));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 1976-04-05T01:02:03Z1976-04-05Z1976-04Z1976Z--04-05Z---05Z--04--Z
-object(stdClass)#4 (8) {
+object(stdClass)#%d (8) {
   ["dateTime"]=>
   string(20) "1976-04-05T01:02:03Z"
   ["time"]=>
diff --git a/ext/soap/tests/schema/schema065.phpt b/ext/soap/tests/schema/schema065.phpt
index eb768ed85171..e3f0d646dccd 100644
--- a/ext/soap/tests/schema/schema065.phpt
+++ b/ext/soap/tests/schema/schema065.phpt
@@ -14,10 +14,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("str"=>"str"));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["str"]=>
   string(3) "str"
   ["int"]=>
diff --git a/ext/soap/tests/schema/schema066.phpt b/ext/soap/tests/schema/schema066.phpt
index 2f2b06242423..b2812719634b 100644
--- a/ext/soap/tests/schema/schema066.phpt
+++ b/ext/soap/tests/schema/schema066.phpt
@@ -14,10 +14,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("str"=>"str"));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["str"]=>
   string(3) "str"
   ["int"]=>
diff --git a/ext/soap/tests/schema/schema067.phpt b/ext/soap/tests/schema/schema067.phpt
index 8aa08d2d2be5..0e4000957a77 100644
--- a/ext/soap/tests/schema/schema067.phpt
+++ b/ext/soap/tests/schema/schema067.phpt
@@ -14,10 +14,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("str"=>"str","int"=>5));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["str"]=>
   string(3) "str"
   ["int"]=>
diff --git a/ext/soap/tests/schema/schema069.phpt b/ext/soap/tests/schema/schema069.phpt
index 67df500906ce..e4f733a1c07a 100644
--- a/ext/soap/tests/schema/schema069.phpt
+++ b/ext/soap/tests/schema/schema069.phpt
@@ -15,10 +15,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("str"=>"str"));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["str"]=>
   string(3) "str"
   ["int"]=>
diff --git a/ext/soap/tests/schema/schema070.phpt b/ext/soap/tests/schema/schema070.phpt
index f9171923c03c..af9abdc10f33 100644
--- a/ext/soap/tests/schema/schema070.phpt
+++ b/ext/soap/tests/schema/schema070.phpt
@@ -17,10 +17,10 @@ EOF;
 test_schema($schema,'type="tns:testType"',(object)array("str"=>"str"));
 echo "ok";
 ?>
---EXPECT--
+--EXPECTF--
 
 
-object(stdClass)#5 (2) {
+object(stdClass)#%d (2) {
   ["str"]=>
   string(3) "str"
   ["int"]=>
diff --git a/ext/soap/tests/schema/schema074.phpt b/ext/soap/tests/schema/schema074.phpt
new file mode 100644
index 000000000000..3dbba0cd251d
--- /dev/null
+++ b/ext/soap/tests/schema/schema074.phpt
@@ -0,0 +1,29 @@
+--TEST--
+SOAP XML Schema 74: Structure with attributes and qualified elements
+--SKIPIF--
+
+--FILE--
+
+		
+			
+		
+		
+	
+EOF;
+
+test_schema($schema,'type="tns:testType"',(object)array("str"=>"str","int"=>123.5), "rpc", "encoded", 'attributeFormDefault="qualified"');
+echo "ok";
+?>
+--EXPECTF--
+
+str
+object(stdClass)#%d (2) {
+  ["str"]=>
+  string(3) "str"
+  ["int"]=>
+  int(123)
+}
+ok
diff --git a/ext/soap/tests/schema/schema075.phpt b/ext/soap/tests/schema/schema075.phpt
new file mode 100644
index 000000000000..2a84be9ce915
--- /dev/null
+++ b/ext/soap/tests/schema/schema075.phpt
@@ -0,0 +1,30 @@
+--TEST--
+SOAP XML Schema 75: Attributes form qualified/unqualified (attributeFormDefault="qualified")
+--SKIPIF--
+
+--FILE--
+
+		
+		
+		
+	
+EOF;
+
+test_schema($schema,'type="tns:testType"',(object)array("int1"=>1.1,"int2"=>2.2,"int3"=>3.3), "rpc", "encoded", 'attributeFormDefault="qualified"');
+echo "ok";
+?>
+--EXPECTF--
+
+
+object(stdClass)#5 (3) {
+  ["int1"]=>
+  int(1)
+  ["int2"]=>
+  int(2)
+  ["int3"]=>
+  int(3)
+}
+ok
diff --git a/ext/soap/tests/schema/schema076.phpt b/ext/soap/tests/schema/schema076.phpt
new file mode 100644
index 000000000000..dfa7791fedcb
--- /dev/null
+++ b/ext/soap/tests/schema/schema076.phpt
@@ -0,0 +1,30 @@
+--TEST--
+SOAP XML Schema 76: Attributes form qualified/unqualified (attributeFormDefault="unqualified")
+--SKIPIF--
+
+--FILE--
+
+		
+		
+		
+	
+EOF;
+
+test_schema($schema,'type="tns:testType"',(object)array("int1"=>1.1,"int2"=>2.2,"int3"=>3.3), "rpc", "encoded", 'attributeFormDefault="unqualified"');
+echo "ok";
+?>
+--EXPECTF--
+
+
+object(stdClass)#5 (3) {
+  ["int1"]=>
+  int(1)
+  ["int2"]=>
+  int(2)
+  ["int3"]=>
+  int(3)
+}
+ok
diff --git a/ext/soap/tests/schema/schema077.phpt b/ext/soap/tests/schema/schema077.phpt
new file mode 100644
index 000000000000..baf10449d601
--- /dev/null
+++ b/ext/soap/tests/schema/schema077.phpt
@@ -0,0 +1,30 @@
+--TEST--
+SOAP XML Schema 77: Attributes form qualified/unqualified (attributeFormDefault - default)
+--SKIPIF--
+
+--FILE--
+
+		
+		
+		
+	
+EOF;
+
+test_schema($schema,'type="tns:testType"',(object)array("int1"=>1.1,"int2"=>2.2,"int3"=>3.3), "rpc", "encoded");
+echo "ok";
+?>
+--EXPECTF--
+
+
+object(stdClass)#5 (3) {
+  ["int1"]=>
+  int(1)
+  ["int2"]=>
+  int(2)
+  ["int3"]=>
+  int(3)
+}
+ok
diff --git a/ext/soap/tests/schema/schema078.phpt b/ext/soap/tests/schema/schema078.phpt
new file mode 100644
index 000000000000..a674270dff49
--- /dev/null
+++ b/ext/soap/tests/schema/schema078.phpt
@@ -0,0 +1,32 @@
+--TEST--
+SOAP XML Schema 78: Element form qualified/unqualified (elementFormDefault="qualified")
+--SKIPIF--
+
+--FILE--
+
+		
+			
+			
+			
+		
+	
+EOF;
+
+test_schema($schema,'type="tns:testType"',(object)array("int1"=>1.1,"int2"=>2.2,"int3"=>3.3), "rpc", "literal", 'elementFormDefault="qualified"');
+echo "ok";
+?>
+--EXPECTF--
+
+123
+object(stdClass)#5 (3) {
+  ["int1"]=>
+  int(1)
+  ["int2"]=>
+  int(2)
+  ["int3"]=>
+  int(3)
+}
+ok
diff --git a/ext/soap/tests/schema/schema079.phpt b/ext/soap/tests/schema/schema079.phpt
new file mode 100644
index 000000000000..d7f2ab97c645
--- /dev/null
+++ b/ext/soap/tests/schema/schema079.phpt
@@ -0,0 +1,32 @@
+--TEST--
+SOAP XML Schema 79: Element form qualified/unqualified (elementFormDefault="unqualified")
+--SKIPIF--
+
+--FILE--
+
+		
+			
+			
+			
+		
+	
+EOF;
+
+test_schema($schema,'type="tns:testType"',(object)array("int1"=>1.1,"int2"=>2.2,"int3"=>3.3), "rpc", "literal", 'elementFormDefault="unqualified"');
+echo "ok";
+?>
+--EXPECTF--
+
+123
+object(stdClass)#5 (3) {
+  ["int1"]=>
+  int(1)
+  ["int2"]=>
+  int(2)
+  ["int3"]=>
+  int(3)
+}
+ok
diff --git a/ext/soap/tests/schema/schema080.phpt b/ext/soap/tests/schema/schema080.phpt
new file mode 100644
index 000000000000..4accf551f114
--- /dev/null
+++ b/ext/soap/tests/schema/schema080.phpt
@@ -0,0 +1,32 @@
+--TEST--
+SOAP XML Schema 80: Element form qualified/unqualified (elementFormDefault - default)
+--SKIPIF--
+
+--FILE--
+
+		
+			
+			
+			
+		
+	
+EOF;
+
+test_schema($schema,'type="tns:testType"',(object)array("int1"=>1.1,"int2"=>2.2,"int3"=>3.3), "rpc", "literal");
+echo "ok";
+?>
+--EXPECTF--
+
+123
+object(stdClass)#5 (3) {
+  ["int1"]=>
+  int(1)
+  ["int2"]=>
+  int(2)
+  ["int3"]=>
+  int(3)
+}
+ok
diff --git a/ext/soap/tests/schema/test_schema.inc b/ext/soap/tests/schema/test_schema.inc
index 64635a10ca9c..e1d4eeb5087a 100644
--- a/ext/soap/tests/schema/test_schema.inc
+++ b/ext/soap/tests/schema/test_schema.inc
@@ -6,7 +6,7 @@ function test($input) {
 	$val = $input;
 }
 
-function test_schema($schema,$type,$param,$style="rpc",$use="encoded") {
+function test_schema($schema,$type,$param,$style="rpc",$use="encoded", $attributeFormDefault='') {
   global $HTTP_RAW_POST_DATA, $val;
 $wsdl  = <<
+    targetNamespace="http://test-uri/"
+    >
   
-  
+  
    
    
   	$schema
@@ -37,7 +38,7 @@ $wsdl  = <<
 			
 			
-				
+				
 			
 		
 	
@@ -53,7 +54,7 @@ EOF;
   $f = fopen($fname,"w");
   fwrite($f,$wsdl);
   fclose($f);
-	ini_set("soap.wsdl_cache_enabled",0);
+  ini_set("soap.wsdl_cache_enabled",0);
   $x = new SoapClient($fname, array("trace"=>1,"exceptions"=>0));
   $y = new SoapServer($fname);
 	$y->addfunction("test");
@@ -62,13 +63,15 @@ EOF;
   $x->test($param);
   $xml = xml_parser_create();
   $req = $x->__getlastrequest();
-  echo $req;
   if ($style == "rpc") {
     $HTTP_RAW_POST_DATA = $req;
     ob_start();
     $y->handle();
     ob_end_clean();
+    echo $req;
     var_dump($val);
+  } else {
+    echo $req;
   }
 }
-?>
\ No newline at end of file
+?>
diff --git a/ext/soap/tests/server021.phpt b/ext/soap/tests/server021.phpt
index d557204b5f02..787e959fb36d 100644
--- a/ext/soap/tests/server021.phpt
+++ b/ext/soap/tests/server021.phpt
@@ -5,7 +5,7 @@ SOAP Server 21: SoapServer::setClass and __call()
 --FILE--
 
 --EXPECT--
 
-return1
+returntrue
 ok
diff --git a/ext/soap/tests/soap12/T77_1.phpt b/ext/soap/tests/soap12/T77_1.phpt
index fea616a9be9c..d847b6cfd884 100644
--- a/ext/soap/tests/soap12/T77_1.phpt
+++ b/ext/soap/tests/soap12/T77_1.phpt
@@ -21,5 +21,5 @@ include "soap12-test.inc";
 ?>
 --EXPECT--
 
-return1
+returntrue
 ok
diff --git a/ext/soap/tests/soap12/T77_2.phpt b/ext/soap/tests/soap12/T77_2.phpt
index 1e49e8a35e01..c829b57892a3 100644
--- a/ext/soap/tests/soap12/T77_2.phpt
+++ b/ext/soap/tests/soap12/T77_2.phpt
@@ -20,5 +20,5 @@ include "soap12-test.inc";
 ?>
 --EXPECT--
 
-return1
+returntrue
 ok
diff --git a/ext/soap/tests/soap12/T77_3.phpt b/ext/soap/tests/soap12/T77_3.phpt
index f404dd0befd4..0e1355a5a281 100644
--- a/ext/soap/tests/soap12/T77_3.phpt
+++ b/ext/soap/tests/soap12/T77_3.phpt
@@ -23,5 +23,5 @@ include "soap12-test.inc";
 ?>
 --EXPECT--
 
-return0
+returnfalse
 ok
diff --git a/ext/soap/tests/transport001.phpt b/ext/soap/tests/transport001.phpt
index ae4de9252407..9134d3d7fb89 100644
--- a/ext/soap/tests/transport001.phpt
+++ b/ext/soap/tests/transport001.phpt
@@ -10,8 +10,8 @@ function Add($x,$y) {
 
 class LocalSoapClient extends SoapClient {
 
-  function LocalSoapClient($wsdl, $options) {
-    $this->SoapClient($wsdl, $options);
+  function __construct($wsdl, $options) {
+    parent::__construct($wsdl, $options);
     $this->server = new SoapServer($wsdl, $options);
     $this->server->addFunction('Add');
   }
diff --git a/ext/sockets/php_sockets.h b/ext/sockets/php_sockets.h
index eb3f3c59f0c2..6a54c5dd06b7 100644
--- a/ext/sockets/php_sockets.h
+++ b/ext/sockets/php_sockets.h
@@ -82,10 +82,6 @@ typedef struct {
 	int		error;
 } php_socket;
 
-typedef struct {
-	zend_bool	use_system_read;
-} php_sockets_globals;
-
 /* Prototypes */
 #ifdef ilia_0 /* not needed, only causes a compiler warning */
 static int php_open_listen_sock(php_socket **php_sock, int port, int backlog TSRMLS_DC);
diff --git a/ext/sockets/php_sockets_win.h b/ext/sockets/php_sockets_win.h
index 4b16ebe7d608..be33ad14c78f 100644
--- a/ext/sockets/php_sockets_win.h
+++ b/ext/sockets/php_sockets_win.h
@@ -41,7 +41,6 @@
 #define errno WSAGetLastError()
 #define h_errno WSAGetLastError()
 #define set_errno(a) WSASetLastError(a)
-#define set_h_errno(a) WSASetLastError(a)
 #define close(a) closesocket(a)
 
 struct	sockaddr_un {
diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c
index 8f2a329c3538..a62d21910597 100644
--- a/ext/sockets/sockets.c
+++ b/ext/sockets/sockets.c
@@ -50,7 +50,6 @@
 # include 
 # define IS_INVALID_SOCKET(a)	(a->bsd_socket < 0)
 # define set_errno(a) (errno = a)
-# define set_h_errno(a) (h_errno = a)
 #else /* windows */
 # include "php_sockets.h"
 # include "php_sockets_win.h"
@@ -322,6 +321,10 @@ static char *php_strerror(int error TSRMLS_DC)
 		buf = hstrerror(error);
 #else
 		{
+			if (SOCKETS_G(strerror_buf)) {
+				efree(SOCKETS_G(strerror_buf));
+			}
+
 			spprintf(&(SOCKETS_G(strerror_buf)), 0, "Host lookup error %d", error);
 			buf = SOCKETS_G(strerror_buf);
 		}
@@ -336,6 +339,11 @@ static char *php_strerror(int error TSRMLS_DC)
 
 		if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |	FORMAT_MESSAGE_IGNORE_INSERTS,
 				  NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &tmp, 0, NULL)) {
+
+			if (SOCKETS_G(strerror_buf)) {
+				efree(SOCKETS_G(strerror_buf));
+			}
+
 			SOCKETS_G(strerror_buf) = estrdup(tmp);
 			LocalFree(tmp);
 		
@@ -533,7 +541,7 @@ static int php_sock_array_to_fd_set(zval *sock_array, fd_set *fds, PHP_SOCKET *m
 		php_sock = (php_socket*) zend_fetch_resource(element TSRMLS_CC, -1, le_socket_name, NULL, 1, le_socket);
 		if (!php_sock) continue; /* If element is not a resource, skip it */
 
-		FD_SET(php_sock->bsd_socket, fds);
+		PHP_SAFE_FD_SET(php_sock->bsd_socket, fds);
 		if (php_sock->bsd_socket > *max_fd) {
 			*max_fd = php_sock->bsd_socket;
 		}
@@ -560,7 +568,7 @@ static int php_sock_array_from_fd_set(zval *sock_array, fd_set *fds TSRMLS_DC)
 		php_sock = (php_socket*) zend_fetch_resource(element TSRMLS_CC, -1, le_socket_name, NULL, 1, le_socket);
 		if (!php_sock) continue; /* If element is not a resource, skip it */
 
-		if (FD_ISSET(php_sock->bsd_socket, fds)) {
+		if (PHP_SAFE_FD_ISSET(php_sock->bsd_socket, fds)) {
 			/* Add fd to new array */
 			zend_hash_next_index_insert(new_hash, (void *)element, sizeof(zval *), (void **)&dest_element);
 			if (dest_element) zval_add_ref(dest_element);
@@ -605,6 +613,8 @@ PHP_FUNCTION(socket_select)
 		RETURN_FALSE;
 	}
 
+	PHP_SAFE_MAX_FD(max_fd, 0); /* someone needs to make this look more like stream_socket_select */
+
 	/* If seconds is not set to null, build the timeval, else we wait indefinitely */
 	if (sec != NULL) {
 		zval tmp;
@@ -662,6 +672,8 @@ PHP_FUNCTION(socket_create_listen)
 		RETURN_FALSE;
 	}
 
+	php_sock->error = 0;
+
 	ZEND_REGISTER_RESOURCE(return_value, php_sock, le_socket);
 }
 /* }}} */
@@ -680,10 +692,11 @@ PHP_FUNCTION(socket_accept)
 	ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
 	
 	if (!php_accept_connect(php_sock, &new_sock, (struct sockaddr *) &sa TSRMLS_CC)) {
-		PHP_SOCKET_ERROR(new_sock, "unable to accept socket connection", errno);
 		RETURN_FALSE;
 	}
-	
+
+	new_sock->error = 0;
+
 	ZEND_REGISTER_RESOURCE(return_value, new_sock, le_socket);
 }
 /* }}} */
@@ -1048,6 +1061,8 @@ PHP_FUNCTION(socket_create)
 		RETURN_FALSE;
 	}
 
+	php_sock->error = 0;
+
 	ZEND_REGISTER_RESOURCE(return_value, php_sock, le_socket);
 }
 /* }}} */
@@ -1684,6 +1699,8 @@ PHP_FUNCTION(socket_create_pair)
 	php_sock[1]->bsd_socket = fds_array[1];
 	php_sock[0]->type		= domain;
 	php_sock[1]->type		= domain;
+	php_sock[0]->error		= 0;
+	php_sock[1]->error		= 0;
 
 	ZEND_REGISTER_RESOURCE(retval[0], php_sock[0], le_socket);
 	ZEND_REGISTER_RESOURCE(retval[1], php_sock[1], le_socket);
diff --git a/ext/spl/examples/autoload.inc b/ext/spl/examples/autoload.inc
index af4b931ff40a..7fecfa5758d1 100755
--- a/ext/spl/examples/autoload.inc
+++ b/ext/spl/examples/autoload.inc
@@ -33,7 +33,10 @@ function __load_class($classname, $dir)
  */
 function __autoload($classname) {
 	$classname = strtolower($classname);
-	foreach(split(':', ini_get('include_path')) as $dir)
+	$inc = split(':', ini_get('include_path'));
+	$inc[] = '.';
+	$inc[] = dirname($_SERVER['PATH_TRANSLATED']);
+	foreach($inc as $dir)
 	{
 		if (__load_class($classname, $dir))
 		{
@@ -41,10 +44,7 @@ function __autoload($classname) {
 			return;
 		}
 	}
-	if (!__load_class($classname, '.'))
-	if (!__load_class($classname, dirname($_SERVER['PATH_TRANSLATED'])))
 	fprintf(STDERR, 'Class not found ('.$classname.")\n");
-	return;
 }
 
 ?>
\ No newline at end of file
diff --git a/ext/spl/examples/dbareader.inc b/ext/spl/examples/dbareader.inc
index 02b084031732..bc3ee83a3003 100755
--- a/ext/spl/examples/dbareader.inc
+++ b/ext/spl/examples/dbareader.inc
@@ -28,32 +28,24 @@ class DbaReader implements Iterator
 	 * @param handler Handler to use for database access.
 	 */
 	function __construct($file, $handler) {
-		$this->db = dba_open($file, 'r', $handler);
+		if (!$this->db = dba_open($file, 'r', $handler)) {
+		    throw new exception('Could not open file ' . $file);
+		}
 	}
 	
 	/**
 	 * Close database.
 	 */
 	function __destruct() {
-		if ($this->db) {
-			dba_close($this->db);
-		}
+		dba_close($this->db);
 	}
 
 	/**
 	 * Rewind to first element.
 	 */
 	function rewind() {
-		if ($this->db) {
-			$this->key = dba_firstkey($this->db);
-		}
-	}
-
-	/**
-	 * @return Current data.
-	 */
-	function current() {
-		return $this->val;
+		$this->key = dba_firstkey($this->db);
+		$this->fetch_data();
 	}
 
 	/**
@@ -62,14 +54,26 @@ class DbaReader implements Iterator
 	 * @return void
 	 */
 	function next() {
-		if ($this->db) {
-			$this->key = dba_nextkey($this->db);
-			if ($this->key !== false) {
-				$this->val = dba_fetch($this->key, $this->db);
-			}
+		$this->key = dba_nextkey($this->db);
+		$this->fetch_data();
+	}
+
+    /**
+     * Fetches the current data if $key is valid
+     */	
+	private function fetch_data() {
+		if ($this->key !== false) {
+			$this->val = dba_fetch($this->key, $this->db);
 		}
 	}
 
+	/**
+	 * @return Current data.
+	 */
+	function current() {
+		return $this->val;
+	}
+
 	/**
 	 * @return Whether more elements are available.
 	 */
diff --git a/ext/spl/php_spl.c b/ext/spl/php_spl.c
index 34597b6afb46..5509374bebb5 100755
--- a/ext/spl/php_spl.c
+++ b/ext/spl/php_spl.c
@@ -157,8 +157,8 @@ PHP_FUNCTION(class_implements)
 	spl_add_classes(&spl_ce_ ## class_name, z_list, sub, allow, ce_flags TSRMLS_CC)
 
 #define SPL_LIST_CLASSES(z_list, sub, allow, ce_flags) \
-	SPL_ADD_CLASS(ArrayObject, z_list, sub, allow, ce_flags); \
 	SPL_ADD_CLASS(ArrayIterator, z_list, sub, allow, ce_flags); \
+	SPL_ADD_CLASS(ArrayObject, z_list, sub, allow, ce_flags); \
 	SPL_ADD_CLASS(CachingIterator, z_list, sub, allow, ce_flags); \
 	SPL_ADD_CLASS(CachingRecursiveIterator, z_list, sub, allow, ce_flags); \
 	SPL_ADD_CLASS(DirectoryIterator, z_list, sub, allow, ce_flags); \
diff --git a/ext/spl/spl.php b/ext/spl/spl.php
index 5c77857ff970..1f4e8ec7e0cf 100755
--- a/ext/spl/spl.php
+++ b/ext/spl/spl.php
@@ -13,6 +13,9 @@
  *
  * SPL - Standard PHP Library
  *
+ * You can download this documentation as a chm file 
+ * here.
+ *
  * (c) Marcus Boerger, 2003 - 2004
  */
 
@@ -337,7 +340,7 @@ function seek($position);
  * This class uses SeekableIterator::seek() if available and rewind() plus
  * a skip loop otehrwise.
  */
-class LimitIetrator implements Iterator
+class LimitIterator implements Iterator
 {
 	/** Construct an instance form a Iterator.
 	 *
@@ -358,8 +361,10 @@ function getInnerIterator();
 	
 	/** Seek to a specific position if available or throw an exception.
 	 * If the inner iterator is an instance of SeekableIterator its seek()
-	 * method will be used. Otherwise the iterator will me manually forwared
-	 * and rewinded first if necessary.
+	 * method will be used. Otherwise the iterator will be rewound if
+	 * necessary and then manually advanced element by element.
+	 *
+	 * \param $position index to seek to.
 	 */
 	function seek($position);
 	
@@ -539,6 +544,13 @@ function getChildren();
 
 /** \ingroup SPL
  * \brief recursive SimpleXML_Element iterator
+ *
+ * The SimpleXMLIterator implements the RecursiveIterator interface. This 
+ * allows iteration over all elements using foreach or an appropriate while
+ * construct, just like SimpleXMLElement does. When using the foreach construct,
+ * you will also iterate over the subelements. For every element which
+ * has subelements, hasChildren() returns true.  This will trigger a call to
+ * getChildren() which returns the iterator for that sub element.
  */
 class SimpleXMLIterator extends SimpleXMLElement implements RecursiveIterator
 {
@@ -551,4 +563,4 @@ function hasChildren();
 	function getChildren();	
 }
 
-?>
\ No newline at end of file
+?>
diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c
index 901bd35552ba..c9ed37b29657 100755
--- a/ext/spl/spl_array.c
+++ b/ext/spl/spl_array.c
@@ -26,6 +26,7 @@
 #include "php_ini.h"
 #include "ext/standard/info.h"
 #include "zend_interfaces.h"
+#include "zend_exceptions.h"
 
 #include "php_spl.h"
 #include "spl_functions.h"
@@ -55,12 +56,12 @@ ZEND_BEGIN_ARG_INFO(arginfo_array___construct, 0)
 ZEND_END_ARG_INFO();
 
 static
-ZEND_BEGIN_ARG_INFO(arginfo_array_offsetGet, 0)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_array_offsetGet, 0, 0, 1)
 	ZEND_ARG_INFO(0, index)
 ZEND_END_ARG_INFO();
 
 static
-ZEND_BEGIN_ARG_INFO(arginfo_array_offsetSet, 0)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_array_offsetSet, 0, 0, 2)
 	ZEND_ARG_INFO(0, index)
 	ZEND_ARG_INFO(0, newval)
 ZEND_END_ARG_INFO();
@@ -110,17 +111,43 @@ static zend_function_entry spl_funcs_ArrayIterator[] = {
 
 
 zend_object_handlers spl_handler_ArrayObject;
-zend_class_entry *   spl_ce_ArrayObject;
+PHPAPI zend_class_entry  *spl_ce_ArrayObject;
 
 zend_object_handlers spl_handler_ArrayIterator;
-zend_class_entry *   spl_ce_ArrayIterator;
+PHPAPI zend_class_entry *spl_ce_ArrayIterator;
 
 typedef struct _spl_array_object {
 	zend_object       std;
 	zval              *array;
 	HashPosition      pos;
+	int               is_ref;
+	zend_function *   fptr_offset_get;
+	zend_function *   fptr_offset_set;
+	zend_function *   fptr_offset_has;
+	zend_function *   fptr_offset_del;
 } spl_array_object;
 
+SPL_API int spl_hash_verify_pos(spl_array_object * intern TSRMLS_DC) /* {{{ */
+{
+	HashTable *ht = HASH_OF(intern->array);
+	Bucket *p;
+
+/*	IS_CONSISTENT(ht);*/
+
+/*	HASH_PROTECT_RECURSION(ht);*/
+	p = ht->pListHead;
+	while (p != NULL) {
+		if (p == intern->pos) {
+			return SUCCESS;
+		}
+		p = p->pListNext;
+	}
+/*	HASH_UNPROTECT_RECURSION(ht); */
+	zend_hash_internal_pointer_reset_ex(HASH_OF(intern->array), &intern->pos);
+	return FAILURE;
+}
+/* }}} */
+
 /* {{{ spl_array_object_free_storage */
 static void spl_array_object_free_storage(void *object TSRMLS_DC)
 {
@@ -141,6 +168,8 @@ static zend_object_value spl_array_object_new_ex(zend_class_entry *class_type, s
 	zend_object_value retval;
 	spl_array_object *intern;
 	zval *tmp;
+	zend_class_entry * parent = class_type;
+	int inherited = 0;
 
 	intern = emalloc(sizeof(spl_array_object));
 	memset(intern, 0, sizeof(spl_array_object));
@@ -154,17 +183,46 @@ static zend_object_value spl_array_object_new_ex(zend_class_entry *class_type, s
 	if (orig) {
 		intern->array = orig->array;
 		ZVAL_ADDREF(intern->array);
+		intern->is_ref = 1;
 	} else {
 		MAKE_STD_ZVAL(intern->array);
 		array_init(intern->array);
+		intern->is_ref = 0;
 	}
 	zend_hash_internal_pointer_reset_ex(HASH_OF(intern->array), &intern->pos);
 
 	retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t) spl_array_object_free_storage, NULL TSRMLS_CC);
-	if (class_type == spl_ce_ArrayIterator) {
-		retval.handlers = &spl_handler_ArrayIterator;
-	} else {
-		retval.handlers = &spl_handler_ArrayObject;
+	while (parent) {
+		if (parent == spl_ce_ArrayIterator) {
+			retval.handlers = &spl_handler_ArrayIterator;
+			break;
+		} else if (parent == spl_ce_ArrayObject) {
+			retval.handlers = &spl_handler_ArrayObject;
+			break;
+		}
+		parent = parent->parent;
+		inherited = 1;
+	}
+	if (!parent) { /* this must never happen */
+		php_error_docref(NULL TSRMLS_CC, E_COMPILE_ERROR, "Internal compiler error, Class is not child of ArrayObject or arrayIterator");
+	}
+	if (inherited) {
+		zend_hash_find(&class_type->function_table, "offsetget",    sizeof("offsetget"),    (void **) &intern->fptr_offset_get);
+		if (intern->fptr_offset_get->common.scope == parent) {
+			intern->fptr_offset_get = NULL;
+		}
+		zend_hash_find(&class_type->function_table, "offsetset",    sizeof("offsetset"),    (void **) &intern->fptr_offset_set);
+		if (intern->fptr_offset_set->common.scope == parent) {
+			intern->fptr_offset_set = NULL;
+		}
+		zend_hash_find(&class_type->function_table, "offsetexists", sizeof("offsetexists"), (void **) &intern->fptr_offset_has);
+		if (intern->fptr_offset_has->common.scope == parent) {
+			intern->fptr_offset_has = NULL;
+		}
+		zend_hash_find(&class_type->function_table, "offsetunset",  sizeof("offsetunset"),  (void **) &intern->fptr_offset_del);
+		if (intern->fptr_offset_del->common.scope == parent) {
+			intern->fptr_offset_del = NULL;
+		}
 	}
 	return retval;
 }
@@ -197,13 +255,16 @@ static zend_object_value spl_array_object_clone(zval *zobject TSRMLS_DC)
 }
 /* }}} */
 
-/* {{{ spl_array_read_dimension */
-static zval *spl_array_read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
+static zval *spl_array_read_dimension_ex(int check_inherited, zval *object, zval *offset, int type TSRMLS_DC) /* {{{ */
 {
 	spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
-	zval **retval;
+	zval **retval, *rv;
 	long index;
 
+	if (check_inherited && intern->fptr_offset_get) {
+		return zend_call_method_with_1_params(&object, Z_OBJCE_P(object), &intern->fptr_offset_get, "offsetGet", &rv, offset);
+	}
+	
 	switch(Z_TYPE_P(offset)) {
 	case IS_STRING:
 		if (zend_symtable_find(HASH_OF(intern->array), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **) &retval) == FAILURE) {
@@ -232,14 +293,23 @@ static zval *spl_array_read_dimension(zval *object, zval *offset, int type TSRML
 		zend_error(E_WARNING, "Illegal offset type");
 		return EG(uninitialized_zval_ptr);
 	}
-}
-/* }}} */
+} /* }}} */
+
+static zval *spl_array_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) /* {{{ */
+{
+	return spl_array_read_dimension_ex(1, object, offset, type TSRMLS_CC);
+} /* }}} */
 
-/* {{{ spl_array_write_dimension */
-static void spl_array_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC)
+static void spl_array_write_dimension_ex(int check_inherited, zval *object, zval *offset, zval *value TSRMLS_DC) /* {{{ */
 {
 	spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
 	long index;
+	zval *rv;
+
+	if (check_inherited && intern->fptr_offset_set) {
+		zend_call_method_with_2_params(&object, Z_OBJCE_P(object), &intern->fptr_offset_set, "offsetSet", &rv, offset, value);
+		return;
+	}
 
 	if (!offset) {
 		value->refcount++;
@@ -267,21 +337,35 @@ static void spl_array_write_dimension(zval *object, zval *offset, zval *value TS
 		zend_error(E_WARNING, "Illegal offset type");
 		return;
 	}
-}
-/* }}} */
+} /* }}} */
 
-/* {{{ spl_array_unset_dimension */
-static void spl_array_unset_dimension(zval *object, zval *offset TSRMLS_DC)
+static void spl_array_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC) /* {{{ */
+{
+	spl_array_write_dimension_ex(1, object, offset, value TSRMLS_CC);
+} /* }}} */
+
+static void spl_array_unset_dimension_ex(int check_inherited, zval *object, zval *offset TSRMLS_DC) /* {{{ */
 {
 	spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
 	long index;
+	zval *rv;
+
+	if (check_inherited && intern->fptr_offset_del) {
+		zend_call_method_with_1_params(&object, Z_OBJCE_P(object), &intern->fptr_offset_del, "offsetUnset", &rv, offset);
+		return;
+	}
 
 	switch(Z_TYPE_P(offset)) {
 	case IS_STRING:
+
+
+
+
+
 		if (zend_symtable_del(HASH_OF(intern->array), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1) == FAILURE) {
 			zend_error(E_NOTICE,"Undefined index:  %s", Z_STRVAL_P(offset));
 		}
-		return;
+		break;
 	case IS_DOUBLE:
 	case IS_RESOURCE:
 	case IS_BOOL: 
@@ -294,19 +378,34 @@ static void spl_array_unset_dimension(zval *object, zval *offset TSRMLS_DC)
 		if (zend_hash_index_del(HASH_OF(intern->array), index) == FAILURE) {
 			zend_error(E_NOTICE,"Undefined offset:  %ld", Z_LVAL_P(offset));
 		}
-		return;
+		break;
 	default:
 		zend_error(E_WARNING, "Illegal offset type");
 		return;
 	}
-}
-/* }}} */
+	spl_hash_verify_pos(intern TSRMLS_CC); /* call rewind on FAILURE */
+} /* }}} */
+
+static void spl_array_unset_dimension(zval *object, zval *offset TSRMLS_DC) /* {{{ */
+{
+	spl_array_unset_dimension_ex(1, object, offset TSRMLS_CC);
+} /* }}} */
 
-/* {{{ spl_array_has_dimension */
-static int spl_array_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC)
+static int spl_array_has_dimension_ex(int check_inherited, zval *object, zval *offset, int check_empty TSRMLS_DC) /* {{{ */
 {
 	spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
 	long index;
+	zval *rv;
+
+	if (check_inherited && intern->fptr_offset_has) {
+		zend_call_method_with_1_params(&object, Z_OBJCE_P(object), &intern->fptr_offset_has, "offsetExists", &rv, offset);
+		if (zend_is_true(rv)) {
+			zval_ptr_dtor(&rv);
+			return 1;
+		}
+		zval_ptr_dtor(&rv);
+		return 0;
+	}
 
 	switch(Z_TYPE_P(offset)) {
 	case IS_STRING:
@@ -325,8 +424,12 @@ static int spl_array_has_dimension(zval *object, zval *offset, int check_empty T
 		zend_error(E_WARNING, "Illegal offset type");
 	}
 	return 0;
-}
-/* }}} */
+} /* }}} */
+
+static int spl_array_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC) /* {{{ */
+{
+	return spl_array_has_dimension_ex(1, object, offset, check_empty TSRMLS_CC);
+} /* }}} */
 
 /* {{{ proto bool ArrayObject::offsetExists(mixed $index)
        proto bool ArrayIterator::offsetExists(mixed $index)
@@ -337,7 +440,7 @@ SPL_METHOD(Array, offsetExists)
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &index) == FAILURE) {
 		return;
 	}
-	RETURN_BOOL(spl_array_has_dimension(getThis(), index, 1 TSRMLS_CC));
+	RETURN_BOOL(spl_array_has_dimension_ex(0, getThis(), index, 1 TSRMLS_CC));
 } /* }}} */
 
 /* {{{ proto bool ArrayObject::offsetGet(mixed $index)
@@ -349,7 +452,7 @@ SPL_METHOD(Array, offsetGet)
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &index) == FAILURE) {
 		return;
 	}
-	value = spl_array_read_dimension(getThis(), index, BP_VAR_R TSRMLS_CC);
+	value = spl_array_read_dimension_ex(0, getThis(), index, BP_VAR_R TSRMLS_CC);
 	RETURN_ZVAL(value, 1, 0);
 } /* }}} */
 
@@ -362,23 +465,15 @@ SPL_METHOD(Array, offsetSet)
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &index, &value) == FAILURE) {
 		return;
 	}
-	spl_array_write_dimension(getThis(), index, value TSRMLS_CC);
+	spl_array_write_dimension_ex(0, getThis(), index, value TSRMLS_CC);
 } /* }}} */
 
-/* {{{ proto void ArrayObject::append(mixed $newval)
-       proto void ArrayIterator::append(mixed $newval)
- Appends the value (cannot be called for objects). */
-SPL_METHOD(Array, append)
+
+void spl_array_iterator_append(zval *object, zval *append_value TSRMLS_DC) /* {{{ */
 {
-	zval *object = getThis();
 	spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
 	HashTable *aht = HASH_OF(intern->array);
 
-	zval *value;
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
-		return;
-	}
-
 	if (!aht) {
 		php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and is no longer an array");
 		return;
@@ -388,12 +483,25 @@ SPL_METHOD(Array, append)
 		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Cannot append properties to objects, use %s::offsetSet() instead", Z_OBJCE_P(object)->name);
 	}
 
-	spl_array_write_dimension(object, NULL, value TSRMLS_CC);
+	spl_array_write_dimension(object, NULL, append_value TSRMLS_CC);
 	if (!intern->pos) {
 		intern->pos = aht->pListTail;
 	}
 } /* }}} */
 
+/* {{{ proto void ArrayObject::append(mixed $newval)
+       proto void ArrayIterator::append(mixed $newval)
+ Appends the value (cannot be called for objects). */
+SPL_METHOD(Array, append)
+{
+	zval *value;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
+		return;
+	}
+	spl_array_iterator_append(getThis(), value TSRMLS_CC);
+} /* }}} */
+
 /* {{{ proto void ArrayObject::offsetUnset(mixed $index)
        proto void ArrayIterator::offsetUnset(mixed $index)
  Unsets the value at the specified $index. */
@@ -403,7 +511,7 @@ SPL_METHOD(Array, offsetUnset)
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &index) == FAILURE) {
 		return;
 	}
-	spl_array_unset_dimension(getThis(), index TSRMLS_CC);
+	spl_array_unset_dimension_ex(0, getThis(), index TSRMLS_CC);
 } /* }}} */
 
 /* {{ proto array ArrayObject::getArrayCopy()
@@ -427,27 +535,6 @@ static HashTable *spl_array_get_properties(zval *object TSRMLS_DC)
 }
 /* }}} */
 
-SPL_API int spl_hash_verify_pos(spl_array_object * intern TSRMLS_DC) /* {{{ */
-{
-	HashTable *ht = HASH_OF(intern->array);
-	Bucket *p;
-
-/*	IS_CONSISTENT(ht);*/
-
-/*	HASH_PROTECT_RECURSION(ht);*/
-	p = ht->pListHead;
-	while (p != NULL) {
-		if (p == intern->pos) {
-			return SUCCESS;
-		}
-		p = p->pListNext;
-	}
-/*	HASH_UNPROTECT_RECURSION(ht); */
-	zend_hash_internal_pointer_reset_ex(HASH_OF(intern->array), &intern->pos);
-	return FAILURE;
-}
-/* }}} */
-
 static int spl_array_skip_protected(spl_array_object *intern TSRMLS_DC) /* {{{ */
 {
 	char *string_key;
@@ -478,11 +565,16 @@ static int spl_array_next(spl_array_object *intern TSRMLS_DC) /* {{{ */
 {
 	HashTable *aht = HASH_OF(intern->array);
 
-	zend_hash_move_forward_ex(aht, &intern->pos);
-	if (Z_TYPE_P(intern->array) == IS_OBJECT) {
-		return spl_array_skip_protected(intern TSRMLS_CC);
+	if (intern->is_ref && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) {
+		php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid");
+		return FAILURE;
 	} else {
-		return zend_hash_has_more_elements_ex(aht, &intern->pos);
+		zend_hash_move_forward_ex(aht, &intern->pos);
+		if (Z_TYPE_P(intern->array) == IS_OBJECT) {
+			return spl_array_skip_protected(intern TSRMLS_CC);
+		} else {
+			return zend_hash_has_more_elements_ex(aht, &intern->pos);
+		}
 	}
 } /* }}} */
 
@@ -513,7 +605,7 @@ static int spl_array_it_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
 		return FAILURE;
 	}
 
-	if (object->pos && object->array->is_ref && spl_hash_verify_pos(object TSRMLS_CC) == FAILURE) {
+	if (object->pos && object->is_ref && spl_hash_verify_pos(object TSRMLS_CC) == FAILURE) {
 		php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::valid(): Array was modified outside object and internal position is no longer valid");
 		return FAILURE;
 	} else {
@@ -545,7 +637,7 @@ static int spl_array_it_get_current_key(zend_object_iterator *iter, char **str_k
 		return HASH_KEY_NON_EXISTANT;
 	}
 
-	if (object->array->is_ref && spl_hash_verify_pos(object TSRMLS_CC) == FAILURE) {
+	if (object->is_ref && spl_hash_verify_pos(object TSRMLS_CC) == FAILURE) {
 		php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::current(): Array was modified outside object and internal position is no longer valid");
 		return HASH_KEY_NON_EXISTANT;
 	}
@@ -566,7 +658,7 @@ static void spl_array_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {
 		return;
 	}
 
-	if (object->array->is_ref && spl_hash_verify_pos(object TSRMLS_CC) == FAILURE) {
+	if (object->is_ref && spl_hash_verify_pos(object TSRMLS_CC) == FAILURE) {
 		php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::next(): Array was modified outside object and internal position is no longer valid");
 	} else {
 		spl_array_next(object TSRMLS_CC);
@@ -574,19 +666,26 @@ static void spl_array_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {
 }
 /* }}} */
 
-static void spl_array_it_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
+static void spl_array_rewind(spl_array_object *intern TSRMLS_DC) /* {{{ */
 {
-	spl_array_it       *iterator = (spl_array_it *)iter;
-	spl_array_object   *object   = iterator->object;
-	HashTable          *aht      = HASH_OF(object->array);
+	HashTable          *aht      = HASH_OF(intern->array);
 
 	if (!aht) {
 		php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::rewind(): Array was modified outside object and is no longer an array");
 		return;
 	}
 
-	zend_hash_internal_pointer_reset_ex(aht, &object->pos);
-	spl_array_skip_protected(object TSRMLS_CC);
+	zend_hash_internal_pointer_reset_ex(aht, &intern->pos);
+	spl_array_skip_protected(intern TSRMLS_CC);
+}
+/* }}} */
+
+static void spl_array_it_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
+{
+	spl_array_it       *iterator = (spl_array_it *)iter;
+	spl_array_object   *object   = iterator->object;
+
+	spl_array_rewind(object TSRMLS_CC);
 }
 /* }}} */
 
@@ -626,8 +725,7 @@ SPL_METHOD(Array, __construct)
 	if (ZEND_NUM_ARGS() == 0) {
 		return; /* nothing to do */
 	}
-/* exceptions do not work yet
-	php_set_error_handling(EH_THROW, zend_exception_get_default() TSRMLS_CC);*/
+	php_set_error_handling(EH_THROW, zend_exception_get_default() TSRMLS_CC);
 
 	intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
 
@@ -641,8 +739,8 @@ SPL_METHOD(Array, __construct)
 		intern->array = other->array;		
 	} else {
 		if (!HASH_OF(*array)) {
-			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passed variable is not an array or object, using empty array instead");
 			php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
+			zend_throw_exception(zend_exception_get_default(), "Passed variable is not an array or object, using empty array instead", 0 TSRMLS_CC);
 			return;
 		}
 		zval_dtor(intern->array);
@@ -684,15 +782,8 @@ SPL_METHOD(Array, rewind)
 {
 	zval *object = getThis();
 	spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
-	HashTable *aht = HASH_OF(intern->array);
-
-	if (!aht) {
-		php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and is no longer an array");
-		return;
-	}
 
-	zend_hash_internal_pointer_reset_ex(aht, &intern->pos);
-	spl_array_skip_protected(intern TSRMLS_CC);
+	spl_array_rewind(intern TSRMLS_CC);
 }
 /* }}} */
 
@@ -700,10 +791,11 @@ SPL_METHOD(Array, rewind)
  Seek to position. */
 SPL_METHOD(Array, seek)
 {
-	long position;
+	long opos, position;
 	zval *object = getThis();
 	spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
 	HashTable *aht = HASH_OF(intern->array);
+	int result;
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &position) == FAILURE) {
 		return;
@@ -714,9 +806,22 @@ SPL_METHOD(Array, seek)
 		return;
 	}
 
-	zend_hash_internal_pointer_reset_ex(aht, &intern->pos);
+	opos = position;
+
+	if (position >= 0) { /* negative values are not supported */
+		zend_hash_internal_pointer_reset_ex(aht, &intern->pos);
+		
+		while (position-- > 0 && (result = spl_array_next(intern TSRMLS_CC)) == SUCCESS);
 	
-	while (position-- > 0 && spl_array_next(intern TSRMLS_CC));
+		if (intern->pos && intern->is_ref && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) {
+			/* fail */
+		} else {
+			if (zend_hash_has_more_elements_ex(aht, &intern->pos) == SUCCESS) {
+				return; /* ok */
+			}
+		}
+	}
+	zend_throw_exception_ex(zend_exception_get_default(), 0 TSRMLS_CC, "Seek position %ld is out of range", opos);
 } /* }}} */
 
 int spl_array_object_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */
@@ -737,9 +842,8 @@ int spl_array_object_count_elements(zval *object, long *count TSRMLS_DC) /* {{{
 		pos = intern->pos;
 		*count = 0;
 		zend_hash_internal_pointer_reset_ex(aht, &intern->pos);
-		while(intern->pos) {
+		while(intern->pos && spl_array_next(intern TSRMLS_CC) == SUCCESS) {
 			(*count)++;
-			spl_array_next(intern TSRMLS_CC);
 		}
 		intern->pos = pos;
 		return SUCCESS;
@@ -774,7 +878,7 @@ SPL_METHOD(Array, current)
 		return;
 	}
 
-	if (intern->array->is_ref && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) {
+	if (intern->is_ref && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) {
 		php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid");
 		return;
 	}
@@ -782,8 +886,7 @@ SPL_METHOD(Array, current)
 	if (zend_hash_get_current_data_ex(aht, (void **) &entry, &intern->pos) == FAILURE) {
 		return;
 	}
-	*return_value = **entry;
-	zval_copy_ctor(return_value);
+	RETVAL_ZVAL(*entry, 1, 0);
 }
 /* }}} */
 
@@ -803,7 +906,7 @@ SPL_METHOD(Array, key)
 		return;
 	}
 
-	if (intern->array->is_ref && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) {
+	if (intern->is_ref && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) {
 		php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid");
 		return;
 	}
@@ -834,11 +937,7 @@ SPL_METHOD(Array, next)
 		return;
 	}
 
-	if (intern->array->is_ref && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) {
-		php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid");
-	} else {
-		spl_array_next(intern TSRMLS_CC);
-	}
+	spl_array_next(intern TSRMLS_CC);
 }
 /* }}} */
 
@@ -855,7 +954,7 @@ SPL_METHOD(Array, valid)
 		return;
 	}
 
-	if (intern->pos && intern->array->is_ref && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) {
+	if (intern->pos && intern->is_ref && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) {
 		php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid");
 		RETURN_FALSE;
 	} else {
diff --git a/ext/spl/spl_array.h b/ext/spl/spl_array.h
index 1e9b402dcb26..e7652abca0ca 100755
--- a/ext/spl/spl_array.h
+++ b/ext/spl/spl_array.h
@@ -24,8 +24,8 @@
 #include "php.h"
 #include "php_spl.h"
 
-extern zend_class_entry *spl_ce_ArrayObject;
-extern zend_class_entry *spl_ce_ArrayIterator;
+extern PHPAPI zend_class_entry *spl_ce_ArrayObject;
+extern PHPAPI zend_class_entry *spl_ce_ArrayIterator;
 
 PHP_MINIT_FUNCTION(spl_array);
 
diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c
index 7a45cf46a1c3..3cbd2cacc930 100755
--- a/ext/spl/spl_directory.c
+++ b/ext/spl/spl_directory.c
@@ -120,9 +120,15 @@ static zend_object_value spl_ce_dir_object_new(zend_class_entry *class_type TSRM
 /* open a directory resource */
 static void spl_ce_dir_open(spl_ce_dir_object* intern, char *path TSRMLS_DC)
 {
+	int path_len = strlen(path);
+
 	intern->dirp = php_stream_opendir(path, ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL);
 
-	intern->path = estrdup(path);
+	if (path_len && (path[path_len-1] == '/' || path[path_len-1] == '\\')) {
+		intern->path = estrndup(path, --path_len);
+	} else {
+		intern->path = estrndup(path, path_len);
+	}
 	intern->index = 0;
 
 	if (intern->dirp == NULL) {
@@ -341,47 +347,47 @@ SPL_METHOD(DirectoryIterator, func_name) \
 }
 /* }}} */
 
-/* {{{ proto int DirectoryIterator::filePerms()
+/* {{{ proto int DirectoryIterator::getPerms()
    Get file permissions */
 FileFunction(getPerms, FS_PERMS)
 /* }}} */
 
-/* {{{ proto int DirectoryIterator::fileInode()
+/* {{{ proto int DirectoryIterator::getInode()
    Get file inode */
 FileFunction(getInode, FS_INODE)
 /* }}} */
 
-/* {{{ proto int DirectoryIterator::fileSize()
+/* {{{ proto int DirectoryIterator::getSize()
    Get file size */
 FileFunction(getSize, FS_SIZE)
 /* }}} */
 
-/* {{{ proto int DirectoryIterator::fileOwner()
+/* {{{ proto int DirectoryIterator::getOwner()
    Get file owner */
 FileFunction(getOwner, FS_OWNER)
 /* }}} */
 
-/* {{{ proto int DirectoryIterator::fileGroup()
+/* {{{ proto int DirectoryIterator::getGroup()
    Get file group */
 FileFunction(getGroup, FS_GROUP)
 /* }}} */
 
-/* {{{ proto int DirectoryIterator::fileATime()
+/* {{{ proto int DirectoryIterator::getATime()
    Get last access time of file */
 FileFunction(getATime, FS_ATIME)
 /* }}} */
 
-/* {{{ proto int DirectoryIterator::fileMTime()
+/* {{{ proto int DirectoryIterator::getMTime()
    Get last modification time of file */
 FileFunction(getMTime, FS_MTIME)
 /* }}} */
 
-/* {{{ proto int DirectoryIterator::fileCTime()
+/* {{{ proto int DirectoryIterator::getCTime()
    Get inode modification time of file */
 FileFunction(getCTime, FS_CTIME)
 /* }}} */
 
-/* {{{ proto string DirectoryIterator::fileType()
+/* {{{ proto string DirectoryIterator::getType()
    Get file type */
 FileFunction(getType, FS_TYPE)
 /* }}} */
diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c
index f0a768c2c00d..44ef7fef82b6 100755
--- a/ext/spl/spl_iterators.c
+++ b/ext/spl/spl_iterators.c
@@ -187,8 +187,9 @@ static void spl_recursive_it_move_forward_ex(spl_recursive_it_object *object TSR
 	zend_class_entry          *ce;
 	zval                      *retval, *child;
 	zend_object_iterator      *sub_iter;
+	int                       has_children;
 
-	while (1) {
+	while (!EG(exception)) {
 next_step:
 		iterator = object->iterators[object->level].iterator;
 		switch (object->iterators[object->level].state) {
@@ -204,19 +205,21 @@ static void spl_recursive_it_move_forward_ex(spl_recursive_it_object *object TSR
 				ce = object->iterators[object->level].ce;
 				zobject = object->iterators[object->level].zobject;
 				zend_call_method_with_0_params(&zobject, ce, NULL, "haschildren", &retval);
-				if (zend_is_true(retval)) {
+				if (retval) {
+					has_children = zend_is_true(retval);
 					zval_ptr_dtor(&retval);
-					switch (object->mode) {
-						case RIT_LEAVES_ONLY:
-						case RIT_CHILD_FIRST:
-							object->iterators[object->level].state = RS_CHILD;
-							goto next_step;
-						case RIT_SELF_FIRST:
-							object->iterators[object->level].state = RS_SELF;
-							goto next_step;
+					if (has_children) {
+						switch (object->mode) {
+							case RIT_LEAVES_ONLY:
+							case RIT_CHILD_FIRST:
+								object->iterators[object->level].state = RS_CHILD;
+								goto next_step;
+							case RIT_SELF_FIRST:
+								object->iterators[object->level].state = RS_SELF;
+								goto next_step;
+						}
 					}
 				}
-				zval_ptr_dtor(&retval);
 				object->iterators[object->level].state = RS_NEXT;
 				return /* self */;
 			case RS_SELF:
@@ -230,7 +233,7 @@ static void spl_recursive_it_move_forward_ex(spl_recursive_it_object *object TSR
 				ce = object->iterators[object->level].ce;
 				zobject = object->iterators[object->level].zobject;
 				zend_call_method_with_0_params(&zobject, ce, NULL, "getchildren", &child);
-				ce = child ? Z_OBJCE_P(child) : NULL;
+				ce = child && Z_TYPE_P(child) == IS_OBJECT ? Z_OBJCE_P(child) : NULL;
 				if (!ce || !instanceof_function(ce, spl_ce_RecursiveIterator TSRMLS_CC)) {
 					if (child) {
 						zval_ptr_dtor(&child);
@@ -314,7 +317,7 @@ zend_object_iterator_funcs spl_recursive_it_iterator_funcs = {
 	spl_recursive_it_rewind
 };
 
-/* {{{ proto RecursiveIteratorIterator::__construct(RecursiveIterator $it)
+/* {{{ proto RecursiveIteratorIterator::__construct(RecursiveIterator it [, int flags = RIT_LEAVES_ONLY])
    Creates a RecursiveIteratorIterator from a RecursiveIterator. */
 SPL_METHOD(RecursiveIteratorIterator, __construct)
 {
@@ -414,8 +417,8 @@ SPL_METHOD(RecursiveIteratorIterator, getDepth)
 	RETURN_LONG(object->level);
 } /* }}} */
 
-/* {{{ proto RecursiveIterator RecursiveIteratorIterator::getSubIterator()
-   The current active sub iterator */
+/* {{{ proto RecursiveIterator RecursiveIteratorIterator::getSubIterator([int level])
+   The current active sub iterator or the iterator at specified level */
 SPL_METHOD(RecursiveIteratorIterator, getSubIterator)
 {
 	spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
@@ -489,18 +492,19 @@ static int spl_dual_it_gets_implemented(zend_class_entry *interface, zend_class_
 }
 #endif
 
-static union _zend_function *spl_dual_it_get_method(zval *object, char *method, int method_len TSRMLS_DC)
+static union _zend_function *spl_dual_it_get_method(zval *object_ptr, char *method, int method_len TSRMLS_DC)
 {
 	union _zend_function *function_handler;
 	spl_dual_it_object   *intern;
 
-	intern = (spl_dual_it_object*)zend_object_store_get_object(object TSRMLS_CC);
+	intern = (spl_dual_it_object*)zend_object_store_get_object(object_ptr TSRMLS_CC);
 
-	function_handler = std_object_handlers.get_method(object, method, method_len TSRMLS_CC);
+	function_handler = std_object_handlers.get_method(object_ptr, method, method_len TSRMLS_CC);
 	if (!function_handler) {
 		if (zend_hash_find(&intern->inner.ce->function_table, method, method_len+1, (void **) &function_handler) == FAILURE) {
 			if (Z_OBJ_HT_P(intern->inner.zobject)->get_method) {
-				function_handler = Z_OBJ_HT_P(intern->inner.zobject)->get_method(intern->inner.zobject, method, method_len TSRMLS_CC);
+				object_ptr = intern->inner.zobject;
+				function_handler = Z_OBJ_HT_P(object_ptr)->get_method(object_ptr, method, method_len TSRMLS_CC);
 			}
 		}
 	}
@@ -609,7 +613,7 @@ static INLINE spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAME
 	return intern;
 }
 
-/* {{{ proto FilterIterator::__construct(Iterator $it) 
+/* {{{ proto FilterIterator::__construct(Iterator it) 
    Create an Iterator from another iterator */
 SPL_METHOD(dual_it, __construct)
 {
@@ -634,8 +638,16 @@ SPL_METHOD(dual_it, getInnerIterator)
 	}
 } /* }}} */
 
+static INLINE void spl_dual_it_require(spl_dual_it_object *intern TSRMLS_DC)
+{
+	if (!intern->inner.iterator) {
+		php_error_docref(NULL TSRMLS_CC, E_ERROR, "The inner constructor wasn't initialized with an iterator instance");
+	}
+}
+
 static INLINE void spl_dual_it_free(spl_dual_it_object *intern TSRMLS_DC)
 {
+	spl_dual_it_require(intern TSRMLS_CC);
 	if (intern->inner.iterator && intern->inner.iterator->funcs->invalidate_current) {
 		intern->inner.iterator->funcs->invalidate_current(intern->inner.iterator TSRMLS_CC);
 	}
@@ -698,6 +710,8 @@ static INLINE void spl_dual_it_next(spl_dual_it_object *intern, int do_free TSRM
 {
 	if (do_free) {
 		spl_dual_it_free(intern TSRMLS_CC);
+	} else {
+		spl_dual_it_require(intern TSRMLS_CC);
 	}
 	intern->inner.iterator->funcs->move_forward(intern->inner.iterator TSRMLS_CC);
 	intern->current.pos++;
@@ -829,7 +843,7 @@ SPL_METHOD(FilterIterator, next)
 	spl_filter_it_next(getThis(), intern TSRMLS_CC);
 } /* }}} */
 
-/* {{{ proto ParentIterator::__construct(RecursiveIterator $it)
+/* {{{ proto ParentIterator::__construct(RecursiveIterator it)
    Create a ParentIterator from a RecursiveIterator */
 SPL_METHOD(ParentIterator, __construct)
 {
@@ -985,7 +999,7 @@ static INLINE void spl_limit_it_seek(spl_dual_it_object *intern, long pos TSRMLS
 	}
 }
 
-/* {{{ proto LimitIterator::__construct(Iterator $it [, int $offset, int $count])
+/* {{{ proto LimitIterator::__construct(Iterator it [, int offset, int count])
    Construct a LimitIterator from an Iterator with a given starting offset and optionally a maximum count */
 SPL_METHOD(LimitIterator, __construct)
 {
@@ -1029,7 +1043,7 @@ SPL_METHOD(LimitIterator, next)
 	}
 } /* }}} */
 
-/* {{{ proto void LimitIterator::seek(int $position)
+/* {{{ proto void LimitIterator::seek(int position)
    Seek to the given position */
 SPL_METHOD(LimitIterator, seek)
 {
@@ -1161,6 +1175,7 @@ static INLINE void spl_caching_it_next(spl_dual_it_object *intern TSRMLS_DC)
 					zval_copy_ctor(intern->u.caching.zstr);
 					zval_dtor(&expr_copy);
 				} else {
+					INIT_PZVAL(intern->u.caching.zstr);
 					zval_copy_ctor(intern->u.caching.zstr);
 				}
 			}
@@ -1177,7 +1192,7 @@ static INLINE void spl_caching_it_rewind(spl_dual_it_object *intern TSRMLS_DC)
 	spl_caching_it_next(intern TSRMLS_CC);
 }
 
-/* {{{ proto CachingIterator::__construct(Iterator $it)
+/* {{{ proto CachingIterator::__construct(Iterator it [, flags = CIT_CALL_TOSTRING])
    Construct a CachingIterator from an Iterator */
 SPL_METHOD(CachingIterator, __construct)
 {
@@ -1218,7 +1233,7 @@ SPL_METHOD(CachingIterator, next)
 } /* }}} */
 
 /* {{{ proto boolean CachingIterator::hasNext()
-   Cehck whether the inner iterator has a valid next element */
+   Check whether the inner iterator has a valid next element */
 SPL_METHOD(CachingIterator, hasNext)
 {
 	spl_dual_it_object   *intern;
@@ -1229,7 +1244,7 @@ SPL_METHOD(CachingIterator, hasNext)
 } /* }}} */
 
 /* {{{ proto string CachingIterator::__toString()
-   Retrun the string representation of the current element */
+   Return the string representation of the current element */
 SPL_METHOD(CachingIterator, __toString)
 {
 	spl_dual_it_object   *intern;
@@ -1249,7 +1264,7 @@ SPL_METHOD(CachingIterator, __toString)
 static
 ZEND_BEGIN_ARG_INFO(arginfo_caching_it___construct, 0) 
 	ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
-	ZEND_ARG_INFO(0, getStrVal)
+	ZEND_ARG_INFO(0, flags)
 ZEND_END_ARG_INFO();
 
 static zend_function_entry spl_funcs_CachingIterator[] = {
@@ -1265,7 +1280,7 @@ static zend_function_entry spl_funcs_CachingIterator[] = {
 	{NULL, NULL, NULL}
 };
 
-/* {{{ proto CachingRecursiveIterator::__construct(RecursiveIterator $it)
+/* {{{ proto CachingRecursiveIterator::__construct(RecursiveIterator it [, flags = CIT_CALL_TOSTRING])
    Create an iterator from a RecursiveIterator */
 SPL_METHOD(CachingRecursiveIterator, __construct)
 {
@@ -1273,7 +1288,7 @@ SPL_METHOD(CachingRecursiveIterator, __construct)
 } /* }}} */
 
 /* {{{ proto bolean CachingRecursiveIterator::hasChildren()
-   Cehck whether the current element of the inner iterator has children */
+   Check whether the current element of the inner iterator has children */
 SPL_METHOD(CachingRecursiveIterator, hasChildren)
 {
 	spl_dual_it_object   *intern;
@@ -1284,7 +1299,7 @@ SPL_METHOD(CachingRecursiveIterator, hasChildren)
 } /* }}} */
 
 /* {{{ proto CachingRecursiveIterator CachingRecursiveIterator::getChildren()
-  Return the inenr iteraor's children as a CachingRecursiveIterator */
+  Return the inner iterator's children as a CachingRecursiveIterator */
 SPL_METHOD(CachingRecursiveIterator, getChildren)
 {
 	spl_dual_it_object   *intern;
@@ -1301,8 +1316,7 @@ SPL_METHOD(CachingRecursiveIterator, getChildren)
 static
 ZEND_BEGIN_ARG_INFO_EX(arginfo_caching_rec_it___construct, 0, ZEND_RETURN_REFERENCE_AGNOSTIC, 2) 
 	ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
-	ZEND_ARG_INFO(0, getStrVal)
-	ZEND_ARG_INFO(0, catch_getChildren)
+	ZEND_ARG_INFO(0, flags)
 ZEND_END_ARG_INFO();
 
 static zend_function_entry spl_funcs_CachingRecursiveIterator[] = {
diff --git a/ext/spl/tests/array_009.phpt b/ext/spl/tests/array_009.phpt
index f9c5fe1c7309..5499caad695f 100755
--- a/ext/spl/tests/array_009.phpt
+++ b/ext/spl/tests/array_009.phpt
@@ -1,5 +1,7 @@
 --TEST--
 SPL: ArrayIterator implementing RecursiveIterator
+--SKIPIF--
+
 --FILE--
 
+
 --FILE--
 
+--FILE--
+count());
+$it->seek(5);
+var_dump($it->current());
+$it->seek(4);
+var_dump($it->current());
+try
+{
+	$it->seek(-1);
+	var_dump($it->current());
+}
+catch(Exception $e)
+{
+	echo $e->getMessage() . "\n";
+}
+
+try
+{
+	$it->seek(12);
+	var_dump($it->current());
+}
+catch(Exception $e)
+{
+	echo $e->getMessage() . "\n";
+}
+
+$pos = 0;
+foreach($it as $v)
+{
+	$it->seek($pos++);
+	var_dump($v);
+}
+
+?>
+===DONE===
+
+--EXPECTF--
+int(11)
+int(5)
+int(4)
+Seek position -1 is out of range
+Seek position 12 is out of range
+int(0)
+int(1)
+int(2)
+int(3)
+int(4)
+int(5)
+int(6)
+int(7)
+int(8)
+int(9)
+int(10)
+===DONE===
diff --git a/ext/spl/tests/array_015.phpt b/ext/spl/tests/array_015.phpt
new file mode 100755
index 000000000000..0a82fc7a5d03
--- /dev/null
+++ b/ext/spl/tests/array_015.phpt
@@ -0,0 +1,85 @@
+--TEST--
+SPL: ArrayIterator::next() with internal arrays
+--FILE--
+getIterator();
+
+$ar->offsetUnset($it->key());
+$it->next();
+
+var_dump($it->current());
+var_dump($ar);
+
+foreach($it as $k => $v)
+{
+	$ar->offsetUnset($k+1);
+	echo "$k=>$v\n";
+}
+
+var_dump($ar);
+
+foreach($it as $k => $v)
+{
+	$ar->offsetUnset($k);
+	echo "$k=>$v\n";
+}
+
+var_dump($ar);
+
+?>
+===DONE===
+
+--EXPECTF--
+object(ArrayObject)#%d (5) {
+  [0]=>
+  int(1)
+  [1]=>
+  int(2)
+  [2]=>
+  int(3)
+  [3]=>
+  int(4)
+  [4]=>
+  int(5)
+}
+
+Notice: ArrayIterator::next(): Array was modified outside object and internal position is no longer valid in %sarray_015.php on line %d
+int(2)
+object(ArrayObject)#%d (4) {
+  [1]=>
+  int(2)
+  [2]=>
+  int(3)
+  [3]=>
+  int(4)
+  [4]=>
+  int(5)
+}
+1=>2
+3=>4
+object(ArrayObject)#%d (2) {
+  [1]=>
+  int(2)
+  [3]=>
+  int(4)
+}
+1=>2
+
+Notice: main(): ArrayIterator::next(): Array was modified outside object and internal position is no longer valid in %sarray_015.php on line %d
+3=>4
+
+Notice: main(): ArrayIterator::next(): Array was modified outside object and internal position is no longer valid in %sarray_015.php on line %d
+object(ArrayObject)#%d (0) {
+}
+===DONE===
diff --git a/ext/spl/tests/bug28822.phpt b/ext/spl/tests/bug28822.phpt
index c3da4607f557..0cf5575367f6 100755
--- a/ext/spl/tests/bug28822.phpt
+++ b/ext/spl/tests/bug28822.phpt
@@ -1,5 +1,7 @@
 --TEST--
-Bug #28822: ArrayObject::offsetExists() works inverted
+Bug #28822 (ArrayObject::offsetExists() works inverted)
+--SKIPIF--
+
 --FILE--
 array[$index]);
+	}
+
+	public function offsetGet($index) {
+		return $this->array[$index];
+	}
+
+	public function offsetSet($index, $value) {
+		echo __METHOD__ . "($index, $value)\n";
+		$this->array[$index] = $value;
+	}
+
+	public function offsetUnset($index) {
+		throw new Exception('FAIL');
+		unset($this->array[$index]);
+	}
+
+}
+
+$i = 0; $j = 0;
+$foo = new FooBar();
+$foo[$j++] = $i++;
+$foo[$j++] = $i++;
+$foo[$j++] = $i++;
+try
+{
+	unset($foo[1]);
+}
+catch (Exception $e)
+{
+	echo "CAUGHT: " . $e->getMessage() . "\n";
+}
+
+print_R($foo);
+?>
+===DONE===
+--EXPECT--
+FooBar::offsetSet(0, 0)
+FooBar::offsetSet(1, 1)
+FooBar::offsetSet(2, 2)
+CAUGHT: FAIL
+FooBar Object
+(
+    [array:private] => Array
+        (
+            [0] => 0
+            [1] => 1
+            [2] => 2
+        )
+
+)
+===DONE===
diff --git a/ext/spl/tests/bug31346.phpt b/ext/spl/tests/bug31346.phpt
new file mode 100755
index 000000000000..9b5618ec0eea
--- /dev/null
+++ b/ext/spl/tests/bug31346.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Bug #31486 (ArrayIterator::next segfaults)
+--FILE--
+var1=1;
+
+$ao = new ArrayObject($obj);
+
+$i = $ao->getIterator();
+
+$ao->offsetUnset($i->key());
+$i->next();
+
+?>
+===DONE===
+--EXPECTF--
+Notice: ArrayIterator::next(): Array was modified outside object and internal position is no longer valid in %sbug31346.php on line %d
+===DONE===
diff --git a/ext/spl/tests/bug31348.phpt b/ext/spl/tests/bug31348.phpt
new file mode 100755
index 000000000000..047e4b223ac2
--- /dev/null
+++ b/ext/spl/tests/bug31348.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Bug #31348 (CachingIterator::rewind() leaks)
+--FILE--
+rewind();
+
+?>
+===DONE===
+--EXPECT--
+===DONE===
diff --git a/ext/spl/tests/bug31926.phpt b/ext/spl/tests/bug31926.phpt
new file mode 100755
index 000000000000..428039b1cb46
--- /dev/null
+++ b/ext/spl/tests/bug31926.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Bug #31926 (php in free() error with RecursiveArrayIterator)
+--FILE--
+ array('world'));
+
+class RecursiveArrayIterator extends ArrayIterator implements
+RecursiveIterator {
+   function hasChildren() {
+       return (is_array($this->current()));
+   }
+
+   function getChildren() {
+       return new self($this->current());
+   }
+}
+
+$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
+foreach($it as $key => $val) {
+   var_dump($key, $val);
+}
+
+?>
+--EXPECT--
+int(0)
+string(5) "world"
diff --git a/ext/spl/tests/bug32134.phpt b/ext/spl/tests/bug32134.phpt
new file mode 100755
index 000000000000..5a880b321d1c
--- /dev/null
+++ b/ext/spl/tests/bug32134.phpt
@@ -0,0 +1,48 @@
+--TEST--
+Bug #32134 (Overloading offsetGet/offsetSet)
+--FILE--
+ 3) exit(1);
+        return parent::offsetGet($index);
+    }
+
+    public function offsetSet($index, $newval)
+    {
+        echo __METHOD__ . "($index,$newval)\n";
+        return parent::offsetSet($index, $newval);
+    }
+
+}
+
+$myArray = new myArray();
+
+$myArray->offsetSet('one', 'one');
+var_dump($myArray->offsetGet('one'));
+
+$myArray['two'] = 'two';
+var_dump($myArray['two']);
+
+?>
+===DONE===
+
+--EXPECT--
+myArray::offsetSet(one,one)
+myArray::offsetGet(one)
+string(3) "one"
+myArray::offsetSet(two,two)
+myArray::offsetGet(two)
+string(3) "two"
+===DONE===
diff --git a/ext/spl/tests/bug32394.phpt b/ext/spl/tests/bug32394.phpt
new file mode 100755
index 000000000000..8189b23f7a97
--- /dev/null
+++ b/ext/spl/tests/bug32394.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Bug #32394 (offsetUnset() segfaults in a foreach)
+--FILE--
+append(1);
+
+foreach($object as $key => $value)
+{
+	$object->offsetUnset($key);
+}
+
+?>
+===DONE===
+--EXPECT--
+===DONE===
diff --git a/ext/spl/tests/dit_001.phpt b/ext/spl/tests/dit_001.phpt
new file mode 100755
index 000000000000..f02291c77ba1
--- /dev/null
+++ b/ext/spl/tests/dit_001.phpt
@@ -0,0 +1,19 @@
+--TEST--
+SPL: Problem with casting to string
+--SKIPIF--
+
+--FILE--
+
+===DONE===
+--EXPECTF--
+object(DirectoryIterator)#%d (0) {
+}
+bool(false)
+bool(false)
+===DONE===
diff --git a/ext/spl/tests/iterator_002.phpt b/ext/spl/tests/iterator_002.phpt
index 25a9ce218d59..b481a0e00fc4 100755
--- a/ext/spl/tests/iterator_002.phpt
+++ b/ext/spl/tests/iterator_002.phpt
@@ -1,5 +1,7 @@
 --TEST--
 SPL: Iterator using getInnerIterator
+--SKIPIF--
+
 --FILE--
 $ext_srcdir/libsqlite/src/sqlite.h
 
-    if test "$ext_shared" = "no"; then
-      echo '#include "php_config.h"' > $ext_srcdir/libsqlite/src/config.h
+    if test "$ext_shared" = "no" || test -d $abs_srcdir/Zend ; then
+      echo '#include ' > $ext_srcdir/libsqlite/src/config.h
     else
       echo "#include \"$abs_builddir/config.h\"" > $ext_srcdir/libsqlite/src/config.h
     fi
diff --git a/ext/sqlite/libsqlite/src/sqlite.w32.h b/ext/sqlite/libsqlite/src/sqlite.w32.h
index becef0979032..996eab06335e 100644
--- a/ext/sqlite/libsqlite/src/sqlite.w32.h
+++ b/ext/sqlite/libsqlite/src/sqlite.w32.h
@@ -167,6 +167,7 @@ int sqlite_exec(
 #define SQLITE_AUTH        23   /* Authorization denied */
 #define SQLITE_FORMAT      24   /* Auxiliary database format error */
 #define SQLITE_RANGE       25   /* 2nd parameter to sqlite_bind out of range */
+#define SQLITE_NOTADB      26   /* File opened that is not a database file */
 #define SQLITE_ROW         100  /* sqlite_step() has another row ready */
 #define SQLITE_DONE        101  /* sqlite_step() has finished executing */
 
diff --git a/ext/sqlite/sess_sqlite.c b/ext/sqlite/sess_sqlite.c
index 8789cd61095a..d3cb132f1039 100644
--- a/ext/sqlite/sess_sqlite.c
+++ b/ext/sqlite/sess_sqlite.c
@@ -21,7 +21,7 @@
 
 #include "php.h"
 
-#if HAVE_PHP_SESSION
+#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
 
 #include "ext/session/php_session.h"
 #include "ext/standard/php_lcg.h"
@@ -185,7 +185,7 @@ PS_GC_FUNC(sqlite)
 	return SQLITE_RETVAL(rv);
 }
 
-#endif /* HAVE_PHP_SESSION */
+#endif /* HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION) */
 
 /*
  * Local variables:
diff --git a/ext/sqlite/sqlite.c b/ext/sqlite/sqlite.c
index 5e6c228ee918..35c5e9c56df5 100644
--- a/ext/sqlite/sqlite.c
+++ b/ext/sqlite/sqlite.c
@@ -49,7 +49,7 @@
 
 ZEND_DECLARE_MODULE_GLOBALS(sqlite)
 
-#if HAVE_PHP_SESSION
+#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
 extern ps_module ps_mod_sqlite;
 #define ps_sqlite_ptr &ps_mod_sqlite
 #endif
@@ -998,6 +998,10 @@ PHP_MINIT_FUNCTION(sqlite)
 	REGISTER_SQLITE_CLASS(Result,     query,     NULL);
 	REGISTER_SQLITE_CLASS(Unbuffered, ub_query,  NULL);
 	REGISTER_SQLITE_CLASS(Exception,  exception, zend_exception_get_default());
+
+	sqlite_ce_db->ce_flags &= ~ZEND_ACC_FINAL_CLASS;
+	sqlite_ce_db->constructor->common.fn_flags |= ZEND_ACC_FINAL;
+
 	sqlite_object_handlers_query.get_class_entry = sqlite_get_ce_query;
 	sqlite_object_handlers_ub_query.get_class_entry = sqlite_get_ce_ub_query;
 	
@@ -1011,7 +1015,7 @@ PHP_MINIT_FUNCTION(sqlite)
 
 	REGISTER_INI_ENTRIES();
 
-#if HAVE_PHP_SESSION
+#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
 	php_session_register_module(ps_sqlite_ptr);
 #endif
 	
@@ -1047,6 +1051,7 @@ PHP_MINIT_FUNCTION(sqlite)
 	REGISTER_LONG_CONSTANT("SQLITE_MISUSE",			SQLITE_MISUSE, CONST_CS|CONST_PERSISTENT);
 	REGISTER_LONG_CONSTANT("SQLITE_NOLFS",			SQLITE_NOLFS, CONST_CS|CONST_PERSISTENT);
 	REGISTER_LONG_CONSTANT("SQLITE_AUTH",			SQLITE_AUTH, CONST_CS|CONST_PERSISTENT);
+	REGISTER_LONG_CONSTANT("SQLITE_NOTADB",			SQLITE_NOTADB, CONST_CS|CONST_PERSISTENT);
 #ifdef SQLITE_FORMAT
 	REGISTER_LONG_CONSTANT("SQLITE_FORMAT",			SQLITE_FORMAT, CONST_CS|CONST_PERSISTENT);
 #endif
@@ -1168,6 +1173,7 @@ PHP_FUNCTION(sqlite_popen)
 	}
 	if (errmsg) {
 		zval_dtor(errmsg);
+		ZVAL_NULL(errmsg);
 	}
 
 	if (strncmp(filename, ":memory:", sizeof(":memory:") - 1)) {
@@ -1243,6 +1249,7 @@ PHP_FUNCTION(sqlite_open)
 	}
 	if (errmsg) {
 		zval_dtor(errmsg);
+		ZVAL_NULL(errmsg);
 	}
 
 	if (strncmp(filename, ":memory:", sizeof(":memory:") - 1)) {
@@ -1297,6 +1304,7 @@ PHP_FUNCTION(sqlite_factory)
 	}
 	if (errmsg) {
 		zval_dtor(errmsg);
+		ZVAL_NULL(errmsg);
 	}
 
 	if (strncmp(filename, ":memory:", sizeof(":memory:") - 1)) {
@@ -1597,7 +1605,7 @@ PHP_FUNCTION(sqlite_fetch_column_types)
 		DB_FROM_ZVAL(db, &zdb);
 	}
 
-	if (!(sql = sqlite_mprintf("SELECT * FROM %q LIMIT 1", tbl))) {
+	if (!(sql = sqlite_mprintf("SELECT * FROM '%q' LIMIT 1", tbl))) {
 		RETURN_FALSE;
 	}
 
@@ -1969,6 +1977,7 @@ PHP_FUNCTION(sqlite_fetch_object)
 	if (res->curr_row < res->nrows) {
 		php_sqlite_fetch_array(res, PHPSQLITE_ASSOC, decode_binary, 1, &dataset TSRMLS_CC);
 	} else {
+		php_std_error_handling();
 		RETURN_FALSE;
 	}
 
@@ -2680,12 +2689,14 @@ PHP_FUNCTION(sqlite_escape_string)
 		enclen = php_sqlite_encode_binary(string, stringlen, ret+1);
 		RETVAL_STRINGL(ret, enclen+1, 0);
 		
-	} else  {
+	} else if (stringlen) {
 		ret = sqlite_mprintf("%q", string);
 		if (ret) {
 			RETVAL_STRING(ret, 1);
 			sqlite_freemem(ret);
 		}
+	} else {
+		RETURN_EMPTY_STRING();
 	}
 }
 /* }}} */
diff --git a/ext/standard/Makefile.frag b/ext/standard/Makefile.frag
index f68fcea4057e..c3a27b0a4886 100644
--- a/ext/standard/Makefile.frag
+++ b/ext/standard/Makefile.frag
@@ -8,6 +8,6 @@ $(srcdir)/var_unserializer.c: $(srcdir)/var_unserializer.re
 $(srcdir)/url_scanner_ex.c: $(srcdir)/url_scanner_ex.re
 	$(RE2C) -b $(srcdir)/url_scanner_ex.re > $@
 
-$(srcdir)/info.c: $(builddir)/../../main/build-defs.h
+$(builddir)/info.lo: $(builddir)/../../main/build-defs.h
 
 $(builddir)/basic_functions.lo: Zend/zend_language_parser.h
diff --git a/ext/standard/array.c b/ext/standard/array.c
index 0b042142ab85..ed87c0c9fcbe 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -65,6 +65,7 @@ php_array_globals array_globals;
 #define SORT_REGULAR			0
 #define SORT_NUMERIC			1
 #define	SORT_STRING				2
+#define	SORT_LOCALE_STRING      5
 
 #define SORT_DESC				3
 #define SORT_ASC				4
@@ -112,6 +113,8 @@ PHP_MINIT_FUNCTION(array)
 	REGISTER_LONG_CONSTANT("SORT_REGULAR", SORT_REGULAR, CONST_CS | CONST_PERSISTENT);
 	REGISTER_LONG_CONSTANT("SORT_NUMERIC", SORT_NUMERIC, CONST_CS | CONST_PERSISTENT);
 	REGISTER_LONG_CONSTANT("SORT_STRING", SORT_STRING, CONST_CS | CONST_PERSISTENT);
+	REGISTER_LONG_CONSTANT("SORT_LOCALE_STRING", SORT_LOCALE_STRING, CONST_CS | CONST_PERSISTENT);
+
 	REGISTER_LONG_CONSTANT("CASE_LOWER", CASE_LOWER, CONST_CS | CONST_PERSISTENT);
 	REGISTER_LONG_CONSTANT("CASE_UPPER", CASE_UPPER, CONST_CS | CONST_PERSISTENT);
 
@@ -141,6 +144,12 @@ static void set_compare_func(int sort_type TSRMLS_DC)
 			ARRAYG(compare_func) = string_compare_function;
 			break;
 
+#if HAVE_STRCOLL
+		case SORT_LOCALE_STRING:
+			ARRAYG(compare_func) = string_locale_compare_function;
+			break;
+#endif
+
 		case SORT_REGULAR:
 		default:
 			ARRAYG(compare_func) = compare_function;
@@ -569,43 +578,66 @@ static int array_user_compare(const void *a, const void *b TSRMLS_DC)
 	}
 }
 
-/* check is comparison function is valid */
+/* check if comparison function is valid */
 #define PHP_ARRAY_CMP_FUNC_CHECK(func_name)	\
 	if (!zend_is_callable(*func_name, 0, NULL)) {	\
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid comparison function.");	\
+		BG(user_compare_fci_cache) = old_user_compare_fci_cache; \
 		BG(user_compare_func_name) = old_compare_func;	\
 		RETURN_FALSE;	\
 	}	\
 
+    /* clear FCI cache otherwise : for example the same or other array with
+       (partly) the same key values has been sorted with uasort() or
+       other sorting function the comparison is cached, however the the name
+       of the function for comparison is not respected. see bug #28739 AND #33295
+
+       following defines will assist in backup / restore values.
+    */
+
+#define PHP_ARRAY_CMP_FUNC_VARS \
+	zval **old_compare_func; \
+	zend_fcall_info_cache old_user_compare_fci_cache
+
+#define PHP_ARRAY_CMP_FUNC_BACKUP() \
+	old_compare_func = BG(user_compare_func_name); \
+	old_user_compare_fci_cache = BG(user_compare_fci_cache); \
+	BG(user_compare_fci_cache) = empty_fcall_info_cache
+
+#define PHP_ARRAY_CMP_FUNC_RESTORE() \
+        BG(user_compare_fci_cache) = old_user_compare_fci_cache; \
+        BG(user_compare_func_name) = old_compare_func
+
+
 /* {{{ proto bool usort(array array_arg, string cmp_function)
    Sort an array by values using a user-defined comparison function */
 PHP_FUNCTION(usort)
 {
 	zval **array;
-	zval **old_compare_func;
 	HashTable *target_hash;
+	PHP_ARRAY_CMP_FUNC_VARS;
+
+	PHP_ARRAY_CMP_FUNC_BACKUP();
 
-	old_compare_func = BG(user_compare_func_name);
-	BG(user_compare_fci_cache) = empty_fcall_info_cache;
 
 	if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &array, &BG(user_compare_func_name)) == FAILURE) {
-		BG(user_compare_func_name) = old_compare_func;
+		PHP_ARRAY_CMP_FUNC_RESTORE();
 		WRONG_PARAM_COUNT;
 	}
 	target_hash = HASH_OF(*array);
 	if (!target_hash) {
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array");
-		BG(user_compare_func_name) = old_compare_func;
+		PHP_ARRAY_CMP_FUNC_RESTORE();
 		RETURN_FALSE;
 	}
 
 	PHP_ARRAY_CMP_FUNC_CHECK(BG(user_compare_func_name))
 	
 	if (zend_hash_sort(target_hash, zend_qsort, array_user_compare, 1 TSRMLS_CC) == FAILURE) {
-		BG(user_compare_func_name) = old_compare_func;
+		PHP_ARRAY_CMP_FUNC_RESTORE();
 		RETURN_FALSE;
 	}
-	BG(user_compare_func_name) = old_compare_func;
+	PHP_ARRAY_CMP_FUNC_RESTORE();
 	RETURN_TRUE;
 }
 /* }}} */
@@ -615,29 +647,30 @@ PHP_FUNCTION(usort)
 PHP_FUNCTION(uasort)
 {
 	zval **array;
-	zval **old_compare_func;
 	HashTable *target_hash;
+	PHP_ARRAY_CMP_FUNC_VARS;
+
+	PHP_ARRAY_CMP_FUNC_BACKUP();
 
-	old_compare_func = BG(user_compare_func_name);
-	BG(user_compare_fci_cache) = empty_fcall_info_cache;
 	if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &array, &BG(user_compare_func_name)) == FAILURE) {
-		BG(user_compare_func_name) = old_compare_func;
+		PHP_ARRAY_CMP_FUNC_RESTORE();
 		WRONG_PARAM_COUNT;
 	}
 	target_hash = HASH_OF(*array);
 	if (!target_hash) {
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array");
-		BG(user_compare_func_name) = old_compare_func;
+		PHP_ARRAY_CMP_FUNC_RESTORE();
 		RETURN_FALSE;
 	}
 
 	PHP_ARRAY_CMP_FUNC_CHECK(BG(user_compare_func_name))
 
 	if (zend_hash_sort(target_hash, zend_qsort, array_user_compare, 0 TSRMLS_CC) == FAILURE) {
-		BG(user_compare_func_name) = old_compare_func;
+		PHP_ARRAY_CMP_FUNC_RESTORE();
 		RETURN_FALSE;
 	}
-	BG(user_compare_func_name) = old_compare_func;
+	PHP_ARRAY_CMP_FUNC_RESTORE();
+
 	RETURN_TRUE;
 }
 /* }}} */
@@ -660,7 +693,7 @@ static int array_user_key_compare(const void *a, const void *b TSRMLS_DC)
 	s = *((Bucket **) b);
 
 	if (f->nKeyLength) {
-		Z_STRVAL(key1) = estrndup(f->arKey, f->nKeyLength);
+		Z_STRVAL(key1) = estrndup(f->arKey, f->nKeyLength-1);
 		Z_STRLEN(key1) = f->nKeyLength-1;
 		Z_TYPE(key1) = IS_STRING;
 	} else {
@@ -668,7 +701,7 @@ static int array_user_key_compare(const void *a, const void *b TSRMLS_DC)
 		Z_TYPE(key1) = IS_LONG;
 	}
 	if (s->nKeyLength) {
-		Z_STRVAL(key2) = estrndup(s->arKey, s->nKeyLength);
+		Z_STRVAL(key2) = estrndup(s->arKey, s->nKeyLength-1);
 		Z_STRLEN(key2) = s->nKeyLength-1;
 		Z_TYPE(key2) = IS_STRING;
 	} else {
@@ -694,28 +727,33 @@ static int array_user_key_compare(const void *a, const void *b TSRMLS_DC)
 PHP_FUNCTION(uksort)
 {
 	zval **array;
-	zval **old_compare_func;
 	HashTable *target_hash;
+	PHP_ARRAY_CMP_FUNC_VARS;
+
+
+	PHP_ARRAY_CMP_FUNC_BACKUP();
 
-	old_compare_func = BG(user_compare_func_name);
 	if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &array, &BG(user_compare_func_name)) == FAILURE) {
-		BG(user_compare_func_name) = old_compare_func;
+		PHP_ARRAY_CMP_FUNC_RESTORE();
 		WRONG_PARAM_COUNT;
 	}
 	target_hash = HASH_OF(*array);
 	if (!target_hash) {
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array");
-		BG(user_compare_func_name) = old_compare_func;
+		PHP_ARRAY_CMP_FUNC_RESTORE();
+
 		RETURN_FALSE;
 	}
 
 	PHP_ARRAY_CMP_FUNC_CHECK(BG(user_compare_func_name))
 
 	if (zend_hash_sort(target_hash, zend_qsort, array_user_key_compare, 0 TSRMLS_CC) == FAILURE) {
-		BG(user_compare_func_name) = old_compare_func;
+		PHP_ARRAY_CMP_FUNC_RESTORE();
+
 		RETURN_FALSE;
 	}
-	BG(user_compare_func_name) = old_compare_func;
+
+	PHP_ARRAY_CMP_FUNC_RESTORE();
 	RETURN_TRUE;
 }
 /* }}} */
@@ -994,11 +1032,12 @@ static int php_array_walk(HashTable *target_hash, zval **userdata, int recursive
 {
 	zval **args[3],			/* Arguments to userland function */
 		  *retval_ptr,			/* Return value - unused */
-		  *key;				/* Entry key */
+		  *key=NULL;				/* Entry key */
 	char  *string_key;
 	uint   string_key_len;
 	ulong  num_key;
 	HashPosition pos;
+	zend_fcall_info_cache array_walk_fci_cache = empty_fcall_info_cache;
 
 	/* Set up known arguments */
 	args[1] = &key;
@@ -1042,8 +1081,10 @@ static int php_array_walk(HashTable *target_hash, zval **userdata, int recursive
 			fci.no_separation = 0;
 
 			/* Call the userland function */
-			if (zend_call_function(&fci, &BG(array_walk_fci_cache) TSRMLS_CC) == SUCCESS) {
-				zval_ptr_dtor(&retval_ptr);
+			if (zend_call_function(&fci, &array_walk_fci_cache TSRMLS_CC) == SUCCESS) {
+				if (retval_ptr) {
+					zval_ptr_dtor(&retval_ptr);
+				}
 			} else {
 				char *func_name;
 
@@ -1053,12 +1094,19 @@ static int php_array_walk(HashTable *target_hash, zval **userdata, int recursive
 					php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call %s() - function does not exist", func_name);
 				}
 
+				if (key) {
+					zval_ptr_dtor(&key);
+					key = NULL;
+				}
 				efree(func_name);
 				break;
 			}
 		}
 
-		zval_ptr_dtor(&key);
+		if (key) {
+			zval_ptr_dtor(&key);
+			key = NULL;
+		}
 		zend_hash_move_forward_ex(target_hash, &pos);
 	}
 	
@@ -1076,7 +1124,6 @@ PHP_FUNCTION(array_walk)
 	HashTable *target_hash;
 
 	argc = ZEND_NUM_ARGS();
-	BG(array_walk_fci_cache) = empty_fcall_info_cache;
 	old_walk_func_name = BG(array_walk_func_name);
 	if (argc < 2 || argc > 3 ||
 		zend_get_parameters_ex(argc, &array, &BG(array_walk_func_name), &userdata) == FAILURE) {
@@ -1113,6 +1160,7 @@ PHP_FUNCTION(array_walk_recursive)
 
 	argc = ZEND_NUM_ARGS();
 	old_walk_func_name = BG(array_walk_func_name);
+	
 	if (argc < 2 || argc > 3 ||
 		zend_get_parameters_ex(argc, &array, &BG(array_walk_func_name), &userdata) == FAILURE) {
 		BG(array_walk_func_name) = old_walk_func_name;
@@ -1372,13 +1420,20 @@ PHP_FUNCTION(extract)
 				if (extract_refs) {
 					zval **orig_var;
 
-					SEPARATE_ZVAL_TO_MAKE_IS_REF(entry);
-					zval_add_ref(entry);
-
 					if (zend_hash_find(EG(active_symbol_table), final_name.c, final_name.len+1, (void **) &orig_var) == SUCCESS) {
+						SEPARATE_ZVAL_TO_MAKE_IS_REF(entry);
+						zval_add_ref(entry);
+						
 						zval_ptr_dtor(orig_var);
+
 						*orig_var = *entry;
 					} else {
+						if ((*var_array)->refcount > 1) {
+							SEPARATE_ZVAL_TO_MAKE_IS_REF(entry);
+						} else {
+							(*entry)->is_ref = 1;
+						}
+						zval_add_ref(entry);
 						zend_hash_update(EG(active_symbol_table), final_name.c, final_name.len+1, (void **) entry, sizeof(zval *), NULL);
 					}
 				} else {
@@ -1470,13 +1525,13 @@ PHP_FUNCTION(array_fill)
 		WRONG_PARAM_COUNT;
 	}
 
-	/* allocate an array for return */
-	array_init(return_value);
-
 	switch (Z_TYPE_PP(start_key)) {
 		case IS_STRING:
 		case IS_LONG:
 		case IS_DOUBLE:
+			/* allocate an array for return */
+			array_init(return_value);
+
 			if (PZVAL_IS_REF(*val)) {
 				SEPARATE_ZVAL(val);
 			}
@@ -1493,6 +1548,8 @@ PHP_FUNCTION(array_fill)
 	convert_to_long_ex(num);
 	i = Z_LVAL_PP(num) - 1;	
 	if (i < 0) {
+		zend_hash_destroy(Z_ARRVAL_P(return_value));
+		efree(Z_ARRVAL_P(return_value));
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of elements must be positive");
 		RETURN_FALSE;
 	}
@@ -1534,7 +1591,7 @@ PHP_FUNCTION(range)
 	array_init(return_value);
 
 	/* If the range is given as strings, generate an array of characters. */
-	if (Z_TYPE_P(zlow) == IS_STRING && Z_TYPE_P(zhigh) == IS_STRING) {
+	if (Z_TYPE_P(zlow) == IS_STRING && Z_TYPE_P(zhigh) == IS_STRING && Z_STRLEN_P(zlow) >= 1 && Z_STRLEN_P(zhigh) >= 1) {
 		int type1, type2;
 		unsigned char *low, *high;
 		long lstep = (long) step;
@@ -1980,8 +2037,8 @@ PHP_FUNCTION(array_unshift)
 	   hashtable and replace it with new one */
 	new_hash = php_splice(Z_ARRVAL_P(stack), 0, 0, &args[1], argc-1, NULL);
 	zend_hash_destroy(Z_ARRVAL_P(stack));
-	efree(Z_ARRVAL_P(stack));
-	Z_ARRVAL_P(stack) = new_hash;
+	*Z_ARRVAL_P(stack) = *new_hash;
+	FREE_HASHTABLE(new_hash);
 
 	/* Clean up and return the number of elements in the stack */
 	efree(args);
@@ -2057,8 +2114,8 @@ PHP_FUNCTION(array_splice)
 	
 	/* Replace input array's hashtable with the new one */
 	zend_hash_destroy(Z_ARRVAL_P(array));
-	efree(Z_ARRVAL_P(array));
-	Z_ARRVAL_P(array) = new_hash;
+	*Z_ARRVAL_P(array) = *new_hash;
+	FREE_HASHTABLE(new_hash);
 	
 	/* Clean up */
 	if (argc == 4)
@@ -2075,7 +2132,8 @@ PHP_FUNCTION(array_slice)
 	zval	   **input,		/* Input array */
 		   **offset,		/* Offset to get elements from */
 		   **length,		/* How many elements to get */
-		   **entry;		/* An array entry */
+		   **entry,			/* An array entry */
+		   **z_preserve_keys; /* Whether to preserve keys while copying to the new array or not */
 	int	     offset_val,	/* Value of the offset argument */
 		     length_val,	/* Value of the length argument */
 		     num_in,		/* Number of elements in the input array */
@@ -2086,10 +2144,11 @@ PHP_FUNCTION(array_slice)
 	uint string_key_len;
 	ulong num_key;
 	HashPosition hpos;
+	zend_bool	 preserve_keys = 0;
 
 	/* Get the arguments and do error-checking */	
 	argc = ZEND_NUM_ARGS();
-	if (argc < 2 || argc > 3 || zend_get_parameters_ex(argc, &input, &offset, &length)) {
+	if (argc < 2 || argc > 4 || zend_get_parameters_ex(argc, &input, &offset, &length, &z_preserve_keys)) {
 		WRONG_PARAM_COUNT;
 	}
 	
@@ -2103,12 +2162,17 @@ PHP_FUNCTION(array_slice)
 	   is not passed */
 	convert_to_long_ex(offset);
 	offset_val = Z_LVAL_PP(offset);
-	if (argc == 3) {
+	if (argc >= 3) {
 		convert_to_long_ex(length);
 		length_val = Z_LVAL_PP(length);
 	} else {
 		length_val = zend_hash_num_elements(Z_ARRVAL_PP(input));
 	}
+
+	if (ZEND_NUM_ARGS() > 3) {
+		convert_to_boolean_ex(z_preserve_keys);
+		preserve_keys = Z_BVAL_PP(z_preserve_keys);
+	}
 	
 	/* Initialize returned array */
 	array_init(return_value);
@@ -2152,8 +2216,12 @@ PHP_FUNCTION(array_slice)
 				break;
 	
 			case HASH_KEY_IS_LONG:
-				zend_hash_next_index_insert(Z_ARRVAL_P(return_value),
-											entry, sizeof(zval *), NULL);
+				if (preserve_keys)
+					zend_hash_index_update(Z_ARRVAL_P(return_value), num_key,
+										   entry, sizeof(zval *), NULL);
+				else
+					zend_hash_next_index_insert(Z_ARRVAL_P(return_value),
+												entry, sizeof(zval *), NULL);
 				break;
 		}
 		pos++;
@@ -2419,6 +2487,32 @@ PHP_FUNCTION(array_count_values)
 				Z_LVAL_PP(tmp)++;
 			}
 		} else if (Z_TYPE_PP(entry) == IS_STRING) {
+			/* make sure our array does not end up with numeric string keys */
+			if (is_numeric_string(Z_STRVAL_PP(entry), Z_STRLEN_PP(entry), NULL, NULL, 0) == IS_LONG) {
+				zval tmp_entry;
+				
+				tmp_entry = **entry;
+				zval_copy_ctor(&tmp_entry);
+
+				convert_to_long(&tmp_entry);
+
+				if (zend_hash_index_find(Z_ARRVAL_P(return_value), 
+										 Z_LVAL(tmp_entry), 
+										 (void**)&tmp) == FAILURE) {
+					zval *data;
+					MAKE_STD_ZVAL(data);
+					Z_TYPE_P(data) = IS_LONG;
+					Z_LVAL_P(data) = 1;
+					zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL(tmp_entry), &data, sizeof(data), NULL);
+				} else {
+					Z_LVAL_PP(tmp)++;
+				}
+				
+				zval_dtor(&tmp_entry);
+				zend_hash_move_forward_ex(myht, &pos);
+				continue;
+			}
+		
 			if (zend_hash_find(Z_ARRVAL_P(return_value), Z_STRVAL_PP(entry), Z_STRLEN_PP(entry)+1, (void**)&tmp) == FAILURE) {
 				zval *data;
 				MAKE_STD_ZVAL(data);
@@ -2554,8 +2648,8 @@ PHP_FUNCTION(array_pad)
 
 	/* Copy the result hash into return value */
 	zend_hash_destroy(Z_ARRVAL_P(return_value));
-	efree(Z_ARRVAL_P(return_value));
-	Z_ARRVAL_P(return_value) = new_hash;
+	*Z_ARRVAL_P(return_value) = *new_hash;
+	FREE_HASHTABLE(new_hash);
 	
 	/* Clean up */
 	efree(pads);
@@ -2653,7 +2747,7 @@ PHP_FUNCTION(array_change_key_case)
 				zend_hash_index_update(Z_ARRVAL_P(return_value), num_key, entry, sizeof(entry), NULL);
 				break;
 			case HASH_KEY_IS_STRING:
-				new_key=estrndup(string_key,str_key_len);
+				new_key=estrndup(string_key,str_key_len - 1);
 				if (change_to_upper)
 					php_strtoupper(new_key, str_key_len - 1);
 				else
@@ -2743,7 +2837,8 @@ static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int
 	Bucket ***lists, **list, ***ptrs, *p;
 	
 	char *callback_name;
-	zval **old_compare_func;
+	PHP_ARRAY_CMP_FUNC_VARS;
+
 	
 	int (*intersect_key_compare_func)(const void *, const void * TSRMLS_DC);
 	int (*intersect_data_compare_func)(const void *, const void * TSRMLS_DC);
@@ -2757,13 +2852,7 @@ static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int
 		WRONG_PARAM_COUNT;
 	}
 
-	old_compare_func = BG(user_compare_func_name);
-	/* clear FCI cache otherwise : for example the same or other array with 
-	   (partly) the same key values has been sorted with uasort() or
-	   other sorting function the comparison is cached, however the the name
-	   of the function for comparison is not respected. see bug #28739
-	*/
-	BG(user_compare_fci_cache) = empty_fcall_info_cache;
+	PHP_ARRAY_CMP_FUNC_BACKUP();
 
 	if (behavior == INTERSECT_NORMAL) {
 		intersect_key_compare_func = array_key_compare;
@@ -2918,6 +3007,15 @@ static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int
 	/* copy the argument array */
 	*return_value = **args[0];
 	zval_copy_ctor(return_value);
+	if (return_value->value.ht == &EG(symbol_table)) {
+		HashTable *ht;
+		zval *tmp;
+
+		ALLOC_HASHTABLE(ht);
+		zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
+		zend_hash_copy(ht, return_value->value.ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+		return_value->value.ht = ht;		
+	}
 
 	if (behavior == INTERSECT_NORMAL && data_compare_type == INTERSECT_COMP_DATA_USER) {
 		/* array_uintersect() */
@@ -3025,7 +3123,8 @@ static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int
 		pefree(lists[i], hash->persistent);
 	}
 	
-	BG(user_compare_func_name) = old_compare_func;
+	PHP_ARRAY_CMP_FUNC_RESTORE();
+
 	
 	efree(ptrs);
 	efree(lists);
@@ -3097,7 +3196,8 @@ static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_
 	Bucket ***lists, **list, ***ptrs, *p;
 	char *callback_name;
 	
-	zval **old_compare_func;
+	PHP_ARRAY_CMP_FUNC_VARS;
+
 	int (*diff_key_compare_func)(const void *, const void * TSRMLS_DC);
 	int (*diff_data_compare_func)(const void *, const void * TSRMLS_DC);
 	
@@ -3111,13 +3211,7 @@ static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_
 		WRONG_PARAM_COUNT;
 	}
 
-	old_compare_func = BG(user_compare_func_name);
-	/* clear FCI cache otherwise : for example the same or other array with 
-	   (partly) the same key values has been sorted with uasort() or
-	   other sorting function the comparison is cached, however the the name
-	   of the function for comparison is not respected. see bug #28739
-	*/
-	BG(user_compare_fci_cache) = empty_fcall_info_cache;
+	PHP_ARRAY_CMP_FUNC_BACKUP();
 
 	if (behavior == DIFF_NORMAL) {
 		diff_key_compare_func = array_key_compare;
@@ -3272,6 +3366,15 @@ static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_
 	/* copy the argument array */
 	*return_value = **args[0];
 	zval_copy_ctor(return_value);
+	if (return_value->value.ht == &EG(symbol_table)) {
+		HashTable *ht;
+		zval *tmp;
+
+		ALLOC_HASHTABLE(ht);
+		zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
+		zend_hash_copy(ht, return_value->value.ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+		return_value->value.ht = ht;		
+	}
 
 	if (behavior == DIFF_NORMAL && data_compare_type == DIFF_COMP_DATA_USER) {
 		/* array_udiff() */
@@ -3366,7 +3469,8 @@ static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_
 		pefree(lists[i], hash->persistent);
 	}
 
-	BG(user_compare_func_name) = old_compare_func;			
+	PHP_ARRAY_CMP_FUNC_RESTORE();
+
 	
 	efree(ptrs);
 	efree(lists);
@@ -3801,7 +3905,11 @@ PHP_FUNCTION(array_reduce)
 	efree(callback_name);
 
 	if (ZEND_NUM_ARGS() > 2) {
-		result = *initial;
+		ALLOC_ZVAL(result);
+		*result = **initial;
+		zval_copy_ctor(result);
+		convert_to_long(result);
+		INIT_PZVAL(result);
 	} else {
 		MAKE_STD_ZVAL(result);
 		ZVAL_NULL(result);
@@ -3817,6 +3925,7 @@ PHP_FUNCTION(array_reduce)
 		if (result) {
 			*return_value = *result;
 			zval_copy_ctor(return_value);
+			zval_ptr_dtor(&result);
 		}
 		return;
 	}
@@ -3866,6 +3975,7 @@ PHP_FUNCTION(array_reduce)
 PHP_FUNCTION(array_filter)
 {
 	zval **input, **callback = NULL;
+	zval *array;
 	zval **operand;
 	zval **args[1];
 	zval *retval = NULL;
@@ -3885,6 +3995,7 @@ PHP_FUNCTION(array_filter)
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "The first argument should be an array");
 		return;
 	}
+	array = *input;
 
 	if (ZEND_NUM_ARGS() > 1) {
 		if (!zend_is_callable(*callback, 0, &callback_name)) {
@@ -3896,13 +4007,13 @@ PHP_FUNCTION(array_filter)
 	}
 
 	array_init(return_value);
-	if (zend_hash_num_elements(Z_ARRVAL_PP(input)) == 0) {
+	if (zend_hash_num_elements(Z_ARRVAL_P(array)) == 0) {
 		return;
 	}
 
-	for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(input), &pos);
-		 zend_hash_get_current_data_ex(Z_ARRVAL_PP(input), (void **)&operand, &pos) == SUCCESS;
-		 zend_hash_move_forward_ex(Z_ARRVAL_PP(input), &pos)) {
+	for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos);
+		 zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **)&operand, &pos) == SUCCESS;
+		 zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos)) {
 
 		if (callback) {
 			zend_fcall_info fci;
@@ -3935,7 +4046,7 @@ PHP_FUNCTION(array_filter)
 		}
 
 		zval_add_ref(operand);
-		switch (zend_hash_get_current_key_ex(Z_ARRVAL_PP(input), &string_key, &string_key_len, &num_key, 0, &pos)) {
+		switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(array), &string_key, &string_key_len, &num_key, 0, &pos)) {
 			case HASH_KEY_IS_STRING:
 				zend_hash_update(Z_ARRVAL_P(return_value), string_key, string_key_len, operand, sizeof(zval *), NULL);
 				break;
@@ -4001,6 +4112,7 @@ PHP_FUNCTION(array_map)
 			efree(array_pos);
 			return;
 		}
+		SEPARATE_ZVAL_IF_NOT_REF(pargs[i]);
 		args[i] = *pargs[i];
 		array_len[i] = zend_hash_num_elements(Z_ARRVAL_PP(pargs[i]));
 		if (array_len[i] > maxlen) {
@@ -4236,7 +4348,7 @@ PHP_FUNCTION(array_combine)
 	}
 
 	if (zend_hash_num_elements(Z_ARRVAL_P(keys)) == 0 || zend_hash_num_elements(Z_ARRVAL_P(values)) == 0) {
-		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Both parameters should have number of elements at least 0");
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Both parameters should have at least 1 element");
 		RETURN_FALSE;
 	}
 
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index 2a8239795e0c..432136abd14b 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -35,11 +35,15 @@
 #include "ext/standard/dns.h"
 #include "ext/standard/php_uuencode.h"
 
+#ifdef PHP_WIN32
+#include "win32/php_win32_globals.h"
+#endif
+
 typedef struct yy_buffer_state *YY_BUFFER_STATE;
 
 #include "zend.h"
 #include "zend_language_scanner.h"
-#include "zend_language_parser.h"
+#include 
 
 #include 
 #include 
@@ -47,18 +51,7 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE;
 #include 
 #include 
 
-#ifndef NETWARE
-#include 
-#else
-/*#include "netware/env.h"*/    /* Temporary */
-#ifdef NEW_LIBC /* Same headers hold good for Winsock and Berkeley sockets */
-#include 
-/*#include */
 #include 
-#else
-#include 
-#endif
-#endif
 
 #if HAVE_ARPA_INET_H
 # include 
@@ -161,6 +154,7 @@ typedef struct _user_tick_function_entry {
 static void user_shutdown_function_dtor(php_shutdown_function_entry *shutdown_function_entry);
 static void user_tick_function_dtor(user_tick_function_entry *tick_function_entry);
 
+#undef sprintf
 
 function_entry basic_functions[] = {
 	PHP_FE(constant,														NULL)
@@ -475,7 +469,6 @@ function_entry basic_functions[] = {
 	PHP_FALIAS(show_source, 		highlight_file,							NULL)
 	PHP_FE(highlight_string,												NULL)
 	PHP_FE(php_strip_whitespace,												NULL)
-	PHP_FE(php_check_syntax,												NULL)
 
 	PHP_FE(ini_get,															NULL)
 	PHP_FE(ini_get_all,														NULL)
@@ -936,7 +929,6 @@ static void basic_globals_ctor(php_basic_globals *basic_globals_p TSRMLS_DC)
 	BG(user_tick_functions) = NULL;
 	BG(user_filter_map) = NULL;
 	BG(user_compare_fci_cache) = empty_fcall_info_cache;
-	/*BG(array_walk_fci_cache) = empty_fcall_info_cache;*/
 	zend_hash_init(&BG(sm_protected_env_vars), 5, NULL, NULL, 1);
 	BG(sm_allowed_env_vars) = NULL;
 
@@ -999,8 +991,14 @@ PHP_MINIT_FUNCTION(basic)
 {
 #ifdef ZTS
 	ts_allocate_id(&basic_globals_id, sizeof(php_basic_globals), (ts_allocate_ctor) basic_globals_ctor, (ts_allocate_dtor) basic_globals_dtor);
+#ifdef PHP_WIN32
+	ts_allocate_id(&php_win32_core_globals_id, sizeof(php_win32_core_globals), (ts_allocate_ctor)php_win32_core_globals_ctor, NULL);
+#endif
 #else
 	basic_globals_ctor(&basic_globals TSRMLS_CC);
+#ifdef PHP_WIN32
+	php_win32_core_globals_ctor(&php_win32_core_globals TSRMLS_CC);
+#endif
 #endif
 
 	REGISTER_LONG_CONSTANT("CONNECTION_ABORTED", PHP_CONNECTION_ABORTED, CONST_CS | CONST_PERSISTENT);
@@ -1099,6 +1097,9 @@ PHP_MSHUTDOWN_FUNCTION(basic)
 {
 #ifdef ZTS
 	ts_free_id(basic_globals_id);
+#ifdef PHP_WIN32
+	ts_free_id(php_win32_core_globals_id);
+#endif
 #else
 	basic_globals_dtor(&basic_globals TSRMLS_CC);
 #endif
@@ -1189,17 +1190,10 @@ PHP_RSHUTDOWN_FUNCTION(basic)
 	}
 	STR_FREE(BG(locale_string));
 
-	if (FG(stream_wrappers)) {
-		zend_hash_destroy(FG(stream_wrappers));
-		efree(FG(stream_wrappers));
-		FG(stream_wrappers) = NULL;
-	}
-
-	if (FG(stream_filters)) {
-		zend_hash_destroy(FG(stream_filters));
-		efree(FG(stream_filters));
-		FG(stream_filters) = NULL;
-	}
+	/*
+	 FG(stream_wrappers) and FG(stream_filters) are destroyed
+	 during php_request_shutdown()
+	 */
 
 	PHP_RSHUTDOWN(filestat)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
 #ifdef HAVE_SYSLOG_H
@@ -1208,6 +1202,9 @@ PHP_RSHUTDOWN_FUNCTION(basic)
 	PHP_RSHUTDOWN(assert)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
 	PHP_RSHUTDOWN(url_scanner_ex)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
 	PHP_RSHUTDOWN(streams)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
+#ifdef PHP_WIN32
+	PHP_RSHUTDOWN(win32_core_globals)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
+#endif
 
 	if (BG(user_tick_functions)) {
 		zend_llist_destroy(BG(user_tick_functions));
@@ -1265,6 +1262,13 @@ PHP_FUNCTION(ip2long)
 	convert_to_string_ex(str);
 
 	if (Z_STRLEN_PP(str) == 0 || (ip = inet_addr(Z_STRVAL_PP(str))) == INADDR_NONE) {
+		/* the only special case when we should return -1 ourselves,
+		 * because inet_addr() considers it wrong.
+		 */
+		if (!memcmp(Z_STRVAL_PP(str), "255.255.255.255", Z_STRLEN_PP(str))) {
+			RETURN_LONG(-1);
+		}
+		
 		RETURN_FALSE;
 	}
 
@@ -1626,7 +1630,11 @@ PHP_FUNCTION(sleep)
 	}
 
 	convert_to_long_ex(num);
+#ifdef PHP_SLEEP_NON_VOID
+	RETURN_LONG(php_sleep(Z_LVAL_PP(num)));
+#else
 	php_sleep(Z_LVAL_PP(num));
+#endif
 }
 /* }}} */
 
@@ -1892,7 +1900,7 @@ PHP_FUNCTION(call_user_func)
 		convert_to_string_ex(params[0]);
 	}
 
-	if (!zend_is_callable(*params[0], 0, &name)) {
+	if (!zend_is_callable(*params[0], IS_CALLABLE_CHECK_NO_ACCESS, &name)) {
 		php_error_docref1(NULL TSRMLS_CC, name, E_WARNING, "First argument is expected to be a valid callback");
 		efree(name);
 		efree(params);
@@ -1947,7 +1955,7 @@ PHP_FUNCTION(call_user_func_array)
 		convert_to_string_ex(func);
 	}
 
-	if (!zend_is_callable(*func, 0, &name)) {
+	if (!zend_is_callable(*func, IS_CALLABLE_CHECK_NO_ACCESS, &name)) {
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "First argument is expected to be a valid callback, '%s' was given", name);
 		efree(name);
 		RETURN_NULL();
@@ -1965,8 +1973,10 @@ PHP_FUNCTION(call_user_func_array)
 		current++;
 	}
 
-	if (call_user_function_ex(EG(function_table), NULL, *func, &retval_ptr, count, func_params, 0, NULL TSRMLS_CC) == SUCCESS && retval_ptr) {
-		COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr);
+	if (call_user_function_ex(EG(function_table), NULL, *func, &retval_ptr, count, func_params, 0, NULL TSRMLS_CC) == SUCCESS) {
+		if (retval_ptr) {
+			COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr);
+		}
 	} else {
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call %s()", name);
 	}
@@ -2084,17 +2094,21 @@ void user_tick_function_dtor(user_tick_function_entry *tick_function_entry)
 static int user_shutdown_function_call(php_shutdown_function_entry *shutdown_function_entry TSRMLS_DC)
 {
 	zval retval;
-
-	if (call_user_function(	EG(function_table), NULL,
-							shutdown_function_entry->arguments[0],
-							&retval, 
-							shutdown_function_entry->arg_count - 1,
-							shutdown_function_entry->arguments + 1 
-							TSRMLS_CC ) == SUCCESS ) {
+	char *function_name = NULL;
+
+	if (!zend_is_callable(shutdown_function_entry->arguments[0], 0, &function_name)) {
+		php_error(E_WARNING, "(Registered shutdown functions) Unable to call %s() - function does not exist", function_name);
+	} else if (call_user_function(EG(function_table), NULL,
+								shutdown_function_entry->arguments[0],
+								&retval, 
+								shutdown_function_entry->arg_count - 1,
+								shutdown_function_entry->arguments + 1 
+								TSRMLS_CC ) == SUCCESS)
+	{
 		zval_dtor(&retval);
-
-	} else {
-		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call %s() - function does not exist", Z_STRVAL_P(shutdown_function_entry->arguments[0]));
+	} 
+	if (function_name) {
+		efree(function_name);
 	}
 	return 0;
 }
@@ -2160,16 +2174,24 @@ static int user_tick_function_compare(user_tick_function_entry * tick_fe1, user_
 	}
 }
 
-void php_call_shutdown_functions(void)
+void php_call_shutdown_functions(TSRMLS_D)
 {
-	TSRMLS_FETCH();
-
 	if (BG(user_shutdown_function_names))
 		zend_try {
 			zend_hash_apply(BG(user_shutdown_function_names), (apply_func_t) user_shutdown_function_call TSRMLS_CC);
 			memcpy(&EG(bailout), &orig_bailout, sizeof(jmp_buf));
+			php_free_shutdown_functions(TSRMLS_C);
+		}
+		zend_end_try();
+}
+
+void php_free_shutdown_functions(TSRMLS_D)
+{
+	if (BG(user_shutdown_function_names))
+		zend_try {
 			zend_hash_destroy(BG(user_shutdown_function_names));
 			FREE_HASHTABLE(BG(user_shutdown_function_names));
+			BG(user_shutdown_function_names) = NULL;
 		}
 		zend_end_try();
 }
@@ -2179,6 +2201,7 @@ void php_call_shutdown_functions(void)
 PHP_FUNCTION(register_shutdown_function)
 {
 	php_shutdown_function_entry shutdown_function_entry;
+	char *function_name = NULL;
 	int i;
 
 	shutdown_function_entry.arg_count = ZEND_NUM_ARGS();
@@ -2187,26 +2210,31 @@ PHP_FUNCTION(register_shutdown_function)
 		WRONG_PARAM_COUNT;
 	}
 
-	shutdown_function_entry.arguments = (pval **) safe_emalloc(sizeof(pval *), shutdown_function_entry.arg_count, 0);
+	shutdown_function_entry.arguments = (zval **) safe_emalloc(sizeof(zval *), shutdown_function_entry.arg_count, 0);
 
 	if (zend_get_parameters_array(ht, shutdown_function_entry.arg_count, shutdown_function_entry.arguments) == FAILURE) {
 		RETURN_FALSE;
 	}
 	
-	/* Prevent entering of anything but arrays/strings */
-	if (Z_TYPE_P(shutdown_function_entry.arguments[0]) != IS_ARRAY) {
-		convert_to_string(shutdown_function_entry.arguments[0]);
-	}
-	
-	if (!BG(user_shutdown_function_names)) {
-		ALLOC_HASHTABLE(BG(user_shutdown_function_names));
-		zend_hash_init(BG(user_shutdown_function_names), 0, NULL, (void (*)(void *)) user_shutdown_function_dtor, 0);
-	}
+	/* Prevent entering of anything but valid callback (syntax check only!) */
+	if (!zend_is_callable(shutdown_function_entry.arguments[0], 1, &function_name)) {
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid shutdown callback '%s' passed", function_name);
+		efree(shutdown_function_entry.arguments);
+		RETVAL_FALSE;
+	} else {
+		if (!BG(user_shutdown_function_names)) {
+			ALLOC_HASHTABLE(BG(user_shutdown_function_names));
+			zend_hash_init(BG(user_shutdown_function_names), 0, NULL, (void (*)(void *)) user_shutdown_function_dtor, 0);
+		}
 
-	for (i = 0; i < shutdown_function_entry.arg_count; i++) {
-		shutdown_function_entry.arguments[i]->refcount++;
+		for (i = 0; i < shutdown_function_entry.arg_count; i++) {
+			shutdown_function_entry.arguments[i]->refcount++;
+		}
+		zend_hash_next_index_insert(BG(user_shutdown_function_names), &shutdown_function_entry, sizeof(php_shutdown_function_entry), NULL);
+	}
+	if (function_name) {
+		efree(function_name);
 	}
-	zend_hash_next_index_insert(BG(user_shutdown_function_names), &shutdown_function_entry, sizeof(php_shutdown_function_entry), NULL);
 }
 /* }}} */
 
@@ -2296,49 +2324,6 @@ PHP_FUNCTION(php_strip_whitespace)
 }
 /* }}} */
 
-/* {{{ proto bool php_check_syntax(string file_name [, &$error_message])
-   Check the syntax of the specified file. */
-PHP_FUNCTION(php_check_syntax)
-{
-	char *filename;
-	int filename_len;
-	zval *errm=NULL;
-	zend_file_handle file_handle = {0};
-
-	int old_errors = PG(display_errors);
-	int log_errors = PG(log_errors);
-
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &filename, &filename_len, &errm) == FAILURE) {
-		RETURN_FALSE;
-	}
-
-	file_handle.type = ZEND_HANDLE_FILENAME;
-	file_handle.filename = filename;
-	file_handle.free_filename = 0;
-	file_handle.opened_path = NULL;	
-
-	PG(log_errors) = PG(display_errors) = 0;
-
-	if (php_lint_script(&file_handle TSRMLS_CC) != SUCCESS) {
-		if (errm && PZVAL_IS_REF(errm)) {
-			char *error_str;
-
-			convert_to_string_ex(&errm);
-			spprintf(&error_str, 0, "%s in %s on line %d", PG(last_error_message), PG(last_error_file), PG(last_error_lineno));
-			ZVAL_STRING(errm, error_str, 0);
-		}
-		RETVAL_FALSE;
-	} else {
-		RETVAL_TRUE;
-	}
-
-	PG(display_errors) = old_errors;
-	PG(log_errors) = log_errors;
-
-	return;
-}
-/* }}} */
-
 /* {{{ proto bool highlight_string(string string [, bool return] )
    Syntax highlight a string or optionally return it */
 PHP_FUNCTION(highlight_string)
@@ -2556,7 +2541,7 @@ PHP_FUNCTION(ini_restore)
 }
 /* }}} */
 
-/* {{{ proto string set_include_path(string varname, string newvalue)
+/* {{{ proto string set_include_path(string new_include_path)
    Sets the include_path configuration option */
 
 PHP_FUNCTION(set_include_path)
diff --git a/ext/standard/basic_functions.h b/ext/standard/basic_functions.h
index 468d27c4449f..7c38deef3960 100644
--- a/ext/standard/basic_functions.h
+++ b/ext/standard/basic_functions.h
@@ -82,7 +82,6 @@ PHP_FUNCTION(register_shutdown_function);
 PHP_FUNCTION(highlight_file);
 PHP_FUNCTION(highlight_string);
 PHP_FUNCTION(php_strip_whitespace);
-PHP_FUNCTION(php_check_syntax);
 ZEND_API void php_get_highlight_struct(zend_syntax_highlighter_ini *syntax_highlighter_ini);
 
 PHP_FUNCTION(ini_get);
@@ -154,7 +153,6 @@ typedef struct _php_basic_globals {
 	ulong strtok_len;
 	char str_ebuf[40];
 	zval **array_walk_func_name;
-	zend_fcall_info_cache array_walk_fci_cache;
 	zval **user_compare_func_name;
 	zend_fcall_info_cache user_compare_fci_cache;
 	zend_llist *user_tick_functions;
diff --git a/ext/standard/browscap.c b/ext/standard/browscap.c
index 2baf3735b1ae..77534f410ceb 100644
--- a/ext/standard/browscap.c
+++ b/ext/standard/browscap.c
@@ -33,12 +33,17 @@ static zval *current_section;
 
 /* OBJECTS_FIXME: This whole extension needs going through. The use of objects looks pretty broken here */
 
-static void browscap_entry_dtor(zval *pvalue)
+static void browscap_entry_dtor(zval **pvalue)
 {
-	if (Z_TYPE_P(pvalue) == IS_ARRAY) {
-		zend_hash_destroy(Z_ARRVAL_P(pvalue));
-		free(Z_ARRVAL_P(pvalue));
+	if (Z_TYPE_PP(pvalue) == IS_ARRAY) {
+		zend_hash_destroy(Z_ARRVAL_PP(pvalue));
+		free(Z_ARRVAL_PP(pvalue));
+	} else if (Z_TYPE_PP(pvalue) == IS_STRING) {
+		if (Z_STRVAL_PP(pvalue) && Z_STRVAL_PP(pvalue) != empty_string) {
+			free(Z_STRVAL_PP(pvalue));
+		}
 	}
+	free(*pvalue);
 }
 
 /* {{{ convert_browscap_pattern
@@ -97,7 +102,7 @@ static void php_browscap_parser_cb(zval *arg1, zval *arg2, int callback_type, vo
 
 				new_property = (zval *) malloc(sizeof(zval));
 				INIT_PZVAL(new_property);
-				Z_STRVAL_P(new_property) = Z_STRLEN_P(arg2)?zend_strndup(Z_STRVAL_P(arg2), Z_STRLEN_P(arg2)):"";
+				Z_STRVAL_P(new_property) = Z_STRLEN_P(arg2)?zend_strndup(Z_STRVAL_P(arg2), Z_STRLEN_P(arg2)):empty_string;
 				Z_STRLEN_P(new_property) = Z_STRLEN_P(arg2);
 				Z_TYPE_P(new_property) = IS_STRING;
 
@@ -123,6 +128,7 @@ static void php_browscap_parser_cb(zval *arg1, zval *arg2, int callback_type, vo
 				section_properties = (HashTable *) malloc(sizeof(HashTable));
 				zend_hash_init(section_properties, 0, NULL, (dtor_func_t) browscap_entry_dtor, 1);
 				current_section->value.ht = section_properties;
+				current_section->type = IS_ARRAY;
 				zend_hash_update(&browser_hash, Z_STRVAL_P(arg1), Z_STRLEN_P(arg1)+1, (void *) ¤t_section, sizeof(zval *), NULL);
 
 				Z_STRVAL_P(processed) = Z_STRVAL_P(arg1);
diff --git a/ext/standard/config.m4 b/ext/standard/config.m4
index 7a8689d8978a..05e66c1e182d 100644
--- a/ext/standard/config.m4
+++ b/ext/standard/config.m4
@@ -5,7 +5,7 @@ divert(3)dnl
 dnl
 dnl Check if flush should be called explicitly after buffered io
 dnl
-AC_DEFUN(AC_FLUSH_IO,[
+AC_DEFUN([AC_FLUSH_IO],[
   AC_CACHE_CHECK([whether flush should be called explicitly after a buffered io], ac_cv_flush_io,[
   AC_TRY_RUN( [
 #include 
@@ -56,7 +56,7 @@ int main(int argc, char **argv)
 dnl
 dnl Check for crypt() capabilities
 dnl
-AC_DEFUN(AC_CRYPT_CAP,[
+AC_DEFUN([AC_CRYPT_CAP],[
 
   if test "$ac_cv_func_crypt" = "no"; then
   AC_CHECK_LIB(crypt, crypt, [
diff --git a/ext/standard/credits.c b/ext/standard/credits.c
index b3eff0a87fee..7cc9137955e7 100644
--- a/ext/standard/credits.c
+++ b/ext/standard/credits.c
@@ -85,9 +85,11 @@ PHPAPI void php_print_credits(int flag TSRMLS_DC)
 
 	if (flag & PHP_CREDITS_DOCS) {
 		php_info_print_table_start();
-		php_info_print_table_header(1, "PHP Documentation Team");
-		php_info_print_table_row(1, "Jouni Ahto, Alexander Aulbach, Stig Bakken, Rasmus Lerdorf, Egon Schmid, Lars Torben Wilson, Jim Winstead");
-		php_info_print_table_row(1, "Edited by:  Stig Bakken and Egon Schmid");
+		php_info_print_table_colspan_header(2, "PHP Documentation");
+		CREDIT_LINE("Authors", "Mehdi Achour, Friedhelm Betz, Antony Dovgal, Nuno Lopes, Philip Olson, Georg Richter, Damien Seguy, Jakub Vrana");
+		CREDIT_LINE("Editor", "Gabor Hojtsy");
+		CREDIT_LINE("User Note Maintainers", "Mehdi Achour, Friedhelm Betz, Vincent Gevers, Aidan Lister, Nuno Lopes, Tom Sommer");
+		CREDIT_LINE("Other Contributors", "Previously active authors, editors and other contributors are listed in the manual.");
 		php_info_print_table_end();
 	}
 
diff --git a/ext/standard/credits_ext.h b/ext/standard/credits_ext.h
index 203af04aecfe..aa2aa4f45d0d 100644
--- a/ext/standard/credits_ext.h
+++ b/ext/standard/credits_ext.h
@@ -46,13 +46,12 @@ CREDIT_LINE("mhash", "Sascha Schumann");
 CREDIT_LINE("mime_magic", "Hartmut Holzgraefe");
 CREDIT_LINE("MING", "Dave Hayden, Frank M. Kromann");
 CREDIT_LINE("mnoGoSearch", "Sergey Kartashoff, Alex Barkov, Ramil Kalimullin");
-CREDIT_LINE("mono", "Sterling Hughes");
+CREDIT_LINE("MS SQL", "Frank M. Kromann");
 CREDIT_LINE("msession", "Mark L. Woodward");
 CREDIT_LINE("mSQL", "Zeev Suraski");
-CREDIT_LINE("MS SQL", "Frank M. Kromann");
 CREDIT_LINE("Multibyte String Functions", "Tsukada Takuya, Rui Hirokawa");
-CREDIT_LINE("MySQLi", "Zak Greant, Georg Richter");
 CREDIT_LINE("MySQL", "Zeev Suraski, Zak Greant, Georg Richter");
+CREDIT_LINE("MySQLi", "Zak Greant, Georg Richter");
 CREDIT_LINE("ncurses", "Ilia Alshanetsky, Wez Furlong, Hartmut Holzgraefe, Georg Richter");
 CREDIT_LINE("OCI8", "Stig Bakken, Thies C. Arntzen, Andy Sautins, David Benson, Maxim Maletsky, Harald Radi, Antony Dovgal");
 CREDIT_LINE("ODBC", "Stig Bakken, Andreas Karajannis, Frank M. Kromann, Daniel R. Kalowsky");
@@ -60,7 +59,6 @@ CREDIT_LINE("OpenSSL", "Stig Venaas, Wez Furlong, Sascha Kettler");
 CREDIT_LINE("Oracle", "Stig Bakken, Mitch Golden, Rasmus Lerdorf, Andreas Karajannis, Thies C. Arntzen");
 CREDIT_LINE("Ovrimos", "Nikos Mavroyanopoulos");
 CREDIT_LINE("pcntl", "Jason Greene");
-CREDIT_LINE("PDF", "Uwe Steinmann, Rainer Schaaf");
 CREDIT_LINE("Perl Compatible Regexps", "Andrei Zmievski");
 CREDIT_LINE("Posix", "Kristian Köhntopp");
 CREDIT_LINE("PostgreSQL", "Jouni Ahto, Zeev Suraski, Yasuo Ohgaki");
@@ -71,9 +69,10 @@ CREDIT_LINE("Sessions", "Sascha Schumann, Andrei Zmievski");
 CREDIT_LINE("Shared Memory Operations", "Slava Poliakov, Ilia Alshanetsky");
 CREDIT_LINE("SimpleXML", "Sterling Hughes, Marcus Boerger, Rob Richards");
 CREDIT_LINE("SNMP", "Rasmus Lerdorf, Harrie Hazewinkel, Mike Jackson, Steven Lawrance, Johann Hanne");
+CREDIT_LINE("SOAP", "Brad Lafountain, Shane Caraveo, Dmitry Stogov");
 CREDIT_LINE("Sockets", "Chris Vandomelen, Sterling Hughes, Daniel Beulshausen, Jason Greene");
 CREDIT_LINE("SPL", "Marcus Boerger");
-CREDIT_LINE("SQLite", "Wez Furlong, Tal Peer, Marcus Börger, Ilia Alshanetsky");
+CREDIT_LINE("SQLite", "Wez Furlong, Tal Peer, Marcus Boerger, Ilia Alshanetsky");
 CREDIT_LINE("Sybase-CT", "Zeev Suraski, Tom May, Timm Friebe");
 CREDIT_LINE("Sybase-DB", "Zeev Suraski");
 CREDIT_LINE("System V Message based IPC", "Wez Furlong");
@@ -84,9 +83,8 @@ CREDIT_LINE("tokenizer", "Andrei Zmievski");
 CREDIT_LINE("Verisign Payflow Pro", "John Donagher, David Croft");
 CREDIT_LINE("W32API", "James Moore");
 CREDIT_LINE("WDDX", "Andrei Zmievski");
-CREDIT_LINE("xmlrpc", "Dan Libby");
 CREDIT_LINE("XML", "Stig Bakken, Thies C. Arntzen, Sterling Hughes");
+CREDIT_LINE("xmlrpc", "Dan Libby");
 CREDIT_LINE("XSL", "Christian Stocker, Rob Richards");
-CREDIT_LINE("YAZ", "Adam Dickmeiss");
 CREDIT_LINE("Yellow Pages", "Stephanie Wehner, Fredrik Ohrn");
 CREDIT_LINE("Zlib", "Rasmus Lerdorf, Stefan Roehrich, Zeev Suraski, Jade Nicoletti");
diff --git a/ext/standard/credits_sapi.h b/ext/standard/credits_sapi.h
index ab7c2755a781..e91957141954 100644
--- a/ext/standard/credits_sapi.h
+++ b/ext/standard/credits_sapi.h
@@ -10,7 +10,6 @@
 
 */
 
-CREDIT_LINE("ActiveScript", "Wez Furlong");
 CREDIT_LINE("AOLserver", "Sascha Schumann");
 CREDIT_LINE("Apache 1.3 (apache_hooks)", "Rasmus Lerdorf, Zeev Suraski, Stig Bakken, David Sklar, George Schlossnagle, Lukas Schroeder");
 CREDIT_LINE("Apache 1.3", "Rasmus Lerdorf, Zeev Suraski, Stig Bakken, David Sklar");
diff --git a/ext/standard/datetime.c b/ext/standard/datetime.c
index 4e455a86a09c..b0a42ae5a8ce 100644
--- a/ext/standard/datetime.c
+++ b/ext/standard/datetime.c
@@ -52,7 +52,7 @@ char *day_short_names[] = {
 };
 
 #if !defined(HAVE_TM_ZONE) && !defined(_TIMEZONE) && !defined(HAVE_DECLARED_TIMEZONE)
-#if defined(NETWARE) && defined(NEW_LIBC)
+#ifdef NETWARE
 #define timezone    _timezone   /* timezone is called '_timezone' in new version of LibC */
 #endif
 extern time_t timezone;
@@ -582,7 +582,7 @@ static void php_date(INTERNAL_FUNCTION_PARAMETERS, int gm)
 				break;
 			case 'r':
 #if HAVE_TM_GMTOFF
-				sprintf(tmp_buff, "%3s, %2d %3s %04d %02d:%02d:%02d %c%02d%02d",
+				sprintf(tmp_buff, "%3s, %02d %3s %04d %02d:%02d:%02d %c%02d%02d",
 					day_short_names[ta->tm_wday],
 					ta->tm_mday,
 					mon_short_names[ta->tm_mon],
@@ -595,7 +595,7 @@ static void php_date(INTERNAL_FUNCTION_PARAMETERS, int gm)
 					abs( (ta->tm_gmtoff % 3600) / 60 )
 				);
 #else
-				sprintf(tmp_buff, "%3s, %2d %3s %04d %02d:%02d:%02d %c%02d%02d",
+				sprintf(tmp_buff, "%3s, %02d %3s %04d %02d:%02d:%02d %c%02d%02d",
 					day_short_names[ta->tm_wday],
 					ta->tm_mday,
 					mon_short_names[ta->tm_mon],
@@ -657,7 +657,7 @@ static void php_date(INTERNAL_FUNCTION_PARAMETERS, int gm)
 					wk = (yd + 6 - wd + fd) / 7 - (fd > 3);
 				}
 
-				sprintf(tmp_buff, "%d", wk);  /* SAFE */
+				sprintf(tmp_buff, "%02d", wk);  /* SAFE */
 				strcat(Z_STRVAL_P(return_value), tmp_buff);
 				break;
 
@@ -945,7 +945,7 @@ char *php_std_date(time_t t TSRMLS_DC)
 	tm1 = php_gmtime_r(&t, &tmbuf);
 	str = emalloc(81);
 	if (PG(y2k_compliance)) {
-		snprintf(str, 80, "%s, %02d-%s-%04d %02d:%02d:%02d GMT",
+		snprintf(str, 80, "%s, %02d %s %04d %02d:%02d:%02d GMT",
 				day_short_names[tm1->tm_wday],
 				tm1->tm_mday,
 				mon_short_names[tm1->tm_mon],
@@ -953,7 +953,7 @@ char *php_std_date(time_t t TSRMLS_DC)
 				tm1->tm_hour, tm1->tm_min, tm1->tm_sec);
 	} else {
 		snprintf(str, 80, "%s, %02d-%s-%02d %02d:%02d:%02d GMT",
-				day_short_names[tm1->tm_wday],
+				day_full_names[tm1->tm_wday],
 				tm1->tm_mday,
 				mon_short_names[tm1->tm_mon],
 				((tm1->tm_year) % 100),
@@ -1080,8 +1080,10 @@ PHP_FUNCTION(strtotime)
 	}
 
 	convert_to_string_ex(z_time);
-	if (Z_STRLEN_PP(z_time) == 0)
-		php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Called with empty time parameter");
+	if (!Z_STRLEN_PP(z_time)) {
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Called with an empty time parameter.");
+		RETURN_LONG(-1);
+	}
 	if (argc == 2) {
 		convert_to_long_ex(z_now);
 		now = Z_LVAL_PP(z_now);
diff --git a/ext/standard/dir.c b/ext/standard/dir.c
index 2ee0ed71122b..227173d5b44b 100644
--- a/ext/standard/dir.c
+++ b/ext/standard/dir.c
@@ -462,7 +462,7 @@ PHP_FUNCTION(scandir)
 	char *dirn;
 	int dirn_len;
 	long flags = 0;
-	php_stream_dirent **namelist;
+	char **namelist;
 	int n, i;
 	zval *zcontext = NULL;
 	php_stream_context *context = NULL;
@@ -488,7 +488,7 @@ PHP_FUNCTION(scandir)
 	array_init(return_value);
 
 	for (i = 0; i < n; i++) {
-		add_next_index_string(return_value, namelist[i]->d_name, 0);
+		add_next_index_string(return_value, namelist[i], 0);
 	}
 
 	if (n) {
diff --git a/ext/standard/dl.c b/ext/standard/dl.c
index 47b35080c133..cdd20fb5b36e 100644
--- a/ext/standard/dl.c
+++ b/ext/standard/dl.c
@@ -39,13 +39,6 @@
 #include "win32/param.h"
 #include "win32/winutil.h"
 #define GET_DL_ERROR()	php_win_err()
-#elif defined(NETWARE)
-#ifdef NEW_LIBC
-#include 
-#else
-#include "netware/param.h"
-#endif
-#define GET_DL_ERROR()	dlerror()
 #else
 #include 
 #define GET_DL_ERROR()	DL_ERROR()
@@ -149,7 +142,6 @@ void php_dl(pval *file, int type, pval *return_value TSRMLS_DC)
 
 	efree(libpath);
 
-#ifndef NETWARE
 	get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "get_module");
 
 	/*
@@ -160,23 +152,6 @@ void php_dl(pval *file, int type, pval *return_value TSRMLS_DC)
 
 	if (!get_module)
 		get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "_get_module");
-#else
-	/* NetWare doesn't support two NLMs exporting same symbol */
-	{
-		char symbol_name[64] = "\0";
-		int module_name_length = Z_STRLEN_P(file) - 4;  /* '.nlm' is 4 characters; knock it off */
-
-		/* Take the module name (e.g.: 'php_ldap') and append '@get_module' to it */
-		strncpy(symbol_name, Z_STRVAL_P(file), module_name_length);
-		symbol_name[module_name_length] = '\0';
-		strcat(symbol_name, "@");
-		strcat(symbol_name, "get_module");
-
-		get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, symbol_name);
-	}
-	/* NetWare doesn't prepend '_' to symbol names; so the corresponding portion of code is also
-	   not required for NetWare */
-#endif
 
 	if (!get_module) {
 		DL_UNLOAD(handle);
@@ -236,6 +211,7 @@ void php_dl(pval *file, int type, pval *return_value TSRMLS_DC)
 	}
 	module_entry->type = type;
 	module_entry->module_number = zend_next_free_module();
+	module_entry->handle = handle;
 	
 	if (zend_register_module_ex(module_entry TSRMLS_CC) == FAILURE) {
 		DL_UNLOAD(handle);
@@ -250,8 +226,6 @@ void php_dl(pval *file, int type, pval *return_value TSRMLS_DC)
 		}
 	}
 	
-	module_entry->handle = handle;
-
 	RETURN_TRUE;
 }
 /* }}} */
diff --git a/ext/standard/file.c b/ext/standard/file.c
index 6041fa4249fa..0a3998fb3539 100644
--- a/ext/standard/file.c
+++ b/ext/standard/file.c
@@ -47,10 +47,6 @@
 #define O_RDONLY _O_RDONLY
 #include "win32/param.h"
 #include "win32/winutil.h"
-#elif defined(NETWARE) && !defined(NEW_LIBC)
-/*#include */
-#include 
-#include "netware/param.h"
 #else
 #if HAVE_SYS_PARAM_H
 #include 
@@ -76,8 +72,6 @@
 #if HAVE_PWD_H
 #ifdef PHP_WIN32
 #include "win32/pwd.h"
-#elif defined(NETWARE)
-#include "netware/pwd.h"
 #else
 #include 
 #endif
@@ -281,13 +275,13 @@ PHP_FUNCTION(flock)
 
 	/* flock_values contains all possible actions if (operation & 4) we won't block on the lock */
 	act = flock_values[act - 1] | (operation & 4 ? LOCK_NB : 0);
-	if (!php_stream_lock(stream, act)) {
+	if (php_stream_lock(stream, act)) {
 		if (operation && errno == EWOULDBLOCK && arg3 && PZVAL_IS_REF(arg3)) {
 			Z_LVAL_P(arg3) = 1;
 		}
-		RETURN_TRUE;
+		RETURN_FALSE;
 	}
-	RETURN_FALSE;
+	RETURN_TRUE;
 }
 
 /* }}} */
@@ -695,7 +689,7 @@ PHP_FUNCTION(tempnam)
 	char *d;
 	char *opened_path;
 	char p[64];
-	FILE *fp;
+	int fd;
 
 	if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
 		WRONG_PARAM_COUNT;
@@ -710,8 +704,8 @@ PHP_FUNCTION(tempnam)
 	d = estrndup(Z_STRVAL_PP(arg1), Z_STRLEN_PP(arg1));
 	strlcpy(p, Z_STRVAL_PP(arg2), sizeof(p));
 
-	if ((fp = php_open_temporary_file(d, p, &opened_path TSRMLS_CC))) {
-		fclose(fp);
+	if ((fd = php_open_temporary_fd(d, p, &opened_path TSRMLS_CC)) >= 0) {
+		close(fd);
 		RETVAL_STRING(opened_path, 0);
 	} else {
 		RETVAL_FALSE;
@@ -803,7 +797,7 @@ PHP_FUNCTION(popen)
 	zval **arg1, **arg2;
 	FILE *fp;
 	char *p, *tmp = NULL;
-	char *b, buf[1024];
+	char *b, *buf = 0;
 	php_stream *stream;
 	
 	if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
@@ -812,6 +806,14 @@ PHP_FUNCTION(popen)
 	convert_to_string_ex(arg1);
 	convert_to_string_ex(arg2);
 	p = estrndup(Z_STRVAL_PP(arg2), Z_STRLEN_PP(arg2));
+#ifndef PHP_WIN32
+	{
+		char *z = memchr(p, 'b', Z_STRLEN_PP(arg2));
+		if (z) {
+			memmove(p + (z - p), z + 1, Z_STRLEN_PP(arg2) - (z - p));
+		}
+	}
+#endif
 	if (PG(safe_mode)){
 		b = strchr(Z_STRVAL_PP(arg1), ' ');
 		if (!b) {
@@ -826,10 +828,11 @@ PHP_FUNCTION(popen)
 				b = NULL;
 			}
 		}
+		
 		if (b) {
-			snprintf(buf, sizeof(buf), "%s%s", PG(safe_mode_exec_dir), b);
+			spprintf(&buf, 0, "%s%s", PG(safe_mode_exec_dir), b);
 		} else {
-			snprintf(buf, sizeof(buf), "%s/%s", PG(safe_mode_exec_dir), Z_STRVAL_PP(arg1));
+			spprintf(&buf, 0, "%s/%s", PG(safe_mode_exec_dir), Z_STRVAL_PP(arg1));
 		}
 
 		tmp = php_escape_shell_cmd(buf);
@@ -839,8 +842,12 @@ PHP_FUNCTION(popen)
 		if (!fp) {
 			php_error_docref2(NULL TSRMLS_CC, buf, p, E_WARNING, "%s", strerror(errno));
 			efree(p);
+			efree(buf);
 			RETURN_FALSE;
 		}
+		
+		efree(buf);
+
 	} else {
 		fp = VCWD_POPEN(Z_STRVAL_PP(arg1), p);
 		if (!fp) {
@@ -1525,7 +1532,7 @@ PHP_NAMED_FUNCTION(php_if_fstat)
 	MAKE_LONG_ZVAL_INCREF(stat_rdev, -1); 
 #endif
 	MAKE_LONG_ZVAL_INCREF(stat_size, stat_ssb.sb.st_size);
-#if defined(NETWARE) && defined(CLIB_STAT_PATCH)
+#ifdef NETWARE
 	MAKE_LONG_ZVAL_INCREF(stat_atime, stat_ssb.sb.st_atime.tv_sec);
 	MAKE_LONG_ZVAL_INCREF(stat_mtime, stat_ssb.sb.st_mtime.tv_sec);
 	MAKE_LONG_ZVAL_INCREF(stat_ctime, stat_ssb.sb.st_ctime.tv_sec);
@@ -1761,6 +1768,8 @@ PHP_FUNCTION(fgetcsv)
 			if (len < 0) {
 				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter may not be negative");
 				RETURN_FALSE;
+			} else if (len == 0) {
+				len = 1;
 			}
 		} else {
 			len = -1;
diff --git a/ext/standard/file.h b/ext/standard/file.h
index e5c23e6a2412..eadd18edb38f 100644
--- a/ext/standard/file.h
+++ b/ext/standard/file.h
@@ -59,7 +59,7 @@ PHP_FUNCTION(get_meta_tags);
 PHP_FUNCTION(flock);
 PHP_FUNCTION(fd_set);
 PHP_FUNCTION(fd_isset);
-#if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
+#if (!defined(__BEOS__) && HAVE_REALPATH) || defined(ZTS)
 PHP_FUNCTION(realpath);
 PHP_FUNCTION(fnmatch);
 #endif
diff --git a/ext/standard/filestat.c b/ext/standard/filestat.c
index 2aa7051a2cbf..5e31f69a7da3 100644
--- a/ext/standard/filestat.c
+++ b/ext/standard/filestat.c
@@ -58,8 +58,6 @@
 #if HAVE_PWD_H
 # ifdef PHP_WIN32
 #  include "win32/pwd.h"
-# elif defined(NETWARE)
-#  include "netware/pwd.h"
 # else
 #  include 
 # endif
@@ -107,9 +105,11 @@ PHP_RSHUTDOWN_FUNCTION(filestat)
 {
 	if (BG(CurrentStatFile)) {
 		efree (BG(CurrentStatFile));
+		BG(CurrentStatFile)=NULL;
 	}
 	if (BG(CurrentLStatFile)) {
 		efree (BG(CurrentLStatFile));
+		BG(CurrentLStatFile)=NULL;
 	}
 	return SUCCESS;
 }
@@ -311,8 +311,12 @@ PHP_FUNCTION(disk_free_space)
 	}
 #elif (defined(HAVE_SYS_STATFS_H) || defined(HAVE_SYS_MOUNT_H)) && defined(HAVE_STATFS)
 	if (statfs(Z_STRVAL_PP(path), &buf)) RETURN_FALSE;
+#ifdef NETWARE
+	bytesfree = (((double)buf.f_bsize) * ((double)buf.f_bfree));
+#else
 	bytesfree = (((double)buf.f_bsize) * ((double)buf.f_bavail));
 #endif
+#endif
 #endif /* WINDOWS */
 
 	RETURN_DOUBLE(bytesfree);
@@ -460,11 +464,7 @@ PHP_FUNCTION(touch)
 {
 	pval **filename, **filetime, **fileatime;
 	int ret;
-#if defined(NETWARE) && defined(CLIB_STAT_PATCH)
-	struct stat_libc sb;
-#else
 	struct stat sb;
-#endif
 	FILE *file;
 	struct utimbuf newtimebuf;
 	struct utimbuf *newtime = NULL;
@@ -546,11 +546,7 @@ PHPAPI void php_stat(const char *filename, php_stat_len filename_length, int typ
 {
 	zval *stat_dev, *stat_ino, *stat_mode, *stat_nlink, *stat_uid, *stat_gid, *stat_rdev,
 	 	*stat_size, *stat_atime, *stat_mtime, *stat_ctime, *stat_blksize, *stat_blocks;
-#if defined(NETWARE) && defined(CLIB_STAT_PATCH)
-	struct stat_libc *stat_sb;
-#else
 	struct stat *stat_sb;
-#endif
 	php_stream_statbuf ssb;
 	int flags = 0, rmask=S_IROTH, wmask=S_IWOTH, xmask=S_IXOTH; /* access rights defaults to other */
 	char *stat_sb_names[13]={"dev", "ino", "mode", "nlink", "uid", "gid", "rdev",
@@ -633,30 +629,26 @@ PHPAPI void php_stat(const char *filename, php_stat_len filename_length, int typ
 	case FS_INODE:
 		RETURN_LONG((long)ssb.sb.st_ino);
 	case FS_SIZE:
-#if defined(NETWARE) && defined(NEW_LIBC)
-		RETURN_LONG((long)(stat_sb->st_size));
-#else
 		RETURN_LONG((long)ssb.sb.st_size);
-#endif
 	case FS_OWNER:
 		RETURN_LONG((long)ssb.sb.st_uid);
 	case FS_GROUP:
 		RETURN_LONG((long)ssb.sb.st_gid);
 	case FS_ATIME:
-#if defined(NETWARE) && defined(NEW_LIBC)
-		RETURN_LONG((long)((stat_sb->st_atime).tv_sec));
+#ifdef NETWARE
+		RETURN_LONG((long)ssb.sb.st_atime.tv_sec);
 #else
 		RETURN_LONG((long)ssb.sb.st_atime);
 #endif
 	case FS_MTIME:
-#if defined(NETWARE) && defined(NEW_LIBC)
-		RETURN_LONG((long)((stat_sb->st_mtime).tv_sec));
+#ifdef NETWARE
+		RETURN_LONG((long)ssb.sb.st_mtime.tv_sec);
 #else
 		RETURN_LONG((long)ssb.sb.st_mtime);
 #endif
 	case FS_CTIME:
-#if defined(NETWARE) && defined(NEW_LIBC)
-		RETURN_LONG((long)((stat_sb->st_ctime).tv_sec));
+#ifdef NETWARE
+		RETURN_LONG((long)ssb.sb.st_ctime.tv_sec);
 #else
 		RETURN_LONG((long)ssb.sb.st_ctime);
 #endif
@@ -707,7 +699,7 @@ PHPAPI void php_stat(const char *filename, php_stat_len filename_length, int typ
 		MAKE_LONG_ZVAL_INCREF(stat_rdev, -1); 
 #endif
 		MAKE_LONG_ZVAL_INCREF(stat_size, stat_sb->st_size);
-#if defined(NETWARE) && defined(NEW_LIBC)
+#ifdef NETWARE
 		MAKE_LONG_ZVAL_INCREF(stat_atime, (stat_sb->st_atime).tv_sec);
 		MAKE_LONG_ZVAL_INCREF(stat_mtime, (stat_sb->st_mtime).tv_sec);
 		MAKE_LONG_ZVAL_INCREF(stat_ctime, (stat_sb->st_ctime).tv_sec);
diff --git a/ext/standard/filters.c b/ext/standard/filters.c
index 94073615582a..0b3fd008775d 100644
--- a/ext/standard/filters.c
+++ b/ext/standard/filters.c
@@ -176,7 +176,9 @@ typedef struct _php_strip_tags_filter {
 static int php_strip_tags_filter_ctor(php_strip_tags_filter *inst, const char *allowed_tags, int allowed_tags_len, int persistent)
 {
 	if (allowed_tags != NULL) {
-		inst->allowed_tags = pemalloc(allowed_tags_len, persistent);
+		if (NULL == (inst->allowed_tags = pemalloc(allowed_tags_len, persistent))) {
+			return FAILURE;
+		}
 		memcpy((char *)inst->allowed_tags, allowed_tags, allowed_tags_len);
 		inst->allowed_tags_len = allowed_tags_len; 
 	} else {
@@ -305,6 +307,7 @@ typedef enum _php_conv_err_t {
 	PHP_CONV_ERR_INVALID_SEQ,
 	PHP_CONV_ERR_UNEXPECTED_EOS,
 	PHP_CONV_ERR_EXISTS,
+	PHP_CONV_ERR_ALLOC,
 	PHP_CONV_ERR_NOT_FOUND
 } php_conv_err_t;
 
@@ -1165,13 +1168,20 @@ static php_conv_err_t php_conv_get_string_prop_ex(const HashTable *ht, char **pr
 	if (zend_hash_find((HashTable *)ht, field_name, field_name_len, (void **)&tmpval) == SUCCESS) {
 		if (Z_TYPE_PP(tmpval) != IS_STRING) {
 			zval zt = **tmpval;
+
 			convert_to_string(&zt);
-			*pretval = pemalloc(Z_STRLEN(zt) + 1, persistent);
+
+			if (NULL == (*pretval = pemalloc(Z_STRLEN(zt) + 1, persistent))) {
+				return PHP_CONV_ERR_ALLOC;
+			}
+
 			*pretval_len = Z_STRLEN(zt);
 			memcpy(*pretval, Z_STRVAL(zt), Z_STRLEN(zt) + 1);
 			zval_dtor(&zt);
 		} else {
-			*pretval = pemalloc(Z_STRLEN_PP(tmpval) + 1, persistent);
+			if (NULL == (*pretval = pemalloc(Z_STRLEN_PP(tmpval) + 1, persistent))) {
+				return PHP_CONV_ERR_ALLOC;
+			}
 			*pretval_len = Z_STRLEN_PP(tmpval);
 			memcpy(*pretval, Z_STRVAL_PP(tmpval), Z_STRLEN_PP(tmpval) + 1);
 		}
@@ -1484,10 +1494,18 @@ static php_stream_filter_status_t strfilter_convert_filter(
 	char *pd;
 	size_t ocnt;
 
-	if (flags != PSFS_FLAG_NORMAL) {
-		/* flush operation */
+	/* Always wind buckets_in whether this is a flush op or not */
+	while (buckets_in->head != NULL) {
+		const char *ps;
+		size_t icnt;
 
-		out_buf_size = 64;
+		bucket = buckets_in->head;
+
+		php_stream_bucket_unlink(bucket TSRMLS_CC);
+		icnt = bucket->buflen;
+		ps = bucket->buf;
+
+		out_buf_size = bucket->buflen;
 		out_buf = pemalloc(out_buf_size, inst->persistent);
 		ocnt = out_buf_size;
 		pd = out_buf;
@@ -1495,8 +1513,8 @@ static php_stream_filter_status_t strfilter_convert_filter(
 		/* trying hard to reduce the number of buckets to hand to the
 		 * next filter */ 
 
-		for (;;) {
-			err = php_conv_convert(inst->cd, NULL, NULL, &pd, &ocnt);
+		while (icnt > 0) {
+			err = php_conv_convert(inst->cd, &ps, &icnt, &pd, &ocnt);
 
 			switch (err) {
 				case PHP_CONV_ERR_UNKNOWN:
@@ -1515,9 +1533,7 @@ static php_stream_filter_status_t strfilter_convert_filter(
 					break;
 			}
 
-			if (err != PHP_CONV_ERR_TOO_BIG) {
-				break;
-			} else {
+			if (err == PHP_CONV_ERR_TOO_BIG) {
 				char *new_out_buf;
 				size_t new_out_buf_size;
 
@@ -1542,6 +1558,10 @@ static php_stream_filter_status_t strfilter_convert_filter(
 				}
 			}
 		}
+
+		/* update consumed by the number of bytes just used */
+		consumed += bucket->buflen - icnt;
+
 		/* give output bucket to next in chain */
 		if (out_buf_size - ocnt > 0) {
 			new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, inst->persistent TSRMLS_CC);
@@ -1549,86 +1569,78 @@ static php_stream_filter_status_t strfilter_convert_filter(
 		} else {
 			pefree(out_buf, inst->persistent);
 		}
-	} else {
-		while (buckets_in->head != NULL) {
-			const char *ps;
-			size_t icnt;
 
-			bucket = buckets_in->head;
+		php_stream_bucket_delref(bucket TSRMLS_CC);
+	}
 
-			php_stream_bucket_unlink(bucket TSRMLS_CC);
-			icnt = bucket->buflen;
-			ps = bucket->buf;
+	if (flags != PSFS_FLAG_NORMAL) {
+		/* flush operation */
 
-			out_buf_size = bucket->buflen;
-			out_buf = pemalloc(out_buf_size, inst->persistent);
-			ocnt = out_buf_size;
-			pd = out_buf;
+		out_buf_size = 64;
+		out_buf = pemalloc(out_buf_size, inst->persistent);
+		ocnt = out_buf_size;
+		pd = out_buf;
 
-			/* trying hard to reduce the number of buckets to hand to the
-			 * next filter */ 
+		/* trying hard to reduce the number of buckets to hand to the
+		 * next filter */ 
 
-			while (icnt > 0) {
-				err = php_conv_convert(inst->cd, &ps, &icnt, &pd, &ocnt);
+		for (;;) {
+			err = php_conv_convert(inst->cd, NULL, NULL, &pd, &ocnt);
 
-				switch (err) {
-					case PHP_CONV_ERR_UNKNOWN:
-						php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): unknown error", inst->filtername);
-						goto out_failure;
+			switch (err) {
+				case PHP_CONV_ERR_UNKNOWN:
+					php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): unknown error", inst->filtername);
+					goto out_failure;
 
-					case PHP_CONV_ERR_INVALID_SEQ:
-						php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): invalid base64 sequence", inst->filtername);
-						goto out_failure;
+				case PHP_CONV_ERR_INVALID_SEQ:
+					php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): invalid base64 sequence", inst->filtername);
+					goto out_failure;
 
-					case PHP_CONV_ERR_UNEXPECTED_EOS:
-						php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): unexpected end of stream", inst->filtername);
-						goto out_failure;
+				case PHP_CONV_ERR_UNEXPECTED_EOS:
+					php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): unexpected end of stream", inst->filtername);
+					goto out_failure;
 
-					default:
-						break;
-				}
+				default:
+					break;
+			}
 
-				if (err == PHP_CONV_ERR_TOO_BIG) {
-					char *new_out_buf;
-					size_t new_out_buf_size;
+			if (err != PHP_CONV_ERR_TOO_BIG) {
+				break;
+			} else {
+				char *new_out_buf;
+				size_t new_out_buf_size;
 
-					new_out_buf_size = out_buf_size << 1;
+				new_out_buf_size = out_buf_size << 1;
 
-					if (new_out_buf_size < out_buf_size) {
-						/* whoa! no bigger buckets are sold anywhere... */
-						new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, inst->persistent TSRMLS_CC);
+				if (new_out_buf_size < out_buf_size) {
+					/* whoa! no bigger buckets are sold anywhere... */
+					new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, inst->persistent TSRMLS_CC);
 
-						php_stream_bucket_append(buckets_out, new_bucket TSRMLS_CC);
+					php_stream_bucket_append(buckets_out, new_bucket TSRMLS_CC);
 
-						out_buf_size = bucket->buflen;
-						out_buf = pemalloc(out_buf_size, inst->persistent);
-						ocnt = out_buf_size;
-						pd = out_buf;
-					} else {
-						new_out_buf = perealloc(out_buf, new_out_buf_size, inst->persistent);
-						pd = new_out_buf + (pd - out_buf);
-						ocnt += (new_out_buf_size - out_buf_size);
-						out_buf = new_out_buf;
-						out_buf_size = new_out_buf_size;
-					}
+					out_buf_size = bucket->buflen;
+					out_buf = pemalloc(out_buf_size, inst->persistent);
+					ocnt = out_buf_size;
+					pd = out_buf;
+				} else {
+					new_out_buf = perealloc(out_buf, new_out_buf_size, inst->persistent);
+					pd = new_out_buf + (pd - out_buf);
+					ocnt += (new_out_buf_size - out_buf_size);
+					out_buf = new_out_buf;
+					out_buf_size = new_out_buf_size;
 				}
 			}
-
-			/* update consumed by the number of bytes just used */
-			consumed += bucket->buflen - icnt;
-
-			/* give output bucket to next in chain */
-			if (out_buf_size - ocnt > 0) {
-				new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, inst->persistent TSRMLS_CC);
-				php_stream_bucket_append(buckets_out, new_bucket TSRMLS_CC);
-			} else {
-				pefree(out_buf, inst->persistent);
-			}
-
-			php_stream_bucket_delref(bucket TSRMLS_CC);
+		}
+		/* give output bucket to next in chain */
+		if (out_buf_size - ocnt > 0) {
+			new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, inst->persistent TSRMLS_CC);
+			php_stream_bucket_append(buckets_out, new_bucket TSRMLS_CC);
+		} else {
+			pefree(out_buf, inst->persistent);
 		}
 	}
 
+
 	if (bytes_consumed) {
 		*bytes_consumed = consumed;
 	}
diff --git a/ext/standard/flock_compat.c b/ext/standard/flock_compat.c
index 373f43f9cd7e..0b1d0b1c222a 100644
--- a/ext/standard/flock_compat.c
+++ b/ext/standard/flock_compat.c
@@ -33,11 +33,7 @@
 #endif
 
 #ifdef NETWARE
-#ifdef NEW_LIBC
 #include 
-#else
-#include 
-#endif
 #endif
 
 #ifndef HAVE_FLOCK
diff --git a/ext/standard/formatted_print.c b/ext/standard/formatted_print.c
index f86694e72b2e..8119ce2f906a 100644
--- a/ext/standard/formatted_print.c
+++ b/ext/standard/formatted_print.c
@@ -303,7 +303,15 @@ php_sprintf_appenddouble(char **buffer, int *pos,
 	char *cvt;
 	register int i = 0, j = 0;
 	int sign, decpt, cvt_len;
-	char decimal_point = EG(float_separator)[0];
+	char decimal_point = '.';
+#ifdef HAVE_LOCALE_H
+	struct lconv lc;
+	char locale_decimal_point;
+	localeconv_r(&lc);
+	locale_decimal_point = (lc.decimal_point)[0];
+#else
+	char locale_decimal_point = '.';
+#endif
 
 	PRINTF_DEBUG(("sprintf: appenddouble(%x, %x, %x, %f, %d, '%c', %d, %c)\n",
 				  *buffer, pos, size, number, width, padding, alignment, fmt));
@@ -336,12 +344,12 @@ php_sprintf_appenddouble(char **buffer, int *pos,
 		numbuf[i++] = '+';
 	}
 
-	if (fmt == 'f') {
+	if (fmt == 'f' || fmt == 'F') {
 		if (decpt <= 0) {
 			numbuf[i++] = '0';
 			if (precision > 0) {
 				int k = precision;
-				numbuf[i++] = decimal_point;
+				numbuf[i++] = fmt == 'F' ? decimal_point : locale_decimal_point;
 				while ((decpt++ < 0) && k--) {
 					numbuf[i++] = '0';
 				}
@@ -351,7 +359,7 @@ php_sprintf_appenddouble(char **buffer, int *pos,
 				numbuf[i++] = j < cvt_len ? cvt[j++] : '0';
 			}
 			if (precision > 0) {
-				numbuf[i++] = decimal_point;
+				numbuf[i++] = fmt == 'F' ? decimal_point : locale_decimal_point;
 				while (precision-- > 0) {
 					numbuf[i++] = j < cvt_len ? cvt[j++] : '0';
 				}
@@ -398,9 +406,6 @@ php_sprintf_appenddouble(char **buffer, int *pos,
 
 	numbuf[i] = '\0';
 
-	if (precision > 0) {
-		width += (precision + 1);
-	}
 	php_sprintf_appendstring(buffer, pos, size, numbuf, width, 0, padding,
 							 alignment, i, sign, 0, always_sign);
 }
@@ -540,12 +545,6 @@ php_formatted_print(int ht, int *len, int use_array, int format_offset TSRMLS_DC
 			php_sprintf_appendchar(&result, &outpos, &size, '%' TSRMLS_CC);
 			inpos += 2;
 		} else {
-			if (currarg >= argc && format[inpos + 1] != '%') {
-				efree(result);
-				efree(args);
-				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too few arguments");
-				return NULL;
-			}
 			/* starting a new format specifier, reset variables */
 			alignment = ALIGN_RIGHT;
 			adjusting = 0;
@@ -576,13 +575,6 @@ php_formatted_print(int ht, int *len, int use_array, int format_offset TSRMLS_DC
 				}
 
 				argnum += format_offset;
-				
-				if (argnum >= argc) {
-					efree(result);
-					efree(args);
-					php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too few arguments");
-					return NULL;
-				}
 
 				/* after argnum comes modifiers */
 				PRINTF_DEBUG(("sprintf: looking for modifiers\n"
@@ -638,6 +630,13 @@ php_formatted_print(int ht, int *len, int use_array, int format_offset TSRMLS_DC
 				argnum = currarg++ + format_offset;
 			}
 
+			if (argnum >= argc) {
+				efree(result);
+				efree(args);
+				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too few arguments");
+				return NULL;
+			}
+
 			if (format[inpos] == 'l') {
 				inpos++;
 			}
@@ -693,6 +692,7 @@ php_formatted_print(int ht, int *len, int use_array, int format_offset TSRMLS_DC
 
 				case 'e':
 				case 'f':
+				case 'F':
 					/* XXX not done */
 					convert_to_double(tmp);
 					php_sprintf_appenddouble(&result, &outpos, &size,
diff --git a/ext/standard/fsock.h b/ext/standard/fsock.h
index e38035a89fe1..9b2df3985e85 100644
--- a/ext/standard/fsock.h
+++ b/ext/standard/fsock.h
@@ -25,14 +25,6 @@
 #ifndef FSOCK_H
 #define FSOCK_H
 
-#ifdef NETWARE
-#ifdef NEW_LIBC
-#include "sys/timeval.h"
-#else
-#include "netware/time_nw.h"    /* For 'timeval' */
-#endif
-#endif
-
 #include "file.h"
 
 #include "php_network.h"
diff --git a/ext/standard/ftok.c b/ext/standard/ftok.c
index ec270d2f14b0..68080068d53f 100644
--- a/ext/standard/ftok.c
+++ b/ext/standard/ftok.c
@@ -31,34 +31,36 @@
    Convert a pathname and a project identifier to a System V IPC key */
 PHP_FUNCTION(ftok)
 {
-    pval **pathname, **proj;
+	zval **pathname, **proj;
+	key_t k;
 
-    key_t k;
-
-    if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &pathname, &proj) == FAILURE) {
-        WRONG_PARAM_COUNT;
-    }
+	if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &pathname, &proj) == FAILURE) {
+		WRONG_PARAM_COUNT;
+	}
 
-    convert_to_string_ex(pathname);
-    convert_to_string_ex(proj);
+	convert_to_string_ex(pathname);
+	convert_to_string_ex(proj);
 
-    if (Z_STRLEN_PP(pathname)==0){
-        php_error_docref(NULL TSRMLS_CC, E_WARNING, "First argument invalid");
-        RETURN_LONG(-1);
-    }
+	if (Z_STRLEN_PP(pathname)==0){
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Pathname is invalid");
+		RETURN_LONG(-1);
+	}
 
-    if (Z_STRLEN_PP(proj)!=1){
-        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Second argument invalid");
-        RETURN_LONG(-1);
-    }
+	if (Z_STRLEN_PP(proj)!=1){
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Project identifier is invalid");
+		RETURN_LONG(-1);
+	}
 
 	if ((PG(safe_mode) && (!php_checkuid(Z_STRVAL_PP(pathname), NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(Z_STRVAL_PP(pathname) TSRMLS_CC)) {
 		RETURN_LONG(-1);
 	}
 
-    k = ftok(Z_STRVAL_PP(pathname),Z_STRVAL_PP(proj)[0]);
+	k = ftok(Z_STRVAL_PP(pathname),Z_STRVAL_PP(proj)[0]);
+	if (k == -1) {
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "ftok() failed - %s", strerror(errno));
+	}
 
-    RETURN_LONG(k);
+	RETURN_LONG(k);
 }
 /* }}} */
 #endif
diff --git a/ext/standard/ftp_fopen_wrapper.c b/ext/standard/ftp_fopen_wrapper.c
index 15e6c6438557..a346f814fb49 100644
--- a/ext/standard/ftp_fopen_wrapper.c
+++ b/ext/standard/ftp_fopen_wrapper.c
@@ -35,14 +35,6 @@
 #include 
 #define O_RDONLY _O_RDONLY
 #include "win32/param.h"
-#elif defined(NETWARE)
-/*#include */
-/*#include */
-#ifdef NEW_LIBC
-#include 
-#else
-#include "netware/param.h"
-#endif
 #else
 #include 
 #endif
@@ -121,13 +113,17 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, char *path
 {
 	php_stream *stream = NULL, *reuseid = NULL;
 	php_url *resource = NULL;
-	int result, use_ssl, use_ssl_on_data = 0;
+	int result, use_ssl, use_ssl_on_data = 0, tmp_len;
 	char *scratch;
 	char tmp_line[512];
 
 	resource = php_url_parse(path);
-	if (resource == NULL || resource->path == NULL)
+	if (resource == NULL || resource->path == NULL) {
+		if (resource && presource) {
+			*presource = resource;
+		}
 		return NULL;
+	}
 
 	use_ssl = resource->scheme && (strlen(resource->scheme) > 3) && resource->scheme[3] == 's';
 
@@ -210,10 +206,24 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, char *path
 #endif
 	}
 
+#define PHP_FTP_CNTRL_CHK(val, val_len, err_msg) {	\
+	unsigned char *s = val, *e = s + val_len;	\
+	while (s < e) {	\
+		if (iscntrl(*s)) {	\
+			php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, err_msg, val);	\
+			goto connect_errexit;	\
+		}	\
+		s++;	\
+	}	\
+}
+
 	/* send the user name */
 	php_stream_write_string(stream, "USER ");
 	if (resource->user != NULL) {
-		php_raw_url_decode(resource->user, strlen(resource->user));
+		tmp_len = php_raw_url_decode(resource->user, strlen(resource->user));
+
+		PHP_FTP_CNTRL_CHK(resource->user, tmp_len, "Invalid login %s")
+
 		php_stream_write_string(stream, resource->user);
 	} else {
 		php_stream_write_string(stream, "anonymous");
@@ -229,7 +239,10 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, char *path
 
 		php_stream_write_string(stream, "PASS ");
 		if (resource->pass != NULL) {
-			php_raw_url_decode(resource->pass, strlen(resource->pass));
+			tmp_len = php_raw_url_decode(resource->pass, strlen(resource->pass));
+
+			PHP_FTP_CNTRL_CHK(resource->pass, tmp_len, "Invalid password %s")
+
 			php_stream_write_string(stream, resource->pass);
 		} else {
 			/* if the user has configured who they are,
@@ -270,7 +283,11 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, char *path
 
 	return stream;
 
- connect_errexit:
+connect_errexit:
+	if (resource) {
+		php_url_free(resource);	
+	}
+
 	if (stream) {
 		php_stream_close(stream);
 	}
@@ -641,12 +658,15 @@ php_stream * php_stream_ftp_opendir(php_stream_wrapper *wrapper, char *path, cha
 {
 	php_stream *stream, *reuseid, *datastream = NULL;
 	php_url *resource = NULL;
-	int result, use_ssl, use_ssl_on_data = 0;
+	int result = 0, use_ssl, use_ssl_on_data = 0;
 	char *hoststart = NULL, tmp_line[512];
 	char ip[sizeof("123.123.123.123")];
 	unsigned short portno;
 
 	stream = php_ftp_fopen_connect(wrapper, path, mode, options, opened_path, context, &reuseid, &resource, &use_ssl, &use_ssl_on_data TSRMLS_CC);
+	if (!stream) {
+		goto opendir_errexit;	
+	}
 
 	/* set the connection to be ascii */
 	php_stream_write_string(stream, "TYPE A\r\n");
@@ -773,9 +793,15 @@ static int php_stream_ftp_url_stat(php_stream_wrapper *wrapper, char *url, int f
 	ssb->sb.st_dev = 0;
 	ssb->sb.st_uid = 0;
 	ssb->sb.st_gid = 0;
+#ifdef NETWARE
+	ssb->sb.st_atime.tv_sec = -1;
+	ssb->sb.st_mtime.tv_sec = -1;
+	ssb->sb.st_ctime.tv_sec = -1;
+#else
 	ssb->sb.st_atime = -1;
 	ssb->sb.st_mtime = -1;
 	ssb->sb.st_ctime = -1;
+#endif
 	ssb->sb.st_nlink = 1;
 	ssb->sb.st_rdev = -1;
 #ifdef HAVE_ST_BLKSIZE
diff --git a/ext/standard/head.c b/ext/standard/head.c
index 096abbc6c7f4..a80e1d2ee560 100644
--- a/ext/standard/head.c
+++ b/ext/standard/head.c
@@ -18,17 +18,11 @@
 /* $Id$ */
 
 #include 
-
-#if defined(NETWARE) && !defined(NEW_LIBC)
-#include 
-#endif
-
 #include "php.h"
 #include "ext/standard/php_standard.h"
 #include "SAPI.h"
 #include "php_main.h"
 #include "head.h"
-#include "SAPI.h"
 #ifdef TM_IN_SYS_TIME
 #include 
 #else
diff --git a/ext/standard/html.c b/ext/standard/html.c
index 4f8a4be46bf0..940945720e5b 100644
--- a/ext/standard/html.c
+++ b/ext/standard/html.c
@@ -27,15 +27,15 @@
  * http://msdn.microsoft.com/workshop/author/dhtml/reference/charsets/charset3.asp
  * http://www.unicode.org/Public/MAPPINGS/OBSOLETE/UNI2SGML.TXT
  *
+ * http://www.w3.org/TR/2002/REC-xhtml1-20020801/dtds.html#h-A2
+ * 
  */
 
 #include "php.h"
 #if PHP_WIN32
 #include "config.w32.h"
-#elif defined NETWARE
-#include "config.nw.h"
 #else
-#include "php_config.h"
+#include 
 #endif
 #include "reg.h"
 #include "html.h"
@@ -58,7 +58,7 @@ enum entity_charset { cs_terminator, cs_8859_1, cs_cp1252,
 					  cs_big5hkscs, cs_sjis, cs_eucjp, cs_koi8r,
 					  cs_cp1251, cs_8859_5, cs_cp866, cs_macroman
 					};
-typedef const char *entity_table_t;
+typedef const char *const entity_table_t;
 
 /* codepage 1252 is a Windows extension to iso-8859-1. */
 static entity_table_t ent_cp_1252[] = {
@@ -106,33 +106,29 @@ static entity_table_t ent_iso_8859_15[] = {
 };
 
 static entity_table_t ent_uni_338_402[] = {
-	/* 338 */
-	"OElig", "oelig", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL,
-	/* 352 */
-	"Scaron", "scaron",
-	/* 354 - 375 */
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	/* 376 */
-	"Yuml",
-	/* 377 - 401 */
+	/* 338 (0x0152) */
+	"OElig", "oelig", NULL, NULL, NULL, NULL,
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	/* 352 (0x0160) */
+	"Scaron", "scaron", NULL, NULL, NULL, NULL, NULL, NULL,
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	/* 402 */
-	"fnof"
+	/* 376 (0x0178) */
+	"Yuml", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	/* 400 (0x0190) */
+	NULL, NULL, "fnof"
 };
 
 static entity_table_t ent_uni_spacing[] = {
 	/* 710 */
 	"circ",
-	/* 711 - 731 */
+	/* 711 - 730 */
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	/* 732 */
-	"tilde",
+	/* 731 - 732 */
+	NULL, "tilde"
 };
 
 static entity_table_t ent_uni_greek[] = {
@@ -147,9 +143,9 @@ static entity_table_t ent_uni_greek[] = {
 	"sigmaf", "sigma", "tau", "upsilon", "phi", "chi", "psi", "omega",
 	/* 970 - 976 are not mapped */
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	"thetasym", "ups1h",
+	"thetasym", "upsih",
 	NULL, NULL, NULL,
-	"p1v" 
+	"piv" 
 };
 
 static entity_table_t ent_uni_punct[] = {
@@ -157,11 +153,13 @@ static entity_table_t ent_uni_punct[] = {
 	"ensp", "emsp", NULL, NULL, NULL, NULL, NULL,
 	"thinsp", NULL, NULL, "zwnj", "zwj", "lrm", "rlm",
 	NULL, NULL, NULL, "ndash", "mdash", NULL, NULL, NULL,
-	"lsquo", "rsquo", "sbquo", NULL, "ldquo", "rdquo", "bdquo",
+	/* 8216 */
+	"lsquo", "rsquo", "sbquo", NULL, "ldquo", "rdquo", "bdquo", NULL,
 	"dagger", "Dagger",	"bull", NULL, NULL, NULL, "hellip",
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "permil", NULL,
-	"prime", "Prime", NULL, NULL, NULL, NULL, NULL, "lsaquo", "rsaquo",
-	NULL, NULL, NULL, "oline", NULL, NULL, NULL, NULL, NULL,
+	/* 8242 */
+	"prime", "Prime", NULL, NULL, NULL, NULL, NULL, "lsaquo", "rsaquo", NULL,
+	NULL, NULL, "oline", NULL, NULL, NULL, NULL, NULL,
 	"frasl"
 };
 
@@ -191,7 +189,7 @@ static entity_table_t ent_uni_8592_9002[] = {
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	/* 8624 (0x21b0) */
-	NULL, NULL, NULL, NULL, "crarr", NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL, "crarr", NULL, NULL,
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	/* 8640 (0x21c0) */
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -206,9 +204,9 @@ static entity_table_t ent_uni_8592_9002[] = {
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	/* 8704 (0x2200) */
 	"forall", "comp", "part", "exist", "nexist", "empty", NULL, "nabla",
-	"isin", "notin", "epsis", NULL, "ni", "bepsi", NULL, "prod",
+	"isin", "notin", "epsis", "ni", "notni", "bepsi", NULL, "prod",
 	/* 8720 (0x2210) */
-	"coprod", "sum", "minus", "mnplus", "plusdo", NULL, "setmn", NULL,
+	"coprod", "sum", "minus", "mnplus", "plusdo", NULL, "setmn", "lowast",
 	"compfn", NULL, "radic", NULL, NULL, "prop", "infin", "ang90",
 	/* 8736 (0x2220) */
 	"ang", "angmsd", "angsph", "mid", "nmid", "par", "npar", "and",
@@ -218,7 +216,7 @@ static entity_table_t ent_uni_8592_9002[] = {
 	NULL, NULL, NULL, NULL, "sim", "bsim", NULL, NULL,
 	/* 8768 (0x2240) */
 	"wreath", "nsim", NULL, "sime", "nsime", "cong", NULL, "ncong",
-	"ap", "nap", "ape", NULL, "bcong", "asymp", "bump", "bumpe",
+	"asymp", "nap", "ape", NULL, "bcong", "asymp", "bump", "bumpe",
 	/* 8784 (0x2250) */
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -230,38 +228,37 @@ static entity_table_t ent_uni_8592_9002[] = {
 	NULL, NULL, "pr", "sc", "cupre", "sscue", "prsim", "scsim",
 	/* 8832 (0x2280) */
 	"npr", "nsc", "sub", "sup", "nsub", "nsup", "sube", "supe",
-	/* 8840 - 8852 */
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	/* 8853 */
-	"oplus", NULL, "otimes",
-	/* 8856 - 8868 */
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	/* 8869 */
-	"perp",
-	/* 8870 - 8901 */
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL,
-	/* 8901 */
-	"sdot",
-	/* 8902 - 8967 */
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL,
-	/* 8968 */
-	"lceil", "rceil", "lfloor", "rfloor",
-	/* 8969 - 9000 */
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL,
-	/* 9001 */
-	"lang", "rang",
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	/* 8848 (0x2290) */
+	NULL, NULL, NULL, NULL, NULL, "oplus", NULL, "otimes",
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	/* 8864 (0x22a0) */
+	NULL, NULL, NULL, NULL, NULL, "perp", NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	/* 8880 (0x22b0) */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	/* 8896 (0x22c0) */
+	NULL, NULL, NULL, NULL, NULL, "sdot", NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	/* 8912 (0x22d0) */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	/* 8928 (0x22e0) */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	/* 8944 (0x22f0) */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	/* 8960 (0x2300) */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	"lceil", "rceil", "lfloor", "rfloor", NULL, NULL, NULL, NULL,
+	/* 8976 (0x2310) */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	/* 8992 (0x2320) */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	NULL, "lang", "rang"
 };
 
 static entity_table_t ent_uni_9674[] = {
@@ -899,8 +896,7 @@ PHPAPI char *php_unescape_html_entities(unsigned char *old, int oldlen, int *new
 
 				if (entity_map[j].table[k - entity_map[j].basechar] == NULL)
 					continue;
-			
-				
+
 				entity[0] = '&';
 				entity_length = strlen(entity_map[j].table[k - entity_map[j].basechar]);
 				strncpy(&entity[1], entity_map[j].table[k - entity_map[j].basechar], sizeof(entity) - 2);
@@ -940,9 +936,11 @@ PHPAPI char *php_unescape_html_entities(unsigned char *old, int oldlen, int *new
 						return 0;
 				}
 
-				replaced = php_str_to_str(ret, retlen, entity, entity_length, replacement, replacement_len, &retlen);
-				efree(ret);
-				ret = replaced;
+				if (php_memnstr(ret, entity, entity_length, ret+retlen)) {
+					replaced = php_str_to_str(ret, retlen, entity, entity_length, replacement, replacement_len, &retlen);
+					efree(ret);
+					ret = replaced;
+				}
 			}
 		}
 	}
@@ -954,10 +952,12 @@ PHPAPI char *php_unescape_html_entities(unsigned char *old, int oldlen, int *new
 		
 		replacement[0] = (unsigned char)basic_entities[j].charcode;
 		replacement[1] = '\0';
-		
-		replaced = php_str_to_str(ret, retlen, basic_entities[j].entity, basic_entities[j].entitylen, replacement, 1, &retlen);
-		efree(ret);
-		ret = replaced;
+
+		if (php_memnstr(ret, basic_entities[j].entity, basic_entities[j].entitylen, ret+retlen)) {		
+			replaced = php_str_to_str(ret, retlen, basic_entities[j].entity, basic_entities[j].entitylen, replacement, 1, &retlen);
+			efree(ret);
+			ret = replaced;
+		}
 	}
 
 	/* replace numeric entities & "&" */
@@ -988,7 +988,11 @@ PHPAPI char *php_unescape_html_entities(unsigned char *old, int oldlen, int *new
 								if ((code >= 0x80 && code < 0xa0) || code > 0xff) {
 									invalid_code = 1;
 								} else {
-									*(q++) = code;
+									if (code == 39 || !quote_style) {
+										invalid_code = 1;
+									} else {
+										*(q++) = code;
+									}
 								}
 								break;
 
diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c
index d45864fedd13..dfa2133e508e 100644
--- a/ext/standard/http_fopen_wrapper.c
+++ b/ext/standard/http_fopen_wrapper.c
@@ -37,14 +37,6 @@
 #ifdef PHP_WIN32
 #define O_RDONLY _O_RDONLY
 #include "win32/param.h"
-#elif defined(NETWARE)
-/*#include */
-/*#include */
-#ifdef NEW_LIBC
-#include 
-#else
-#include "netware/param.h"
-#endif
 #else
 #include 
 #endif
@@ -109,6 +101,8 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
 	char *transport_string, *errstr = NULL;
 	int transport_len, have_header = 0, request_fulluri = 0;
 
+	tmp_line[0] = '\0';
+
 	if (redirect_max < 1) {
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Circular redirect, aborting.");
 		return NULL;
@@ -525,6 +519,34 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
 			} else {
 				strlcpy(new_path, location, sizeof(new_path));
 			}
+
+			php_url_free(resource);
+			/* check for invalid redirection URLs */
+			if ((resource = php_url_parse(new_path)) == NULL) {
+				php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Invalid redirect url! %s", new_path);
+				goto out;
+			}
+
+#define CHECK_FOR_CNTRL_CHARS(val) {	\
+	if (val) {	\
+		unsigned char *s, *e;	\
+		int l;	\
+		l = php_url_decode(val, strlen(val));	\
+		s = val; e = s + l;	\
+		while (s < e) {	\
+			if (iscntrl(*s)) {	\
+				php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Invalid redirect url! %s", new_path);	\
+				goto out;	\
+			}	\
+			s++;	\
+		}	\
+	}	\
+}	\
+			/* check for control characters in login, password & path */
+			CHECK_FOR_CNTRL_CHARS(resource->user)
+			CHECK_FOR_CNTRL_CHARS(resource->pass)
+			CHECK_FOR_CNTRL_CHARS(resource->path)
+
 			stream = php_stream_url_wrap_http_ex(NULL, new_path, mode, options, opened_path, context, --redirect_max, 0 STREAMS_CC TSRMLS_CC);
 			if (stream && stream->wrapperdata)	{
 				entryp = &entry;
@@ -549,7 +571,9 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
 		efree(http_header_line);
 	if (scratch)
 		efree(scratch);
-	php_url_free(resource);
+	if (resource) {
+		php_url_free(resource);
+	}
 
 	if (stream) {
 		if (header_init) {
diff --git a/ext/standard/image.c b/ext/standard/image.c
index c2c3c7ab8626..7aec82b8923e 100644
--- a/ext/standard/image.c
+++ b/ext/standard/image.c
@@ -21,9 +21,6 @@
 
 #include "php.h"
 #include 
-#if defined(NETWARE) && !defined(NEW_LIBC)
-#include 
-#endif
 #if HAVE_FCNTL_H
 #include 
 #endif
@@ -401,7 +398,7 @@ static unsigned int php_next_marker(php_stream * stream, int last_marker, int co
 				last_marker = M_PSEUDO; /* stop skipping non 0xff for M_COM */
 			}
 		}
-		if (++a > 10)
+		if (++a > 25)
 		{
 			/* who knows the maxim amount of 0xff? though 7 */
 			/* but found other implementations              */
@@ -604,7 +601,7 @@ static struct gfxinfo *php_handle_jpc(php_stream * stream TSRMLS_DC)
 {
 	struct gfxinfo *result = NULL;
 	unsigned short dummy_short;
-	int dummy_int, highest_bit_depth, bit_depth;
+	int highest_bit_depth, bit_depth;
 	unsigned char first_marker_id;
 	unsigned int i;
 
@@ -628,17 +625,28 @@ static struct gfxinfo *php_handle_jpc(php_stream * stream TSRMLS_DC)
 
 	dummy_short = php_read2(stream TSRMLS_CC); /* Lsiz */
 	dummy_short = php_read2(stream TSRMLS_CC); /* Rsiz */
-	result->height = php_read4(stream TSRMLS_CC); /* Xsiz */
 	result->width = php_read4(stream TSRMLS_CC); /* Ysiz */
+	result->height = php_read4(stream TSRMLS_CC); /* Xsiz */
 
-	dummy_int = php_read4(stream TSRMLS_CC); /* XOsiz */
-	dummy_int = php_read4(stream TSRMLS_CC); /* YOsiz */
-	dummy_int = php_read4(stream TSRMLS_CC); /* XTsiz */
-	dummy_int = php_read4(stream TSRMLS_CC); /* YTsiz */
-	dummy_int = php_read4(stream TSRMLS_CC); /* XTOsiz */
-	dummy_int = php_read4(stream TSRMLS_CC); /* YTOsiz */
+#if MBO_0
+	php_read4(stream TSRMLS_CC); /* XOsiz */
+	php_read4(stream TSRMLS_CC); /* YOsiz */
+	php_read4(stream TSRMLS_CC); /* XTsiz */
+	php_read4(stream TSRMLS_CC); /* YTsiz */
+	php_read4(stream TSRMLS_CC); /* XTOsiz */
+	php_read4(stream TSRMLS_CC); /* YTOsiz */
+#else
+	if (php_stream_seek(stream, 24, SEEK_CUR)) {
+		efree(result);
+		return NULL;
+	}
+#endif
 
 	result->channels = php_read2(stream TSRMLS_CC); /* Csiz */
+	if (result->channels < 0 || result->channels > 256) {
+		efree(result);
+		return NULL;
+	}
 
 	/* Collect bit depth info */
 	highest_bit_depth = bit_depth = 0;
@@ -700,8 +708,15 @@ static struct gfxinfo *php_handle_jp2(php_stream *stream TSRMLS_DC)
 			break;
 		}
 
+		/* Stop if this was the last box */
+		if ((int)box_length <= 0) {
+			break;
+		}
+
 		/* Skip over LBox (Which includes both TBox and LBox itself */
-		php_stream_seek(stream, box_length - 8, SEEK_CUR); 
+		if (php_stream_seek(stream, box_length - 8, SEEK_CUR)) {
+			break;
+		}
 	}
 
 	if (result == NULL) {
@@ -864,43 +879,49 @@ static struct gfxinfo *php_handle_tiff (php_stream * stream, pval *info, int mot
  */
 static struct gfxinfo *php_handle_iff(php_stream * stream TSRMLS_DC)
 {
-	struct gfxinfo *result = NULL;
+	struct gfxinfo * result;
 	unsigned char a[10];
 	int chunkId;
 	int size;
+	short width, height, bits;
 
-	if (php_stream_read(stream, a, 8) != 8)
+	if (php_stream_read(stream, a, 8) != 8) {
 		return NULL;
-	if (strncmp(a+4, "ILBM", 4) && strncmp(a+4, "PBM ", 4))
+	}
+	if (strncmp(a+4, "ILBM", 4) && strncmp(a+4, "PBM ", 4)) {
 		return NULL;
-
-	result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo));
+	}
 
 	/* loop chunks to find BMHD chunk */
 	do {
 		if (php_stream_read(stream, a, 8) != 8) {
-			efree(result);
 			return NULL;
 		}
 		chunkId = php_ifd_get32s(a+0, 1);
 		size    = php_ifd_get32s(a+4, 1);
+		if (size < 0) {
+			return NULL;
+		}
 		if ((size & 1) == 1) {
 			size++;
 		}
 		if (chunkId == 0x424d4844) { /* BMHD chunk */
-			if (php_stream_read(stream, a, 9) != 9) {
-				efree(result);
+			if (size < 9 || php_stream_read(stream, a, 9) != 9) {
 				return NULL;
 			}
-			result->width    = php_ifd_get16s(a+0, 1);
-			result->height   = php_ifd_get16s(a+2, 1);
-			result->bits     = a[8] & 0xff;
-			result->channels = 0;
-			if (result->width > 0 && result->height > 0 && result->bits > 0 && result->bits < 33)
+			width  = php_ifd_get16s(a+0, 1);
+			height = php_ifd_get16s(a+2, 1);
+			bits   = a[8] & 0xff;
+			if (width > 0 && height > 0 && bits > 0 && bits < 33) {
+				result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo));
+				result->width    = width;
+				result->height   = height;
+				result->bits     = bits;
+				result->channels = 0;
 				return result;
+			}
 		} else {
 			if (php_stream_seek(stream, size, SEEK_CUR)) {
-				efree(result);
 				return NULL;
 			}
 		}
@@ -955,6 +976,11 @@ static int php_get_wbmp(php_stream *stream, struct gfxinfo **result, int check T
 		}
 		height = (height << 7) | (i & 0x7f);
 	} while (i & 0x80);
+
+	/* maximum valid sizes for wbmp (although 127x127 may be a more accurate one) */
+	if (!height || !width || height > 2048 || width > 2048) {
+		return 0;
+	}
 	
 	if (!check) {
 		(*result)->width = width;
@@ -1283,11 +1309,14 @@ PHP_FUNCTION(getimagesize)
 		case IMAGE_FILETYPE_SWF:
 			result = php_handle_swf(stream TSRMLS_CC);
 			break;
-#if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB)
 		case IMAGE_FILETYPE_SWC:
+#if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB)
 			result = php_handle_swc(stream TSRMLS_CC);
-			break;
+#else
+			php_error_docref(NULL TSRMLS_CC, E_NOTICE, "The image is a compressed SWF file, but you do not have a static version of the zlib extension enabled.");
+
 #endif
+			break;
 		case IMAGE_FILETYPE_PSD:
 			result = php_handle_psd(stream TSRMLS_CC);
 			break;
diff --git a/ext/standard/incomplete_class.c b/ext/standard/incomplete_class.c
index 911491c9518b..49b0ed69f532 100644
--- a/ext/standard/incomplete_class.c
+++ b/ext/standard/incomplete_class.c
@@ -26,39 +26,33 @@
 #define INCOMPLETE_CLASS_MSG \
 		"The script tried to execute a method or "  \
 		"access a property of an incomplete object. " \
-		"Please ensure that the class definition %s of the object " \
+		"Please ensure that the class definition \"%s\" of the object " \
 		"you are trying to operate on was loaded _before_ " \
-		"the session was started"
+		"unserialize() gets called or provide a __autoload() function " \
+		"to load the class definition "
 
 
 static zend_object_handlers php_incomplete_object_handlers;
 
 /* {{{ incomplete_class_message
  */
-static void incomplete_class_message(int error_type TSRMLS_DC)
+static void incomplete_class_message(zval *object, int error_type TSRMLS_DC)
 {
-	char buf[1024];
-	char *class_name = NULL;
+	char *class_name;
 
-	if(EG(This)) {
-		class_name = php_lookup_class_name(EG(This), NULL);
-	}
+	class_name = php_lookup_class_name(object, NULL);
 	
 	if (!class_name) {
-		class_name = estrndup("unknown", sizeof("unknown")-1);
+		class_name = "unknown";
 	}
 	
-	snprintf(buf, sizeof(buf)-1, INCOMPLETE_CLASS_MSG, class_name);
-	
-	efree(class_name);
-
-	php_error_docref(NULL TSRMLS_CC, error_type, "%s", buf);
+	php_error_docref(NULL TSRMLS_CC, error_type, INCOMPLETE_CLASS_MSG, class_name);
 }
 /* }}} */
 
 static zval *incomplete_class_get_property(zval *object, zval *member, int type TSRMLS_DC)
 {
-	incomplete_class_message(E_NOTICE TSRMLS_CC);
+	incomplete_class_message(object, E_NOTICE TSRMLS_CC);
 	if(type == BP_VAR_W || type == BP_VAR_RW) {
 		return EG(error_zval_ptr);
 	} else {
@@ -68,28 +62,28 @@ static zval *incomplete_class_get_property(zval *object, zval *member, int type
 
 static void incomplete_class_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
 {
-	incomplete_class_message(E_NOTICE TSRMLS_CC);
+	incomplete_class_message(object, E_NOTICE TSRMLS_CC);
 }
 	
 static zval **incomplete_class_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC)
 {
-	incomplete_class_message(E_NOTICE TSRMLS_CC);
+	incomplete_class_message(object, E_NOTICE TSRMLS_CC);
 	return &EG(error_zval_ptr);
 }
 
 static void incomplete_class_unset_property(zval *object, zval *member TSRMLS_DC)
 {
-	incomplete_class_message(E_NOTICE TSRMLS_CC);
+	incomplete_class_message(object, E_NOTICE TSRMLS_CC);
 }
 
 static int incomplete_class_has_property(zval *object, zval *member, int check_empty TSRMLS_DC)
 {
-	incomplete_class_message(E_NOTICE TSRMLS_CC);
+	incomplete_class_message(object, E_NOTICE TSRMLS_CC);
 	return 0;
 }
 
-static union _zend_function *incomplete_class_get_method(zval *object, char *method, int method_len TSRMLS_DC) {
-	incomplete_class_message(E_ERROR TSRMLS_CC);
+static union _zend_function *incomplete_class_get_method(zval *object_ptr, char *method, int method_len TSRMLS_DC) {
+	incomplete_class_message(object_ptr, E_ERROR TSRMLS_CC);
 	return NULL;
 }
 
diff --git a/ext/standard/info.c b/ext/standard/info.c
index afed5551931f..e4a2bd96d474 100644
--- a/ext/standard/info.c
+++ b/ext/standard/info.c
@@ -135,10 +135,25 @@ static void php_print_gpcse_array(char *name, uint name_length TSRMLS_DC)
 				PUTS(" => ");
 			}
 			if (Z_TYPE_PP(tmp) == IS_ARRAY) {
+				zval *tmp3;
+
+				MAKE_STD_ZVAL(tmp3);
+
 				if (!sapi_module.phpinfo_as_text) {
 					PUTS("
");
 				}
+				php_start_ob_buffer(NULL, 4096, 1 TSRMLS_CC);
+				
 				zend_print_zval_r(*tmp, 0 TSRMLS_CC);
+				
+				php_ob_get_buffer(tmp3 TSRMLS_CC);
+				php_end_ob_buffer(0, 0 TSRMLS_CC);
+				
+				elem_esc = php_info_html_esc(Z_STRVAL_P(tmp3) TSRMLS_CC);
+				PUTS(elem_esc);
+				efree(elem_esc);
+				zval_ptr_dtor(&tmp3);
+
 				if (!sapi_module.phpinfo_as_text) {
 					PUTS("
"); } @@ -198,7 +213,7 @@ void php_info_print_style(TSRMLS_D) PHPAPI char *php_info_html_esc(char *string TSRMLS_DC) { int new_len; - return php_escape_html_entities(string, strlen(string), &new_len, 0, ENT_NOQUOTES, NULL TSRMLS_CC); + return php_escape_html_entities(string, strlen(string), &new_len, 0, ENT_QUOTES, NULL TSRMLS_CC); } /* }}} */ @@ -406,7 +421,9 @@ PHPAPI void php_print_info(int flag TSRMLS_DC) if (expose_php && !sapi_module.phpinfo_as_text) { PUTS("\"Zend\n"); } @@ -570,7 +595,9 @@ PHPAPI void php_print_info(int flag TSRMLS_DC) php_info_print_hr(); PUTS("

"); PUTS("PHP Credits"); diff --git a/ext/standard/lcg.c b/ext/standard/lcg.c index 5d1f1cd12873..f31fe294f63f 100644 --- a/ext/standard/lcg.c +++ b/ext/standard/lcg.c @@ -27,12 +27,6 @@ #ifdef PHP_WIN32 #include "win32/time.h" -#elif defined(NETWARE) -#ifdef NEW_LIBC -#include -#else -#include "netware/time_nw.h" -#endif #else #include #endif diff --git a/ext/standard/link.c b/ext/standard/link.c index 42ab3d8d251e..87b5531ea901 100644 --- a/ext/standard/link.c +++ b/ext/standard/link.c @@ -33,8 +33,6 @@ #if HAVE_PWD_H #ifdef PHP_WIN32 #include "win32/pwd.h" -#elif defined(NETWARE) -#include "netware/pwd.h" #else #include #endif @@ -65,6 +63,14 @@ PHP_FUNCTION(readlink) } convert_to_string_ex(filename); + if (PG(safe_mode) && !php_checkuid(Z_STRVAL_PP(filename), NULL, CHECKUID_CHECK_FILE_AND_DIR)) { + RETURN_FALSE; + } + + if (php_check_open_basedir(Z_STRVAL_PP(filename) TSRMLS_CC)) { + RETURN_FALSE; + } + ret = readlink(Z_STRVAL_PP(filename), buff, MAXPATHLEN-1); if (ret == -1) { @@ -83,11 +89,7 @@ PHP_FUNCTION(readlink) PHP_FUNCTION(linkinfo) { zval **filename; -#if defined(NETWARE) && defined(CLIB_STAT_PATCH) - struct stat_libc sb; -#else struct stat sb; -#endif int ret; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &filename) == FAILURE) { diff --git a/ext/standard/mail.c b/ext/standard/mail.c index 37973bbc139b..ab51be2f5d64 100644 --- a/ext/standard/mail.c +++ b/ext/standard/mail.c @@ -42,8 +42,8 @@ #endif #ifdef NETWARE -#include "netware/pipe.h" /* For popen(), pclose() */ -#include "netware/sysexits.h" /* For exit status codes like EX_OK */ +#define EX_OK 0 /* successful termination */ +#define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */ #endif #define SKIP_LONG_HEADER_SEP(str, pos) \ @@ -86,7 +86,7 @@ PHP_FUNCTION(mail) char *subject=NULL, *extra_cmd=NULL; int to_len, message_len, headers_len; int subject_len, extra_cmd_len, i; - char *force_extra_parameters = INI_STR("mail_force_extra_parameters"); + char *force_extra_parameters = INI_STR("mail.force_extra_parameters"); char *to_r, *subject_r; if (PG(safe_mode) && (ZEND_NUM_ARGS() == 5)) { diff --git a/ext/standard/math.c b/ext/standard/math.c index 1ab898569b7c..a851da409b09 100644 --- a/ext/standard/math.c +++ b/ext/standard/math.c @@ -1136,17 +1136,22 @@ PHP_FUNCTION(number_format) } convert_to_double_ex(num); convert_to_long_ex(dec); - convert_to_string_ex(d_p); - convert_to_string_ex(t_s); - if (Z_STRLEN_PP(d_p)==1) { - dec_point=Z_STRVAL_PP(d_p)[0]; - } else if (Z_STRLEN_PP(d_p)==0) { - dec_point=0; + + if (Z_TYPE_PP(d_p) != IS_NULL) { + convert_to_string_ex(d_p); + if (Z_STRLEN_PP(d_p)>=1) { + dec_point=Z_STRVAL_PP(d_p)[0]; + } else if (Z_STRLEN_PP(d_p)==0) { + dec_point=0; + } } - if (Z_STRLEN_PP(t_s)==1) { - thousand_sep=Z_STRVAL_PP(t_s)[0]; - } else if(Z_STRLEN_PP(t_s)==0) { - thousand_sep=0; + if (Z_TYPE_PP(t_s) != IS_NULL) { + convert_to_string_ex(t_s); + if (Z_STRLEN_PP(t_s)>=1) { + thousand_sep=Z_STRVAL_PP(t_s)[0]; + } else if(Z_STRLEN_PP(t_s)==0) { + thousand_sep=0; + } } RETURN_STRING(_php_math_number_format(Z_DVAL_PP(num), Z_LVAL_PP(dec), dec_point, thousand_sep), 0); break; diff --git a/ext/standard/md5.c b/ext/standard/md5.c index ef76ebf29d28..00108c49e038 100644 --- a/ext/standard/md5.c +++ b/ext/standard/md5.c @@ -23,9 +23,7 @@ * md5_file() added by Alessandro Astarita */ -#include #include "php.h" - #include "md5.h" PHPAPI void make_digest(char *md5str, unsigned char *digest) @@ -81,40 +79,31 @@ PHP_NAMED_FUNCTION(php_if_md5_file) unsigned char digest[16]; PHP_MD5_CTX context; int n; - FILE *fp; + php_stream *stream; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) { return; } - - if (PG(safe_mode) && (!php_checkuid(arg, NULL, CHECKUID_CHECK_FILE_AND_DIR))) { - RETURN_FALSE; - } - - if (php_check_open_basedir(arg TSRMLS_CC)) { - RETURN_FALSE; - } - - if ((fp = VCWD_FOPEN(arg, "rb")) == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open file"); + + stream = php_stream_open_wrapper(arg, "rb", REPORT_ERRORS | ENFORCE_SAFE_MODE, NULL); + if (!stream) { RETURN_FALSE; } PHP_MD5Init(&context); - while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) { + while ((n = php_stream_read(stream, buf, sizeof(buf))) > 0) { PHP_MD5Update(&context, buf, n); } PHP_MD5Final(digest, &context); - if (ferror(fp)) { - fclose(fp); + php_stream_close(stream); + + if (n<0) { RETURN_FALSE; } - fclose(fp); - if (raw_output) { RETURN_STRINGL(digest, 16, 1); } else { diff --git a/ext/standard/microtime.c b/ext/standard/microtime.c index 801c73afba5c..cbd09677452e 100644 --- a/ext/standard/microtime.c +++ b/ext/standard/microtime.c @@ -25,12 +25,6 @@ #endif #ifdef PHP_WIN32 #include "win32/time.h" -#elif defined(NETWARE) -#ifdef NEW_LIBC -#include -#else -#include "netware/time_nw.h" -#endif #else #include #endif @@ -152,6 +146,7 @@ PHP_FUNCTION(getrusage) PHP_RUSAGE_PARA(ru_nsignals); PHP_RUSAGE_PARA(ru_nvcsw); PHP_RUSAGE_PARA(ru_nivcsw); + PHP_RUSAGE_PARA(ru_nswap); #endif /*_OSD_POSIX*/ PHP_RUSAGE_PARA(ru_utime.tv_usec); PHP_RUSAGE_PARA(ru_utime.tv_sec); diff --git a/ext/standard/pack.c b/ext/standard/pack.c index 0376a7316a5a..3f1c87294455 100644 --- a/ext/standard/pack.c +++ b/ext/standard/pack.c @@ -30,17 +30,12 @@ #include "win32/param.h" #elif defined(NETWARE) #ifdef USE_WINSOCK -/*#include */ #include #else #include #endif -#ifdef NEW_LIBC #include #else -#include "netware/param.h" -#endif -#else #include #endif #include "ext/standard/head.h" @@ -50,8 +45,6 @@ #if HAVE_PWD_H #ifdef PHP_WIN32 #include "win32/pwd.h" -#elif defined(NETWARE) -#include "netware/pwd.h" #else #include #endif @@ -61,6 +54,13 @@ #include #endif +#define INC_OUTPUTPOS(a,b) \ + if ((a) < 0 || ((INT_MAX - outputpos)/(b)) < (a)) { \ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: integer overflow in format string", code); \ + RETURN_FALSE; \ + } \ + outputpos += (a)*(b); + /* Whether machine is little endian */ char machine_little_endian; @@ -244,7 +244,7 @@ PHP_FUNCTION(pack) switch ((int) code) { case 'h': case 'H': - outputpos += (arg + 1) / 2; /* 4 bit per arg */ + INC_OUTPUTPOS((arg + 1) / 2,1) /* 4 bit per arg */ break; case 'a': @@ -252,34 +252,34 @@ PHP_FUNCTION(pack) case 'c': case 'C': case 'x': - outputpos += arg; /* 8 bit per arg */ + INC_OUTPUTPOS(arg,1) /* 8 bit per arg */ break; case 's': case 'S': case 'n': case 'v': - outputpos += arg * 2; /* 16 bit per arg */ + INC_OUTPUTPOS(arg,2) /* 16 bit per arg */ break; case 'i': case 'I': - outputpos += arg * sizeof(int); + INC_OUTPUTPOS(arg,sizeof(int)) break; case 'l': case 'L': case 'N': case 'V': - outputpos += arg * 4; /* 32 bit per arg */ + INC_OUTPUTPOS(arg,4) /* 32 bit per arg */ break; case 'f': - outputpos += arg * sizeof(float); + INC_OUTPUTPOS(arg,sizeof(float)) break; case 'd': - outputpos += arg * sizeof(double); + INC_OUTPUTPOS(arg,sizeof(double)) break; case 'X': @@ -648,6 +648,11 @@ PHP_FUNCTION(unpack) sprintf(n, "%.*s", namelen, name); } + if (size != 0 && size != -1 && INT_MAX - size + 1 < inputpos) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: integer overflow", type); + inputpos = 0; + } + if ((inputpos + size) <= inputlen) { switch ((int) type) { case 'a': @@ -818,6 +823,12 @@ PHP_FUNCTION(unpack) } inputpos += size; + if (inputpos < 0) { + if (size != -1) { /* only print warning if not working with * */ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: outside of string", type); + } + inputpos = 0; + } } else if (arg < 0) { /* Reached end of input for '*' repeater */ break; diff --git a/ext/standard/pageinfo.c b/ext/standard/pageinfo.c index 9f02be2be54c..d8783ffe9906 100644 --- a/ext/standard/pageinfo.c +++ b/ext/standard/pageinfo.c @@ -27,11 +27,6 @@ #if HAVE_PWD_H #ifdef PHP_WIN32 #include "win32/pwd.h" -#elif defined(NETWARE) -#ifdef ZTS -extern int basic_globals_id; -#endif -#include "netware/pwd.h" #else #include #endif @@ -64,11 +59,7 @@ extern int basic_globals_id; */ PHPAPI void php_statpage(TSRMLS_D) { -#if defined(NETWARE) && defined(CLIB_STAT_PATCH) - struct stat_libc *pstat; -#else struct stat *pstat; -#endif pstat = sapi_get_stat(TSRMLS_C); @@ -77,8 +68,8 @@ PHPAPI void php_statpage(TSRMLS_D) BG(page_uid) = pstat->st_uid; BG(page_gid) = pstat->st_gid; BG(page_inode) = pstat->st_ino; -#if defined(NETWARE) && defined(NEW_LIBC) - BG(page_mtime) = (pstat->st_mtime).tv_nsec; +#ifdef NETWARE + BG(page_mtime) = (pstat->st_mtime).tv_sec; #else BG(page_mtime) = pstat->st_mtime; #endif diff --git a/ext/standard/parsedate.y b/ext/standard/parsedate.y index 6776550d24c7..883df33dd079 100644 --- a/ext/standard/parsedate.y +++ b/ext/standard/parsedate.y @@ -635,7 +635,7 @@ static TABLE const OtherTable[] = { { "now", tDAY_UNIT, 0 }, { "last", tUNUMBER, -1 }, { "this", tUNUMBER, 0 }, - { "next", tUNUMBER, 2 }, + { "next", tUNUMBER, 1 }, { "first", tUNUMBER, 1 }, /* { "second", tUNUMBER, 2 }, */ { "third", tUNUMBER, 3 }, @@ -1079,7 +1079,7 @@ time_t php_parse_date(char *p, time_t *now) tm.tm_year = ToYear (date.yyYear) - TM_YEAR_ORIGIN + date.yyRelYear; tm.tm_mon = date.yyMonth - 1 + date.yyRelMonth; tm.tm_mday = date.yyDay + date.yyRelDay; - if (date.yyHaveTime /*|| (date.yyHaveRel && !date.yyHaveDate && !date.yyHaveDay) */) + if (date.yyHaveTime || (date.yyHaveRel && !date.yyHaveDate && !date.yyHaveDay)) { tm.tm_hour = ToHour (date.yyHour, date.yyMeridian); if (tm.tm_hour < 0) diff --git a/ext/standard/php_http.h b/ext/standard/php_http.h index c97fda4cedbd..8885bc1503d3 100644 --- a/ext/standard/php_http.h +++ b/ext/standard/php_http.h @@ -29,7 +29,7 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr, const char *key_prefix, int key_prefix_len, const char *key_suffix, int key_suffix_len, zval *type TSRMLS_DC); -#define php_url_encode_hash(ht, formstr) php_url_encode_hash_ex((ht), (formstr), NULL, 0, NULL, 0, NULL, 0 TSRMLS_CC) +#define php_url_encode_hash(ht, formstr) php_url_encode_hash_ex((ht), (formstr), NULL, 0, NULL, 0, NULL, 0, NULL TSRMLS_CC) PHP_FUNCTION(http_build_query); diff --git a/ext/standard/php_incomplete_class.h b/ext/standard/php_incomplete_class.h index 8c7f68ae1534..408a04b6a7e1 100644 --- a/ext/standard/php_incomplete_class.h +++ b/ext/standard/php_incomplete_class.h @@ -26,18 +26,18 @@ #define PHP_IC_ENTRY \ BG(incomplete_class) -#define PHP_SET_CLASS_ATTRIBUTES(struc) \ - /* OBJECTS_FIXME: Fix for new object model */ \ - if (Z_OBJCE_P(struc) == BG(incomplete_class)) { \ - class_name = php_lookup_class_name(struc, &name_len); \ - free_class_name = 1; \ +#define PHP_SET_CLASS_ATTRIBUTES(struc) \ + /* OBJECTS_FIXME: Fix for new object model */ \ + if (Z_OBJ_HT_P(struc)->get_class_entry && \ + Z_OBJCE_P(struc) == BG(incomplete_class)) { \ + class_name = php_lookup_class_name(struc, &name_len); \ + free_class_name = 1; \ incomplete_class = 1; \ - } else { \ - class_name = Z_OBJCE_P(struc)->name; \ - name_len = Z_OBJCE_P(struc)->name_length; \ + } else { \ + free_class_name = !zend_get_object_classname(struc, &class_name, &name_len TSRMLS_CC);\ } -#define PHP_CLEANUP_CLASS_ATTRIBUTES() \ +#define PHP_CLEANUP_CLASS_ATTRIBUTES() \ if (free_class_name) efree(class_name) #define PHP_CLASS_ATTRIBUTES \ diff --git a/ext/standard/php_string.h b/ext/standard/php_string.h index 3097d4f114c2..327bda0e2d0f 100644 --- a/ext/standard/php_string.h +++ b/ext/standard/php_string.h @@ -112,13 +112,14 @@ PHP_MINIT_FUNCTION(nl_langinfo); PHPAPI int strnatcmp_ex(char const *a, size_t a_len, char const *b, size_t b_len, int fold_case); #ifdef HAVE_LOCALECONV -struct lconv *localeconv_r(struct lconv *out); +PHPAPI struct lconv *localeconv_r(struct lconv *out); #endif PHPAPI char *php_strtoupper(char *s, size_t len); PHPAPI char *php_strtolower(char *s, size_t len); PHPAPI char *php_strtr(char *str, int len, char *str_from, char *str_to, int trlen); PHPAPI char *php_addslashes(char *str, int length, int *new_length, int freeit TSRMLS_DC); +PHPAPI char *php_addslashes_ex(char *str, int length, int *new_length, int freeit, int ignore_sybase TSRMLS_DC); PHPAPI char *php_addcslashes(char *str, int length, int *new_length, int freeit, char *what, int wlength TSRMLS_DC); PHPAPI void php_stripslashes(char *str, int *len TSRMLS_DC); PHPAPI void php_stripcslashes(char *str, int *len); diff --git a/ext/standard/php_var.h b/ext/standard/php_var.h index 52c4f65f4d73..b3c4dd54941a 100644 --- a/ext/standard/php_var.h +++ b/ext/standard/php_var.h @@ -41,12 +41,13 @@ PHPAPI void php_debug_zval_dump(zval **struc, int level TSRMLS_DC); struct php_unserialize_data { void *first; + void *first_dtor; }; typedef struct php_unserialize_data php_unserialize_data_t; PHPAPI void php_var_serialize(smart_str *buf, zval **struc, php_serialize_data_t *var_hash TSRMLS_DC); -PHPAPI int php_var_unserialize(zval **rval, const char **p, const char *max, php_unserialize_data_t *var_hash TSRMLS_DC); +PHPAPI int php_var_unserialize(zval **rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash TSRMLS_DC); #define PHP_VAR_SERIALIZE_INIT(var_hash) \ zend_hash_init(&(var_hash), 10, NULL, NULL, 0) @@ -54,7 +55,8 @@ PHPAPI int php_var_unserialize(zval **rval, const char **p, const char *max, php zend_hash_destroy(&(var_hash)) #define PHP_VAR_UNSERIALIZE_INIT(var_hash) \ - (var_hash).first = 0 + (var_hash).first = 0; \ + (var_hash).first_dtor = 0 #define PHP_VAR_UNSERIALIZE_DESTROY(var_hash) \ var_destroy(&(var_hash)) diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c index 8b036faea418..ca084e573dfa 100644 --- a/ext/standard/proc_open.c +++ b/ext/standard/proc_open.c @@ -35,6 +35,11 @@ #include "php_globals.h" #include "SAPI.h" +#ifdef NETWARE +#include +#include +#endif + #if HAVE_SYS_WAIT_H #include #endif @@ -214,6 +219,7 @@ static void proc_open_rsrc_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) WaitForSingleObject(proc->child, INFINITE); GetExitCodeProcess(proc->child, &wstatus); FG(pclose_ret) = wstatus; + CloseHandle(proc->child); #elif HAVE_SYS_WAIT_H @@ -396,13 +402,20 @@ PHP_FUNCTION(proc_get_status) exitcode = WEXITSTATUS(wstatus); } if (WIFSIGNALED(wstatus)) { + running = 0; signaled = 1; +#ifdef NETWARE + termsig = WIFTERMSIG(wstatus); +#else termsig = WTERMSIG(wstatus); +#endif } if (WIFSTOPPED(wstatus)) { stopped = 1; stopsig = WSTOPSIG(wstatus); } + } else if (wait_pid == -1) { + running = 0; } #endif @@ -477,6 +490,13 @@ PHP_FUNCTION(proc_open) SECURITY_ATTRIBUTES security; char *command_with_cmd; UINT old_error_mode; +#endif +#ifdef NETWARE + char** child_argv = NULL; + char* command_dup = NULL; + char* orig_cwd = NULL; + int command_num_args = 0; + wiring_t channel; #endif php_process_id_t child; struct php_process_handle *proc; @@ -741,6 +761,46 @@ PHP_FUNCTION(proc_open) child = pi.hProcess; CloseHandle(pi.hThread); +#elif defined(NETWARE) + if (cwd) { + orig_cwd = getcwd(NULL, PATH_MAX); + chdir2(cwd); + } + channel.infd = descriptors[0].childend; + channel.outfd = descriptors[1].childend; + channel.errfd = -1; + /* Duplicate the command as processing downwards will modify it*/ + command_dup = strdup(command); + /* get a number of args */ + construct_argc_argv(command_dup, NULL, &command_num_args, NULL); + child_argv = (char**) malloc((command_num_args + 1) * sizeof(char*)); + if(!child_argv) { + free(command_dup); + if (cwd && orig_cwd) { + chdir2(orig_cwd); + free(orig_cwd); + } + } + /* fill the child arg vector */ + construct_argc_argv(command_dup, NULL, &command_num_args, child_argv); + child_argv[command_num_args] = NULL; + child = procve(child_argv[0], PROC_DETACHED|PROC_INHERIT_CWD, NULL, &channel, NULL, NULL, 0, NULL, (const char**)child_argv); + free(child_argv); + free(command_dup); + if (cwd && orig_cwd) { + chdir2(orig_cwd); + free(orig_cwd); + } + if (child < 0) { + /* failed to fork() */ + /* clean up all the descriptors */ + for (i = 0; i < ndesc; i++) { + close(descriptors[i].childend); + close(descriptors[i].parentend); + } + php_error_docref(NULL TSRMLS_CC, E_WARNING, "procve failed - %s", strerror(errno)); + goto exit_fail; + } #elif HAVE_FORK /* the unix way */ child = fork(); diff --git a/ext/standard/rand.c b/ext/standard/rand.c index 851508c45c54..f35967acd28a 100644 --- a/ext/standard/rand.c +++ b/ext/standard/rand.c @@ -24,10 +24,6 @@ #include -#if defined(NETWARE) && !defined(NEW_LIBC) /* For getpid() used below */ -#include "netware/pwd.h" -#endif - #include "php.h" #include "php_math.h" #include "php_rand.h" diff --git a/ext/standard/reg.c b/ext/standard/reg.c index cf8e15cd95b2..6c4124576ca7 100644 --- a/ext/standard/reg.c +++ b/ext/standard/reg.c @@ -33,6 +33,8 @@ typedef struct { int cflags; } reg_cache; +static int reg_magic = 0; + /* {{{ _php_regcomp */ static int _php_regcomp(regex_t *preg, const char *pattern, int cflags) @@ -42,8 +44,39 @@ static int _php_regcomp(regex_t *preg, const char *pattern, int cflags) reg_cache *rc = NULL; TSRMLS_FETCH(); - if(zend_hash_find(®(ht_rc), (char *) pattern, patlen+1, (void **) &rc) == FAILURE || - rc->cflags != cflags) { + if(zend_hash_find(®(ht_rc), (char *) pattern, patlen+1, (void **) &rc) == SUCCESS + && rc->cflags == cflags) { +#ifdef HAVE_REGEX_T_RE_MAGIC + /* + * We use a saved magic number to see whether cache is corrupted, and if it + * is, we flush it and compile the pattern from scratch. + */ + if (rc->preg.re_magic != reg_magic) { + zend_hash_clean(®(ht_rc)); + } else { + memcpy(preg, &rc->preg, sizeof(*preg)); + return r; + } + } + + r = regcomp(preg, pattern, cflags); + if(!r) { + reg_cache rcp; + + rcp.cflags = cflags; + memcpy(&rcp.preg, preg, sizeof(*preg)); + /* + * Since we don't have access to the actual MAGIC1 definition in the private + * header file, we save the magic value immediately after compilation. Hopefully, + * it's good. + */ + if (!reg_magic) reg_magic = preg->re_magic; + zend_hash_update(®(ht_rc), (char *) pattern, patlen+1, + (void *) &rcp, sizeof(rcp), NULL); + } +#else + memcpy(preg, &rc->preg, sizeof(*preg)); + } else { r = regcomp(preg, pattern, cflags); if(!r) { reg_cache rcp; @@ -51,12 +84,10 @@ static int _php_regcomp(regex_t *preg, const char *pattern, int cflags) rcp.cflags = cflags; memcpy(&rcp.preg, preg, sizeof(*preg)); zend_hash_update(®(ht_rc), (char *) pattern, patlen+1, - (void *) &rcp, sizeof(rcp), NULL); + (void *) &rcp, sizeof(rcp), NULL); } - } else { - memcpy(preg, &rc->preg, sizeof(*preg)); } - +#endif return r; } /* }}} */ diff --git a/ext/standard/scanf.c b/ext/standard/scanf.c index ba158e598c21..8d84d50a9dd6 100644 --- a/ext/standard/scanf.c +++ b/ext/standard/scanf.c @@ -78,6 +78,7 @@ #endif #include "zend_execute.h" #include "zend_operators.h" +#include "zend_strtod.h" #include "php_globals.h" #include "basic_functions.h" #include "scanf.h" @@ -1204,7 +1205,7 @@ PHPAPI int php_sscanf_internal( char *string, char *format, if (!(flags & SCAN_SUPPRESS)) { double dvalue; *end = '\0'; - dvalue = strtod(buf, NULL); + dvalue = zend_strtod(buf, NULL); if (numVars) { current = args[objIndex++]; convert_to_double( *current ); diff --git a/ext/standard/sha1.c b/ext/standard/sha1.c index a115e6fa9be0..0e132100d58a 100644 --- a/ext/standard/sha1.c +++ b/ext/standard/sha1.c @@ -18,7 +18,6 @@ /* $Id$ */ -#include #include "php.h" /* This code is heavily based on the PHP md5 implementation */ @@ -67,6 +66,7 @@ PHP_FUNCTION(sha1) /* }}} */ + /* {{{ proto string sha1_file(string filename [, bool raw_output]) Calculate the sha1 hash of given filename */ PHP_FUNCTION(sha1_file) @@ -79,40 +79,31 @@ PHP_FUNCTION(sha1_file) unsigned char digest[20]; PHP_SHA1_CTX context; int n; - FILE *fp; + php_stream *stream; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) { return; } - - if (PG(safe_mode) && (!php_checkuid(arg, NULL, CHECKUID_CHECK_FILE_AND_DIR))) { - RETURN_FALSE; - } - - if (php_check_open_basedir(arg TSRMLS_CC)) { - RETURN_FALSE; - } - - if ((fp = VCWD_FOPEN(arg, "rb")) == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open file"); + + stream = php_stream_open_wrapper(arg, "rb", REPORT_ERRORS | ENFORCE_SAFE_MODE, NULL); + if (!stream) { RETURN_FALSE; } PHP_SHA1Init(&context); - while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) { + while ((n = php_stream_read(stream, buf, sizeof(buf))) > 0) { PHP_SHA1Update(&context, buf, n); } PHP_SHA1Final(digest, &context); - if (ferror(fp)) { - fclose(fp); + php_stream_close(stream); + + if (n<0) { RETURN_FALSE; } - fclose(fp); - if (raw_output) { RETURN_STRINGL(digest, 20, 1); } else { diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c index b73fabe8d8dc..8b6ee90ca782 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -217,7 +217,7 @@ PHP_FUNCTION(stream_socket_accept) if (peername) { zval_dtor(peername); - ZVAL_STRING(peername, "", 1); + ZVAL_NULL(peername); } if (0 == php_stream_xport_accept(stream, &clistream, @@ -227,10 +227,12 @@ PHP_FUNCTION(stream_socket_accept) &tv, &errstr TSRMLS_CC) && clistream) { + if (peername) { + Z_TYPE_P(peername) = IS_STRING; + } php_stream_to_zval(clistream, return_value); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "accept failed: %s", errstr ? errstr : "Unknown error"); - RETVAL_FALSE; } @@ -273,7 +275,7 @@ PHP_FUNCTION(stream_socket_sendto) php_stream *stream; zval *zstream; long flags = 0; - char *data, *target_addr = NULL; + char *data, *target_addr; int datalen, target_addr_len = 0; php_sockaddr_storage sa; socklen_t sl = 0; @@ -283,7 +285,7 @@ PHP_FUNCTION(stream_socket_sendto) } php_stream_from_zval(stream, &zstream); - if (target_addr) { + if (target_addr_len) { /* parse the address */ if (FAILURE == php_network_parse_network_address_with_port(target_addr, target_addr_len, (struct sockaddr*)&sa, &sl TSRMLS_CC)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse `%s' into a valid network address", target_addr); @@ -317,6 +319,11 @@ PHP_FUNCTION(stream_socket_recvfrom) ZVAL_NULL(zremote); Z_STRLEN_P(zremote) = 0; } + + if (to_read <= 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0."); + RETURN_FALSE; + } read_buf = emalloc(to_read + 1); @@ -341,6 +348,7 @@ PHP_FUNCTION(stream_socket_recvfrom) } } + efree(read_buf); RETURN_FALSE; } /* }}} */ @@ -537,8 +545,10 @@ static int stream_array_to_fd_set(zval *stream_array, fd_set *fds, php_socket_t * when casting. It is only used here so that the buffered data warning * is not displayed. * */ - if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&this_fd, 1)) { - FD_SET(this_fd, fds); + if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&this_fd, 1) && this_fd >= 0) { + + PHP_SAFE_FD_SET(this_fd, fds); + if (this_fd > *max_fd) { *max_fd = this_fd; } @@ -573,8 +583,8 @@ static int stream_array_from_fd_set(zval *stream_array, fd_set *fds TSRMLS_DC) * when casting. It is only used here so that the buffered data warning * is not displayed. */ - if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&this_fd, 1)) { - if (FD_ISSET(this_fd, fds)) { + if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&this_fd, 1) && this_fd >= 0) { + if (PHP_SAFE_FD_ISSET(this_fd, fds)) { zend_hash_next_index_insert(new_hash, (void *)elem, sizeof(zval *), (void **)&dest_elem); if (dest_elem) { zval_add_ref(dest_elem); @@ -659,6 +669,7 @@ PHP_FUNCTION(stream_select) int max_fd = 0; int retval, sets = 0; long usec = 0; + int set_count, max_set_count = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!a!z!|l", &r_array, &w_array, &e_array, &sec, &usec) == FAILURE) return; @@ -667,15 +678,34 @@ PHP_FUNCTION(stream_select) FD_ZERO(&wfds); FD_ZERO(&efds); - if (r_array != NULL) sets += stream_array_to_fd_set(r_array, &rfds, &max_fd TSRMLS_CC); - if (w_array != NULL) sets += stream_array_to_fd_set(w_array, &wfds, &max_fd TSRMLS_CC); - if (e_array != NULL) sets += stream_array_to_fd_set(e_array, &efds, &max_fd TSRMLS_CC); + if (r_array != NULL) { + set_count = stream_array_to_fd_set(r_array, &rfds, &max_fd TSRMLS_CC); + if (set_count > max_set_count) + max_set_count = set_count; + sets += set_count; + } + + if (w_array != NULL) { + set_count = stream_array_to_fd_set(w_array, &wfds, &max_fd TSRMLS_CC); + if (set_count > max_set_count) + max_set_count = set_count; + sets += set_count; + } + + if (e_array != NULL) { + set_count = stream_array_to_fd_set(e_array, &efds, &max_fd TSRMLS_CC); + if (set_count > max_set_count) + max_set_count = set_count; + sets += set_count; + } if (!sets) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "No stream arrays were passed"); RETURN_FALSE; } + PHP_SAFE_MAX_FD(max_fd, max_set_count); + /* If seconds is not set to null, build the timeval, else we wait indefinitely */ if (sec != NULL) { convert_to_long_ex(&sec); @@ -1028,11 +1058,11 @@ PHP_FUNCTION(stream_filter_append) /* }}} */ -/* {{{ proto string stream_get_line(resource stream, int maxlen, string ending) +/* {{{ proto string stream_get_line(resource stream, int maxlen [, string ending]) Read up to maxlen bytes from a stream or until the ending string is found */ PHP_FUNCTION(stream_get_line) { - char *str; + char *str = NULL; int str_len; long max_length; zval *zstream; @@ -1040,7 +1070,7 @@ PHP_FUNCTION(stream_get_line) size_t buf_size; php_stream *stream; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rls", &zstream, &max_length, &str, &str_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|s", &zstream, &max_length, &str, &str_len) == FAILURE) { RETURN_FALSE; } diff --git a/ext/standard/string.c b/ext/standard/string.c index 4ee93264fbdd..2cdfd018c958 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -136,7 +136,7 @@ static char *php_bin2hex(const unsigned char *old, const size_t oldlen, size_t * #ifdef HAVE_LOCALECONV /* {{{ localeconv_r * glibc's localeconv is not reentrant, so lets make it so ... sorta */ -struct lconv *localeconv_r(struct lconv *out) +PHPAPI struct lconv *localeconv_r(struct lconv *out) { struct lconv *res; @@ -1090,7 +1090,7 @@ PHPAPI void php_basename(char *s, size_t len, char *suffix, size_t sufflen, char case 0: goto quit_loop; case 1: -#ifdef PHP_WIN32 +#if defined(PHP_WIN32) || defined(NETWARE) if (*c == '/' || *c == '\\') { #else if (*c == '/') { @@ -1175,6 +1175,22 @@ PHPAPI size_t php_dirname(char *path, size_t len) return len; } } +#elif defined(NETWARE) + /* + * Find the first occurence of : from the left + * move the path pointer to the position just after : + * increment the len_adjust to the length of path till colon character(inclusive) + * If there is no character beyond : simple return len + */ + char *colonpos = NULL; + colonpos = strchr(path, ':'); + if(colonpos != NULL) { + len_adjust = ((colonpos - path) + 1); + path += len_adjust; + if(len_adjust == len) { + return len; + } + } #endif if (len == 0) { @@ -1199,9 +1215,21 @@ PHPAPI size_t php_dirname(char *path, size_t len) } if (end < path) { /* No slash found, therefore return '.' */ +#ifdef NETWARE + if(len_adjust == 0) { + path[0] = '.'; + path[1] = '\0'; + return 1; //only one character + } + else { + path[0] = '\0'; + return len_adjust; + } +#else path[0] = '.'; path[1] = '\0'; return 1 + len_adjust; +#endif } /* Strip slashes which came before the file name */ @@ -1382,8 +1410,6 @@ PHP_FUNCTION(stristr) if (!Z_STRLEN_PP(needle)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty delimiter."); efree(haystack_orig); - zval_ptr_dtor(haystack); - zval_ptr_dtor(needle); RETURN_FALSE; } @@ -1409,8 +1435,6 @@ PHP_FUNCTION(stristr) RETVAL_FALSE; } - zval_ptr_dtor(haystack); - zval_ptr_dtor(needle); efree(haystack_orig); } /* }}} */ @@ -1838,6 +1862,16 @@ PHP_FUNCTION(chunk_split) RETURN_FALSE; } + if (chunklen > Z_STRLEN_PP(p_str)) { + /* to maintain BC, we must return original string + ending */ + result_len = endlen + Z_STRLEN_PP(p_str); + result = emalloc(result_len + 1); + memcpy(result, Z_STRVAL_PP(p_str), Z_STRLEN_PP(p_str)); + memcpy(result + Z_STRLEN_PP(p_str), end, endlen); + result[result_len] = '\0'; + RETURN_STRINGL(result, result_len, 0); + } + if (!Z_STRLEN_PP(p_str)) { RETURN_EMPTY_STRING(); } @@ -2851,6 +2885,14 @@ PHPAPI char *php_addcslashes(char *str, int length, int *new_length, int should_ /* {{{ php_addslashes */ PHPAPI char *php_addslashes(char *str, int length, int *new_length, int should_free TSRMLS_DC) +{ + return php_addslashes_ex(str, length, new_length, should_free, 0 TSRMLS_CC); +} +/* }}} */ + +/* {{{ php_addslashes_ex + */ +PHPAPI char *php_addslashes_ex(char *str, int length, int *new_length, int should_free, int ignore_sybase TSRMLS_DC) { /* maximum string length, worst case situation */ char *new_str; @@ -2870,7 +2912,7 @@ PHPAPI char *php_addslashes(char *str, int length, int *new_length, int should_f end = source + length; target = new_str; - if (PG(magic_quotes_sybase)) { + if (!ignore_sybase && PG(magic_quotes_sybase)) { while (source < end) { switch (*source) { case '\0': @@ -2933,12 +2975,12 @@ PHPAPI int php_char_to_str_ex(char *str, uint len, char from, char *to, int to_l char *source, *target, *tmp, *source_end=str+len, *tmp_end = NULL; for (source = str; source < source_end; source++) { - if (*source == from) { + if ((case_sensitivity && *source == from) || (!case_sensitivity && tolower(*source) == tolower(from))) { char_count++; } } - if (char_count == 0) { + if (char_count == 0 && case_sensitivity) { ZVAL_STRINGL(result, str, len, 1); return 0; } @@ -3741,18 +3783,6 @@ PHP_FUNCTION(setlocale) efree(args); RETVAL_STRING(retval, 1); - if (cat == LC_NUMERIC || cat == LC_ALL) { - struct lconv lc; - localeconv_r(&lc); - - EG(float_separator)[0] = (lc.decimal_point)[0]; - - if ((lc.decimal_point)[0] != '.') { - /* set locale back to C */ - setlocale(LC_NUMERIC, "C"); - } - } - return; } @@ -4724,7 +4754,7 @@ PHP_FUNCTION(str_split) } if (split_length <= 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The the length of each segment must be greater then zero."); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "The length of each segment must be greater than zero."); RETURN_FALSE; } diff --git a/ext/standard/sunfuncs.c b/ext/standard/sunfuncs.c index 2eea641f4dfe..0a41c85ba5f6 100644 --- a/ext/standard/sunfuncs.c +++ b/ext/standard/sunfuncs.c @@ -192,7 +192,11 @@ static void php_do_date_sunrise_sunset(INTERNAL_FUNCTION_PARAMETERS, int calc_su } case 5: gmt_offset = php_idate('Z', time, 0) / 3600; + case 6: + break; default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid format"); + RETURN_FALSE; break; } @@ -200,7 +204,7 @@ static void php_do_date_sunrise_sunset(INTERNAL_FUNCTION_PARAMETERS, int calc_su switch (retformat) { case SUNFUNCS_RET_TIMESTAMP: - RETURN_LONG((int) (time - (time % (24 * 3600))) + (int) (60 * ret)); + RETURN_LONG((int) (time - (time % (24 * 3600))) + (int) (3600 * ret)); break; case SUNFUNCS_RET_STRING: N = (int) ret; @@ -210,9 +214,6 @@ static void php_do_date_sunrise_sunset(INTERNAL_FUNCTION_PARAMETERS, int calc_su case SUNFUNCS_RET_DOUBLE: RETURN_DOUBLE(ret); break; - default: - php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid format"); - RETURN_FALSE; } } /* }}} */ diff --git a/ext/standard/syslog.c b/ext/standard/syslog.c index eeb6849c8615..9af2efee2c01 100644 --- a/ext/standard/syslog.c +++ b/ext/standard/syslog.c @@ -75,7 +75,7 @@ PHP_MINIT_FUNCTION(syslog) /* AIX doesn't have LOG_AUTHPRIV */ REGISTER_LONG_CONSTANT("LOG_AUTHPRIV", LOG_AUTHPRIV, CONST_CS | CONST_PERSISTENT); #endif -#if !defined(PHP_WIN32) && !defined(NETWARE) +#ifndef PHP_WIN32 REGISTER_LONG_CONSTANT("LOG_LOCAL0", LOG_LOCAL0, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("LOG_LOCAL1", LOG_LOCAL1, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("LOG_LOCAL2", LOG_LOCAL2, CONST_CS | CONST_PERSISTENT); @@ -119,6 +119,9 @@ PHP_RSHUTDOWN_FUNCTION(syslog) if (BG(syslog_device)) { efree(BG(syslog_device)); } +#ifdef PHP_WIN32 + closelog(); +#endif return SUCCESS; } @@ -141,7 +144,9 @@ static void start_syslog(TSRMLS_D) SET_VAR_LONG("LOG_MAIL", LOG_MAIL); /* log to email */ SET_VAR_LONG("LOG_DAEMON", LOG_DAEMON); /* other system daemons */ SET_VAR_LONG("LOG_AUTH", LOG_AUTH); +#ifndef NETWARE SET_VAR_LONG("LOG_SYSLOG", LOG_SYSLOG); +#endif SET_VAR_LONG("LOG_LPR", LOG_LPR); #ifdef LOG_NEWS /* No LOG_NEWS on HP-UX */ diff --git a/ext/standard/tests/array/array_walk_recursive.phpt b/ext/standard/tests/array/array_walk_recursive.phpt new file mode 100644 index 000000000000..c3b37c321c21 --- /dev/null +++ b/ext/standard/tests/array/array_walk_recursive.phpt @@ -0,0 +1,26 @@ +--TEST-- +Test array_walk_recursive() +--FILE-- + +--EXPECTF-- +1 foo +2 foo +3 foo +bool(true) +1 bar +2 bar +3 bar +bool(true) diff --git a/ext/standard/tests/array/bug29253.phpt b/ext/standard/tests/array/bug29253.phpt new file mode 100755 index 000000000000..a495d65cfcfe --- /dev/null +++ b/ext/standard/tests/array/bug29253.phpt @@ -0,0 +1,13 @@ +--TEST-- +Bug #29253 array_diff with $GLOBALS argument fails +--FILE-- + +--EXPECT-- +array(0) { +} +string(4) "afad" diff --git a/ext/standard/tests/array/bug29493.phpt b/ext/standard/tests/array/bug29493.phpt new file mode 100644 index 000000000000..0cfe45910bed --- /dev/null +++ b/ext/standard/tests/array/bug29493.phpt @@ -0,0 +1,115 @@ +--TEST-- +Bug #29493 (extract(EXTR_REFS) fails if array has multiple referrals) +--FILE-- + 'aaa'); + // refcount($a) = 1 + // refcount($a['foo']) = 1 + $b = $a; + // refcount($a) = 2 + // refcount($a['foo']) = 1 + $b['foo'] = 'bbb'; + // refcount($a) = 1 + // refcount($a['foo']) = 1 + + var_dump($a, $b); + + extract($a, EXTR_REFS); + + $foo = 'noo'; + + var_dump($a, $b); +} + +function t2() +{ + $a = array('foo' => 'aaa'); + // refcount($a) = 1 + // refcount($a['foo']) = 1 + $b = &$a; + // refcount($a) = 2 + // is_ref($a) = true + // refcount($a['foo']) = 1 + $b['foo'] = 'bbb'; + // refcount($a) = 2 + // refcount($a['foo']) = 1 + + var_dump($a, $b); + + extract($a, EXTR_REFS); + + $foo = 'noo'; + + var_dump($a, $b); +} + +function t3() +{ + $a = array('foo' => 'aaa'); + // refcount($a) = 1 + // refcount($a['foo']) = 1 + $b = &$a; + // refcount($a) = 2 + // is_ref($a) = true + // refcount($a['foo']) = 1 + unset($b); + // refcount($a) = 1 + // is_ref($a) = true + // refcount($a['foo']) = 1 + + var_dump($a); + + extract($a, EXTR_REFS); + + $foo = 'noo'; + + var_dump($a); +} + +t1(); +t2(); +t3(); +?> +--EXPECT-- +array(1) { + ["foo"]=> + string(3) "aaa" +} +array(1) { + ["foo"]=> + string(3) "bbb" +} +array(1) { + ["foo"]=> + &string(3) "noo" +} +array(1) { + ["foo"]=> + string(3) "bbb" +} +array(1) { + ["foo"]=> + string(3) "bbb" +} +array(1) { + ["foo"]=> + string(3) "bbb" +} +array(1) { + ["foo"]=> + &string(3) "noo" +} +array(1) { + ["foo"]=> + &string(3) "noo" +} +array(1) { + ["foo"]=> + string(3) "aaa" +} +array(1) { + ["foo"]=> + &string(3) "noo" +} diff --git a/ext/standard/tests/array/bug29992.phpt b/ext/standard/tests/array/bug29992.phpt new file mode 100755 index 000000000000..74be2918913f --- /dev/null +++ b/ext/standard/tests/array/bug29992.phpt @@ -0,0 +1,44 @@ +--TEST-- +Bug #29992 (foreach by reference corrupts the array) +--FILE-- + +===DONE=== +--EXPECT-- +Array +( + [0] => 1 + [1] => 2 + [2] => 3 +) +int(1) +int(2) +int(3) +int(1) +int(2) +int(3) +int(1) +int(2) +int(3) +int(1) +int(2) +int(3) +Array +( + [0] => 1 + [1] => 2 + [2] => 3 +) +===DONE=== diff --git a/ext/standard/tests/array/bug30833.phpt b/ext/standard/tests/array/bug30833.phpt new file mode 100644 index 000000000000..61701a532ff0 --- /dev/null +++ b/ext/standard/tests/array/bug30833.phpt @@ -0,0 +1,35 @@ +--TEST-- +bug #30833 (array_count_values() modifying input array) +--FILE-- + +--EXPECT-- +array(2) { + [0]=> + string(3) "abc" + [1]=> + string(4) "0000" +} +array(2) { + ["abc"]=> + int(1) + [0]=> + int(1) +} +array(2) { + [0]=> + string(3) "abc" + [1]=> + string(4) "0000" +} +Done diff --git a/ext/standard/tests/array/bug31158.phpt b/ext/standard/tests/array/bug31158.phpt new file mode 100755 index 000000000000..e672a10b28d6 --- /dev/null +++ b/ext/standard/tests/array/bug31158.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #31158 (array_splice on $GLOBALS crashes) +--FILE-- + +--EXPECTF-- +Notice: Undefined variable: GLOBALS in %sbug31158.php on line 6 +ok + diff --git a/ext/standard/tests/array/bug31213.phpt b/ext/standard/tests/array/bug31213.phpt new file mode 100644 index 000000000000..6aa31d5e0ef0 --- /dev/null +++ b/ext/standard/tests/array/bug31213.phpt @@ -0,0 +1,57 @@ +--TEST-- +Bug #31213 (Sideeffects caused by bug #29493) +--FILE-- + $a, + '_b' => &$b + ); + + var_dump($a, $b); + + if ($use_extract) { + extract($arr, EXTR_REFS); + } else { + $_a = &$arr['_a']; + $_b = &$arr['_b']; + } + + $_a++; + $_b++; + + var_dump($a, $b, $_a, $_b, $arr); +} + +test(false); +test(true); + +?> +--EXPECT-- +int(1) +int(1) +int(1) +int(2) +int(2) +int(2) +array(2) { + ["_a"]=> + &int(2) + ["_b"]=> + &int(2) +} +int(1) +int(1) +int(1) +int(2) +int(2) +int(2) +array(2) { + ["_a"]=> + &int(2) + ["_b"]=> + &int(2) +} diff --git a/ext/standard/tests/array/bug32021.phpt b/ext/standard/tests/array/bug32021.phpt new file mode 100644 index 000000000000..5d3b421ab468 --- /dev/null +++ b/ext/standard/tests/array/bug32021.phpt @@ -0,0 +1,14 @@ +--TEST-- +Bug #32021 (Crash caused by range('', 'z')) +--FILE-- + +ALIVE +--EXPECT-- +array(1) { + [0]=> + int(0) +} +ALIVE diff --git a/ext/standard/tests/array/bug33940.phpt b/ext/standard/tests/array/bug33940.phpt new file mode 100755 index 000000000000..f5727297c65f --- /dev/null +++ b/ext/standard/tests/array/bug33940.phpt @@ -0,0 +1,62 @@ +--TEST-- +Bug #33940 array_map() fails to pass by reference when called recursively +--INI-- +error_reporting=4095 +--FILE-- + +--EXPECT-- +Array: Array +( + [0] => Array + ( + [0] => 0 + ) + + [1] => 0 +) +Return: Array +( + [0] => Array + ( + [0] => 2 + ) + + [1] => 2 +) +Array: Array +( + [0] => Array + ( + [0] => 1 + ) + + [1] => 1 +) +Return: Array +( + [0] => Array + ( + [0] => 2 + ) + + [1] => 2 +) diff --git a/ext/standard/tests/array/bug33989.phpt b/ext/standard/tests/array/bug33989.phpt new file mode 100755 index 000000000000..ccef172d61cc --- /dev/null +++ b/ext/standard/tests/array/bug33989.phpt @@ -0,0 +1,10 @@ +--TEST-- +Bug #33989 (extract($GLOBALS,EXTR_REFS) crashes PHP) +--FILE-- + +--EXPECT-- +ok diff --git a/ext/standard/tests/array/bug34227.phpt b/ext/standard/tests/array/bug34227.phpt new file mode 100755 index 000000000000..29762b72332f --- /dev/null +++ b/ext/standard/tests/array/bug34227.phpt @@ -0,0 +1,100 @@ +--TEST-- +Bug #34277 (array_filter() crashes with references and objects) +--FILE-- +m2(); + } + + function m2() + { + $this->m3(); + } + + function m3() + { + $this->m4(); + } + + function m4() + { + $this->m5(); + } + + function m5() + { + $this->m6(); + } + + function m6() + { + $this->m7(); + } + + function m7() + { + $this->m8(); + } + + function m8() + { + $this->m9(); + } + + function m9() + { + $this->m10(); + } + + function m10() + { + $this->m11(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + function m11($a1, $a2, $a3, $a4, $a5, $a6, $a7, $a8, $a9, $a10) + { + $arr = explode('a', 'b'); + } +} + +function f($str) +{ + $obj = new C; + $obj->m1(); + return TRUE; +} + +function p5($a1, $a2, $a3, $a4, $a5, $a6, $a7, $a8, $a9, $a10, $a11, $a12) +{ + $ret = array_filter(array(0), 'f'); +} + +function p4() +{ + p5(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); +} + +function p3() +{ + p4(); +} + +function p2() +{ + p3(); +} + +function p1() +{ + p2(); +} + +p1(); +echo "ok\n"; +?> +--EXPECT-- +ok diff --git a/ext/standard/tests/array/var_export2.phpt b/ext/standard/tests/array/var_export2.phpt new file mode 100644 index 000000000000..2b8a1f97ef9b Binary files /dev/null and b/ext/standard/tests/array/var_export2.phpt differ diff --git a/ext/standard/tests/file/bug30362.phpt b/ext/standard/tests/file/bug30362.phpt new file mode 100644 index 000000000000..1c2b4be979a1 --- /dev/null +++ b/ext/standard/tests/file/bug30362.phpt @@ -0,0 +1,26 @@ +--TEST-- +Bug #30362 (stream_get_line() not working as documented) +--FILE-- + +--EXPECT-- +111 +111111111 +111111111 +111111111 +111111111 +111111111 +111111111 +111111111 +111111111 +111111111 diff --git a/ext/standard/tests/file/bug30362.txt b/ext/standard/tests/file/bug30362.txt new file mode 100644 index 000000000000..3a1b7f448cb0 --- /dev/null +++ b/ext/standard/tests/file/bug30362.txt @@ -0,0 +1 @@ +111Y111111111Y111111111Y111111111Y111111111Y111111111Y111111111Y111111111Y111111111Y111111111 diff --git a/ext/standard/tests/filters/bug22538.phpt b/ext/standard/tests/filters/bug22538.phpt index c01978730b59..438b5be31f8d 100644 --- a/ext/standard/tests/filters/bug22538.phpt +++ b/ext/standard/tests/filters/bug22538.phpt @@ -15,7 +15,7 @@ do { $path2 = sprintf("%s/%s%db", dirname(__FILE__), uniqid(), time()); } while ($path1 == $path2); -$fp = fopen($path1, "w"); +$fp = fopen($path1, "w") or die("Can not open $path1\n"); $str = "abcdefghijklmnopqrstuvwxyz\n"; $str_len = strlen($str); $cnt = $size; @@ -24,8 +24,8 @@ while (($cnt -= $str_len) > 0) { } $cnt = $size - ($str_len + $cnt); fclose($fp); -$fin = fopen($path1, "r"); -$fout = fopen($path2, "w"); +$fin = fopen($path1, "r") or die("Can not open $path1\n");; +$fout = fopen($path2, "w") or die("Can not open $path2\n");; stream_filter_append($fout, "string.rot13"); my_stream_copy_to_stream($fin, $fout); fclose($fout); diff --git a/ext/standard/tests/general_functions/bug31190.phpt b/ext/standard/tests/general_functions/bug31190.phpt new file mode 100644 index 000000000000..8fdf8eea7564 --- /dev/null +++ b/ext/standard/tests/general_functions/bug31190.phpt @@ -0,0 +1,26 @@ +--TEST-- +bug #31190 (exception in call_user_func_array()) +--FILE-- +getMessage(); +} + +try { + call_user_func_array($array, array(1, 2)); +} catch (Exception $e) { + echo $e->getMessage(); +} +?> +--EXPECT-- +Hello World! +Hello World! + diff --git a/ext/standard/tests/general_functions/bug32647.phpt b/ext/standard/tests/general_functions/bug32647.phpt new file mode 100644 index 000000000000..ca98f429a735 --- /dev/null +++ b/ext/standard/tests/general_functions/bug32647.phpt @@ -0,0 +1,55 @@ +--TEST-- +Bug #32647 (Using register_shutdown_function() with invalid callback can crash PHP) +--INI-- +error_reporting=2047 +display_errors=1 +--FILE-- + +--EXPECTF-- +Notice: Undefined variable: obj in %s on line %d + +Warning: register_shutdown_function(): Invalid shutdown callback 'Array' passed in %s on line %d + +Notice: Undefined variable: obj in %s on line %d + +Warning: register_shutdown_function(): Invalid shutdown callback 'Array' passed in %s on line %d + +Warning: register_shutdown_function(): Invalid shutdown callback 'Array' passed in %s on line %d + +Warning: register_shutdown_function(): Invalid shutdown callback 'Array' passed in %s on line %d + +Warning: (Registered shutdown functions) Unable to call bar::foo() - function does not exist in Unknown on line 0 + +Warning: (Registered shutdown functions) Unable to call bar() - function does not exist in Unknown on line 0 +joo! +bar! + +Warning: (Registered shutdown functions) Unable to call bar::foobar() - function does not exist in Unknown on line 0 +bar! diff --git a/ext/standard/tests/image/getimagesize_swc.phpt b/ext/standard/tests/image/getimagesize_swc.phpt index b9b83f437372..f8c74498a43c 100644 --- a/ext/standard/tests/image/getimagesize_swc.phpt +++ b/ext/standard/tests/image/getimagesize_swc.phpt @@ -3,7 +3,7 @@ GetImageSize() for compressed swf files --SKIPIF-- --FILE-- diff --git a/ext/standard/tests/math/bug27646.phpt b/ext/standard/tests/math/bug27646.phpt index 2df6d8f37a8d..7b4a923f1f01 100755 --- a/ext/standard/tests/math/bug27646.phpt +++ b/ext/standard/tests/math/bug27646.phpt @@ -2,6 +2,7 @@ Bug #27646 (Cannot serialize/unserialize non-finite numeric values) --FILE-- --EXPECT-- 12345678 -12,345,678 +1,234.5678 1,23405678 1,234.5678 diff --git a/ext/standard/tests/math/bug30695.phpt b/ext/standard/tests/math/bug30695.phpt new file mode 100644 index 000000000000..c515784ee2ac --- /dev/null +++ b/ext/standard/tests/math/bug30695.phpt @@ -0,0 +1,54 @@ +--TEST-- +Bug #30695 (32 bit issues) +--FILE-- +> 6) & 0x1f)) . + chr(0x80 | ($char_code & 0x3f)) ); + break; + case !($char_code & 0xffff0000): // 16 bit + $char = ( chr(0xe0 | (($char_code >> 12) & 0x0f)) . + chr(0x80 | (($char_code >> 6) & 0x3f)) . + chr(0x80 | ($char_code & 0x3f)) ); + break; + case !($char_code & 0xffe00000): // 21 bit + $char = ( chr(0xf0 | (($char_code >> 18) & 0x07)) . + chr(0x80 | (($char_code >> 12) & 0x3f)) . + chr(0x80 | (($char_code >> 6) & 0x3f)) . + chr(0x80 | ($char_code & 0x3f)) ); + break; + case !($char_code & 0xfc000000): // 26 bit + $char = ( chr(0xf8 | (($char_code >> 24) & 0x03)) . + chr(0x80 | (($char_code >> 18) & 0x3f)) . + chr(0x80 | (($char_code >> 12) & 0x3f)) . + chr(0x80 | (($char_code >> 6) & 0x3f)) . + chr(0x80 | ($char_code & 0x3f)) ); + default: // 31 bit + $char = ( chr(0xfc | (($char_code >> 30) & 0x01)) . + chr(0x80 | (($char_code >> 24) & 0x3f)) . + chr(0x80 | (($char_code >> 18) & 0x3f)) . + chr(0x80 | (($char_code >> 12) & 0x3f)) . + chr(0x80 | (($char_code >> 6) & 0x3f)) . + chr(0x80 | ($char_code & 0x3f)) ); + } + return $char; + } + + + echo "\n", toUTF8(65), "\n", toUTF8(233), "\n", toUTF8(1252), "\n", toUTF8(20095), "\n"; +?> +--EXPECT-- + +A +é +Ó¤ +乿 diff --git a/ext/standard/tests/serialize/002.phpt b/ext/standard/tests/serialize/002.phpt new file mode 100644 index 000000000000..3085d1cf4f76 --- /dev/null +++ b/ext/standard/tests/serialize/002.phpt @@ -0,0 +1,44 @@ +--TEST-- +Bug #25378 (unserialize() crashes with invalid data) +--FILE-- + +===DONE=== +--EXPECTF-- +bool(false) +bool(true) +int(823) +string(0) "" +string(3) "foo" +array(1) { + [0]=> + string(2) "12" +} +array(2) { + [0]=> + array(0) { + } + [1]=> + array(0) { + } +} +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "bar" + [2]=> + string(3) "baz" +} +object(stdClass)#%d (0) { +} +===DONE=== diff --git a/ext/standard/tests/serialize/autoload_implements.p5c b/ext/standard/tests/serialize/autoload_implements.p5c new file mode 100755 index 000000000000..2c3479c86078 --- /dev/null +++ b/ext/standard/tests/serialize/autoload_implements.p5c @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/ext/standard/tests/serialize/autoload_interface.p5c b/ext/standard/tests/serialize/autoload_interface.p5c new file mode 100755 index 000000000000..6908155e610e --- /dev/null +++ b/ext/standard/tests/serialize/autoload_interface.p5c @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/ext/standard/tests/serialize/bug14293.phpt b/ext/standard/tests/serialize/bug14293.phpt index 976eeffc0ee0..3fca7e406edc 100644 --- a/ext/standard/tests/serialize/bug14293.phpt +++ b/ext/standard/tests/serialize/bug14293.phpt @@ -25,6 +25,8 @@ var_dump($t); ?> --EXPECTF-- __sleep called + +Notice: serialize(): "b" returned as member variable from __sleep() but does not exist in %sbug14293.php on line %d O:1:"t":2:{s:1:"a";s:5:"hello";s:1:"b";N;} object(t)#%d (2) { ["a"]=> diff --git a/ext/standard/tests/serialize/bug25378.phpt b/ext/standard/tests/serialize/bug25378.phpt index e59044002f1b..e865b96e9935 100644 --- a/ext/standard/tests/serialize/bug25378.phpt +++ b/ext/standard/tests/serialize/bug25378.phpt @@ -3,7 +3,57 @@ Bug #25378 (unserialize() crashes with invalid data) --FILE-- +===DONE=== --EXPECTF-- -Notice: unserialize(): Error at offset 0 of 8 bytes in %s on line %d +Notice: unserialize(): Error at offset 0 of 8 bytes in %sbug25378.php on line %d bool(false) + +Notice: unserialize(): Error at offset 0 of 5 bytes in %sbug25378.php on line %d +bool(false) + +Notice: unserialize(): Error at offset 13 of 19 bytes in %sbug25378.php on line %d +bool(false) + +Notice: unserialize(): Error at offset 14 of 19 bytes in %sbug25378.php on line %d +bool(false) + +Notice: unserialize(): Error at offset 2 of 22 bytes in %sbug25378.php on line %d +bool(false) + +Notice: unserialize(): Error at offset 17 of 18 bytes in %sbug25378.php on line %d +bool(false) + +Notice: unserialize(): Error at offset 24 of 33 bytes in %sbug25378.php on line %d +bool(false) + +Notice: unserialize(): Error at offset 17 of 33 bytes in %sbug25378.php on line %d +bool(false) + +Notice: unserialize(): Error at offset 33 of 32 bytes in %sbug25378.php on line %d +bool(false) + +Notice: unserialize(): Error at offset 2 of 13 bytes in %sbug25378.php on line %d +bool(false) + +Notice: unserialize(): Error at offset 2 of 11 bytes in %sbug25378.php on line %d +bool(false) + +Notice: unserialize(): Error at offset 8 of 9 bytes in %sbug25378.php on line %d +bool(false) + +Notice: unserialize(): Error at offset 5 of 10 bytes in %sbug25378.php on line %d +bool(false) +===DONE=== diff --git a/ext/standard/tests/serialize/bug30234.phpt b/ext/standard/tests/serialize/bug30234.phpt new file mode 100755 index 000000000000..37fc8cde3c83 --- /dev/null +++ b/ext/standard/tests/serialize/bug30234.phpt @@ -0,0 +1,40 @@ +--TEST-- +#30234 (__autoload() not invoked for interfaces) +--SKIPIF-- + +--FILE-- + +===DONE=== +--EXPECTF-- +bool(false) +bool(false) +__autoload(autoload_interface) +__autoload(Autoload_Implements) +object(autoload_implements)#%d (0) { +} +bool(true) +bool(true) +bool(true) +===DONE=== diff --git a/ext/standard/tests/serialize/bug31402.phpt b/ext/standard/tests/serialize/bug31402.phpt new file mode 100644 index 000000000000..0fbb445d0aeb --- /dev/null +++ b/ext/standard/tests/serialize/bug31402.phpt @@ -0,0 +1,72 @@ +--TEST-- +Bug #31402 (unserialize() generates references when it should not) +--FILE-- +i = $i; + } +} + +class Y { + public $A = array(); + public $B; + + function Y() { + $this->A[1] = new X(1); + $this->A[2] = new X(2); + $this->B = $this->A[1]; + } +} + +$before = new Y(); +$ser = serialize($before); +$after = unserialize($ser); + +var_dump($before, $after); + +?> +--EXPECTF-- +object(Y)#%d (2) { + ["A"]=> + array(2) { + [1]=> + object(X)#%d (1) { + ["i"]=> + int(1) + } + [2]=> + object(X)#%d (1) { + ["i"]=> + int(2) + } + } + ["B"]=> + object(X)#%d (1) { + ["i"]=> + int(1) + } +} +object(Y)#%d (2) { + ["A"]=> + array(2) { + [1]=> + object(X)#%d (1) { + ["i"]=> + int(1) + } + [2]=> + object(X)#%d (1) { + ["i"]=> + int(2) + } + } + ["B"]=> + object(X)#%d (1) { + ["i"]=> + int(1) + } +} diff --git a/ext/standard/tests/strings/bug22207.phpt b/ext/standard/tests/strings/bug22207.phpt index 1623fb8e41a0..688bb5b74493 100644 --- a/ext/standard/tests/strings/bug22207.phpt +++ b/ext/standard/tests/strings/bug22207.phpt @@ -7,5 +7,5 @@ Bug #22207 (missing 0 when using the e notation in *printf functions) ?> --EXPECT-- 1.1000e+0 -string(17) " 1.1000e+0 +string(11) " 1.1000e+0 " diff --git a/ext/standard/tests/strings/bug28633.phpt b/ext/standard/tests/strings/bug28633.phpt new file mode 100644 index 000000000000..5a1c2567fac5 --- /dev/null +++ b/ext/standard/tests/strings/bug28633.phpt @@ -0,0 +1,10 @@ +--TEST-- +Bug #28633 (sprintf incorrectly adding padding to floats) +--FILE-- + +--EXPECT-- +00.02 +02.02 diff --git a/ext/standard/tests/strings/bug29119.phpt b/ext/standard/tests/strings/bug29119.phpt new file mode 100644 index 000000000000..8b419b81a155 --- /dev/null +++ b/ext/standard/tests/strings/bug29119.phpt @@ -0,0 +1,8 @@ +--TEST-- +Bug #29119 (html_entity_decode() misbehaves with UTF-8) +--FILE-- + +--EXPECT-- +string(42) "e28082e28089e28098e280a0e280b2e28184e282ac" diff --git a/ext/standard/tests/strings/bug33076.phpt b/ext/standard/tests/strings/bug33076.phpt new file mode 100644 index 000000000000..dafb8161b0f1 --- /dev/null +++ b/ext/standard/tests/strings/bug33076.phpt @@ -0,0 +1,14 @@ +--TEST-- +Bug #33076 (str_ireplace() incorrectly counts result string length and may cause segfault) +--FILE-- + +--EXPECT-- +string(6) "bzexbz" +Done diff --git a/ext/standard/tests/strings/chunk_split.phpt b/ext/standard/tests/strings/chunk_split.phpt index 6aec9fd24df9..b6bed3ab486d 100644 --- a/ext/standard/tests/strings/chunk_split.phpt +++ b/ext/standard/tests/strings/chunk_split.phpt @@ -5,6 +5,7 @@ chunk_split() function echo chunk_split('abc', 1, '-')."\n"; echo chunk_split('foooooooooooooooo', 5)."\n"; echo chunk_split(str_repeat('X', 2*76))."\n"; +echo chunk_split("test", 10, "|end") . "\n"; ?> --EXPECT-- a-b-c- @@ -15,3 +16,5 @@ oo XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + +test|end diff --git a/ext/standard/tests/strings/htmlentities17.phpt b/ext/standard/tests/strings/htmlentities17.phpt new file mode 100644 index 000000000000..b203e7c3e027 --- /dev/null +++ b/ext/standard/tests/strings/htmlentities17.phpt @@ -0,0 +1,50 @@ +--TEST-- +htmlentities() / html_entity_decode() #8592 - #9002 table test +--FILE-- + +--EXPECT-- +string(8) "≀" +string(7) "⊕" +string(8) "⊗" +string(6) "⊥" +string(6) "⋅" +string(7) "⌈" +string(7) "⌉" +string(8) "⌊" +string(8) "⌋" +string(6) "⟨" +string(6) "⟩" +string(6) "e28980" +string(6) "e28a95" +string(6) "e28a97" +string(6) "e28aa5" +string(6) "e28b85" +string(6) "e28c88" +string(6) "e28c89" +string(6) "e28c8a" +string(6) "e28c8b" +string(6) "e28ca9" +string(6) "e28caa" diff --git a/ext/standard/tests/strings/strval.phpt b/ext/standard/tests/strings/strval.phpt new file mode 100644 index 000000000000..3f8b5cc985d1 --- /dev/null +++ b/ext/standard/tests/strings/strval.phpt @@ -0,0 +1,24 @@ +--TEST-- +strval() function +--FILE-- + +--EXPECT-- +string(3) "bar" +string(3) "BAR" +string(6) "foobar" +string(1) "1" +string(3) "1.1" +string(1) "1" +string(0) "" +string(5) "Array" diff --git a/ext/standard/tests/strings/url_t.phpt b/ext/standard/tests/strings/url_t.phpt index 88e6e4800d93..f6fec50de944 100644 --- a/ext/standard/tests/strings/url_t.phpt +++ b/ext/standard/tests/strings/url_t.phpt @@ -66,7 +66,10 @@ $sample_urls = array ( 'file:///path/to/file', 'file://path/to/file', 'file:/path/to/file', -'http://1.2.3.4:/abc.asp?a=1&b=2' +'http://1.2.3.4:/abc.asp?a=1&b=2', +'http://foo.com#bar', +'scheme:', +'foo+bar://baz@bang/bla', ); foreach ($sample_urls as $url) { @@ -648,3 +651,25 @@ array(4) { ["query"]=> string(7) "a=1&b=2" } +array(3) { + ["scheme"]=> + string(4) "http" + ["host"]=> + string(7) "foo.com" + ["fragment"]=> + string(3) "bar" +} +array(1) { + ["scheme"]=> + string(6) "scheme" +} +array(4) { + ["scheme"]=> + string(7) "foo+bar" + ["host"]=> + string(4) "bang" + ["user"]=> + string(3) "baz" + ["path"]=> + string(4) "/bla" +} diff --git a/ext/standard/tests/time/001.phpt b/ext/standard/tests/time/001.phpt index 74802ec7fcfb..3b0ed8a77f40 100644 --- a/ext/standard/tests/time/001.phpt +++ b/ext/standard/tests/time/001.phpt @@ -17,7 +17,7 @@ set_time_limit(0); for ($i=1;$i<=100000;$i++) { list($micro,$time)=explode(" ",microtime()); - if ($time > $last_t || ($time == $last_t && $micro > $last_m)) { + if ($time > $last_t || ($time == $last_t && $micro >= $last_m)) { $passed++; } else if ($failed++ <=10) { $result .= sprintf('%06d', $i).": $time $micro < $last_t $last_m\n"; diff --git a/ext/standard/tests/time/bug13142.phpt b/ext/standard/tests/time/bug13142.phpt index af3e1f2f316d..25bf11589f18 100644 --- a/ext/standard/tests/time/bug13142.phpt +++ b/ext/standard/tests/time/bug13142.phpt @@ -16,5 +16,5 @@ echo date("r\n", strtotime("Sep 04 16:39:45 2001")); echo date("r\n", strtotime("Sep 04 2001 16:39:45")); ?> --EXPECT-- -Tue, 4 Sep 2001 16:39:45 -0400 -Tue, 4 Sep 2001 16:39:45 -0400 +Tue, 04 Sep 2001 16:39:45 -0400 +Tue, 04 Sep 2001 16:39:45 -0400 diff --git a/ext/standard/tests/time/bug28599.phpt b/ext/standard/tests/time/bug28599.phpt new file mode 100644 index 000000000000..79ac9c84b1a8 --- /dev/null +++ b/ext/standard/tests/time/bug28599.phpt @@ -0,0 +1,8 @@ +--TEST-- +Bug #28599 (strtotime fails with zero base time) +--FILE-- + +--EXPECT-- +15-11-2004 16:49:33 diff --git a/ext/standard/type.c b/ext/standard/type.c index 3005df1dce56..979435401169 100644 --- a/ext/standard/type.c +++ b/ext/standard/type.c @@ -213,6 +213,10 @@ static void php_is_type(INTERNAL_FUNCTION_PARAMETERS, int type) if (Z_TYPE_PP(arg) == type) { if (type == IS_OBJECT) { zend_class_entry *ce; + if(Z_OBJ_HT_PP(arg)->get_class_entry == NULL) { + /* if there's no get_class_entry it's not a PHP object, so it can't be INCOMPLETE_CLASS */ + RETURN_TRUE; + } ce = Z_OBJCE_PP(arg); if (!strcmp(ce->name, INCOMPLETE_CLASS)) { RETURN_FALSE; diff --git a/ext/standard/url.c b/ext/standard/url.c index 9055583ec367..85375de6d835 100644 --- a/ext/standard/url.c +++ b/ext/standard/url.c @@ -60,15 +60,16 @@ PHPAPI void php_url_free(php_url *theurl) /* {{{ php_replace_controlchars */ -PHPAPI char *php_replace_controlchars(char *str) +PHPAPI char *php_replace_controlchars_ex(char *str, int len) { unsigned char *s = (unsigned char *)str; + unsigned char *e = (unsigned char *)str + len; if (!str) { return (NULL); } - while (*s) { + while (s < e) { if (iscntrl(*s)) { *s='_'; @@ -79,13 +80,21 @@ PHPAPI char *php_replace_controlchars(char *str) return (str); } /* }}} */ - + +PHPAPI char *php_replace_controlchars(char *str) +{ + return php_replace_controlchars_ex(str, strlen(str)); +} + +PHPAPI php_url *php_url_parse(char const *str) +{ + return php_url_parse_ex(str, strlen(str)); +} /* {{{ php_url_parse */ -PHPAPI php_url *php_url_parse(char const *str) +PHPAPI php_url *php_url_parse_ex(char const *str, int length) { - int length = strlen(str); char port_buf[6]; php_url *ret = ecalloc(1, sizeof(php_url)); char const *s, *e, *p, *pp, *ue; @@ -94,7 +103,27 @@ PHPAPI php_url *php_url_parse(char const *str) ue = s + length; /* parse scheme */ - if ((e = strchr(s, ':')) && (e-s)) { + if ((e = memchr(s, ':', length)) && (e - s)) { + /* validate scheme */ + p = s; + while (p < e) { + /* scheme = 1*[ lowalpha | digit | "+" | "-" | "." ] */ + if (!isalpha(*p) && !isdigit(*p) && *p != '+' && *p != '.' && *p != '-') { + if (e + 1 < ue) { + goto parse_port; + } else { + goto just_path; + } + } + p++; + } + + if (*(e + 1) == '\0') { /* only scheme is available */ + ret->scheme = estrndup(s, (e - s)); + php_replace_controlchars_ex(ret->scheme, (e - s)); + goto end; + } + /* * certain schemas like mailto: and zlib: may not have any / after them * this check ensures we support those. @@ -113,14 +142,14 @@ PHPAPI php_url *php_url_parse(char const *str) } ret->scheme = estrndup(s, (e-s)); - php_replace_controlchars(ret->scheme); + php_replace_controlchars_ex(ret->scheme, (e - s)); length -= ++e - s; s = e; goto just_path; } else { ret->scheme = estrndup(s, (e-s)); - php_replace_controlchars(ret->scheme); + php_replace_controlchars_ex(ret->scheme, (e - s)); if (*(e+2) == '/') { s = e + 3; @@ -136,8 +165,8 @@ PHPAPI php_url *php_url_parse(char const *str) } } } else { - s = e + 1; if (!strncasecmp("file", ret->scheme, sizeof("file"))) { + s = e + 1; goto nohost; } else { length -= ++e - s; @@ -170,8 +199,10 @@ PHPAPI php_url *php_url_parse(char const *str) e = ue; - if (!(p = strchr(s, '/'))) { - if ((p = strchr(s, '?'))) { + if (!(p = memchr(s, '/', (ue - s)))) { + if ((p = memchr(s, '?', (ue - s)))) { + e = p; + } else if ((p = memchr(s, '#', (ue - s)))) { e = p; } } else { @@ -183,17 +214,17 @@ PHPAPI php_url *php_url_parse(char const *str) if ((pp = memchr(s, ':', (p-s)))) { if ((pp-s) > 0) { ret->user = estrndup(s, (pp-s)); - php_replace_controlchars(ret->user); + php_replace_controlchars_ex(ret->user, (pp - s)); } pp++; if (p-pp > 0) { ret->pass = estrndup(pp, (p-pp)); - php_replace_controlchars(ret->pass); + php_replace_controlchars_ex(ret->pass, (p-pp)); } } else { ret->user = estrndup(s, (p-s)); - php_replace_controlchars(ret->user); + php_replace_controlchars_ex(ret->user, (p-s)); } s = p + 1; @@ -241,7 +272,7 @@ PHPAPI php_url *php_url_parse(char const *str) } ret->host = estrndup(s, (p-s)); - php_replace_controlchars(ret->host); + php_replace_controlchars_ex(ret->host, (p - s)); if (e == ue) { return ret; @@ -251,7 +282,7 @@ PHPAPI php_url *php_url_parse(char const *str) nohost: - if ((p = strchr(s, '?'))) { + if ((p = memchr(s, '?', (ue - s)))) { pp = strchr(s, '#'); if (pp && pp < p) { @@ -261,24 +292,24 @@ PHPAPI php_url *php_url_parse(char const *str) if (p - s) { ret->path = estrndup(s, (p-s)); - php_replace_controlchars(ret->path); + php_replace_controlchars_ex(ret->path, (p - s)); } if (pp) { if (pp - ++p) { ret->query = estrndup(p, (pp-p)); - php_replace_controlchars(ret->query); + php_replace_controlchars_ex(ret->query, (pp - p)); } p = pp; goto label_parse; } else if (++p - ue) { ret->query = estrndup(p, (ue-p)); - php_replace_controlchars(ret->query); + php_replace_controlchars_ex(ret->query, (ue - p)); } - } else if ((p = strchr(s, '#'))) { + } else if ((p = memchr(s, '#', (ue - s)))) { if (p - s) { ret->path = estrndup(s, (p-s)); - php_replace_controlchars(ret->path); + php_replace_controlchars_ex(ret->path, (p - s)); } label_parse: @@ -286,13 +317,13 @@ PHPAPI php_url *php_url_parse(char const *str) if (ue - p) { ret->fragment = estrndup(p, (ue-p)); - php_replace_controlchars(ret->fragment); + php_replace_controlchars_ex(ret->fragment, (ue - p)); } } else { ret->path = estrndup(s, (ue-s)); - php_replace_controlchars(ret->path); + php_replace_controlchars_ex(ret->path, (ue - s)); } - +end: return ret; } /* }}} */ @@ -309,7 +340,7 @@ PHP_FUNCTION(parse_url) return; } - resource = php_url_parse(str); + resource = php_url_parse_ex(str, str_len); if (resource == NULL) { php_error_docref1(NULL TSRMLS_CC, str, E_WARNING, "Unable to parse url"); RETURN_FALSE; diff --git a/ext/standard/url.h b/ext/standard/url.h index 709e830c2672..da15cf71ce0c 100644 --- a/ext/standard/url.h +++ b/ext/standard/url.h @@ -33,6 +33,7 @@ typedef struct php_url { PHPAPI void php_url_free(php_url *theurl); PHPAPI php_url *php_url_parse(char const *str); +PHPAPI php_url *php_url_parse_ex(char const *str, int length); PHPAPI int php_url_decode(char *str, int len); /* return value: length of decoded string */ PHPAPI int php_raw_url_decode(char *str, int len); /* return value: length of decoded string */ PHPAPI char *php_url_encode(char const *s, int len, int *new_length); diff --git a/ext/standard/url_scanner_ex.c b/ext/standard/url_scanner_ex.c index 174afb9ad56c..80d30531ee08 100644 --- a/ext/standard/url_scanner_ex.c +++ b/ext/standard/url_scanner_ex.c @@ -1,5 +1,5 @@ -/* Generated by re2c 0.9.2 on Sat Mar 13 15:56:45 2004 */ -#line 1 "/usr/src/php5/ext/standard/url_scanner_ex.re" +/* Generated by re2c 0.9.6 on Fri Apr 15 01:39:15 2005 */ +#line 1 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" /* +----------------------------------------------------------------------+ | PHP Version 5 | @@ -89,7 +89,7 @@ PHP_INI_BEGIN() STD_PHP_INI_ENTRY("url_rewriter.tags", "a=href,area=href,frame=src,form=,fieldset=", PHP_INI_ALL, OnUpdateTags, url_adapt_state_ex, php_basic_globals, basic_globals) PHP_INI_END() -#line 95 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 95 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" #define YYFILL(n) goto done @@ -108,7 +108,7 @@ static inline void append_modified_url(smart_str *url, smart_str *dest, smart_st scan: -#line 7 "re2c-output.c" +#line 7 "" { YYCTYPE yych; unsigned int yyaccept; @@ -147,44 +147,48 @@ static inline void append_modified_url(smart_str *url, smart_str *dest, smart_st 128, 128, 128, 128, 128, 128, 128, 128, }; goto yy0; -yy1: ++YYCURSOR; + ++YYCURSOR; yy0: if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; - if(yybm[0+yych] & 128) goto yy8; + if(yybm[0+yych] & 128) { + goto yy8; + } if(yych <= '9') goto yy6; if(yych >= ';') goto yy4; goto yy2; -yy2: yych = *++YYCURSOR; +yy2: ++YYCURSOR; goto yy3; yy3: -#line 113 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 113 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" { smart_str_append(dest, url); return; } -#line 59 "re2c-output.c" -yy4: yych = *++YYCURSOR; +#line 61 "" +yy4: ++YYCURSOR; goto yy5; yy5: -#line 114 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 114 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" { sep = separator; goto scan; } -#line 65 "re2c-output.c" -yy6: yych = *++YYCURSOR; +#line 67 "" +yy6: ++YYCURSOR; goto yy7; yy7: -#line 115 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 115 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" { bash = p - 1; goto done; } -#line 71 "re2c-output.c" +#line 73 "" yy8: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; goto yy9; -yy9: if(yybm[0+yych] & 128) goto yy8; +yy9: if(yybm[0+yych] & 128) { + goto yy8; + } goto yy10; yy10: -#line 116 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 116 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" { goto scan; } -#line 81 "re2c-output.c" +#line 86 "" } -#line 117 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 117 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" done: @@ -353,7 +357,7 @@ static inline void xx_mainloop(url_adapt_state_ex_t *ctx, const char *newdata, s state_plain: start = YYCURSOR; -#line 85 "re2c-output.c" +#line 90 "" { YYCTYPE yych; unsigned int yyaccept; @@ -392,36 +396,40 @@ static inline void xx_mainloop(url_adapt_state_ex_t *ctx, const char *newdata, s 128, 128, 128, 128, 128, 128, 128, 128, }; goto yy11; -yy12: ++YYCURSOR; + ++YYCURSOR; yy11: if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; - if(yybm[0+yych] & 128) goto yy15; + if(yybm[0+yych] & 128) { + goto yy15; + } goto yy13; -yy13: yych = *++YYCURSOR; +yy13: ++YYCURSOR; goto yy14; yy14: -#line 285 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 285 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" { passthru(STD_ARGS); STATE = STATE_TAG; goto state_tag; } -#line 135 "re2c-output.c" +#line 142 "" yy15: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; goto yy16; -yy16: if(yybm[0+yych] & 128) goto yy15; +yy16: if(yybm[0+yych] & 128) { + goto yy15; + } goto yy17; yy17: -#line 286 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 286 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" { passthru(STD_ARGS); goto state_plain; } -#line 145 "re2c-output.c" +#line 155 "" } -#line 287 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 287 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" state_tag: start = YYCURSOR; -#line 149 "re2c-output.c" +#line 159 "" { YYCTYPE yych; unsigned int yyaccept; @@ -460,7 +468,7 @@ yy16: if(yybm[0+yych] & 128) goto yy15; 0, 0, 0, 0, 0, 0, 0, 0, }; goto yy18; -yy19: ++YYCURSOR; + ++YYCURSOR; yy18: if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); yych = *YYCURSOR; @@ -469,26 +477,29 @@ yy19: ++YYCURSOR; if(yych <= '`') goto yy22; if(yych >= '{') goto yy22; goto yy20; -yy20: yych = *++YYCURSOR; +yy20: ++YYCURSOR; + yych = *YYCURSOR; goto yy25; yy21: -#line 292 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 292 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" { handle_tag(STD_ARGS); /* Sets STATE */; passthru(STD_ARGS); if (STATE == STATE_PLAIN) goto state_plain; else goto state_next_arg; } -#line 202 "re2c-output.c" -yy22: yych = *++YYCURSOR; +#line 212 "" +yy22: ++YYCURSOR; goto yy23; yy23: -#line 293 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 293 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" { passthru(STD_ARGS); goto state_plain_begin; } -#line 208 "re2c-output.c" +#line 218 "" yy24: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; goto yy25; -yy25: if(yybm[0+yych] & 128) goto yy24; +yy25: if(yybm[0+yych] & 128) { + goto yy24; + } goto yy21; } -#line 294 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 294 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" state_next_arg_begin: @@ -497,7 +508,7 @@ yy25: if(yybm[0+yych] & 128) goto yy24; state_next_arg: start = YYCURSOR; -#line 218 "re2c-output.c" +#line 231 "" { YYCTYPE yych; unsigned int yyaccept; @@ -536,13 +547,13 @@ yy25: if(yybm[0+yych] & 128) goto yy24; 0, 0, 0, 0, 0, 0, 0, 0, }; goto yy26; -yy27: ++YYCURSOR; + ++YYCURSOR; yy26: if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); yych = *YYCURSOR; if(yych <= '='){ - if(yych <= '\v'){ - if(yych <= '\b') goto yy34; + if(yych <= 0x0B){ + if(yych <= 0x08) goto yy34; goto yy30; } else { if(yych == ' ') goto yy30; @@ -559,44 +570,47 @@ yy27: ++YYCURSOR; goto yy34; } } -yy28: yych = *++YYCURSOR; +yy28: ++YYCURSOR; goto yy29; yy29: -#line 302 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 302 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" { passthru(STD_ARGS); handle_form(STD_ARGS); goto state_plain_begin; } -#line 285 "re2c-output.c" -yy30: yych = *++YYCURSOR; +#line 298 "" +yy30: ++YYCURSOR; + yych = *YYCURSOR; goto yy37; yy31: -#line 303 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 303 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" { passthru(STD_ARGS); goto state_next_arg; } -#line 291 "re2c-output.c" -yy32: yych = *++YYCURSOR; +#line 304 "" +yy32: ++YYCURSOR; goto yy33; yy33: -#line 304 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 304 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" { --YYCURSOR; STATE = STATE_ARG; goto state_arg; } -#line 297 "re2c-output.c" -yy34: yych = *++YYCURSOR; +#line 310 "" +yy34: ++YYCURSOR; goto yy35; yy35: -#line 305 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 305 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" { passthru(STD_ARGS); goto state_plain_begin; } -#line 303 "re2c-output.c" +#line 316 "" yy36: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; goto yy37; -yy37: if(yybm[0+yych] & 128) goto yy36; +yy37: if(yybm[0+yych] & 128) { + goto yy36; + } goto yy31; } -#line 306 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 306 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" state_arg: start = YYCURSOR; -#line 313 "re2c-output.c" +#line 329 "" { YYCTYPE yych; unsigned int yyaccept; @@ -635,7 +649,7 @@ yy37: if(yybm[0+yych] & 128) goto yy36; 0, 0, 0, 0, 0, 0, 0, 0, }; goto yy38; -yy39: ++YYCURSOR; + ++YYCURSOR; yy38: if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); yych = *YYCURSOR; @@ -644,32 +658,35 @@ yy39: ++YYCURSOR; if(yych <= '`') goto yy42; if(yych >= '{') goto yy42; goto yy40; -yy40: yych = *++YYCURSOR; +yy40: ++YYCURSOR; + yych = *YYCURSOR; goto yy45; yy41: -#line 311 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 311 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" { passthru(STD_ARGS); handle_arg(STD_ARGS); STATE = STATE_BEFORE_VAL; goto state_before_val; } -#line 366 "re2c-output.c" -yy42: yych = *++YYCURSOR; +#line 382 "" +yy42: ++YYCURSOR; goto yy43; yy43: -#line 312 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 312 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" { passthru(STD_ARGS); STATE = STATE_NEXT_ARG; goto state_next_arg; } -#line 372 "re2c-output.c" +#line 388 "" yy44: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; goto yy45; -yy45: if(yybm[0+yych] & 128) goto yy44; +yy45: if(yybm[0+yych] & 128) { + goto yy44; + } goto yy41; } -#line 313 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 313 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" state_before_val: start = YYCURSOR; -#line 382 "re2c-output.c" +#line 401 "" { YYCTYPE yych; unsigned int yyaccept; @@ -708,7 +725,7 @@ yy45: if(yybm[0+yych] & 128) goto yy44; 0, 0, 0, 0, 0, 0, 0, 0, }; goto yy46; -yy47: ++YYCURSOR; + ++YYCURSOR; yy46: if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); yych = *YYCURSOR; @@ -721,22 +738,25 @@ yy48: yyaccept = 0; if(yych == '=') goto yy53; goto yy49; yy49: -#line 319 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 319 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" { --YYCURSOR; goto state_next_arg_begin; } -#line 436 "re2c-output.c" -yy50: yych = *++YYCURSOR; +#line 455 "" +yy50: ++YYCURSOR; + yych = *YYCURSOR; goto yy54; yy51: -#line 318 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 318 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" { passthru(STD_ARGS); STATE = STATE_VAL; goto state_val; } -#line 442 "re2c-output.c" +#line 461 "" yy52: yych = *++YYCURSOR; goto yy49; yy53: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; goto yy54; -yy54: if(yybm[0+yych] & 128) goto yy53; +yy54: if(yybm[0+yych] & 128) { + goto yy53; + } goto yy51; yy55: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); @@ -750,14 +770,14 @@ yy57: YYCURSOR = YYMARKER; case 0: goto yy49; } } -#line 320 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 320 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" state_val: start = YYCURSOR; -#line 465 "re2c-output.c" +#line 488 "" { YYCTYPE yych; unsigned int yyaccept; @@ -796,13 +816,13 @@ yy57: YYCURSOR = YYMARKER; 248, 248, 248, 248, 248, 248, 248, 248, }; goto yy58; -yy59: ++YYCURSOR; + ++YYCURSOR; yy58: if((YYLIMIT - YYCURSOR) < 3) YYFILL(3); yych = *YYCURSOR; if(yych <= '!'){ - if(yych <= '\n'){ - if(yych <= '\b') goto yy63; + if(yych <= 0x0A){ + if(yych <= 0x08) goto yy63; goto yy64; } else { if(yych == ' ') goto yy64; @@ -822,47 +842,56 @@ yy60: yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); goto yy77; yy61: -#line 328 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 328 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" { handle_val(STD_ARGS, 0, '\0'); goto state_next_arg_begin; } -#line 532 "re2c-output.c" +#line 555 "" yy62: yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); goto yy69; yy63: yych = *++YYCURSOR; goto yy67; -yy64: yych = *++YYCURSOR; +yy64: ++YYCURSOR; goto yy65; yy65: -#line 329 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 329 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" { passthru(STD_ARGS); goto state_next_arg_begin; } -#line 543 "re2c-output.c" +#line 566 "" yy66: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; goto yy67; -yy67: if(yybm[0+yych] & 8) goto yy66; +yy67: if(yybm[0+yych] & 8) { + goto yy66; + } goto yy61; yy68: yyaccept = 0; YYMARKER = ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); + if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); yych = *YYCURSOR; goto yy69; -yy69: if(yybm[0+yych] & 16) goto yy68; +yy69: if(yybm[0+yych] & 16) { + goto yy68; + } if(yych <= '&') goto yy72; if(yych >= '(') goto yy61; goto yy70; -yy70: yych = *++YYCURSOR; - if(yybm[0+yych] & 8) goto yy66; +yy70: ++YYCURSOR; + if(yybm[0+(yych = *YYCURSOR)] & 8) { + yych = *YYCURSOR; + goto yy66; + } goto yy71; yy71: -#line 327 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 327 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" { handle_val(STD_ARGS, 1, '\''); goto state_next_arg_begin; } -#line 565 "re2c-output.c" +#line 595 "" yy72: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; goto yy73; -yy73: if(yybm[0+yych] & 32) goto yy72; +yy73: if(yybm[0+yych] & 32) { + goto yy72; + } if(yych <= '=') goto yy75; goto yy74; yy74: YYCURSOR = YYMARKER; @@ -873,31 +902,39 @@ yy75: yych = *++YYCURSOR; goto yy71; yy76: yyaccept = 0; YYMARKER = ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); + if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); yych = *YYCURSOR; goto yy77; -yy77: if(yybm[0+yych] & 64) goto yy76; +yy77: if(yybm[0+yych] & 64) { + goto yy76; + } if(yych <= '!') goto yy80; if(yych >= '#') goto yy61; goto yy78; -yy78: yych = *++YYCURSOR; - if(yybm[0+yych] & 8) goto yy66; +yy78: ++YYCURSOR; + if(yybm[0+(yych = *YYCURSOR)] & 8) { + yych = *YYCURSOR; + goto yy66; + } goto yy79; yy79: -#line 326 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 326 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" { handle_val(STD_ARGS, 1, '"'); goto state_next_arg_begin; } -#line 594 "re2c-output.c" +#line 631 "" yy80: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; goto yy81; -yy81: if(yybm[0+yych] & 128) goto yy80; +yy81: if(yybm[0+yych] & 128) { + goto yy80; + } if(yych >= '>') goto yy74; goto yy82; -yy82: yych = *++YYCURSOR; +yy82: ++YYCURSOR; + yych = *YYCURSOR; goto yy79; } -#line 330 "/usr/src/php5/ext/standard/url_scanner_ex.re" +#line 330 "/usr/src/php/php_5_0/ext/standard/url_scanner_ex.re" stop: @@ -987,16 +1024,31 @@ static void php_url_scanner_output_handler(char *output, uint output_len, char * { size_t len; - if (BG(url_adapt_state_ex).url_app.len != 0) { - *handled_output = url_adapt_ext(output, output_len, &len, (zend_bool) (mode & (PHP_OUTPUT_HANDLER_END|PHP_OUTPUT_HANDLER_CONT) ? 1 : 0) TSRMLS_CC); + if (BG(url_adapt_state_ex).url_app.len != 0) { + *handled_output = url_adapt_ext(output, output_len, &len, (zend_bool) (mode & PHP_OUTPUT_HANDLER_END ? 1 : 0) TSRMLS_CC); if (sizeof(uint) < sizeof(size_t)) { if (len > UINT_MAX) len = UINT_MAX; } *handled_output_len = len; - } else { - *handled_output = NULL; - } + } else if (BG(url_adapt_state_ex).url_app.len == 0) { + url_adapt_state_ex_t *ctx = &BG(url_adapt_state_ex); + if (ctx->buf.len) { + smart_str_appendl(&ctx->result, ctx->buf.c, ctx->buf.len); + smart_str_appendl(&ctx->result, output, output_len); + + *handled_output = ctx->result.c; + *handled_output_len = ctx->buf.len + output_len; + + ctx->result.c = NULL; + ctx->result.len = 0; + smart_str_free(&ctx->buf); + } else { + *handled_output = NULL; + } + } else { + *handled_output = NULL; + } } int php_url_scanner_add_var(char *name, int name_len, char *value, int value_len, int urlencode TSRMLS_DC) @@ -1044,7 +1096,7 @@ int php_url_scanner_reset_vars(TSRMLS_D) BG(url_adapt_state_ex).form_app.len = 0; BG(url_adapt_state_ex).url_app.len = 0; - return FAILURE; + return SUCCESS; } PHP_MINIT_FUNCTION(url_scanner) diff --git a/ext/standard/url_scanner_ex.re b/ext/standard/url_scanner_ex.re index a7d688abcb9d..5debff724440 100644 --- a/ext/standard/url_scanner_ex.re +++ b/ext/standard/url_scanner_ex.re @@ -416,16 +416,31 @@ static void php_url_scanner_output_handler(char *output, uint output_len, char * { size_t len; - if (BG(url_adapt_state_ex).url_app.len != 0) { - *handled_output = url_adapt_ext(output, output_len, &len, (zend_bool) (mode & (PHP_OUTPUT_HANDLER_END|PHP_OUTPUT_HANDLER_CONT) ? 1 : 0) TSRMLS_CC); + if (BG(url_adapt_state_ex).url_app.len != 0) { + *handled_output = url_adapt_ext(output, output_len, &len, (zend_bool) (mode & PHP_OUTPUT_HANDLER_END ? 1 : 0) TSRMLS_CC); if (sizeof(uint) < sizeof(size_t)) { if (len > UINT_MAX) len = UINT_MAX; } *handled_output_len = len; - } else { - *handled_output = NULL; - } + } else if (BG(url_adapt_state_ex).url_app.len == 0) { + url_adapt_state_ex_t *ctx = &BG(url_adapt_state_ex); + if (ctx->buf.len) { + smart_str_appendl(&ctx->result, ctx->buf.c, ctx->buf.len); + smart_str_appendl(&ctx->result, output, output_len); + + *handled_output = ctx->result.c; + *handled_output_len = ctx->buf.len + output_len; + + ctx->result.c = NULL; + ctx->result.len = 0; + smart_str_free(&ctx->buf); + } else { + *handled_output = NULL; + } + } else { + *handled_output = NULL; + } } int php_url_scanner_add_var(char *name, int name_len, char *value, int value_len, int urlencode TSRMLS_DC) @@ -473,7 +488,7 @@ int php_url_scanner_reset_vars(TSRMLS_D) BG(url_adapt_state_ex).form_app.len = 0; BG(url_adapt_state_ex).url_app.len = 0; - return FAILURE; + return SUCCESS; } PHP_MINIT_FUNCTION(url_scanner) diff --git a/ext/standard/user_filters.c b/ext/standard/user_filters.c index e1ecf3c2060a..b45c4f98a180 100644 --- a/ext/standard/user_filters.c +++ b/ext/standard/user_filters.c @@ -135,11 +135,6 @@ static void userfilter_dtor(php_stream_filter *thisfilter TSRMLS_DC) if (retval) zval_ptr_dtor(&retval); - if (SUCCESS == zend_hash_find(Z_OBJPROP_P(obj), "filter", sizeof("filter"), (void**)&tmp)) { - zend_list_delete(Z_LVAL_PP(tmp)); - FREE_ZVAL(*tmp); - } - /* kill the object */ zval_ptr_dtor(&obj); } @@ -345,6 +340,8 @@ static php_stream_filter *user_filter_factory_create(const char *filtername, ZEND_REGISTER_RESOURCE(zfilter, filter, le_userfilters); filter->abstract = obj; add_property_zval(obj, "filter", zfilter); + /* add_property_zval increments the refcount which is unwanted here */ + zval_ptr_dtor(&zfilter); return filter; } @@ -470,6 +467,8 @@ PHP_FUNCTION(stream_bucket_new) ZEND_REGISTER_RESOURCE(zbucket, bucket, le_bucket); object_init(return_value); add_property_zval(return_value, "bucket", zbucket); + /* add_property_zval increments the refcount which is unwanted here */ + zval_ptr_dtor(&zbucket); add_property_stringl(return_value, "data", bucket->buf, bucket->buflen, 1); add_property_long(return_value, "datalen", bucket->buflen); } diff --git a/ext/standard/uuencode.c b/ext/standard/uuencode.c index 544fda1cac0b..9606fbaccb2d 100644 --- a/ext/standard/uuencode.c +++ b/ext/standard/uuencode.c @@ -136,9 +136,18 @@ PHPAPI int php_uudecode(char *src, int src_len, char **dest) if ((len = PHP_UU_DEC(*s++)) <= 0) { break; } + /* sanity check */ + if (len > src_len) { + goto err; + } + total_len += len; ee = s + (len == 45 ? 60 : (int) floor(len * 1.33)); + /* sanity check */ + if (ee > e) { + goto err; + } while (s < ee) { *p++ = PHP_UU_DEC(*s) << 2 | PHP_UU_DEC(*(s + 1)) >> 4; @@ -168,6 +177,10 @@ PHPAPI int php_uudecode(char *src, int src_len, char **dest) *(*dest + total_len) = '\0'; return total_len; + +err: + efree(*dest); + return -1; } /* {{{ proto string uuencode(string data) @@ -199,6 +212,10 @@ PHP_FUNCTION(convert_uudecode) } dst_len = php_uudecode(src, src_len, &dst); + if (dst_len < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "The given parameter is not a valid uuencoded string."); + RETURN_FALSE; + } RETURN_STRINGL(dst, dst_len, 0); } diff --git a/ext/standard/var.c b/ext/standard/var.c index 6d512fac1ed4..28c73b98f4ed 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -21,6 +21,7 @@ /* $Id$ */ + /* {{{ includes */ @@ -319,20 +320,13 @@ static int php_array_element_export(zval **zv, int num_args, va_list args, zend_ if (hash_key->nKeyLength==0) { /* numeric key */ php_printf("%*c%ld => ", level + 1, ' ', hash_key->h); } else { /* string key */ - /* XXX: perphaps when we are inside the class we should permit access to - * private & protected values - */ - if (va_arg(args, int) && hash_key->arKey[0] == '\0') { - return 0; - } else { - char *key; - int key_len; - key = php_addcslashes(hash_key->arKey, hash_key->nKeyLength - 1, &key_len, 0, "'\\", 2 TSRMLS_CC); - php_printf("%*c'", level + 1, ' '); - PHPWRITE(key, key_len); - php_printf("' => "); - efree(key); - } + char *key; + int key_len; + key = php_addcslashes(hash_key->arKey, hash_key->nKeyLength - 1, &key_len, 0, "'\\", 2 TSRMLS_CC); + php_printf("%*c'", level + 1, ' '); + PHPWRITE(key, key_len); + php_printf("' => "); + efree(key); } php_var_export(zv, level + 2 TSRMLS_CC); PUTS (",\n"); @@ -470,7 +464,7 @@ static inline int php_add_var_hash(HashTable *var_hash, zval *var, void *var_old /* relies on "(long)" being a perfect hash function for data pointers, however the actual identity of an object has had to be determined by its object handle and the class entry since 5.0. */ - if (Z_TYPE_P(var) == IS_OBJECT) { + if ((Z_TYPE_P(var) == IS_OBJECT) && Z_OBJ_HT_P(var)->get_class_entry != NULL) { p = smart_str_print_long(id + sizeof(id) - 1, (((unsigned long)Z_OBJCE_P(var) << 5) | ((unsigned long)Z_OBJCE_P(var) >> (sizeof(long) * 8 - 5))) @@ -578,14 +572,44 @@ static void php_var_serialize_class(smart_str *buf, zval **struc, zval *retval_p smart_str_appendl(buf,"N;", 2); continue; } - - php_var_serialize_string(buf, Z_STRVAL_PP(name), Z_STRLEN_PP(name)); - if (zend_hash_find(Z_OBJPROP_PP(struc), Z_STRVAL_PP(name), Z_STRLEN_PP(name) + 1, (void *) &d) == SUCCESS) { - php_var_serialize_intern(buf, d, var_hash TSRMLS_CC); + php_var_serialize_string(buf, Z_STRVAL_PP(name), Z_STRLEN_PP(name)); + php_var_serialize_intern(buf, d, var_hash TSRMLS_CC); } else { - php_var_serialize_intern(buf, &nvalp, var_hash TSRMLS_CC); + zend_class_entry *ce; + ce = zend_get_class_entry(*struc TSRMLS_CC); + if (ce) { + char *prot_name, *priv_name; + int prop_name_length; + + do { + zend_mangle_property_name(&priv_name, &prop_name_length, ce->name, ce->name_length, + Z_STRVAL_PP(name), Z_STRLEN_PP(name), ce->type & ZEND_INTERNAL_CLASS); + if (zend_hash_find(Z_OBJPROP_PP(struc), priv_name, prop_name_length+1, (void *) &d) == SUCCESS) { + php_var_serialize_string(buf, priv_name, prop_name_length); + efree(priv_name); + php_var_serialize_intern(buf, d, var_hash TSRMLS_CC); + break; + } + efree(priv_name); + zend_mangle_property_name(&prot_name, &prop_name_length, "*", 1, + Z_STRVAL_PP(name), Z_STRLEN_PP(name), ce->type & ZEND_INTERNAL_CLASS); + if (zend_hash_find(Z_OBJPROP_PP(struc), prot_name, prop_name_length+1, (void *) &d) == SUCCESS) { + php_var_serialize_string(buf, prot_name, prop_name_length); + efree(prot_name); + php_var_serialize_intern(buf, d, var_hash TSRMLS_CC); + break; + } + efree(prot_name); + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "\"%s\" returned as member variable from __sleep() but does not exist", Z_STRVAL_PP(name)); + php_var_serialize_string(buf, Z_STRVAL_PP(name), Z_STRLEN_PP(name)); + php_var_serialize_intern(buf, &nvalp, var_hash TSRMLS_CC); + } while (0); + } else { + php_var_serialize_string(buf, Z_STRVAL_PP(name), Z_STRLEN_PP(name)); + php_var_serialize_intern(buf, &nvalp, var_hash TSRMLS_CC); + } } } } @@ -648,7 +672,8 @@ static void php_var_serialize_intern(smart_str *buf, zval **struc, HashTable *va zval fname; int res; - if(Z_OBJCE_PP(struc) != PHP_IC_ENTRY) { + if (Z_OBJ_HT_PP(struc)->get_class_entry && Z_OBJCE_PP(struc) != PHP_IC_ENTRY && + zend_hash_exists(&Z_OBJCE_PP(struc)->function_table, "__sleep", sizeof("__sleep"))) { INIT_PZVAL(&fname); ZVAL_STRINGL(&fname, "__sleep", sizeof("__sleep") - 1, 0); res = call_user_function_ex(CG(function_table), struc, &fname, @@ -793,7 +818,7 @@ PHP_FUNCTION(unserialize) } if (Z_TYPE_PP(buf) == IS_STRING) { - const char *p = Z_STRVAL_PP(buf); + const unsigned char *p = (unsigned char*)Z_STRVAL_PP(buf); if (Z_STRLEN_PP(buf) == 0) { RETURN_FALSE; @@ -803,12 +828,12 @@ PHP_FUNCTION(unserialize) if (!php_var_unserialize(&return_value, &p, p + Z_STRLEN_PP(buf), &var_hash TSRMLS_CC)) { PHP_VAR_UNSERIALIZE_DESTROY(var_hash); zval_dtor(return_value); - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Error at offset %ld of %d bytes", (long)(p - Z_STRVAL_PP(buf)), Z_STRLEN_PP(buf)); + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Error at offset %ld of %d bytes", (long)((char*)p - Z_STRVAL_PP(buf)), Z_STRLEN_PP(buf)); RETURN_FALSE; } PHP_VAR_UNSERIALIZE_DESTROY(var_hash); } else { - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Argument is not an string"); + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Argument is not a string"); RETURN_FALSE; } } diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index 261c1fc79138..0db64025a3e6 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -1,5 +1,5 @@ -/* Generated by re2c 0.9.2 on Sat Mar 27 02:27:57 2004 */ -#line 1 "/usr/src/php5/ext/standard/var_unserializer.re" +/* Generated by re2c 0.9.6 on Fri Apr 15 01:39:24 2005 */ +#line 1 "/usr/src/php/php_5_0/ext/standard/var_unserializer.re" /* +----------------------------------------------------------------------+ | PHP Version 5 | @@ -29,7 +29,7 @@ typedef struct { zval *data[VAR_ENTRIES_MAX]; - int used_slots; + long used_slots; void *next; } var_entries; @@ -56,9 +56,33 @@ static inline void var_push(php_unserialize_data_t *var_hashx, zval **rval) var_hash->data[var_hash->used_slots++] = *rval; } +static inline void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval) +{ + var_entries *var_hash = var_hashx->first_dtor, *prev = NULL; + + while (var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) { + prev = var_hash; + var_hash = var_hash->next; + } + + if (!var_hash) { + var_hash = emalloc(sizeof(var_entries)); + var_hash->used_slots = 0; + var_hash->next = 0; + + if (!var_hashx->first_dtor) + var_hashx->first_dtor = var_hash; + else + prev->next = var_hash; + } + + (*rval)->refcount++; + var_hash->data[var_hash->used_slots++] = *rval; +} + PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval **nzval) { - int i; + long i; var_entries *var_hash = var_hashx->first; while (var_hash) { @@ -72,7 +96,7 @@ PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval **n } } -static int var_access(php_unserialize_data_t *var_hashx, int id, zval ***store) +static int var_access(php_unserialize_data_t *var_hashx, long id, zval ***store) { var_entries *var_hash = var_hashx->first; @@ -83,7 +107,7 @@ static int var_access(php_unserialize_data_t *var_hashx, int id, zval ***store) if (!var_hash) return !SUCCESS; - if (id >= var_hash->used_slots) return !SUCCESS; + if (id < 0 || id >= var_hash->used_slots) return !SUCCESS; *store = &var_hash->data[id]; @@ -93,6 +117,7 @@ static int var_access(php_unserialize_data_t *var_hashx, int id, zval ***store) PHPAPI void var_destroy(php_unserialize_data_t *var_hashx) { void *next; + long i; var_entries *var_hash = var_hashx->first; while (var_hash) { @@ -100,6 +125,17 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx) efree(var_hash); var_hash = next; } + + var_hash = var_hashx->first_dtor; + + while (var_hash) { + for (i = 0; i < var_hash->used_slots; i++) { + zval_ptr_dtor(&var_hash->data[i]); + } + next = var_hash->next; + efree(var_hash); + var_hash = next; + } } /* }}} */ @@ -111,15 +147,15 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx) #define YYMARKER marker -#line 118 "/usr/src/php5/ext/standard/var_unserializer.re" +#line 154 "/usr/src/php/php_5_0/ext/standard/var_unserializer.re" -static inline int parse_iv2(const char *p, const char **q) +static inline long parse_iv2(const unsigned char *p, const unsigned char **q) { char cursor; - int result = 0; + long result = 0; int neg = 0; switch (*p) { @@ -131,7 +167,7 @@ static inline int parse_iv2(const char *p, const char **q) } while (1) { - cursor = *p; + cursor = (char)*p; if (cursor >= '0' && cursor <= '9') { result = result * 10 + cursor - '0'; } else { @@ -144,18 +180,40 @@ static inline int parse_iv2(const char *p, const char **q) return result; } -static inline int parse_iv(const char *p) +static inline long parse_iv(const unsigned char *p) { return parse_iv2(p, NULL); } -#define UNSERIALIZE_PARAMETER zval **rval, const char **p, const char *max, php_unserialize_data_t *var_hash TSRMLS_DC +/* no need to check for length - re2c already did */ +static inline size_t parse_uiv(const unsigned char *p) +{ + unsigned char cursor; + size_t result = 0; + + if (*p == '+') { + p++; + } + + while (1) { + cursor = *p; + if (cursor >= '0' && cursor <= '9') { + result = result * 10 + (size_t)(cursor - (unsigned char)'0'); + } else { + break; + } + p++; + } + return result; +} + +#define UNSERIALIZE_PARAMETER zval **rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash TSRMLS_DC #define UNSERIALIZE_PASSTHRU rval, p, max, var_hash TSRMLS_CC -static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, int elements) +static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long elements) { while (elements-- > 0) { - zval *key, *data; + zval *key, *data, **old_data; ALLOC_INIT_ZVAL(key); @@ -165,6 +223,12 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, int return 0; } + if (Z_TYPE_P(key) != IS_LONG && Z_TYPE_P(key) != IS_STRING) { + zval_dtor(key); + FREE_ZVAL(key); + return 0; + } + ALLOC_INIT_ZVAL(data); if (!php_var_unserialize(&data, p, max, var_hash TSRMLS_CC)) { @@ -177,16 +241,26 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, int switch (Z_TYPE_P(key)) { case IS_LONG: + if (zend_hash_index_find(ht, Z_LVAL_P(key), (void **)&old_data)==SUCCESS) { + var_push_dtor(var_hash, old_data); + } zend_hash_index_update(ht, Z_LVAL_P(key), &data, sizeof(data), NULL); break; case IS_STRING: + if (zend_hash_find(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&old_data)==SUCCESS) { + var_push_dtor(var_hash, old_data); + } zend_hash_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &data, sizeof(data), NULL); break; - } zval_dtor(key); FREE_ZVAL(key); + + if (elements && *(*p-1) != ';' && *(*p-1) != '}') { + (*p)--; + return 0; + } } return 1; @@ -205,7 +279,7 @@ static inline int finish_nested_data(UNSERIALIZE_PARAMETER) static inline int object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce) { - int elements; + long elements; elements = parse_iv2((*p) + 2, p); @@ -215,7 +289,7 @@ static inline int object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce) return elements; } -static inline int object_common2(UNSERIALIZE_PARAMETER, int elements) +static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) { zval *retval_ptr = NULL; zval fname; @@ -224,7 +298,8 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, int elements) return 0; } - if(Z_OBJCE_PP(rval) != PHP_IC_ENTRY) { + if (Z_OBJCE_PP(rval) != PHP_IC_ENTRY && + zend_hash_exists(&Z_OBJCE_PP(rval)->function_table, "__wakeup", sizeof("__wakeup"))) { INIT_PZVAL(&fname); ZVAL_STRINGL(&fname, "__wakeup", sizeof("__wakeup") - 1, 0); call_user_function_ex(CG(function_table), rval, &fname, &retval_ptr, 0, 0, 1, NULL TSRMLS_CC); @@ -253,7 +328,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) -#line 7 "re2c-output.c" +#line 7 "" { YYCTYPE yych; unsigned int yyaccept; @@ -292,7 +367,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) 0, 0, 0, 0, 0, 0, 0, 0, }; goto yy0; -yy1: ++YYCURSOR; + ++YYCURSOR; yy0: if((YYLIMIT - YYCURSOR) < 7) YYFILL(7); yych = *YYCURSOR; @@ -332,7 +407,7 @@ yy1: ++YYCURSOR; goto yy16; } else { if(yych <= '}') goto yy14; - if(yych <= '\277') goto yy16; + if(yych <= 0xBF) goto yy16; goto yy2; } } @@ -343,18 +418,18 @@ yy2: YYCURSOR = YYMARKER; } yy3: yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); - if(yych == ':') goto yy89; + if(yych == ':') goto yy87; goto yy4; yy4: -#line 478 "/usr/src/php5/ext/standard/var_unserializer.re" +#line 589 "/usr/src/php/php_5_0/ext/standard/var_unserializer.re" { return 0; } -#line 102 "re2c-output.c" +#line 102 "" yy5: yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); - if(yych == ':') goto yy83; + if(yych == ':') goto yy81; goto yy4; yy6: yych = *++YYCURSOR; - if(yych == ';') goto yy81; + if(yych == ';') goto yy79; goto yy4; yy7: yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); @@ -384,43 +459,48 @@ yy13: yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); if(yych == ':') goto yy17; goto yy4; -yy14: yych = *++YYCURSOR; +yy14: ++YYCURSOR; goto yy15; yy15: -#line 472 "/usr/src/php5/ext/standard/var_unserializer.re" +#line 583 "/usr/src/php/php_5_0/ext/standard/var_unserializer.re" { /* this is the case where we have less data than planned */ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data"); return 0; /* not sure if it should be 0 or 1 here? */ } -#line 147 "re2c-output.c" +#line 147 "" yy16: yych = *++YYCURSOR; goto yy4; yy17: yych = *++YYCURSOR; - if(yybm[0+yych] & 128) goto yy19; + if(yybm[0+yych] & 128) { + goto yy19; + } if(yych != '+') goto yy2; goto yy18; yy18: yych = *++YYCURSOR; - if(yybm[0+yych] & 128) goto yy19; + if(yybm[0+yych] & 128) { + goto yy19; + } goto yy2; yy19: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); + if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); yych = *YYCURSOR; goto yy20; -yy20: if(yybm[0+yych] & 128) goto yy19; +yy20: if(yybm[0+yych] & 128) { + goto yy19; + } if(yych != ':') goto yy2; goto yy21; yy21: yych = *++YYCURSOR; if(yych != '"') goto yy2; goto yy22; -yy22: yych = *++YYCURSOR; +yy22: ++YYCURSOR; goto yy23; yy23: -#line 393 "/usr/src/php5/ext/standard/var_unserializer.re" +#line 483 "/usr/src/php/php_5_0/ext/standard/var_unserializer.re" { - int len; - int elements; - int len2; + size_t len, len2, len3, maxlen; + long elements; char *class_name; zend_class_entry *ce; zend_class_entry **pce; @@ -432,13 +512,35 @@ yy22: yych = *++YYCURSOR; zval *arg_func_name; INIT_PZVAL(*rval); - len2 = len = parse_iv(start + 2); - if (len == 0) + len2 = len = parse_uiv(start + 2); + maxlen = max - YYCURSOR; + if (maxlen < len || len == 0) { + *p = start + 2; return 0; + } + + class_name = (char*)YYCURSOR; - class_name = estrndup(YYCURSOR, len); YYCURSOR += len; + if (*(YYCURSOR) != '"') { + *p = YYCURSOR; + return 0; + } + if (*(YYCURSOR+1) != ':') { + *p = YYCURSOR+1; + return 0; + } + + len3 = strspn(class_name, "0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); + if (len3 != len) + { + *p = YYCURSOR + len3 - len; + return 0; + } + + class_name = estrndup(class_name, len); + do { /* Try to find class directly */ if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) { @@ -495,7 +597,7 @@ yy22: yych = *++YYCURSOR; return object_common2(UNSERIALIZE_PASSTHRU, elements); } -#line 249 "re2c-output.c" +#line 277 "" yy24: yych = *++YYCURSOR; if(yych <= ','){ if(yych != '+') goto yy2; @@ -511,7 +613,7 @@ yy25: yych = *++YYCURSOR; if(yych >= ':') goto yy2; goto yy26; yy26: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); + if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); yych = *YYCURSOR; goto yy27; yy27: if(yych <= '/') goto yy2; @@ -521,10 +623,10 @@ yy27: if(yych <= '/') goto yy2; yy28: yych = *++YYCURSOR; if(yych != '"') goto yy2; goto yy29; -yy29: yych = *++YYCURSOR; +yy29: ++YYCURSOR; goto yy30; yy30: -#line 385 "/usr/src/php5/ext/standard/var_unserializer.re" +#line 475 "/usr/src/php/php_5_0/ext/standard/var_unserializer.re" { INIT_PZVAL(*rval); @@ -532,7 +634,7 @@ yy29: yych = *++YYCURSOR; return object_common2(UNSERIALIZE_PASSTHRU, object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR)); } -#line 286 "re2c-output.c" +#line 315 "" yy31: yych = *++YYCURSOR; if(yych == '+') goto yy32; if(yych <= '/') goto yy2; @@ -543,7 +645,7 @@ yy32: yych = *++YYCURSOR; if(yych >= ':') goto yy2; goto yy33; yy33: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); + if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); yych = *YYCURSOR; goto yy34; yy34: if(yych <= '/') goto yy2; @@ -553,15 +655,23 @@ yy34: if(yych <= '/') goto yy2; yy35: yych = *++YYCURSOR; if(yych != '{') goto yy2; goto yy36; -yy36: yych = *++YYCURSOR; +yy36: ++YYCURSOR; goto yy37; yy37: -#line 367 "/usr/src/php5/ext/standard/var_unserializer.re" +#line 449 "/usr/src/php/php_5_0/ext/standard/var_unserializer.re" { - int elements = parse_iv(start + 2); - + long elements = parse_iv(start + 2); + /* use iv() not uiv() in order to check data range */ *p = YYCURSOR; + if (elements < 0) { + return 0; + } + + if (elements < 0) { + return 0; + } + INIT_PZVAL(*rval); Z_TYPE_PP(rval) = IS_ARRAY; ALLOC_HASHTABLE(Z_ARRVAL_PP(rval)); @@ -574,7 +684,7 @@ yy36: yych = *++YYCURSOR; return finish_nested_data(UNSERIALIZE_PASSTHRU); } -#line 328 "re2c-output.c" +#line 366 "" yy38: yych = *++YYCURSOR; if(yych == '+') goto yy39; if(yych <= '/') goto yy2; @@ -585,7 +695,7 @@ yy39: yych = *++YYCURSOR; if(yych >= ':') goto yy2; goto yy40; yy40: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); + if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); yych = *YYCURSOR; goto yy41; yy41: if(yych <= '/') goto yy2; @@ -595,30 +705,38 @@ yy41: if(yych <= '/') goto yy2; yy42: yych = *++YYCURSOR; if(yych != '"') goto yy2; goto yy43; -yy43: yych = *++YYCURSOR; +yy43: ++YYCURSOR; goto yy44; yy44: -#line 347 "/usr/src/php5/ext/standard/var_unserializer.re" +#line 421 "/usr/src/php/php_5_0/ext/standard/var_unserializer.re" { - int len; + size_t len, maxlen; char *str; - len = parse_iv(start + 2); + len = parse_uiv(start + 2); + maxlen = max - YYCURSOR; + if (maxlen < len) { + *p = start + 2; + return 0; + } - if (len == 0) { - str = empty_string; - } else { - str = estrndup(YYCURSOR, len); + str = (char*)YYCURSOR; + + YYCURSOR += len; + + if (*(YYCURSOR) != '"') { + *p = YYCURSOR; + return 0; } - YYCURSOR += len + 2; + YYCURSOR += 2; *p = YYCURSOR; INIT_PZVAL(*rval); - ZVAL_STRINGL(*rval, str, len, 0); + ZVAL_STRINGL(*rval, str, len, 1); return 1; } -#line 372 "re2c-output.c" +#line 419 "" yy45: yych = *++YYCURSOR; if(yych <= '/'){ if(yych <= ','){ @@ -660,7 +778,7 @@ yy49: yych = *++YYCURSOR; if(yych >= ':') goto yy2; goto yy50; yy50: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); + if((YYLIMIT - YYCURSOR) < 4) YYFILL(4); yych = *YYCURSOR; goto yy51; yy51: if(yych <= ':'){ @@ -687,7 +805,7 @@ yy52: yych = *++YYCURSOR; if(yych >= ':') goto yy2; goto yy53; yy53: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); + if((YYLIMIT - YYCURSOR) < 4) YYFILL(4); yych = *YYCURSOR; goto yy54; yy54: if(yych <= ';'){ @@ -704,17 +822,17 @@ yy54: if(yych <= ';'){ goto yy2; } } -yy55: yych = *++YYCURSOR; +yy55: ++YYCURSOR; goto yy56; yy56: -#line 340 "/usr/src/php5/ext/standard/var_unserializer.re" +#line 414 "/usr/src/php/php_5_0/ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); - ZVAL_DOUBLE(*rval, atof(start + 2)); + ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL)); return 1; } -#line 468 "re2c-output.c" +#line 517 "" yy57: yych = *++YYCURSOR; if(yych <= ','){ if(yych != '+') goto yy2; @@ -771,16 +889,14 @@ yy64: yych = *++YYCURSOR; yy65: yych = *++YYCURSOR; if(yych != ';') goto yy2; goto yy66; -yy66: yych = *++YYCURSOR; +yy66: ++YYCURSOR; goto yy67; yy67: -#line 323 "/usr/src/php5/ext/standard/var_unserializer.re" +#line 399 "/usr/src/php/php_5_0/ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); -#if defined(HAVE_ATOF_ACCEPTS_NAN) && defined(HAVE_ATOF_ACCEPTS_INF) - ZVAL_DOUBLE(*rval, atof(start + 2)); -#else + if (!strncmp(start + 2, "NAN", 3)) { ZVAL_DOUBLE(*rval, php_get_nan()); } else if (!strncmp(start + 2, "INF", 3)) { @@ -788,10 +904,10 @@ yy66: yych = *++YYCURSOR; } else if (!strncmp(start + 2, "-INF", 4)) { ZVAL_DOUBLE(*rval, -php_get_inf()); } -#endif + return 1; } -#line 545 "re2c-output.c" +#line 594 "" yy68: yych = *++YYCURSOR; if(yych == 'N') goto yy65; goto yy2; @@ -817,89 +933,74 @@ yy72: if(yych <= '/') goto yy2; if(yych <= '9') goto yy71; if(yych != ';') goto yy2; goto yy73; -yy73: yych = *++YYCURSOR; +yy73: ++YYCURSOR; goto yy74; yy74: -#line 316 "/usr/src/php5/ext/standard/var_unserializer.re" +#line 392 "/usr/src/php/php_5_0/ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_LONG(*rval, parse_iv(start + 2)); return 1; } -#line 581 "re2c-output.c" +#line 631 "" yy75: yych = *++YYCURSOR; - if(yych <= ','){ - if(yych != '+') goto yy2; - goto yy76; - } else { - if(yych <= '-') goto yy76; - if(yych <= '/') goto yy2; - if(yych <= '9') goto yy77; - goto yy2; - } -yy76: yych = *++YYCURSOR; if(yych <= '/') goto yy2; - if(yych >= ':') goto yy2; + if(yych >= '2') goto yy2; + goto yy76; +yy76: yych = *++YYCURSOR; + if(yych != ';') goto yy2; goto yy77; yy77: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; goto yy78; -yy78: if(yych <= '/') goto yy2; - if(yych <= '9') goto yy77; - if(yych != ';') goto yy2; - goto yy79; -yy79: yych = *++YYCURSOR; - goto yy80; -yy80: -#line 309 "/usr/src/php5/ext/standard/var_unserializer.re" +yy78: +#line 385 "/usr/src/php/php_5_0/ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_BOOL(*rval, parse_iv(start + 2)); return 1; } -#line 614 "re2c-output.c" -yy81: yych = *++YYCURSOR; - goto yy82; -yy82: -#line 302 "/usr/src/php5/ext/standard/var_unserializer.re" +#line 649 "" +yy79: ++YYCURSOR; + goto yy80; +yy80: +#line 378 "/usr/src/php/php_5_0/ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_NULL(*rval); return 1; } -#line 625 "re2c-output.c" -yy83: yych = *++YYCURSOR; +#line 660 "" +yy81: yych = *++YYCURSOR; if(yych <= ','){ if(yych != '+') goto yy2; - goto yy84; + goto yy82; } else { - if(yych <= '-') goto yy84; + if(yych <= '-') goto yy82; if(yych <= '/') goto yy2; - if(yych <= '9') goto yy85; + if(yych <= '9') goto yy83; goto yy2; } -yy84: yych = *++YYCURSOR; +yy82: yych = *++YYCURSOR; if(yych <= '/') goto yy2; if(yych >= ':') goto yy2; - goto yy85; -yy85: ++YYCURSOR; + goto yy83; +yy83: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; - goto yy86; -yy86: if(yych <= '/') goto yy2; - if(yych <= '9') goto yy85; + goto yy84; +yy84: if(yych <= '/') goto yy2; + if(yych <= '9') goto yy83; if(yych != ';') goto yy2; - goto yy87; -yy87: yych = *++YYCURSOR; - goto yy88; -yy88: -#line 281 "/usr/src/php5/ext/standard/var_unserializer.re" + goto yy85; +yy85: ++YYCURSOR; + goto yy86; +yy86: +#line 355 "/usr/src/php/php_5_0/ext/standard/var_unserializer.re" { - int id; + long id; *p = YYCURSOR; if (!var_hash) return 0; @@ -908,6 +1009,8 @@ yy87: yych = *++YYCURSOR; if (id == -1 || var_access(var_hash, id, &rval_ref) != SUCCESS) { return 0; } + + if (*rval == *rval_ref) return 0; if (*rval != NULL) { zval_ptr_dtor(rval); @@ -918,35 +1021,35 @@ yy87: yych = *++YYCURSOR; return 1; } -#line 672 "re2c-output.c" -yy89: yych = *++YYCURSOR; +#line 710 "" +yy87: yych = *++YYCURSOR; if(yych <= ','){ if(yych != '+') goto yy2; - goto yy90; + goto yy88; } else { - if(yych <= '-') goto yy90; + if(yych <= '-') goto yy88; if(yych <= '/') goto yy2; - if(yych <= '9') goto yy91; + if(yych <= '9') goto yy89; goto yy2; } -yy90: yych = *++YYCURSOR; +yy88: yych = *++YYCURSOR; if(yych <= '/') goto yy2; if(yych >= ':') goto yy2; - goto yy91; -yy91: ++YYCURSOR; + goto yy89; +yy89: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; - goto yy92; -yy92: if(yych <= '/') goto yy2; - if(yych <= '9') goto yy91; + goto yy90; +yy90: if(yych <= '/') goto yy2; + if(yych <= '9') goto yy89; if(yych != ';') goto yy2; - goto yy93; -yy93: yych = *++YYCURSOR; - goto yy94; -yy94: -#line 260 "/usr/src/php5/ext/standard/var_unserializer.re" + goto yy91; +yy91: ++YYCURSOR; + goto yy92; +yy92: +#line 334 "/usr/src/php/php_5_0/ext/standard/var_unserializer.re" { - int id; + long id; *p = YYCURSOR; if (!var_hash) return 0; @@ -965,9 +1068,9 @@ yy93: yych = *++YYCURSOR; return 1; } -#line 719 "re2c-output.c" +#line 758 "" } -#line 480 "/usr/src/php5/ext/standard/var_unserializer.re" +#line 591 "/usr/src/php/php_5_0/ext/standard/var_unserializer.re" return 0; diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index 6ae7424b7778..94bbacccc7d7 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -27,7 +27,7 @@ typedef struct { zval *data[VAR_ENTRIES_MAX]; - int used_slots; + long used_slots; void *next; } var_entries; @@ -54,9 +54,33 @@ static inline void var_push(php_unserialize_data_t *var_hashx, zval **rval) var_hash->data[var_hash->used_slots++] = *rval; } +static inline void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval) +{ + var_entries *var_hash = var_hashx->first_dtor, *prev = NULL; + + while (var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) { + prev = var_hash; + var_hash = var_hash->next; + } + + if (!var_hash) { + var_hash = emalloc(sizeof(var_entries)); + var_hash->used_slots = 0; + var_hash->next = 0; + + if (!var_hashx->first_dtor) + var_hashx->first_dtor = var_hash; + else + prev->next = var_hash; + } + + (*rval)->refcount++; + var_hash->data[var_hash->used_slots++] = *rval; +} + PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval **nzval) { - int i; + long i; var_entries *var_hash = var_hashx->first; while (var_hash) { @@ -70,7 +94,7 @@ PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval **n } } -static int var_access(php_unserialize_data_t *var_hashx, int id, zval ***store) +static int var_access(php_unserialize_data_t *var_hashx, long id, zval ***store) { var_entries *var_hash = var_hashx->first; @@ -81,7 +105,7 @@ static int var_access(php_unserialize_data_t *var_hashx, int id, zval ***store) if (!var_hash) return !SUCCESS; - if (id >= var_hash->used_slots) return !SUCCESS; + if (id < 0 || id >= var_hash->used_slots) return !SUCCESS; *store = &var_hash->data[id]; @@ -91,6 +115,7 @@ static int var_access(php_unserialize_data_t *var_hashx, int id, zval ***store) PHPAPI void var_destroy(php_unserialize_data_t *var_hashx) { void *next; + long i; var_entries *var_hash = var_hashx->first; while (var_hash) { @@ -98,6 +123,17 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx) efree(var_hash); var_hash = next; } + + var_hash = var_hashx->first_dtor; + + while (var_hash) { + for (i = 0; i < var_hash->used_slots; i++) { + zval_ptr_dtor(&var_hash->data[i]); + } + next = var_hash->next; + efree(var_hash); + var_hash = next; + } } /* }}} */ @@ -119,10 +155,10 @@ any = [\000-\277]; -static inline int parse_iv2(const char *p, const char **q) +static inline long parse_iv2(const unsigned char *p, const unsigned char **q) { char cursor; - int result = 0; + long result = 0; int neg = 0; switch (*p) { @@ -134,7 +170,7 @@ static inline int parse_iv2(const char *p, const char **q) } while (1) { - cursor = *p; + cursor = (char)*p; if (cursor >= '0' && cursor <= '9') { result = result * 10 + cursor - '0'; } else { @@ -147,18 +183,40 @@ static inline int parse_iv2(const char *p, const char **q) return result; } -static inline int parse_iv(const char *p) +static inline long parse_iv(const unsigned char *p) { return parse_iv2(p, NULL); } -#define UNSERIALIZE_PARAMETER zval **rval, const char **p, const char *max, php_unserialize_data_t *var_hash TSRMLS_DC +/* no need to check for length - re2c already did */ +static inline size_t parse_uiv(const unsigned char *p) +{ + unsigned char cursor; + size_t result = 0; + + if (*p == '+') { + p++; + } + + while (1) { + cursor = *p; + if (cursor >= '0' && cursor <= '9') { + result = result * 10 + (size_t)(cursor - (unsigned char)'0'); + } else { + break; + } + p++; + } + return result; +} + +#define UNSERIALIZE_PARAMETER zval **rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash TSRMLS_DC #define UNSERIALIZE_PASSTHRU rval, p, max, var_hash TSRMLS_CC -static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, int elements) +static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long elements) { while (elements-- > 0) { - zval *key, *data; + zval *key, *data, **old_data; ALLOC_INIT_ZVAL(key); @@ -168,6 +226,12 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, int return 0; } + if (Z_TYPE_P(key) != IS_LONG && Z_TYPE_P(key) != IS_STRING) { + zval_dtor(key); + FREE_ZVAL(key); + return 0; + } + ALLOC_INIT_ZVAL(data); if (!php_var_unserialize(&data, p, max, var_hash TSRMLS_CC)) { @@ -180,16 +244,26 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, int switch (Z_TYPE_P(key)) { case IS_LONG: + if (zend_hash_index_find(ht, Z_LVAL_P(key), (void **)&old_data)==SUCCESS) { + var_push_dtor(var_hash, old_data); + } zend_hash_index_update(ht, Z_LVAL_P(key), &data, sizeof(data), NULL); break; case IS_STRING: + if (zend_hash_find(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&old_data)==SUCCESS) { + var_push_dtor(var_hash, old_data); + } zend_hash_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &data, sizeof(data), NULL); break; - } zval_dtor(key); FREE_ZVAL(key); + + if (elements && *(*p-1) != ';' && *(*p-1) != '}') { + (*p)--; + return 0; + } } return 1; @@ -208,7 +282,7 @@ static inline int finish_nested_data(UNSERIALIZE_PARAMETER) static inline int object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce) { - int elements; + long elements; elements = parse_iv2((*p) + 2, p); @@ -218,7 +292,7 @@ static inline int object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce) return elements; } -static inline int object_common2(UNSERIALIZE_PARAMETER, int elements) +static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) { zval *retval_ptr = NULL; zval fname; @@ -227,7 +301,8 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, int elements) return 0; } - if(Z_OBJCE_PP(rval) != PHP_IC_ENTRY) { + if (Z_OBJCE_PP(rval) != PHP_IC_ENTRY && + zend_hash_exists(&Z_OBJCE_PP(rval)->function_table, "__wakeup", sizeof("__wakeup"))) { INIT_PZVAL(&fname); ZVAL_STRINGL(&fname, "__wakeup", sizeof("__wakeup") - 1, 0); call_user_function_ex(CG(function_table), rval, &fname, &retval_ptr, 0, 0, 1, NULL TSRMLS_CC); @@ -258,7 +333,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) /*!re2c "R:" iv ";" { - int id; + long id; *p = YYCURSOR; if (!var_hash) return 0; @@ -279,7 +354,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) } "r:" iv ";" { - int id; + long id; *p = YYCURSOR; if (!var_hash) return 0; @@ -288,6 +363,8 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) if (id == -1 || var_access(var_hash, id, &rval_ref) != SUCCESS) { return 0; } + + if (*rval == *rval_ref) return 0; if (*rval != NULL) { zval_ptr_dtor(rval); @@ -306,7 +383,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) return 1; } -"b:" iv ";" { +"b:" [01] ";" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_BOOL(*rval, parse_iv(start + 2)); @@ -323,9 +400,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) "d:" ("NAN" | "-"? "INF") ";" { *p = YYCURSOR; INIT_PZVAL(*rval); -#if defined(HAVE_ATOF_ACCEPTS_NAN) && defined(HAVE_ATOF_ACCEPTS_INF) - ZVAL_DOUBLE(*rval, atof(start + 2)); -#else + if (!strncmp(start + 2, "NAN", 3)) { ZVAL_DOUBLE(*rval, php_get_nan()); } else if (!strncmp(start + 2, "INF", 3)) { @@ -333,42 +408,58 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) } else if (!strncmp(start + 2, "-INF", 4)) { ZVAL_DOUBLE(*rval, -php_get_inf()); } -#endif + return 1; } "d:" (iv | nv | nvexp) ";" { *p = YYCURSOR; INIT_PZVAL(*rval); - ZVAL_DOUBLE(*rval, atof(start + 2)); + ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL)); return 1; } "s:" uiv ":" ["] { - int len; + size_t len, maxlen; char *str; - len = parse_iv(start + 2); + len = parse_uiv(start + 2); + maxlen = max - YYCURSOR; + if (maxlen < len) { + *p = start + 2; + return 0; + } - if (len == 0) { - str = empty_string; - } else { - str = estrndup(YYCURSOR, len); + str = (char*)YYCURSOR; + + YYCURSOR += len; + + if (*(YYCURSOR) != '"') { + *p = YYCURSOR; + return 0; } - YYCURSOR += len + 2; + YYCURSOR += 2; *p = YYCURSOR; INIT_PZVAL(*rval); - ZVAL_STRINGL(*rval, str, len, 0); + ZVAL_STRINGL(*rval, str, len, 1); return 1; } "a:" uiv ":" "{" { - int elements = parse_iv(start + 2); - + long elements = parse_iv(start + 2); + /* use iv() not uiv() in order to check data range */ *p = YYCURSOR; + if (elements < 0) { + return 0; + } + + if (elements < 0) { + return 0; + } + INIT_PZVAL(*rval); Z_TYPE_PP(rval) = IS_ARRAY; ALLOC_HASHTABLE(Z_ARRVAL_PP(rval)); @@ -391,9 +482,8 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) } "O:" uiv ":" ["] { - int len; - int elements; - int len2; + size_t len, len2, len3, maxlen; + long elements; char *class_name; zend_class_entry *ce; zend_class_entry **pce; @@ -405,13 +495,35 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) zval *arg_func_name; INIT_PZVAL(*rval); - len2 = len = parse_iv(start + 2); - if (len == 0) + len2 = len = parse_uiv(start + 2); + maxlen = max - YYCURSOR; + if (maxlen < len || len == 0) { + *p = start + 2; return 0; + } + + class_name = (char*)YYCURSOR; - class_name = estrndup(YYCURSOR, len); YYCURSOR += len; + if (*(YYCURSOR) != '"') { + *p = YYCURSOR; + return 0; + } + if (*(YYCURSOR+1) != ':') { + *p = YYCURSOR+1; + return 0; + } + + len3 = strspn(class_name, "0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); + if (len3 != len) + { + *p = YYCURSOR + len3 - len; + return 0; + } + + class_name = estrndup(class_name, len); + do { /* Try to find class directly */ if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) { diff --git a/ext/sybase/php_sybase_db.c b/ext/sybase/php_sybase_db.c index f2c98c76408e..8080b0d67233 100644 --- a/ext/sybase/php_sybase_db.c +++ b/ext/sybase/php_sybase_db.c @@ -1108,9 +1108,11 @@ PHP_FUNCTION(sybase_fetch_object) { php_sybase_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU); if (Z_TYPE_P(return_value)==IS_ARRAY) { - Z_TYPE_P(return_value)=IS_OBJECT; - Z_OBJPROP_P(return_value) = Z_ARRVAL_P(return_value); - Z_OBJCE_P(return_value) = ZEND_STANDARD_CLASS_DEF_PTR; + object_and_properties_init( + return_value, + ZEND_STANDARD_CLASS_DEF_PTR, + Z_ARRVAL_P(return_value) + ); } } /* }}} */ diff --git a/ext/sybase_ct/php_sybase_ct.c b/ext/sybase_ct/php_sybase_ct.c index 43dca5df2a5c..f1cf9f125792 100644 --- a/ext/sybase_ct/php_sybase_ct.c +++ b/ext/sybase_ct/php_sybase_ct.c @@ -118,13 +118,12 @@ static int _clean_invalid_results(list_entry *le TSRMLS_DC) return 0; } - static void _free_sybase_result(sybase_result *result) { int i, j; if (result->data) { - for (i=0; i<(result->store ? result->num_rows : 0); i++) { + for (i = 0; i < (result->store ? result->num_rows : MIN(1, result->num_rows)); i++) { for (j=0; jnum_fields; j++) { zval_dtor(&result->data[i][j]); } @@ -144,10 +143,21 @@ static void _free_sybase_result(sybase_result *result) efree(result); } +/* Forward declaration */ +static int php_sybase_finish_results (sybase_result *result); + static void php_free_sybase_result(zend_rsrc_list_entry *rsrc TSRMLS_DC) { sybase_result *result = (sybase_result *)rsrc->ptr; + /* Check to see if we've read all rows */ + if (result->sybase_ptr && result->sybase_ptr->active_result_index) { + if (result->sybase_ptr->cmd) { + ct_cancel(NULL, result->sybase_ptr->cmd, CS_CANCEL_ALL); + } + php_sybase_finish_results(result); + } + _free_sybase_result(result); } @@ -1042,11 +1052,15 @@ static int php_sybase_finish_results (sybase_result *result) case CS_PARAM_RESULT: case CS_ROW_RESULT: /* Unexpected results, cancel them. */ - case CS_STATUS_RESULT: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Sybase: Unexpected results, cancelling current"); ct_cancel(NULL, result->sybase_ptr->cmd, CS_CANCEL_CURRENT); break; + case CS_STATUS_RESULT: + /* Status result from a stored procedure, cancel it but do not tell user */ + ct_cancel(NULL, result->sybase_ptr->cmd, CS_CANCEL_CURRENT); + break; + default: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Sybase: Unexpected results, cancelling all"); ct_cancel(NULL, result->sybase_ptr->cmd, CS_CANCEL_ALL); @@ -1087,6 +1101,19 @@ static int php_sybase_finish_results (sybase_result *result) return retcode; } +#define RETURN_DOUBLE_VAL(result, buf, length) \ + if ((length - 1) <= EG(precision)) { \ + errno = 0; \ + Z_DVAL(result) = strtod(buf, NULL); \ + if (errno != ERANGE) { \ + Z_TYPE(result) = IS_DOUBLE; \ + } else { \ + ZVAL_STRINGL(&result, buf, length- 1, 1); \ + } \ + } else { \ + ZVAL_STRINGL(&result, buf, length- 1, 1); \ + } + static int php_sybase_fetch_result_row (sybase_result *result, int numrows) { int i, j; @@ -1107,7 +1134,6 @@ static int php_sybase_fetch_result_row (sybase_result *result, int numrows) } */ - /* i= result->num_rows++; */ result->num_rows++; i= result->store ? result->num_rows- 1 : 0; if (i >= result->blocks_initialized*SYBASE_ROWS_BLOCK) { @@ -1117,27 +1143,48 @@ static int php_sybase_fetch_result_row (sybase_result *result, int numrows) result->data[i] = (zval *) safe_emalloc(sizeof(zval), result->num_fields, 0); } - for (j=0; jnum_fields; j++) { + for (j = 0; j < result->num_fields; j++) { + + /* If we are in non-storing mode, free the previous result */ + if (!result->store && result->num_rows > 1 && Z_TYPE(result->data[i][j]) == IS_STRING) { + efree(Z_STRVAL(result->data[i][j])); + } + if (result->indicators[j] == -1) { /* null value */ ZVAL_NULL(&result->data[i][j]); } else { - Z_STRLEN(result->data[i][j]) = result->lengths[j]-1; /* we don't need the NULL in the length */ - Z_STRVAL(result->data[i][j]) = estrndup(result->tmp_buffer[j], result->lengths[j]); - Z_TYPE(result->data[i][j]) = IS_STRING; - switch (result->numerics[j]) { - case 1: - convert_to_long(&result->data[i][j]); + case 1: { + /* This indicates a long */ + ZVAL_LONG(&result->data[i][j], strtol(result->tmp_buffer[j], NULL, 10)); break; - case 2: - convert_to_double(&result->data[i][j]); + } + + case 2: { + /* This indicates a float */ + RETURN_DOUBLE_VAL(result->data[i][j], result->tmp_buffer[j], result->lengths[j]); break; - case 3: - /* This signals we have an integer datatype, but we need to convert to double if we - * overflow. - */ - convert_scalar_to_number(&result->data[i][j] TSRMLS_CC); + } + + case 3: { + /* This indicates either a long or a float, which ever fits */ + errno = 0; + Z_LVAL(result->data[i][j]) = strtol(result->tmp_buffer[j], NULL, 10); + if (errno == ERANGE) { + + /* An overflow occurred, so try to fit it into a double */ + RETURN_DOUBLE_VAL(result->data[i][j], result->tmp_buffer[j], result->lengths[j]); + break; + } + Z_TYPE(result->data[i][j]) = IS_LONG; + break; + } + + default: { + /* This indicates anything else, return it as string */ + ZVAL_STRINGL(&result->data[i][j], result->tmp_buffer[j], result->lengths[j]- 1, 1); break; + } } } } @@ -1280,9 +1327,12 @@ static sybase_result * php_sybase_fetch_result_set (sybase_link *sybase_ptr, int Z_TYPE(result->fields[i]) = result->types[i]; } - retcode= php_sybase_fetch_result_row(result, buffered ? 1 : -1); - if (retcode == CS_FAIL) { - return NULL; + if (buffered) { + retcode = CS_SUCCEED; + } else { + if ((retcode = php_sybase_fetch_result_row(result, -1)) == CS_FAIL) { + return NULL; + } } result->last_retcode = retcode; @@ -1322,9 +1372,14 @@ static void php_sybase_query (INTERNAL_FUNCTION_PARAMETERS, int buffered) if (zend_get_parameters_ex(3, &query, &sybase_link_index, &store_mode)==FAILURE) { RETURN_FALSE; } + if (!buffered) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "cannot use non-storing mode with buffered queries"); + store = 1; + } else { + convert_to_long_ex(store_mode); + store= (Z_LVAL_PP(store_mode) != 0); + } id = -1; - convert_to_long_ex(store_mode); - store= (Z_LVAL_PP(store_mode) != 0); break; default: WRONG_PARAM_COUNT; @@ -1760,19 +1815,23 @@ PHP_FUNCTION(sybase_fetch_object) switch (Z_TYPE_PP(object)) { case IS_OBJECT: - ce= Z_OBJCE_PP(object); + ce = Z_OBJCE_PP(object); break; - default: - convert_to_string_ex(object); - zend_str_tolower(Z_STRVAL_PP(object), Z_STRLEN_PP(object)); - zend_hash_find(EG(class_table), Z_STRVAL_PP(object), Z_STRLEN_PP(object)+1, (void **)&ce); + case IS_NULL: + break; + default: { + zend_class_entry **pce = NULL; - if (!ce) { + convert_to_string_ex(object); + if (zend_lookup_class(Z_STRVAL_PP(object), Z_STRLEN_PP(object), &pce TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Sybase: Class %s has not been declared", Z_STRVAL_PP(object)); - ce= ZEND_STANDARD_CLASS_DEF_PTR; + } else { + ce = *pce; } + } } - + + /* Reset no. of arguments to 1 so that we can use INTERNAL_FUNCTION_PARAM_PASSTHRU */ ht= 1; } @@ -1780,7 +1839,7 @@ PHP_FUNCTION(sybase_fetch_object) if (Z_TYPE_P(return_value)==IS_ARRAY) { object_and_properties_init( return_value, - object ? ce : ZEND_STANDARD_CLASS_DEF_PTR, + ce ? ce : ZEND_STANDARD_CLASS_DEF_PTR, Z_ARRVAL_P(return_value) ); } @@ -1821,11 +1880,11 @@ PHP_FUNCTION(sybase_data_seek) /* Unbuffered ? */ if (result->last_retcode != CS_END_DATA && result->last_retcode != CS_END_RESULTS && Z_LVAL_PP(offset)>=result->num_rows) { - php_sybase_fetch_result_row(result, Z_LVAL_PP(offset)); + php_sybase_fetch_result_row(result, Z_LVAL_PP(offset)+ 1); } if (Z_LVAL_PP(offset)<0 || Z_LVAL_PP(offset)>=result->num_rows) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Bad row offset"); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Bad row offset %ld, must be betweem 0 and %d", Z_LVAL_PP(offset), result->num_rows - 1); RETURN_FALSE; } @@ -1947,11 +2006,6 @@ PHP_FUNCTION(sybase_field_seek) convert_to_long_ex(offset); field_offset = Z_LVAL_PP(offset); - /* Unbuffered ? */ - if (result->last_retcode != CS_END_DATA && result->last_retcode != CS_END_RESULTS && field_offset>=result->num_rows) { - php_sybase_fetch_result_row(result, field_offset); - } - if (field_offset<0 || field_offset >= result->num_fields) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Bad column offset"); RETURN_FALSE; diff --git a/ext/sybase_ct/tests/skipif.inc b/ext/sybase_ct/tests/skipif.inc index 8c07f7e61e3e..3bbc1e8a6246 100644 --- a/ext/sybase_ct/tests/skipif.inc +++ b/ext/sybase_ct/tests/skipif.inc @@ -4,5 +4,5 @@ * $Id$ */ - if (!extension_loaded('sybase_ct')) die('Sybase-CT extension not loaded'); + if (!extension_loaded('sybase_ct')) die('skip Sybase-CT extension not loaded'); ?> diff --git a/ext/sysvmsg/sysvmsg.c b/ext/sysvmsg/sysvmsg.c index 59d3c0ead781..ca80c5916138 100644 --- a/ext/sysvmsg/sysvmsg.c +++ b/ext/sysvmsg/sysvmsg.c @@ -330,10 +330,11 @@ PHP_FUNCTION(msg_receive) /* got it! */ ZVAL_LONG(out_msgtype, messagebuffer->mtype); + RETVAL_TRUE; if (do_unserialize) { php_unserialize_data_t var_hash; zval *tmp = NULL; - const char *p = (const char *) messagebuffer->mtext; + const unsigned char *p = (const unsigned char *) messagebuffer->mtext; MAKE_STD_ZVAL(tmp); PHP_VAR_UNSERIALIZE_INIT(var_hash); @@ -347,7 +348,6 @@ PHP_FUNCTION(msg_receive) } else { ZVAL_STRINGL(out_message, messagebuffer->mtext, result, 1); } - RETVAL_TRUE; } else if (zerrcode) { ZVAL_LONG(zerrcode, errno); } @@ -391,10 +391,33 @@ PHP_FUNCTION(msg_send) message_len = msg_var.len; smart_str_free(&msg_var); } else { - convert_to_string_ex(&message); - messagebuffer = emalloc(sizeof(struct php_msgbuf) + Z_STRLEN_P(message)); - memcpy(messagebuffer->mtext, Z_STRVAL_P(message), Z_STRLEN_P(message) + 1); - message_len = Z_STRLEN_P(message); + char *p; + switch (Z_TYPE_P(message)) { + case IS_STRING: + p = Z_STRVAL_P(message); + message_len = Z_STRLEN_P(message); + break; + + case IS_LONG: + case IS_BOOL: + message_len = spprintf(&p, 0, "%ld", Z_LVAL_P(message)); + break; + + case IS_DOUBLE: + message_len = spprintf(&p, 0, "%f", Z_DVAL_P(message)); + break; + + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Message parameter must be either a string or a number."); + RETURN_FALSE; + } + + messagebuffer = emalloc(sizeof(struct php_msgbuf) + message_len); + memcpy(messagebuffer->mtext, p, message_len + 1); + + if (Z_TYPE_P(message) != IS_STRING) { + efree(p); + } } /* set the message type */ diff --git a/ext/sysvmsg/tests/002.phpt b/ext/sysvmsg/tests/002.phpt new file mode 100644 index 000000000000..e603ed02b5e0 --- /dev/null +++ b/ext/sysvmsg/tests/002.phpt @@ -0,0 +1,23 @@ +--TEST-- +msg_receive() should return false when unserialize() failed +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Warning: msg_receive(): message corrupted in %s002.php on line %d +bool(false) +Done diff --git a/ext/sysvsem/sysvsem.c b/ext/sysvsem/sysvsem.c index d07893095c14..6f5a1f762e84 100644 --- a/ext/sysvsem/sysvsem.c +++ b/ext/sysvsem/sysvsem.c @@ -304,7 +304,7 @@ static void php_sysvsem_semop(INTERNAL_FUNCTION_PARAMETERS, int acquire) break; } - ZEND_FETCH_RESOURCE(sem_ptr, sysvsem_sem *, arg_id, -1, "SysV semphore", php_sysvsem_module.le_sem); + ZEND_FETCH_RESOURCE(sem_ptr, sysvsem_sem *, arg_id, -1, "SysV semaphore", php_sysvsem_module.le_sem); if (!acquire && sem_ptr->count == 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "SysV semaphore %ld (key 0x%x) is not currently acquired", Z_LVAL_PP(arg_id), sem_ptr->key); @@ -364,7 +364,7 @@ PHP_FUNCTION(sem_remove) WRONG_PARAM_COUNT; } - ZEND_FETCH_RESOURCE(sem_ptr, sysvsem_sem *, arg_id, -1, "SysV semphore", php_sysvsem_module.le_sem); + ZEND_FETCH_RESOURCE(sem_ptr, sysvsem_sem *, arg_id, -1, "SysV semaphore", php_sysvsem_module.le_sem); #if HAVE_SEMUN un.buf = &buf; @@ -372,7 +372,7 @@ PHP_FUNCTION(sem_remove) #else if (semctl(sem_ptr->semid, 0, IPC_STAT, NULL) < 0) { #endif - php_error_docref(NULL TSRMLS_CC, E_WARNING, "SysV semphore %ld does not (any longer) exist", Z_LVAL_PP(arg_id)); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "SysV semaphore %ld does not (any longer) exist", Z_LVAL_PP(arg_id)); RETURN_FALSE; } diff --git a/ext/sysvshm/sysvshm.c b/ext/sysvshm/sysvshm.c index 47b979072d74..31254a7eff27 100644 --- a/ext/sysvshm/sysvshm.c +++ b/ext/sysvshm/sysvshm.c @@ -189,7 +189,7 @@ PHP_FUNCTION(shm_detach) convert_to_long_ex(arg_id); shm_list_ptr = (sysvshm_shm *) zend_list_find(Z_LVAL_PP(arg_id), &type); if (!shm_list_ptr || type != php_sysvshm.le_shm) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The parameter is not a valid shm_indentifier"); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "The parameter is not a valid shm_identifier"); RETURN_FALSE; } @@ -217,7 +217,7 @@ PHP_FUNCTION(shm_remove) shm_list_ptr = (sysvshm_shm *) zend_list_find(id, &type); if (!shm_list_ptr) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The parameter is not a valid shm_indentifier"); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "The parameter is not a valid shm_identifier"); RETURN_FALSE; } @@ -318,7 +318,7 @@ PHP_FUNCTION(shm_get_var) PHP_VAR_UNSERIALIZE_INIT(var_hash); if (php_var_unserialize(&return_value, (const char **) &shm_data, shm_data + shm_var->length, &var_hash TSRMLS_CC) != 1) { PHP_VAR_UNSERIALIZE_DESTROY(var_hash); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "variable data in shared memory is corruped"); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "variable data in shared memory is corrupted"); RETURN_FALSE; } PHP_VAR_UNSERIALIZE_DESTROY(var_hash); diff --git a/ext/tidy/php_tidy.h b/ext/tidy/php_tidy.h index c6db213256dc..7ca065936d39 100644 --- a/ext/tidy/php_tidy.h +++ b/ext/tidy/php_tidy.h @@ -40,9 +40,7 @@ extern zend_module_entry tidy_module_entry; #define TIDY_ATTR_ME(name, param) TIDY_METHOD_MAP(name, tam_ ##name, param) PHP_MINIT_FUNCTION(tidy); -PHP_MSHUTDOWN_FUNCTION(tidy); PHP_RINIT_FUNCTION(tidy); -PHP_RSHUTDOWN_FUNCTION(tidy); PHP_MINFO_FUNCTION(tidy); PHP_FUNCTION(tidy_getopt); diff --git a/ext/tidy/tests/005.phpt b/ext/tidy/tests/005.phpt index b8da50721b92..1d3a10c2ffad 100644 --- a/ext/tidy/tests/005.phpt +++ b/ext/tidy/tests/005.phpt @@ -4,7 +4,7 @@ tidy_parse_file() --FILE-- diff --git a/ext/tidy/tests/007.phpt b/ext/tidy/tests/007.phpt index d2fbb2ceb4fd..26867ff3fb27 100644 --- a/ext/tidy/tests/007.phpt +++ b/ext/tidy/tests/007.phpt @@ -6,7 +6,7 @@ Verbose tidy_getopt() tidy.default_config= --FILE-- getopt("tidy-mark")); echo "Current Value of 'error-file': "; diff --git a/ext/tidy/tests/013.phpt b/ext/tidy/tests/013.phpt index 37efa3d69de8..8f1ac94ef4a1 100644 --- a/ext/tidy/tests/013.phpt +++ b/ext/tidy/tests/013.phpt @@ -4,7 +4,7 @@ Parsing a file using constructor --FILE-- true)); + $tidy = new tidy(dirname(__FILE__)."/013.html", array("show-body-only"=>true)); $tidy->cleanRepair(); echo $tidy; diff --git a/ext/tidy/tests/015.phpt b/ext/tidy/tests/015.phpt index 080d3db4aa1c..03018ffa198f 100644 --- a/ext/tidy/tests/015.phpt +++ b/ext/tidy/tests/015.phpt @@ -4,7 +4,7 @@ Passing configuration options through tidy_parse_file(). --FILE-- true)); + $tidy = tidy_parse_file(dirname(__FILE__)."/015.html", array('show-body-only'=>true)); tidy_clean_repair($tidy); echo tidy_get_output($tidy); diff --git a/ext/tidy/tests/016.phpt b/ext/tidy/tests/016.phpt index 660b85e33734..c2fddce6fee3 100644 --- a/ext/tidy/tests/016.phpt +++ b/ext/tidy/tests/016.phpt @@ -4,7 +4,7 @@ Passing configuration file through tidy_parse_file() --FILE-- diff --git a/ext/tidy/tidy.c b/ext/tidy/tidy.c index 8299e0b1f9d1..660f5e5993f8 100644 --- a/ext/tidy/tidy.c +++ b/ext/tidy/tidy.c @@ -295,9 +295,9 @@ zend_module_entry tidy_module_entry = { "tidy", tidy_functions, PHP_MINIT(tidy), - PHP_MSHUTDOWN(tidy), + NULL, PHP_RINIT(tidy), - PHP_RSHUTDOWN(tidy), + NULL, PHP_MINFO(tidy), PHP_TIDY_MODULE_VERSION, STANDARD_MODULE_PROPERTIES @@ -324,7 +324,7 @@ void php_tidy_free(void *buf) void php_tidy_panic(ctmbstr msg) { - TSRMLS_FETCH(); + TSRMLS_FETCH(); php_error_docref(NULL TSRMLS_CC, E_ERROR, "Could not allocate memory for tidy! (Reason: %s)", (char *)msg); } @@ -334,7 +334,7 @@ static int _php_tidy_set_tidy_opt(TidyDoc doc, char *optname, zval *value TSRMLS zval conv = *value; if (!opt) { - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown Tidy Configuration Option '%s'", optname); + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown Tidy Configuration Option '%s'", optname); return FAILURE; } @@ -375,7 +375,7 @@ static int _php_tidy_set_tidy_opt(TidyDoc doc, char *optname, zval *value TSRMLS zval_copy_ctor(&conv); convert_to_long(&conv); } - if (tidyOptSetBool(doc, tidyOptGetId(opt), Z_LVAL(conv))) { + if (tidyOptSetBool(doc, tidyOptGetId(opt), Z_LVAL(conv))) { return SUCCESS; } break; @@ -396,9 +396,9 @@ static void php_tidy_quick_repair(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_fil TidyDoc doc; TidyBuffer *errbuf; zval *config; - - TIDY_SET_CONTEXT; - + + TIDY_SET_CONTEXT; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zsb", &arg1, &arg1_len, &config, &enc, &enc_len, &use_include_path) == FAILURE) { RETURN_FALSE; } @@ -428,15 +428,17 @@ static void php_tidy_quick_repair(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_fil TIDY_SET_DEFAULT_CONFIG(doc); /* We can't use TIDY_APPLY_CONFIG_ZVAL() here, it uses RETURN_FALSE */ - - if(Z_TYPE_P(config) == IS_ARRAY) { - _php_tidy_apply_config_array(doc, HASH_OF(config) TSRMLS_CC); - } else { - convert_to_string_ex(&config); - TIDY_SAFE_MODE_CHECK(Z_STRVAL_P(config)); - if (tidyLoadConfig(doc, Z_STRVAL_P(config)) < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not load configuration file '%s'", Z_STRVAL_P(config)); - RETVAL_FALSE; + + if (ZEND_NUM_ARGS() > 1) { + if(Z_TYPE_P(config) == IS_ARRAY) { + _php_tidy_apply_config_array(doc, HASH_OF(config) TSRMLS_CC); + } else { + convert_to_string_ex(&config); + TIDY_SAFE_MODE_CHECK(Z_STRVAL_P(config)); + if (tidyLoadConfig(doc, Z_STRVAL_P(config)) < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not load configuration file '%s'", Z_STRVAL_P(config)); + RETVAL_FALSE; + } } } @@ -497,13 +499,15 @@ static void tidy_object_free_storage(void *object TSRMLS_DC) zend_hash_destroy(intern->std.properties); FREE_HASHTABLE(intern->std.properties); - intern->ptdoc->ref_count--; + if (intern->ptdoc) { + intern->ptdoc->ref_count--; - if (intern->ptdoc->ref_count <= 0) { - tidyBufFree(intern->ptdoc->errbuf); - efree(intern->ptdoc->errbuf); - tidyRelease(intern->ptdoc->doc); - efree(intern->ptdoc); + if (intern->ptdoc->ref_count <= 0) { + tidyBufFree(intern->ptdoc->errbuf); + efree(intern->ptdoc->errbuf); + tidyRelease(intern->ptdoc->doc); + efree(intern->ptdoc); + } } efree(object); @@ -600,7 +604,7 @@ static zval * tidy_instanciate(zend_class_entry *pce, zval *object TSRMLS_DC) if (!object) { ALLOC_ZVAL(object); } - + Z_TYPE_P(object) = IS_OBJECT; object_init_ex(object, pce); object->refcount = 1; @@ -859,7 +863,7 @@ static int _php_tidy_apply_config_array(TidyDoc doc, HashTable *ht_options TSRML php_error_docref(NULL TSRMLS_CC, E_ERROR, "Could not retrieve key from option array"); return FAILURE; } - + if(opt_name) { _php_tidy_set_tidy_opt(doc, opt_name, *opt_val TSRMLS_CC); opt_name = NULL; @@ -895,12 +899,12 @@ static int php_tidy_parse_string(PHPTidyObj *obj, char *string, char *enc TSRMLS static void tidy_globals_ctor(void *global TSRMLS_DC) { - + } static void tidy_globals_dtor(void *global TSRMLS_DC) { - + } PHP_MINIT_FUNCTION(tidy) @@ -925,12 +929,6 @@ PHP_MINIT_FUNCTION(tidy) return SUCCESS; } - -PHP_MSHUTDOWN_FUNCTION(tidy) -{ - return SUCCESS; -} - PHP_RINIT_FUNCTION(tidy) { if (INI_BOOL("tidy.clean_output") == TRUE) { @@ -942,11 +940,6 @@ PHP_RINIT_FUNCTION(tidy) return SUCCESS; } -PHP_RSHUTDOWN_FUNCTION(tidy) -{ - return SUCCESS; -} - PHP_MINFO_FUNCTION(tidy) { php_info_print_table_start(); @@ -1015,8 +1008,8 @@ PHP_FUNCTION(tidy_parse_string) zval *options = NULL; PHPTidyObj *obj; - - TIDY_SET_CONTEXT; + + TIDY_SET_CONTEXT; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zs", &input, &input_len, &options, &enc, &enc_len) == FAILURE) { RETURN_FALSE; @@ -1076,7 +1069,7 @@ PHP_FUNCTION(tidy_parse_file) zval *options = NULL; PHPTidyObj *obj; - TIDY_SET_CONTEXT; + TIDY_SET_CONTEXT; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zsb", &inputfile, &input_len, &options, &enc, &enc_len, &use_include_path) == FAILURE) { @@ -1088,7 +1081,7 @@ PHP_FUNCTION(tidy_parse_file) if (!(contents = php_tidy_file_to_mem(inputfile, use_include_path TSRMLS_CC))) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot Load '%s' into memory %s", inputfile, (use_include_path) ? "(Using include path)" : ""); - return; + RETURN_FALSE; } TIDY_APPLY_CONFIG_ZVAL(obj->ptdoc->doc, options); @@ -1098,7 +1091,7 @@ PHP_FUNCTION(tidy_parse_file) INIT_ZVAL(*return_value); RETVAL_FALSE; } - + efree(contents); } /* }}} */ @@ -1122,7 +1115,7 @@ PHP_FUNCTION(tidy_clean_repair) Repair a string using an optionally provided configuration file */ PHP_FUNCTION(tidy_repair_string) { - TIDY_SET_CONTEXT; + TIDY_SET_CONTEXT; php_tidy_quick_repair(INTERNAL_FUNCTION_PARAM_PASSTHRU, FALSE); } /* }}} */ @@ -1131,7 +1124,7 @@ PHP_FUNCTION(tidy_repair_string) Repair a file using an optionally provided configuration file */ PHP_FUNCTION(tidy_repair_file) { - TIDY_SET_CONTEXT; + TIDY_SET_CONTEXT; php_tidy_quick_repair(INTERNAL_FUNCTION_PARAM_PASSTHRU, TRUE); } /* }}} */ @@ -1155,8 +1148,8 @@ PHP_FUNCTION(tidy_diagnose) Get release date (version) for Tidy library */ PHP_FUNCTION(tidy_get_release) { - TIDY_SET_CONTEXT; - + TIDY_SET_CONTEXT; + if (ZEND_NUM_ARGS()) { WRONG_PARAM_COUNT; } @@ -1295,7 +1288,7 @@ PHP_FUNCTION(tidy_getopt) TidyOption opt; TidyOptionType optt; - TIDY_SET_CONTEXT; + TIDY_SET_CONTEXT; if (object) { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &optname, &optname_len) == FAILURE) { @@ -1310,7 +1303,7 @@ PHP_FUNCTION(tidy_getopt) obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC); opt = tidyGetOptionByName(obj->ptdoc->doc, optname); - + if (!opt) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown Tidy Configuration Option '%s'", optname); RETURN_FALSE; @@ -1352,7 +1345,7 @@ TIDY_DOC_METHOD(__construct) zval *options = NULL; PHPTidyObj *obj; - TIDY_SET_CONTEXT; + TIDY_SET_CONTEXT; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|szsb", &inputfile, &input_len, &options, &enc, &enc_len, &use_include_path) == FAILURE) { @@ -1361,20 +1354,18 @@ TIDY_DOC_METHOD(__construct) obj = (PHPTidyObj *)zend_object_store_get_object(object TSRMLS_CC); - if(inputfile) { - - if (!(contents = php_tidy_file_to_mem(inputfile, use_include_path TSRMLS_CC))) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot Load '%s' into memory %s", inputfile, (use_include_path) ? "(Using include path)" : ""); - return; - } - - TIDY_APPLY_CONFIG_ZVAL(obj->ptdoc->doc, options); - - php_tidy_parse_string(obj, contents, enc TSRMLS_CC); - - efree(contents); - } - + if (inputfile) { + if (!(contents = php_tidy_file_to_mem(inputfile, use_include_path TSRMLS_CC))) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot Load '%s' into memory %s", inputfile, (use_include_path) ? "(Using include path)" : ""); + return; + } + + TIDY_APPLY_CONFIG_ZVAL(obj->ptdoc->doc, options); + + php_tidy_parse_string(obj, contents, enc TSRMLS_CC); + + efree(contents); + } } TIDY_DOC_METHOD(parseFile) @@ -1384,10 +1375,10 @@ TIDY_DOC_METHOD(parseFile) zend_bool use_include_path = 0; char *contents; zval *options = NULL; - PHPTidyObj *obj; - - TIDY_SET_CONTEXT; - + PHPTidyObj *obj; + + TIDY_SET_CONTEXT; + obj = (PHPTidyObj *)zend_object_store_get_object(object TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zsb", &inputfile, &input_len, @@ -1417,8 +1408,8 @@ TIDY_DOC_METHOD(parseString) int input_len, enc_len = 0; zval *options = NULL; PHPTidyObj *obj; - - TIDY_SET_CONTEXT; + + TIDY_SET_CONTEXT; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zs", &input, &input_len, &options, &enc, &enc_len) == FAILURE) { RETURN_FALSE; @@ -1440,7 +1431,7 @@ TIDY_DOC_METHOD(parseString) Returns a TidyNode Object representing the root of the tidy parse tree */ PHP_FUNCTION(tidy_get_root) { - TIDY_SET_CONTEXT; + TIDY_SET_CONTEXT; php_tidy_create_node(INTERNAL_FUNCTION_PARAM_PASSTHRU, is_root_node); } /* }}} */ @@ -1449,7 +1440,7 @@ PHP_FUNCTION(tidy_get_root) Returns a TidyNode Object starting from the tag of the tidy parse tree */ PHP_FUNCTION(tidy_get_html) { - TIDY_SET_CONTEXT; + TIDY_SET_CONTEXT; php_tidy_create_node(INTERNAL_FUNCTION_PARAM_PASSTHRU, is_html_node); } /* }}} */ @@ -1458,7 +1449,7 @@ PHP_FUNCTION(tidy_get_html) Returns a TidyNode Object starting from the tag of the tidy parse tree */ PHP_FUNCTION(tidy_get_head) { - TIDY_SET_CONTEXT; + TIDY_SET_CONTEXT; php_tidy_create_node(INTERNAL_FUNCTION_PARAM_PASSTHRU, is_head_node); } /* }}} */ @@ -1467,19 +1458,19 @@ PHP_FUNCTION(tidy_get_head) Returns a TidyNode Object starting from the tag of the tidy parse tree */ PHP_FUNCTION(tidy_get_body) { - TIDY_SET_CONTEXT; + TIDY_SET_CONTEXT; php_tidy_create_node(INTERNAL_FUNCTION_PARAM_PASSTHRU, is_body_node); } /* }}} */ -/* {{{ proto void tidy_node::tidy_node() +/* {{{ proto tidyNode::tidyNode() Constructor. */ TIDY_NODE_METHOD(__construct) { } /* }}} */ -/* {{{ proto boolean tidy_node::hasChildren() +/* {{{ proto boolean tidyNode::hasChildren() Returns true if this node has children */ TIDY_NODE_METHOD(hasChildren) { @@ -1493,7 +1484,7 @@ TIDY_NODE_METHOD(hasChildren) } /* }}} */ -/* {{{ proto boolean tidy_node::hasSiblings() +/* {{{ proto boolean tidyNode::hasSiblings() Returns true if this node has siblings */ TIDY_NODE_METHOD(hasSiblings) { @@ -1507,7 +1498,7 @@ TIDY_NODE_METHOD(hasSiblings) } /* }}} */ -/* {{{ proto boolean tidy_node::isComment() +/* {{{ proto boolean tidyNode::isComment() Returns true if this node represents a comment */ TIDY_NODE_METHOD(isComment) { @@ -1521,7 +1512,7 @@ TIDY_NODE_METHOD(isComment) } /* }}} */ -/* {{{ proto boolean tidy_node::isHtml() +/* {{{ proto boolean tidyNode::isHtml() Returns true if this node is part of a HTML document */ TIDY_NODE_METHOD(isHtml) { @@ -1535,7 +1526,7 @@ TIDY_NODE_METHOD(isHtml) } /* }}} */ -/* {{{ proto boolean tidy_node::isXhtml() +/* {{{ proto boolean tidyNode::isXhtml() Returns true if this node is part of a XHTML document */ TIDY_NODE_METHOD(isXhtml) { @@ -1549,7 +1540,7 @@ TIDY_NODE_METHOD(isXhtml) } /* }}} */ -/* {{{ proto boolean tidy_node::isXml() +/* {{{ proto boolean tidyNode::isXml() Returns true if this node is part of a XML document */ TIDY_NODE_METHOD(isXml) { @@ -1563,7 +1554,7 @@ TIDY_NODE_METHOD(isXml) } /* }}} */ -/* {{{ proto boolean tidy_node::isText() +/* {{{ proto boolean tidyNode::isText() Returns true if this node represents text (no markup) */ TIDY_NODE_METHOD(isText) { @@ -1577,7 +1568,7 @@ TIDY_NODE_METHOD(isText) } /* }}} */ -/* {{{ proto boolean tidy_node::isJste() +/* {{{ proto boolean tidyNode::isJste() Returns true if this node is JSTE */ TIDY_NODE_METHOD(isJste) { @@ -1591,7 +1582,7 @@ TIDY_NODE_METHOD(isJste) } /* }}} */ -/* {{{ proto boolean tidy_node::isAsp() +/* {{{ proto boolean tidyNode::isAsp() Returns true if this node is ASP */ TIDY_NODE_METHOD(isAsp) { @@ -1605,7 +1596,7 @@ TIDY_NODE_METHOD(isAsp) } /* }}} */ -/* {{{ proto boolean tidy_node::isPhp() +/* {{{ proto boolean tidyNode::isPhp() Returns true if this node is PHP */ TIDY_NODE_METHOD(isPhp) { diff --git a/ext/tokenizer/tokenizer.c b/ext/tokenizer/tokenizer.c index 292603a7cae9..5c4ad3e9bc7f 100644 --- a/ext/tokenizer/tokenizer.c +++ b/ext/tokenizer/tokenizer.c @@ -88,7 +88,7 @@ struct yy_buffer_state #include "zend.h" #include "zend_language_scanner.h" -#include "zend_language_parser.h" +#include #define zendtext LANG_SCNG(yy_text) #define zendleng LANG_SCNG(yy_leng) diff --git a/ext/wddx/tests/wddx.xml b/ext/wddx/tests/wddx.xml index 46ad58d66418..00857095c980 100644 --- a/ext/wddx/tests/wddx.xml +++ b/ext/wddx/tests/wddx.xml @@ -20,7 +20,7 @@ 1980-06-12T04:32:12+00 - 2040-06-12T04:32:12 + 2040-06-12T04:32:12+00 diff --git a/ext/wddx/wddx.c b/ext/wddx/wddx.c index 33dbfbd9fd1e..682691bcdb6d 100644 --- a/ext/wddx/wddx.c +++ b/ext/wddx/wddx.c @@ -223,7 +223,7 @@ static void release_wddx_packet_rsrc(zend_rsrc_list_entry *rsrc TSRMLS_DC) #include "ext/session/php_session.h" -#if HAVE_PHP_SESSION +#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION) /* {{{ PS_SERIALIZER_ENCODE_FUNC */ PS_SERIALIZER_ENCODE_FUNC(wddx) @@ -302,7 +302,7 @@ PHP_MINIT_FUNCTION(wddx) { le_wddx = zend_register_list_destructors_ex(release_wddx_packet_rsrc, NULL, "wddx", module_number); -#if HAVE_PHP_SESSION +#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION) php_session_register_serializer("wddx", PS_SERIALIZER_ENCODE_NAME(wddx), PS_SERIALIZER_DECODE_NAME(wddx)); @@ -317,7 +317,7 @@ PHP_MINIT_FUNCTION(wddx) PHP_MINFO_FUNCTION(wddx) { php_info_print_table_start(); -#if HAVE_PHP_SESSION +#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION) php_info_print_table_header(2, "WDDX Support", "enabled" ); php_info_print_table_row(2, "WDDX Session Serializer", "enabled" ); #else @@ -522,7 +522,10 @@ static void php_wddx_serialize_object(wddx_packet *packet, zval *obj) continue; if (zend_hash_get_current_key_ex(HASH_OF(obj), &key, &key_len, &idx, 0, NULL) == HASH_KEY_IS_STRING) { - php_wddx_serialize_var(packet, *ent, key, key_len TSRMLS_CC); + char *class_name, *prop_name; + + zend_unmangle_property_name(key, &class_name, &prop_name); + php_wddx_serialize_var(packet, *ent, prop_name, strlen(prop_name)+1 TSRMLS_CC); } else { key_len = sprintf(tmp_buf, "%ld", idx); php_wddx_serialize_var(packet, *ent, tmp_buf, key_len TSRMLS_CC); @@ -617,6 +620,7 @@ void php_wddx_serialize_var(wddx_packet *packet, zval *var, char *name, int name char tmp_buf[WDDX_BUF_LEN]; char *name_esc; int name_esc_len; + HashTable *ht; if (name) { name_esc = php_escape_html_entities(name, name_len, &name_esc_len, 0, ENT_QUOTES, NULL TSRMLS_CC); @@ -644,11 +648,25 @@ void php_wddx_serialize_var(wddx_packet *packet, zval *var, char *name, int name break; case IS_ARRAY: + ht = Z_ARRVAL_P(var); + if (ht->nApplyCount > 1) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "WDDX doesn't support circular references"); + return; + } + ht->nApplyCount++; php_wddx_serialize_array(packet, var); + ht->nApplyCount--; break; case IS_OBJECT: - php_wddx_serialize_object(packet, var); + ht = Z_OBJPROP_P(var); + if (ht->nApplyCount > 1) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "WDDX doesn't support circular references"); + return; + } + ht->nApplyCount++; + php_wddx_serialize_object(packet, var); + ht->nApplyCount--; break; } @@ -972,6 +990,13 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name) /* Clean up class name var entry */ zval_ptr_dtor(&ent1->data); + } else if (Z_TYPE_P(ent2->data) == IS_OBJECT) { + zend_class_entry *old_scope = EG(scope); + + EG(scope) = Z_OBJCE_P(ent2->data); + ent1->data->refcount--; + add_property_zval(ent2->data, ent1->varname, ent1->data); + EG(scope) = old_scope; } else zend_hash_update(target_hash, ent1->varname, strlen(ent1->varname)+1, diff --git a/ext/xml/compat.c b/ext/xml/compat.c index 396393ee51b5..c2a6dfebd353 100644 --- a/ext/xml/compat.c +++ b/ext/xml/compat.c @@ -76,6 +76,14 @@ _start_element_handler_ns(void *user, const xmlChar *name, const xmlChar *prefix int z = 0; int y = 0; + if (nb_namespaces > 0 && parser->h_start_ns != NULL) { + for (i = 0; i < nb_namespaces; i += 1) { + parser->h_start_ns(parser->user, (const XML_Char *) namespaces[y], (const XML_Char *) namespaces[y+1]); + y += 2; + } + y = 0; + } + if (parser->h_start_element == NULL) { return; } @@ -88,7 +96,7 @@ _start_element_handler_ns(void *user, const xmlChar *name, const xmlChar *prefix for (i = 0; i < nb_attributes; i += 1) { if (attributes[y+1] != NULL) { - _qualify_namespace(parser, attributes[y] , attributes[2], &qualified_name_attr); + _qualify_namespace(parser, attributes[y] , attributes[y + 2], &qualified_name_attr); } else { qualified_name_attr = xmlStrdup(attributes[y]); } @@ -211,12 +219,12 @@ _notation_decl_handler(void *user, const xmlChar *notation, const xmlChar *sys_i static void _build_comment(const xmlChar *data, int data_len, xmlChar **comment, int *comment_len) { - *comment_len = data_len + 6; + *comment_len = data_len + 7; *comment = xmlMalloc(*comment_len + 1); - memcpy(*comment, "<--", 3); - memcpy(*comment + 3, data, data_len); - memcpy(*comment + 3 + data_len, "-->", 3); + memcpy(*comment, "", 3); (*comment)[*comment_len] = '\0'; } @@ -247,33 +255,55 @@ _build_entity(const xmlChar *name, int len, xmlChar **entity, int *entity_len) (*entity)[*entity_len] = '\0'; } -static xmlEntityPtr -_get_entity(void *user, const xmlChar *name) +static void +_external_entity_ref_handler(void *user, const xmlChar *names, int type, const xmlChar *sys_id, const xmlChar *pub_id, xmlChar *content) { XML_Parser parser = (XML_Parser) user; - if (parser->h_default) { - xmlChar *entity; - int len; - - _build_entity(name, xmlStrlen(name), &entity, &len); - parser->h_default(parser->user, (const xmlChar *) entity, len); - xmlFree(entity); + if (parser->h_external_entity_ref == NULL) { + return; } - return NULL; + parser->h_external_entity_ref(parser, names, "", sys_id, pub_id); } -static void -_external_entity_ref_handler(void *user, const xmlChar *names, int type, const xmlChar *sys_id, const xmlChar *pub_id, xmlChar *content) +static xmlEntityPtr +_get_entity(void *user, const xmlChar *name) { XML_Parser parser = (XML_Parser) user; - - if (parser->h_external_entity_ref == NULL) { - return; + xmlEntityPtr ret = NULL; + + if (parser->parser->inSubset == 0) { + ret = xmlGetPredefinedEntity(name); + if (ret == NULL) + ret = xmlGetDocEntity(parser->parser->myDoc, name); + + if (ret == NULL || (parser->parser->instate != XML_PARSER_ENTITY_VALUE && parser->parser->instate != XML_PARSER_ATTRIBUTE_VALUE)) { + if (ret == NULL || ret->etype == XML_INTERNAL_GENERAL_ENTITY || ret->etype == XML_INTERNAL_PARAMETER_ENTITY || ret->etype == XML_INTERNAL_PREDEFINED_ENTITY) { + /* Predefined entities will expand unless no cdata handler is present */ + if (parser->h_default && ! (ret && ret->etype == XML_INTERNAL_PREDEFINED_ENTITY && parser->h_cdata)) { + xmlChar *entity; + int len; + + _build_entity(name, xmlStrlen(name), &entity, &len); + parser->h_default(parser->user, (const xmlChar *) entity, len); + xmlFree(entity); + } else { + /* expat will not expand internal entities if default handler is present otherwise + it will expand and pass them to cdata handler */ + if (parser->h_cdata && ret) { + parser->h_cdata(parser->user, ret->content, xmlStrlen(ret->content)); + } + } + } else { + if (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) { + _external_entity_ref_handler(user, ret->name, ret->etype, ret->SystemID, ret->ExternalID, NULL); + } + } + } } - parser->h_external_entity_ref(parser, names, "", sys_id, pub_id); + return ret; } static xmlSAXHandler @@ -284,7 +314,7 @@ php_xml_compat_handlers = { NULL, /* hasExternalSubset */ NULL, /* resolveEntity */ _get_entity, /* getEntity */ - _external_entity_ref_handler, /* entityDecl */ + NULL, /* entityDecl */ _notation_decl_handler, NULL, /* attributeDecl */ NULL, /* elementDecl */ @@ -305,9 +335,10 @@ php_xml_compat_handlers = { NULL, /* getParameterEntity */ _cdata_handler, /* cdataBlock */ NULL, /* externalSubset */ - 1 -#if LIBXML_VERSION >= 20600 - , +#if LIBXML_VERSION < 20600 + 1, +#else + XML_SAX2_MAGIC, NULL, _start_element_handler_ns, _end_element_handler_ns, @@ -348,16 +379,27 @@ XML_ParserCreate_MM(const XML_Char *encoding, const XML_Memory_Handling_Suite *m } if (encoding != NULL) { parser->parser->encoding = xmlStrdup(encoding); +#if LIBXML_VERSION <= 20617 + /* for older versions of libxml2, allow correct detection of + * charset in documents with a BOM: */ } else { parser->parser->charset = XML_CHAR_ENCODING_NONE; +#endif } parser->parser->replaceEntities = 1; + parser->parser->wellFormed = 0; if (sep != NULL) { parser->use_namespace = 1; #if LIBXML_VERSION >= 20600 parser->parser->sax2 = 1; #endif parser->_ns_seperator = xmlStrdup(sep); +#if LIBXML_VERSION >= 20600 + } else { + /* Reset flag as XML_SAX2_MAGIC is needed for xmlCreatePushParserCtxt + so must be set in the handlers */ + parser->parser->sax->initialized = 1; +#endif } return parser; } @@ -440,6 +482,33 @@ XML_Parse(XML_Parser parser, const XML_Char *data, int data_len, int is_final) { #if LIBXML_VERSION >= 20600 int error; +#endif + +/* The following is a hack to keep BC with PHP 4 while avoiding +the inifite loop in libxml <= 2.6.17 which occurs when no encoding +has been defined and none can be detected */ +#if LIBXML_VERSION <= 20617 + if (parser->parser->charset == XML_CHAR_ENCODING_NONE) { + if (data_len >= 4 || (parser->parser->input->buf->buffer->use + data_len >= 4)) { + xmlChar start[4]; + int char_count; + + char_count = parser->parser->input->buf->buffer->use; + if (char_count > 4) { + char_count = 4; + } + + memcpy(start, parser->parser->input->buf->buffer->content, (size_t)char_count); + memcpy(start + char_count, data, (size_t)(4 - char_count)); + + if (xmlDetectCharEncoding(&start[0], 4) == XML_CHAR_ENCODING_NONE) { + parser->parser->charset = XML_CHAR_ENCODING_UTF8; + } + } + } +#endif + +#if LIBXML_VERSION >= 20600 error = xmlParseChunk(parser->parser, data, data_len, is_final); if (!error) { return 1; @@ -463,9 +532,9 @@ const XML_Char *error_mapping[] = { "No error", "Internal error", "No memory", - "XML_ERR_DOCUMENT_START", + "Invalid document start", "Empty document", - "XML_ERR_DOCUMENT_END", + "Invalid document end", "Invalid hexadecimal character reference", "Invalid decimal character reference", "Invalid character reference", @@ -478,14 +547,14 @@ const XML_Char *error_mapping[] = { "XML_ERR_ENTITYREF_IN_PROLOG", "XML_ERR_ENTITYREF_IN_EPILOG", "XML_ERR_ENTITYREF_IN_DTD", - "XML_ERR_PEREF_AT_EOF", - "XML_ERR_PEREF_IN_PROLOG", - "XML_ERR_PEREF_IN_EPILOG", - "XML_ERR_PEREF_IN_INT_SUBSET", + "PEReference at end of document", + "PEReference in prolog", + "PEReference in epilog", + "PEReference: forbidden within markup decl in internal subset", "XML_ERR_ENTITYREF_NO_NAME", - "XML_ERR_ENTITYREF_SEMICOL_MISSING", - "XML_ERR_PEREF_NO_NAME", - "XML_ERR_PEREF_SEMICOL_MISSING", + "EntityRef: expecting ';'", + "PEReference: no name", + "PEReference: expecting ';'", "Undeclared entity error", "Undeclared entity warning", "Unparsed Entity", @@ -493,82 +562,82 @@ const XML_Char *error_mapping[] = { "XML_ERR_ENTITY_IS_PARAMETER", "Unknown encoding", "Unsupported encoding", - "XML_ERR_STRING_NOT_STARTED", - "XML_ERR_STRING_NOT_CLOSED", + "String not started expecting ' or \"", + "String not closed expecting \" or '", "Namespace declaration error", - "XML_ERR_ENTITY_NOT_STARTED", - "XML_ERR_ENTITY_NOT_FINISHED", - "XML_ERR_LT_IN_ATTRIBUTE", - "XML_ERR_ATTRIBUTE_NOT_STARTED", - "XML_ERR_ATTRIBUTE_NOT_FINISHED", - "XML_ERR_ATTRIBUTE_WITHOUT_VALUE", - "XML_ERR_ATTRIBUTE_REDEFINED", - "XML_ERR_LITERAL_NOT_STARTED", - "XML_ERR_LITERAL_NOT_FINISHED", + "EntityValue: \" or ' expected", + "EntityValue: \" or ' expected", + "< in attribute", + "Attribute not started", + "Attribute not finished", + "Attribute without value", + "Attribute redefined", + "SystemLiteral \" or ' expected", + "SystemLiteral \" or ' expected", /* "XML_ERR_COMMENT_NOT_STARTED", <= eliminated on purpose */ - "XML_ERR_COMMENT_NOT_FINISHED", - "XML_ERR_PI_NOT_STARTED", - "XML_ERR_PI_NOT_FINISHED", - "XML_ERR_NOTATION_NOT_STARTED", - "XML_ERR_NOTATION_NOT_FINISHED", - "XML_ERR_ATTLIST_NOT_STARTED", - "XML_ERR_ATTLIST_NOT_FINISHED", - "XML_ERR_MIXED_NOT_STARTED", + "Comment not finished", + "Processing Instruction not started", + "Processing Instruction not finished", + "NOTATION: Name expected here", + "'>' required to close NOTATION declaration", + "'(' required to start ATTLIST enumeration", + "'(' required to start ATTLIST enumeration", + "MixedContentDecl : '|' or ')*' expected", "XML_ERR_MIXED_NOT_FINISHED", - "XML_ERR_ELEMCONTENT_NOT_STARTED", - "XML_ERR_ELEMCONTENT_NOT_FINISHED", - "XML_ERR_XMLDECL_NOT_STARTED", - "XML_ERR_XMLDECL_NOT_FINISHED", + "ELEMENT in DTD not started", + "ELEMENT in DTD not finished", + "XML declaration not started", + "XML declaration not finished", "XML_ERR_CONDSEC_NOT_STARTED", - "XML_ERR_CONDSEC_NOT_FINISHED", - "XML_ERR_EXT_SUBSET_NOT_FINISHED", - "XML_ERR_DOCTYPE_NOT_FINISHED", - "XML_ERR_MISPLACED_CDATA_END", - "XML_ERR_CDATA_NOT_FINISHED", - "XML_ERR_RESERVED_XML_NAME", - "XML_ERR_SPACE_REQUIRED", + "XML conditional section not closed", + "Content error in the external subset", + "DOCTYPE not finished", + "Sequence ']]>' not allowed in content", + "CDATA not finished", + "Reserved XML Name", + "Space required", "XML_ERR_SEPARATOR_REQUIRED", - "XML_ERR_NMTOKEN_REQUIRED", + "NmToken expected in ATTLIST enumeration", "XML_ERR_NAME_REQUIRED", - "XML_ERR_PCDATA_REQUIRED", - "XML_ERR_URI_REQUIRED", - "XML_ERR_PUBID_REQUIRED", - "XML_ERR_LT_REQUIRED", - "XML_ERR_GT_REQUIRED", - "XML_ERR_LTSLASH_REQUIRED", - "XML_ERR_EQUAL_REQUIRED", - "XML_ERR_TAG_NAME_MISMATCH", - "XML_ERR_TAG_NOT_FINISHED", - "XML_ERR_STANDALONE_VALUE", - "XML_ERR_ENCODING_NAME", - "XML_ERR_HYPHEN_IN_COMMENT", + "MixedContentDecl : '#PCDATA' expected", + "SYSTEM or PUBLIC, the URI is missing", + "PUBLIC, the Public Identifier is missing", + "< required", + "> required", + "= (int)sizeof(error_mapping)) { + if (code < 0 || code >= (int)(sizeof(error_mapping) / sizeof(error_mapping[0]))) { return "Unknown"; } return error_mapping[code]; diff --git a/ext/xml/config.m4 b/ext/xml/config.m4 index 72c98ed8145f..0d4d553a9599 100644 --- a/ext/xml/config.m4 +++ b/ext/xml/config.m4 @@ -13,31 +13,37 @@ fi PHP_ARG_WITH(libexpat-dir, libexpat install dir, [ --with-libexpat-dir=DIR XML: libexpat install prefix (deprecated)], no, no) -if test "$PHP_XML" != "no" && test "$PHP_LIBXML" != "no" -o "$PHP_LIBEXPAT_DIR" != "no"; then +if test "$PHP_XML" != "no"; then + dnl - dnl Default to libxml2. + dnl Default to libxml2 if --with-libexpat-dir is not used. dnl - PHP_SETUP_LIBXML(XML_SHARED_LIBADD, [ - xml_extra_sources="compat.c" - ], [ - if test "$PHP_LIBEXPAT_DIR" = "no"; then - AC_MSG_ERROR([xml2-config not found. Use --with-libxml-dir=]) + if test "$PHP_LIBEXPAT_DIR" = "no"; then + + if test "$PHP_LIBXML" = "no"; then + AC_MSG_ERROR([XML extension requires LIBXML extension, add --enable-libxml]) fi - ]) + + PHP_SETUP_LIBXML(XML_SHARED_LIBADD, [ + xml_extra_sources="compat.c" + ], [ + AC_MSG_ERROR([xml2-config not found. Use --with-libxml-dir=]) + ]) + fi dnl dnl Check for expat only if --with-libexpat-dir is used. dnl if test "$PHP_LIBEXPAT_DIR" != "no"; then for i in $PHP_XML $PHP_LIBEXPAT_DIR; do - if test -f "$i/lib/libexpat.a" -o -f "$i/lib/libexpat.$SHLIB_SUFFIX_NAME"; then + if test -f "$i/lib/libexpat.a" || test -f "$i/lib/libexpat.$SHLIB_SUFFIX_NAME"; then EXPAT_DIR=$i break fi done if test -z "$EXPAT_DIR"; then - AC_MSG_ERROR(not found. Please reinstall the expat distribution.) + AC_MSG_ERROR([not found. Please reinstall the expat distribution.]) fi PHP_ADD_INCLUDE($EXPAT_DIR/include) diff --git a/ext/xml/php_xml.h b/ext/xml/php_xml.h index 1864937b04f8..d8e71c18f0c1 100644 --- a/ext/xml/php_xml.h +++ b/ext/xml/php_xml.h @@ -90,6 +90,7 @@ typedef struct { char **ltags; int lastwasopen; int skipwhite; + int isparsing; XML_Char *baseURI; } xml_parser; diff --git a/ext/xml/tests/bug32001.phpt b/ext/xml/tests/bug32001.phpt new file mode 100644 index 000000000000..57b0d130c8f9 --- /dev/null +++ b/ext/xml/tests/bug32001.phpt @@ -0,0 +1,483 @@ +--TEST-- +Bug #32001 (xml_parse*() goes into infinite loop when autodetection in effect) +--SKIPIF-- +encoding = $enc; + $this->chunk_size = $chunk_size; + $this->bom = $bom; + $this->prologue = !$omit_prologue; + $this->tags = array(); + } + + function start_element($parser, $name, $attrs) { + $attrs = array_map('bin2hex', $attrs); + $this->tags[] = bin2hex($name).": ".implode(', ', $attrs); + } + + function end_element($parser, $name) { + } + + function run() { + $data = ''; + + if ($this->prologue) { + $canonical_name = preg_replace('/BE|LE/i', '', $this->encoding); + $data .= "\n"; + } + + $data .= << + <テスト:テスト2 テスト="テスト"> + <テスト:テスト3> + test! + + + +HERE; + + $data = iconv("UTF-8", $this->encoding, $data); + + if ($this->bom) { + switch (strtoupper($this->encoding)) { + case 'UTF-8': + case 'UTF8': + $data = "\xef\xbb\xbf".$data; + break; + + case 'UTF-16': + case 'UTF16': + case 'UTF-16BE': + case 'UTF16BE': + case 'UCS-2': + case 'UCS2': + case 'UCS-2BE': + case 'UCS2BE': + $data = "\xfe\xff".$data; + break; + + case 'UTF-16LE': + case 'UTF16LE': + case 'UCS-2LE': + case 'UCS2LE': + $data = "\xff\xfe".$data; + break; + + case 'UTF-32': + case 'UTF32': + case 'UTF-32BE': + case 'UTF32BE': + case 'UCS-4': + case 'UCS4': + case 'UCS-4BE': + case 'UCS4BE': + $data = "\x00\x00\xfe\xff".$data; + break; + + case 'UTF-32LE': + case 'UTF32LE': + case 'UCS-4LE': + case 'UCS4LE': + $data = "\xff\xfe\x00\x00".$data; + break; + } + } + + $parser = xml_parser_create(NULL); + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); + xml_set_element_handler($parser, "start_element", "end_element"); + xml_set_object($parser, $this); + + if ($this->chunk_size == 0) { + $success = @xml_parse($parser, $data, true); + } else { + for ($offset = 0; $offset < strlen($data); + $offset += $this->chunk_size) { + $success = @xml_parse($parser, substr($data, $offset, $this->chunk_size), false); + if (!$success) { + break; + } + } + if ($success) { + $success = @xml_parse($parser, "", true); + } + } + + echo "Encoding: $this->encoding\n"; + echo "XML Prologue: ".($this->prologue ? 'present': 'not present'), "\n"; + echo "Chunk size: ".($this->chunk_size ? "$this->chunk_size byte(s)\n": "all data at once\n"); + echo "BOM: ".($this->bom ? 'prepended': 'not prepended'), "\n"; + + if ($success) { + var_dump($this->tags); + } else { + echo "[Error] ", xml_error_string(xml_get_error_code($parser)), "\n"; + } + } +} +$suite = array( + new testcase("UTF-8", 0, 0, 0), + new testcase("UTF-8", 0, 0, 1), + new testcase("UTF-8", 0, 1, 0), + new testcase("UTF-8", 0, 1, 1), + new testcase("UTF-16BE", 0, 0, 0), + new testcase("UTF-16BE", 0, 1, 0), + new testcase("UTF-16BE", 0, 1, 1), + new testcase("UTF-16LE", 0, 0, 0), + new testcase("UTF-16LE", 0, 1, 0), + new testcase("UTF-16LE", 0, 1, 1), + new testcase("UTF-8", 1, 0, 0), + new testcase("UTF-8", 1, 0, 1), + new testcase("UTF-8", 1, 1, 0), + new testcase("UTF-8", 1, 1, 1), + new testcase("UTF-16BE", 1, 0, 0), + new testcase("UTF-16BE", 1, 1, 0), + new testcase("UTF-16BE", 1, 1, 1), + new testcase("UTF-16LE", 1, 0, 0), + new testcase("UTF-16LE", 1, 1, 0), + new testcase("UTF-16LE", 1, 1, 1), + new testcase("EUC-JP" , 0), + new testcase("EUC-JP" , 1), + new testcase("Shift_JIS", 0), + new testcase("Shift_JIS", 1), + new testcase("GB2312", 0), + new testcase("GB2312", 1), +); + +if (XML_SAX_IMPL == 'libxml') { + preg_match("/^libxml2 Version.*\$/im", `$_ENV[TEST_PHP_EXECUTABLE] -i`, $match); + echo $match[0], "\n"; +} else { + echo "libxml2 Version => NONE\n"; +} + +foreach ($suite as $testcase) { + $testcase->run(); +} + +// vim600: sts=4 sw=4 ts=4 encoding=UTF-8 +?> +--EXPECTF-- +libxml2 Version => %s +Encoding: UTF-8 +XML Prologue: present +Chunk size: all data at once +BOM: not prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: UTF-8 +XML Prologue: not present +Chunk size: all data at once +BOM: not prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: UTF-8 +XML Prologue: present +Chunk size: all data at once +BOM: prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: UTF-8 +XML Prologue: not present +Chunk size: all data at once +BOM: prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: UTF-16BE +XML Prologue: present +Chunk size: all data at once +BOM: not prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: UTF-16BE +XML Prologue: present +Chunk size: all data at once +BOM: prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: UTF-16BE +XML Prologue: not present +Chunk size: all data at once +BOM: prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: UTF-16LE +XML Prologue: present +Chunk size: all data at once +BOM: not prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: UTF-16LE +XML Prologue: present +Chunk size: all data at once +BOM: prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: UTF-16LE +XML Prologue: not present +Chunk size: all data at once +BOM: prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: UTF-8 +XML Prologue: present +Chunk size: 1 byte(s) +BOM: not prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: UTF-8 +XML Prologue: not present +Chunk size: 1 byte(s) +BOM: not prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: UTF-8 +XML Prologue: present +Chunk size: 1 byte(s) +BOM: prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: UTF-8 +XML Prologue: not present +Chunk size: 1 byte(s) +BOM: prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: UTF-16BE +XML Prologue: present +Chunk size: 1 byte(s) +BOM: not prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: UTF-16BE +XML Prologue: present +Chunk size: 1 byte(s) +BOM: prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: UTF-16BE +XML Prologue: not present +Chunk size: 1 byte(s) +BOM: prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: UTF-16LE +XML Prologue: present +Chunk size: 1 byte(s) +BOM: not prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: UTF-16LE +XML Prologue: present +Chunk size: 1 byte(s) +BOM: prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: UTF-16LE +XML Prologue: not present +Chunk size: 1 byte(s) +BOM: prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: EUC-JP +XML Prologue: present +Chunk size: all data at once +BOM: not prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: EUC-JP +XML Prologue: present +Chunk size: 1 byte(s) +BOM: not prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: Shift_JIS +XML Prologue: present +Chunk size: all data at once +BOM: not prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: Shift_JIS +XML Prologue: present +Chunk size: 1 byte(s) +BOM: not prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: GB2312 +XML Prologue: present +Chunk size: all data at once +BOM: not prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} +Encoding: GB2312 +XML Prologue: present +Chunk size: 1 byte(s) +BOM: not prepended +array(3) { + [0]=> + string(128) "e38386e382b9e383883ae38386e382b9e3838831: 687474703a2f2f7777772e6578616d706c652e636f6d2fe38386e382b9e383882f, e38386e382b9e38388" + [1]=> + string(60) "e38386e382b9e383883ae38386e382b9e3838832: e38386e382b9e38388" + [2]=> + string(42) "e38386e382b9e383883ae38386e382b9e3838833: " +} diff --git a/ext/xml/xml.c b/ext/xml/xml.c index f17601f8ebb3..5c1d8192ce86 100644 --- a/ext/xml/xml.c +++ b/ext/xml/xml.c @@ -74,9 +74,6 @@ ZEND_GET_MODULE(xml) /* {{{ function prototypes */ PHP_MINIT_FUNCTION(xml); -PHP_RINIT_FUNCTION(xml); -PHP_MSHUTDOWN_FUNCTION(xml); -PHP_RSHUTDOWN_FUNCTION(xml); PHP_MINFO_FUNCTION(xml); static void xml_parser_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC); @@ -147,9 +144,9 @@ zend_module_entry xml_module_entry = { "xml", /* extension name */ xml_functions, /* extension function list */ PHP_MINIT(xml), /* extension-wide startup function */ - PHP_MSHUTDOWN(xml), /* extension-wide shutdown function */ - PHP_RINIT(xml), /* per-request startup function */ - PHP_RSHUTDOWN(xml), /* per-request shutdown function */ + NULL, /* extension-wide shutdown function */ + NULL, /* per-request startup function */ + NULL, /* per-request shutdown function */ PHP_MINFO(xml), /* information function */ NO_VERSION_YET, STANDARD_MODULE_PROPERTIES @@ -176,7 +173,7 @@ static int le_xml_parser; #ifdef ZTS static void php_xml_init_globals(php_xml_globals *xml_globals_p TSRMLS_DC) { - XML(default_encoding) = "ISO-8859-1"; + XML(default_encoding) = "UTF-8"; } #endif @@ -204,7 +201,7 @@ PHP_MINIT_FUNCTION(xml) #ifdef ZTS ts_allocate_id(&xml_globals_id, sizeof(php_xml_globals), (ts_allocate_ctor) php_xml_init_globals, NULL); #else - XML(default_encoding) = "ISO-8859-1"; + XML(default_encoding) = "UTF-8"; #endif REGISTER_LONG_CONSTANT("XML_ERROR_NONE", XML_ERROR_NONE, CONST_CS|CONST_PERSISTENT); @@ -251,25 +248,6 @@ PHP_MINIT_FUNCTION(xml) return SUCCESS; } - -PHP_RINIT_FUNCTION(xml) -{ - return SUCCESS; -} - - -PHP_MSHUTDOWN_FUNCTION(xml) -{ - return SUCCESS; -} - - -PHP_RSHUTDOWN_FUNCTION(xml) -{ - return SUCCESS; -} - - PHP_MINFO_FUNCTION(xml) { php_info_print_table_start(); @@ -410,12 +388,12 @@ static void xml_set_handler(zval **handler, zval **data) /* {{{ xml_call_handler() */ static zval *xml_call_handler(xml_parser *parser, zval *handler, zend_function *function_ptr, int argc, zval **argv) { + int i; TSRMLS_FETCH(); - if (parser && handler) { + if (parser && handler && !EG(exception)) { zval ***args; zval *retval; - int i; int result; zend_fcall_info fci; @@ -459,10 +437,14 @@ static zval *xml_call_handler(xml_parser *parser, zval *handler, zend_function * if (result == FAILURE) { return NULL; } else { - return retval; + return EG(exception) ? NULL : retval; } + } else { + for (i = 0; i < argc; i++) { + zval_ptr_dtor(&argv[i]); } return NULL; + } } /* }}} */ @@ -1094,6 +1076,8 @@ static void php_xml_parser_create_impl(INTERNAL_FUNCTION_PARAMETERS, int ns_supp parser->target_encoding = encoding; parser->case_folding = 1; parser->object = NULL; + parser->isparsing = 0; + XML_SetUserData(parser->parser, parser); ZEND_REGISTER_RESOURCE(return_value, parser,le_xml_parser); @@ -1352,7 +1336,9 @@ PHP_FUNCTION(xml_parse) isFinal = 0; } + parser->isparsing = 1; ret = XML_Parse(parser->parser, Z_STRVAL_PP(data), Z_STRLEN_PP(data), isFinal); + parser->isparsing = 0; RETVAL_LONG(ret); } @@ -1391,7 +1377,9 @@ PHP_FUNCTION(xml_parse_into_struct) XML_SetElementHandler(parser->parser, _xml_startElementHandler, _xml_endElementHandler); XML_SetCharacterDataHandler(parser->parser, _xml_characterDataHandler); + parser->isparsing = 1; ret = XML_Parse(parser->parser, Z_STRVAL_PP(data), Z_STRLEN_PP(data), 1); + parser->isparsing = 0; RETVAL_LONG(ret); } @@ -1492,6 +1480,11 @@ PHP_FUNCTION(xml_parser_free) ZEND_FETCH_RESOURCE(parser,xml_parser *, pind, -1, "XML Parser", le_xml_parser); + if (parser->isparsing == 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parser cannot be freed while it is parsing."); + RETURN_FALSE; + } + if (zend_list_delete(parser->index) == FAILURE) { RETURN_FALSE; } diff --git a/ext/xmlreader/CREDITS b/ext/xmlreader/CREDITS deleted file mode 100644 index 35f3af193305..000000000000 --- a/ext/xmlreader/CREDITS +++ /dev/null @@ -1,2 +0,0 @@ -XMLReader -Rob Richards diff --git a/ext/xmlreader/EXPERIMENTAL b/ext/xmlreader/EXPERIMENTAL deleted file mode 100644 index dfa49ae4967b..000000000000 --- a/ext/xmlreader/EXPERIMENTAL +++ /dev/null @@ -1,4 +0,0 @@ -this module is experimental, -its functions may change their names -so do not rely to much on them -you have been warned! diff --git a/ext/xmlreader/README b/ext/xmlreader/README deleted file mode 100644 index 0d946f62da4b..000000000000 --- a/ext/xmlreader/README +++ /dev/null @@ -1,5 +0,0 @@ -XMLReader represents a reader that provides non-cached, -forward-only access to XML data. It is based upon the -xmlTextReader api from libxml - -This extension is designed to only work under PHP 5. diff --git a/ext/xmlreader/TODO b/ext/xmlreader/TODO deleted file mode 100644 index 5bf20edcc33e..000000000000 --- a/ext/xmlreader/TODO +++ /dev/null @@ -1,6 +0,0 @@ -- Refactor internals once libxml 2.6.x is minimum requirement for PHP 5 - use new api for creating the xmlTextReaderPtr - -- Add Custom Error Handling - - diff --git a/ext/xmlreader/config.m4 b/ext/xmlreader/config.m4 deleted file mode 100644 index 2de9292ca8db..000000000000 --- a/ext/xmlreader/config.m4 +++ /dev/null @@ -1,22 +0,0 @@ -dnl -dnl $Id$ -dnl - -PHP_ARG_WITH(xmlreader, for XMLReader support, -[ --with-xmlreader Include XMLReader support.]) - -if test -z "$PHP_LIBXML_DIR"; then - PHP_ARG_WITH(libxml-dir, libxml2 install dir, - [ --with-libxml-dir=DIR XMLReader: libxml2 install prefix], no, no) -fi - -if test "$PHP_XMLREADER" != "no" && test "$PHP_LIBXML" != "no"; then - - PHP_SETUP_LIBXML(XMLREADER_SHARED_LIBADD, [ - AC_DEFINE(HAVE_XMLREADER,1,[ ]) - PHP_NEW_EXTENSION(xmlreader, php_xmlreader.c, $ext_shared) - PHP_SUBST(XMLREADER_SHARED_LIBADD) - ], [ - AC_MSG_ERROR([xml2-config not found. Please check your libxml2 installation.]) - ]) -fi diff --git a/ext/xmlreader/config.w32 b/ext/xmlreader/config.w32 deleted file mode 100644 index 1788356c9e32..000000000000 --- a/ext/xmlreader/config.w32 +++ /dev/null @@ -1,14 +0,0 @@ -// $Id$ -// vim:ft=javascript - -ARG_WITH("xmlreader", "XMLReader support", "yes"); - -if (PHP_XMLREADER == "yes" && PHP_LIBXML == "yes") { - EXTENSION("xmlreader", "php_xmlreader.c"); - AC_DEFINE("HAVE_XMLREADER", 1, "XMLReader support"); - if (!PHP_XMLREADER_SHARED) { - ADD_FLAG("CFLAGS_XMLREADER", "/D LIBXML_STATIC"); - } - ADD_EXTENSION_DEP('xmlreader', 'libxml'); -} - diff --git a/ext/xmlreader/examples/dtdexample.dtd b/ext/xmlreader/examples/dtdexample.dtd deleted file mode 100644 index ce53f0bc18c9..000000000000 --- a/ext/xmlreader/examples/dtdexample.dtd +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/ext/xmlreader/examples/dtdexample.xml b/ext/xmlreader/examples/dtdexample.xml deleted file mode 100644 index 052889c05d29..000000000000 --- a/ext/xmlreader/examples/dtdexample.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - -Move Title 1 -Location 1 - - - -Move Title 2 - -Location 2 - - - diff --git a/ext/xmlreader/examples/relaxNG.rng b/ext/xmlreader/examples/relaxNG.rng deleted file mode 100644 index f4357e04ef8a..000000000000 --- a/ext/xmlreader/examples/relaxNG.rng +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - diff --git a/ext/xmlreader/examples/relaxNG.xml b/ext/xmlreader/examples/relaxNG.xml deleted file mode 100644 index 6b0cac122505..000000000000 --- a/ext/xmlreader/examples/relaxNG.xml +++ /dev/null @@ -1 +0,0 @@ -hello \ No newline at end of file diff --git a/ext/xmlreader/examples/relaxNG2.rng b/ext/xmlreader/examples/relaxNG2.rng deleted file mode 100644 index 4adae7b15113..000000000000 --- a/ext/xmlreader/examples/relaxNG2.rng +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ext/xmlreader/examples/relaxNG3.rng b/ext/xmlreader/examples/relaxNG3.rng deleted file mode 100644 index 73e1eb616510..000000000000 --- a/ext/xmlreader/examples/relaxNG3.rng +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/ext/xmlreader/examples/xmlreader.xml b/ext/xmlreader/examples/xmlreader.xml deleted file mode 100644 index 4c53743de66b..000000000000 --- a/ext/xmlreader/examples/xmlreader.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - The Grapes of Wrath - John Steinbeck - - - The Pearl - John Steinbeck - - diff --git a/ext/xmlreader/examples/xmlreader_file.php b/ext/xmlreader/examples/xmlreader_file.php deleted file mode 100644 index 480b152d7e53..000000000000 --- a/ext/xmlreader/examples/xmlreader_file.php +++ /dev/null @@ -1,20 +0,0 @@ -open('xmlreader.xml'); -while ($reader->read()) { - if ($reader->nodeType != XMLREADER_END_ELEMENT) { - print "Node Name: ".$reader->name."\n"; - print "Node Value: ".$reader->value."\n"; - print "Node Depth: ".$reader->depth."\n"; - if ($reader->nodeType==XMLREADER_ELEMENT && $reader->hasAttributes) { - $attr = $reader->moveToFirstAttribute(); - while ($attr) { - print " Attribute Name: ".$reader->name."\n"; - print " Attribute Value: ".$reader->value."\n"; - $attr = $reader->moveToNextAttribute(); - } - } - print "\n"; - } -} -?> diff --git a/ext/xmlreader/examples/xmlreader_relaxNG.php b/ext/xmlreader/examples/xmlreader_relaxNG.php deleted file mode 100644 index e56739a2fb26..000000000000 --- a/ext/xmlreader/examples/xmlreader_relaxNG.php +++ /dev/null @@ -1,25 +0,0 @@ -open('relaxNG.xml'); -/* -Example setting relaxNG using string: -$reader->setRelaxNGSchemaSource(file_get_contents('relaxNG.rng')); -*/ -if ($reader->setRelaxNGSchema('relaxNG.rng')) { - while ($reader->read()) { - /* Print node name indenting it based on depth and $indent var */ - print str_repeat(" ", $reader->depth * $indent).$reader->name."\n"; - } -} - -print "\n"; - -if (! $reader->isValid()) { - print "Document is not valid\n"; -} else { - print "Document is valid\n"; -} - -?> \ No newline at end of file diff --git a/ext/xmlreader/examples/xmlreader_string.php b/ext/xmlreader/examples/xmlreader_string.php deleted file mode 100644 index d545c22c8b38..000000000000 --- a/ext/xmlreader/examples/xmlreader_string.php +++ /dev/null @@ -1,31 +0,0 @@ - - - The Grapes of Wrath - John Steinbeck - - - The Pearl - John Steinbeck - -'; - -$reader = new XMLReader(); -$reader->XML($xmlstring); -while ($reader->read()) { - if ($reader->nodeType != XMLREADER_END_ELEMENT) { - print "Node Name: ".$reader->name."\n"; - print "Node Value: ".$reader->value."\n"; - print "Node Depth: ".$reader->depth."\n"; - if ($reader->nodeType==XMLREADER_ELEMENT && $reader->hasAttributes) { - $attr = $reader->moveToFirstAttribute(); - while ($attr) { - print " Attribute Name: ".$reader->name."\n"; - print " Attribute Value: ".$reader->value."\n"; - $attr = $reader->moveToNextAttribute(); - } - } - print "\n"; - } -} -?> diff --git a/ext/xmlreader/examples/xmlreader_validatedtd.php b/ext/xmlreader/examples/xmlreader_validatedtd.php deleted file mode 100644 index 5173154f5a1e..000000000000 --- a/ext/xmlreader/examples/xmlreader_validatedtd.php +++ /dev/null @@ -1,18 +0,0 @@ -open("dtdexample.xml"); -$xml->setParserProperty(XMLREADER_LOADDTD, TRUE); -$xml->setParserProperty(XMLREADER_VALIDATE, TRUE); -while($xml->read()) { - /* Print node name indenting it based on depth and $indent var */ - print str_repeat(" ", $xml->depth * $indent).$xml->name."\n"; - if ($xml->hasAttributes) { - $attCount = $xml->attributeCount; - print str_repeat(" ", $xml->depth * $indent)." Number of Attributes: ".$xml->attributeCount."\n"; - } -} -print "\n\nValid:\n"; -var_dump($xml->isValid()); -?> \ No newline at end of file diff --git a/ext/xmlreader/package.xml b/ext/xmlreader/package.xml deleted file mode 100644 index 45dcbc3708f1..000000000000 --- a/ext/xmlreader/package.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - xmlreader - Provides fast, non-cached, forward-only access to XML data. - - This extension wraps the libxml xmlReader API. The reader acts as a cursor - going forward on the document stream and stopping at each node in the way. - xmlReader is similar to SAX though uses a much simpler API. - - PHP License - - - rrichards - Rob Richards - rrichards@php.net - lead - - - chregu - lead - Christian Stocker - chregu@php.net - - - - 0.2 - 2004-05-10 - beta - - Allow open and XML methods to be called statically. - Add expand() support to export copies of nodes as DOM objects. (chregu) - Add next() support to skip to next sibling node. (chregu) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - libxml - - - diff --git a/ext/xmlreader/php_xmlreader.c b/ext/xmlreader/php_xmlreader.c deleted file mode 100644 index 2c9b5b83551d..000000000000 --- a/ext/xmlreader/php_xmlreader.c +++ /dev/null @@ -1,1152 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Rob Richards | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - - -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "php_xmlreader.h" -#ifdef HAVE_DOM -#include "ext/dom/xml_common.h" -#endif -#include - -zend_class_entry *xmlreader_class_entry; - -static zend_object_handlers xmlreader_object_handlers; - -static HashTable xmlreader_prop_handlers; - -typedef int (*xmlreader_read_int_t)(xmlTextReaderPtr reader); -typedef unsigned char *(*xmlreader_read_char_t)(xmlTextReaderPtr reader); -typedef int (*xmlreader_write_t)(xmlreader_object *obj, zval *newval TSRMLS_DC); - -typedef unsigned char *(*xmlreader_read_one_char_t)(xmlTextReaderPtr reader, const unsigned char *); - -typedef struct _xmlreader_prop_handler { - xmlreader_read_int_t read_int_func; - xmlreader_read_char_t read_char_func; - xmlreader_write_t write_func; - int type; -} xmlreader_prop_handler; - -#define XMLREADER_LOAD_STRING 0 -#define XMLREADER_LOAD_FILE 1 - -static void xmlreader_register_prop_handler(HashTable *prop_handler, char *name, xmlreader_read_int_t read_int_func, xmlreader_read_char_t read_char_func, int rettype TSRMLS_DC) -{ - xmlreader_prop_handler hnd; - - hnd.read_char_func = read_char_func; - hnd.read_int_func = read_int_func; - hnd.type = rettype; - zend_hash_add(prop_handler, name, strlen(name)+1, &hnd, sizeof(xmlreader_prop_handler), NULL); -} - -static int xmlreader_property_reader(xmlreader_object *obj, xmlreader_prop_handler *hnd, zval **retval TSRMLS_DC) -{ - char *retchar = NULL; - int retint = 0; - - if (obj->ptr != NULL) { - if (hnd->read_char_func) { - retchar = hnd->read_char_func(obj->ptr); - } else { - if (hnd->read_int_func) { - retint = hnd->read_int_func(obj->ptr); - if (retint == -1) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal libxml error returned"); - return FAILURE; - } - } - } - } - - ALLOC_ZVAL(*retval); - - switch (hnd->type) { - case IS_STRING: - if (retchar) { - ZVAL_STRING(*retval, retchar, 1); - xmlFree(retchar); - } else { - ZVAL_EMPTY_STRING(*retval); - } - break; - case IS_BOOL: - ZVAL_BOOL(*retval, retint); - break; - case IS_LONG: - ZVAL_LONG(*retval, retint); - break; - default: - ZVAL_NULL(*retval); - } - - return SUCCESS; -} - -/* {{{ xmlreader_read_property */ -zval *xmlreader_read_property(zval *object, zval *member, int type TSRMLS_DC) -{ - xmlreader_object *obj; - zval tmp_member; - zval *retval; - xmlreader_prop_handler *hnd; - zend_object_handlers *std_hnd; - int ret; - - if (member->type != IS_STRING) { - tmp_member = *member; - zval_copy_ctor(&tmp_member); - convert_to_string(&tmp_member); - member = &tmp_member; - } - - ret = FAILURE; - obj = (xmlreader_object *)zend_objects_get_address(object TSRMLS_CC); - - if (obj->prop_handler != NULL) { - ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd); - } - if (ret == SUCCESS) { - ret = xmlreader_property_reader(obj, hnd, &retval TSRMLS_CC); - if (ret == SUCCESS) { - /* ensure we're creating a temporary variable */ - retval->refcount = 0; - } else { - retval = EG(uninitialized_zval_ptr); - } - } else { - std_hnd = zend_get_std_object_handlers(); - retval = std_hnd->read_property(object, member, type TSRMLS_CC); - } - - if (member == &tmp_member) { - zval_dtor(member); - } - return retval; -} -/* }}} */ - -/* {{{ xmlreader_write_property */ -void xmlreader_write_property(zval *object, zval *member, zval *value TSRMLS_DC) -{ - xmlreader_object *obj; - zval tmp_member; - xmlreader_prop_handler *hnd; - zend_object_handlers *std_hnd; - int ret; - - if (member->type != IS_STRING) { - tmp_member = *member; - zval_copy_ctor(&tmp_member); - convert_to_string(&tmp_member); - member = &tmp_member; - } - - ret = FAILURE; - obj = (xmlreader_object *)zend_objects_get_address(object TSRMLS_CC); - - if (obj->prop_handler != NULL) { - ret = zend_hash_find((HashTable *)obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd); - } - if (ret == SUCCESS) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot write to read-only property"); - } else { - std_hnd = zend_get_std_object_handlers(); - std_hnd->write_property(object, member, value TSRMLS_CC); - } - - if (member == &tmp_member) { - zval_dtor(member); - } -} -/* }}} */ - -/* _xmlreader_get_valid_file_path and _xmlreader_get_relaxNG should be made a - common function in libxml extension as code is common to a few xml extensions */ -char *_xmlreader_get_valid_file_path(char *source, char *resolved_path, int resolved_path_len TSRMLS_DC) { - xmlURI *uri; - xmlChar *escsource; - char *file_dest; - int isFileUri = 0; - - uri = xmlCreateURI(); - escsource = xmlURIEscapeStr(source, ":"); - xmlParseURIReference(uri, escsource); - xmlFree(escsource); - - if (uri->scheme != NULL) { - /* absolute file uris - libxml only supports localhost or empty host */ - if (strncasecmp(source, "file:///",8) == 0) { - isFileUri = 1; -#ifdef PHP_WIN32 - source += 8; -#else - source += 7; -#endif - } else if (strncasecmp(source, "file://localhost/",17) == 0) { - isFileUri = 1; -#ifdef PHP_WIN32 - source += 17; -#else - source += 16; -#endif - } - } - - file_dest = source; - - if ((uri->scheme == NULL || isFileUri)) { - /* XXX possible buffer overflow if VCWD_REALPATH does not know size of resolved_path */ - if (! VCWD_REALPATH(source, resolved_path)) { - expand_filepath(source, resolved_path TSRMLS_CC); - } - file_dest = resolved_path; - } - - xmlFreeURI(uri); - - return file_dest; -} - -#ifdef LIBXML_SCHEMAS_ENABLED -static xmlRelaxNGPtr _xmlreader_get_relaxNG(char *source, int source_len, int type, - xmlRelaxNGValidityErrorFunc error_func, - xmlRelaxNGValidityWarningFunc warn_func TSRMLS_DC) -{ - char *valid_file = NULL; - xmlRelaxNGParserCtxtPtr parser = NULL; - xmlRelaxNGPtr sptr; - char resolved_path[MAXPATHLEN + 1]; - - switch (type) { - case XMLREADER_LOAD_FILE: - valid_file = _xmlreader_get_valid_file_path(source, resolved_path, MAXPATHLEN TSRMLS_CC); - if (!valid_file) { - return NULL; - } - parser = xmlRelaxNGNewParserCtxt(valid_file); - break; - case XMLREADER_LOAD_STRING: - parser = xmlRelaxNGNewMemParserCtxt(source, source_len); - /* If loading from memory, we need to set the base directory for the document - but it is not apparent how to do that for schema's */ - break; - default: - return NULL; - } - - if (parser == NULL) { - return NULL; - } - - if (error_func || warn_func) { - xmlRelaxNGSetParserErrors(parser, - (xmlRelaxNGValidityErrorFunc) error_func, - (xmlRelaxNGValidityWarningFunc) warn_func, - parser); - } - sptr = xmlRelaxNGParse(parser); - xmlRelaxNGFreeParserCtxt(parser); - - return sptr; -} -#endif - -/* {{{ xmlreader_module_entry - */ -zend_module_entry xmlreader_module_entry = { - STANDARD_MODULE_HEADER, - "xmlreader", - NULL, - PHP_MINIT(xmlreader), - PHP_MSHUTDOWN(xmlreader), - NULL, - NULL, - PHP_MINFO(xmlreader), - "0.1", /* Replace with version number for your extension */ - STANDARD_MODULE_PROPERTIES -}; -/* }}} */ - -#ifdef COMPILE_DL_XMLREADER -ZEND_GET_MODULE(xmlreader) -#endif - -/* {{{ xmlreader_objects_clone */ -void xmlreader_objects_clone(void *object, void **object_clone TSRMLS_DC) -{ - /* TODO */ -} -/* }}} */ - -static void xmlreader_free_resources(xmlreader_object *intern) { - if (intern) { - if (intern->input) { - xmlFreeParserInputBuffer(intern->input); - intern->input = NULL; - } - - if (intern->ptr) { - xmlFreeTextReader(intern->ptr); - intern->ptr = NULL; - } -#ifdef LIBXML_SCHEMAS_ENABLED - if (intern->schema) { - xmlRelaxNGFree((xmlRelaxNGPtr) intern->schema); - intern->schema = NULL; - } -#endif - } -} - -/* {{{ xmlreader_objects_free_storage */ -void xmlreader_objects_free_storage(void *object TSRMLS_DC) -{ - xmlreader_object *intern = (xmlreader_object *)object; - - zend_hash_destroy(intern->std.properties); - FREE_HASHTABLE(intern->std.properties); - - xmlreader_free_resources(intern); - - efree(object); -} -/* }}} */ - -/* {{{ xmlreader_objects_new */ -zend_object_value xmlreader_objects_new(zend_class_entry *class_type TSRMLS_DC) -{ - zend_object_value retval; - xmlreader_object *intern; - zval *tmp; - - intern = emalloc(sizeof(xmlreader_object)); - intern->std.ce = class_type; - intern->std.in_get = 0; - intern->std.in_set = 0; - intern->ptr = NULL; - intern->input = NULL; - intern->schema = NULL; - intern->prop_handler = &xmlreader_prop_handlers; - - ALLOC_HASHTABLE(intern->std.properties); - zend_hash_init(intern->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0); - zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); - retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t) xmlreader_objects_free_storage, xmlreader_objects_clone TSRMLS_CC); - intern->handle = retval.handle; - retval.handlers = &xmlreader_object_handlers; - return retval; -} -/* }}} */ - -static void php_xmlreader_string_arg(INTERNAL_FUNCTION_PARAMETERS, xmlreader_read_one_char_t internal_function) { - zval *id; - int name_len = 0; - char *retchar = NULL; - xmlreader_object *intern; - char *name; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) { - return; - } - - if (!name_len) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument cannot be an empty string"); - RETURN_FALSE; - } - - id = getThis(); - - intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC); - if (intern && intern->ptr) { - retchar = internal_function(intern->ptr, name); - } - if (retchar) { - RETVAL_STRING(retchar, 1); - xmlFree(retchar); - return; - } else { - RETVAL_EMPTY_STRING(); - } -} - -static void php_xmlreader_no_arg(INTERNAL_FUNCTION_PARAMETERS, xmlreader_read_int_t internal_function) { - zval *id; - int retval; - xmlreader_object *intern; - - id = getThis(); - - intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC); - if (intern && intern->ptr) { - retval = internal_function(intern->ptr); - if (retval == 1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* This function not yet needed until some additional functions are implemented in libxml -static void php_xmlreader_no_arg_string(INTERNAL_FUNCTION_PARAMETERS, xmlreader_read_char_t internal_function) { - zval *id; - char *retchar = NULL; - xmlreader_object *intern; - - id = getThis(); - - intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC); - if (intern && intern->ptr) { - retchar = xmlTextReaderReadString(intern->ptr); - } - if (retchar) { - RETVAL_STRING(retchar, 1); - xmlFree(retchar); - return; - } else { - RETVAL_EMPTY_STRING(); - } -} -*/ - -static void php_xmlreader_set_relaxng_schema(INTERNAL_FUNCTION_PARAMETERS, int type) { -#ifdef LIBXML_SCHEMAS_ENABLED - zval *id; - int source_len = 0, retval = -1; - xmlreader_object *intern; - xmlRelaxNGPtr schema = NULL; - char *source; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!", &source, &source_len) == FAILURE) { - return; - } - - if (source != NULL && !source_len) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Schema data source is requried"); - RETURN_FALSE; - } - - id = getThis(); - - intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC); - if (intern && intern->ptr) { - if (source) { - schema = _xmlreader_get_relaxNG(source, source_len, type, NULL, NULL TSRMLS_CC); - if (schema) { - retval = xmlTextReaderRelaxNGSetSchema(intern->ptr, schema); - } - } else { - /* unset the associated relaxNG context and schema if one exists */ - retval = xmlTextReaderRelaxNGSetSchema(intern->ptr, NULL); - } - - if (retval == 0) { - if (intern->schema) { - xmlRelaxNGFree((xmlRelaxNGPtr) intern->schema); - } - - intern->schema = schema; - - RETURN_TRUE; - } - } - - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set schema. This must be set prior to reading or schema contains errors."); - - RETURN_FALSE; -#else - php_error_docref(NULL TSRMLS_CC, E_WARNING, "No Schema support built into libxml."); - - RETURN_FALSE; -#endif -} - -/* {{{ proto boolean close() -Closes xmlreader - current frees resources until xmlTextReaderClose is fixed in libxml */ -PHP_METHOD(xmlreader, close) -{ - zval *id; - xmlreader_object *intern; - - id = getThis(); - intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC); - /* libxml is segfaulting in versions up to 2.6.8 using xmlTextReaderClose so for - now we will free the whole reader when close is called as it would get rebuilt on - a new load anyways */ - xmlreader_free_resources(intern); - - RETURN_TRUE; -} - -/* {{{ proto string getAttribute(string name) -Get value of an attribute from current element */ -PHP_METHOD(xmlreader, getAttribute) -{ - php_xmlreader_string_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderGetAttribute); -} -/* }}} */ - -/* {{{ proto string getAttributeNo(int index) -Get value of an attribute at index from current element */ -PHP_METHOD(xmlreader, getAttributeNo) -{ - zval *id; - int attr_pos; - char *retchar = NULL; - xmlreader_object *intern; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &attr_pos) == FAILURE) { - return; - } - - id = getThis(); - - intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC); - if (intern && intern->ptr) { - retchar = xmlTextReaderGetAttributeNo(intern->ptr,attr_pos); - } - if (retchar) { - RETVAL_STRING(retchar, 1); - xmlFree(retchar); - return; - } else { - RETURN_EMPTY_STRING(); - } -} -/* }}} */ - -/* {{{ proto string getAttributeNs(string name, string namespaceURI) -Get value of a attribute via name and namespace from current element */ -PHP_METHOD(xmlreader, getAttributeNs) -{ - zval *id; - int name_len = 0, ns_uri_len = 0; - xmlreader_object *intern; - char *name, *ns_uri, *retchar = NULL; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &name, &name_len, &ns_uri, &ns_uri_len) == FAILURE) { - return; - } - - if (name_len == 0 || ns_uri_len == 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attribute Name and Namespace URI cannot be empty"); - RETURN_FALSE; - } - - id = getThis(); - - intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC); - if (intern && intern->ptr) { - retchar = xmlTextReaderGetAttributeNs(intern->ptr, name, ns_uri); - } - if (retchar) { - RETVAL_STRING(retchar, 1); - xmlFree(retchar); - return; - } else { - RETURN_EMPTY_STRING(); - } -} -/* }}} */ - -/* {{{ proto boolean getParserProperty(int property) -Indicates wether given property (one of the parser option constants) is set or not on parser */ -PHP_METHOD(xmlreader, getParserProperty) -{ - zval *id; - int property, retval = -1; - xmlreader_object *intern; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &property) == FAILURE) { - return; - } - - id = getThis(); - - intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC); - if (intern && intern->ptr) { - retval = xmlTextReaderGetParserProp(intern->ptr,property); - } - if (retval == -1) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid parser property"); - RETURN_FALSE; - } - - RETURN_BOOL(retval); -} -/* }}} */ - -/* {{{ proto boolean isValid() -Returns boolean indicating if parsed document is valid or not. -Must set XMLREADER_LOADDTD or XMLREADER_VALIDATE parser option prior to the first call to read -or this method will always return FALSE */ -PHP_METHOD(xmlreader, isValid) -{ - php_xmlreader_no_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderIsValid); -} -/* }}} */ - -/* {{{ proto string lookupNamespace(string prefix) -Return namespaceURI for associated prefix on current node */ -PHP_METHOD(xmlreader, lookupNamespace) -{ - php_xmlreader_string_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderLookupNamespace); -} -/* }}} */ - -/* {{{ proto boolean moveToAttribute(string name) -Positions reader at specified attribute - Returns TRUE on success and FALSE on failure */ -PHP_METHOD(xmlreader, moveToAttribute) -{ - zval *id; - int name_len = 0, retval; - xmlreader_object *intern; - char *name; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) { - return; - } - - if (name_len == 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attribute Name is required"); - RETURN_FALSE; - } - - id = getThis(); - - intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC); - if (intern && intern->ptr) { - retval = xmlTextReaderMoveToAttribute(intern->ptr, name); - if (retval == 1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} -/* }}} */ - -/* {{{ proto boolean moveToAttributeNo(int index) -Positions reader at attribute at spcecified index. -Returns TRUE on success and FALSE on failure */ -PHP_METHOD(xmlreader, moveToAttributeNo) -{ - zval *id; - int attr_pos, retval; - xmlreader_object *intern; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &attr_pos) == FAILURE) { - return; - } - - id = getThis(); - - intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC); - if (intern && intern->ptr) { - retval = xmlTextReaderMoveToAttributeNo(intern->ptr, attr_pos); - if (retval == 1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} -/* }}} */ - -/* {{{ proto boolean moveToAttributeNs(string name, string namespaceURI) -Positions reader at attribute spcified by name and namespaceURI. -Returns TRUE on success and FALSE on failure */ -PHP_METHOD(xmlreader, moveToAttributeNs) -{ - zval *id; - int name_len=0, ns_uri_len=0, retval; - xmlreader_object *intern; - char *name, *ns_uri; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &name, &name_len, &ns_uri, &ns_uri_len) == FAILURE) { - return; - } - - if (name_len == 0 || ns_uri_len == 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attribute Name and Namespace URI cannot be empty"); - RETURN_FALSE; - } - - id = getThis(); - - intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC); - if (intern && intern->ptr) { - retval = xmlTextReaderMoveToAttributeNs(intern->ptr, name, ns_uri); - if (retval == 1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} -/* }}} */ - -/* {{{ proto boolean moveToElement() -Moves the position of the current instance to the node that contains the current Attribute node. */ -PHP_METHOD(xmlreader, moveToElement) -{ - php_xmlreader_no_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderMoveToElement); -} -/* }}} */ - -/* {{{ proto boolean moveToFirstAttribute() -Moves the position of the current instance to the first attribute associated with the current node. */ -PHP_METHOD(xmlreader, moveToFirstAttribute) -{ - php_xmlreader_no_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderMoveToFirstAttribute); -} -/* }}} */ - -/* {{{ proto boolean moveToNextAttribute() -Moves the position of the current instance to the next attribute associated with the current node. */ -PHP_METHOD(xmlreader, moveToNextAttribute) -{ - php_xmlreader_no_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderMoveToNextAttribute); -} -/* }}} */ - -/* {{{ proto boolean read() -Moves the position of the current instance to the next node in the stream. */ -PHP_METHOD(xmlreader, read) -{ - zval *id; - int retval; - xmlreader_object *intern; - - id = getThis(); - intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC); - if (intern != NULL && intern->ptr != NULL) { - retval = xmlTextReaderRead(intern->ptr); - if (retval == -1) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "An Error Occured while reading"); - RETURN_FALSE; - } else { - RETURN_BOOL(retval); - } - } - - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Load Data before trying to read"); - RETURN_FALSE; -} -/* }}} */ - -/* {{{ proto boolean read() -Moves the position of the current instance to the next node in the stream. */ -PHP_METHOD(xmlreader, next) -{ - zval *id; - int retval; - xmlreader_object *intern; - - id = getThis(); - intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC); - if (intern != NULL && intern->ptr != NULL) { - retval = xmlTextReaderNext(intern->ptr); - if (retval == -1) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "An Error Occured while reading"); - RETURN_FALSE; - } else { - RETURN_BOOL(retval); - } - } - - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Load Data before trying to read"); - RETURN_FALSE; -} -/* }}} */ - -/* {{{ proto boolean open(string URI) -Sets the URI that the the XMLReader will parse. */ -PHP_METHOD(xmlreader, open) -{ - zval *id; - int source_len = 0; - xmlreader_object *intern; - char *source, *valid_file = NULL; - char resolved_path[MAXPATHLEN + 1]; - xmlTextReaderPtr reader = NULL; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &source, &source_len) == FAILURE) { - return; - } - - id = getThis(); - if (id != NULL) { - if (! instanceof_function(Z_OBJCE_P(id), xmlreader_class_entry TSRMLS_CC)) { - id = NULL; - } else { - intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC); - xmlreader_free_resources(intern); - } - } - - if (!source_len) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string supplied as input"); - RETURN_FALSE; - } - - valid_file = _xmlreader_get_valid_file_path(source, resolved_path, MAXPATHLEN TSRMLS_CC); - - if (valid_file) { - reader = xmlNewTextReaderFilename(valid_file); - } - - if (reader == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open source data"); - RETURN_FALSE; - } - - if (id == NULL) { - object_init_ex(return_value, xmlreader_class_entry); - intern = (xmlreader_object *)zend_objects_get_address(return_value TSRMLS_CC); - intern->ptr = reader; - return; - } - - intern->ptr = reader; - - RETURN_TRUE; - -} -/* }}} */ - -/* Not Yet Implemented in libxml - functions exist just not coded -PHP_METHOD(xmlreader, readInnerXml) -{ - php_xmlreader_no_arg_string(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderReadInnerXml); -} - -PHP_METHOD(xmlreader, readOuterXml) -{ - php_xmlreader_no_arg_string(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderReadInnerXml); -} - -PHP_METHOD(xmlreader, readString) -{ - php_xmlreader_no_arg_string(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderReadString); -} - -PHP_METHOD(xmlreader, resetState) -{ - -} -*/ - -/* {{{ proto boolean setParserProperty(int property, boolean value) -Sets parser property (one of the parser option constants). -Properties must be set after open() or XML() and before the first read() is called */ -PHP_METHOD(xmlreader, setParserProperty) -{ - zval *id; - int property, value, retval = -1; - xmlreader_object *intern; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lb", &property, &value) == FAILURE) { - return; - } - - id = getThis(); - - intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC); - if (intern && intern->ptr) { - retval = xmlTextReaderSetParserProp(intern->ptr,property, value); - } - if (retval == -1) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid parser property"); - RETURN_FALSE; - } - - RETURN_TRUE; -} -/* }}} */ - -/* {{{ proto boolean setRelaxNGSchemaSource(string filename) -Sets the string that the the XMLReader will parse. */ -PHP_METHOD(xmlreader, setRelaxNGSchema) -{ - php_xmlreader_set_relaxng_schema(INTERNAL_FUNCTION_PARAM_PASSTHRU, XMLREADER_LOAD_FILE); -} -/* }}} */ - -/* {{{ proto boolean setRelaxNGSchemaSource(string source) -Sets the string that the the XMLReader will parse. */ -PHP_METHOD(xmlreader, setRelaxNGSchemaSource) -{ - php_xmlreader_set_relaxng_schema(INTERNAL_FUNCTION_PARAM_PASSTHRU, XMLREADER_LOAD_STRING); -} -/* }}} */ - -/* {{{ proto boolean XML(string source) -Sets the string that the the XMLReader will parse. */ -PHP_METHOD(xmlreader, XML) -{ - zval *id; - int source_len = 0; - xmlreader_object *intern; - char *source, *uri = NULL; - int resolved_path_len; - char *directory=NULL, resolved_path[MAXPATHLEN]; - xmlParserInputBufferPtr inputbfr; - xmlTextReaderPtr reader; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &source, &source_len) == FAILURE) { - return; - } - - id = getThis(); - if (id != NULL && ! instanceof_function(Z_OBJCE_P(id), xmlreader_class_entry TSRMLS_CC)) { - id = NULL; - } - if (id != NULL) { - intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC); - xmlreader_free_resources(intern); - } - - if (!source_len) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string supplied as input"); - RETURN_FALSE; - } - - inputbfr = xmlParserInputBufferCreateMem(source, source_len, XML_CHAR_ENCODING_NONE); - - if (inputbfr != NULL) { -/* Get the URI of the current script so that we can set the base directory in libxml */ -#if HAVE_GETCWD - directory = VCWD_GETCWD(resolved_path, MAXPATHLEN); -#elif HAVE_GETWD - directory = VCWD_GETWD(resolved_path); -#endif - if (directory) { - resolved_path_len = strlen(resolved_path); - if (resolved_path[resolved_path_len - 1] != DEFAULT_SLASH) { - resolved_path[resolved_path_len] = DEFAULT_SLASH; - resolved_path[++resolved_path_len] = '\0'; - } - uri = (char *) xmlCanonicPath((const xmlChar *) resolved_path); - } - reader = xmlNewTextReader(inputbfr, uri); - if (uri) { - xmlFree(uri); - } - if (reader != NULL) { - if (id == NULL) { - object_init_ex(return_value, xmlreader_class_entry); - intern = (xmlreader_object *)zend_objects_get_address(return_value TSRMLS_CC); - intern->input = inputbfr; - intern->ptr = reader; - return; - } else { - intern->input = inputbfr; - intern->ptr = reader; - RETURN_TRUE; - - } - } - } - - if (inputbfr) { - xmlFreeParserInputBuffer(inputbfr); - } - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to load source data"); - RETURN_FALSE; -} -/* }}} */ - -/* {{{ proto boolean expand() -Moves the position of the current instance to the next node in the stream. */ -PHP_METHOD(xmlreader, expand) -{ -#ifdef HAVE_DOM - zval *id, *rv = NULL; - int ret; - xmlreader_object *intern; - xmlNode *node, *nodec; - - id = getThis(); - intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC); - - if (intern && intern->ptr) { - node = xmlTextReaderExpand(intern->ptr); - - if (node == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "An Error Occured while expanding "); - RETURN_FALSE; - } else { - nodec = xmlCopyNode(node, 1); - DOM_RET_OBJ(rv, nodec, &ret, NULL); - } - } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Load Data before trying to expand"); - RETURN_FALSE; - } -#else - php_error(E_WARNING, "DOM support is not enabled"); - return; -#endif -} -/* }}} */ - -static zend_function_entry xmlreader_functions[] = { - PHP_ME(xmlreader, close, NULL, ZEND_ACC_PUBLIC) - PHP_ME(xmlreader, getAttribute, NULL, ZEND_ACC_PUBLIC) - PHP_ME(xmlreader, getAttributeNo, NULL, ZEND_ACC_PUBLIC) - PHP_ME(xmlreader, getAttributeNs, NULL, ZEND_ACC_PUBLIC) - PHP_ME(xmlreader, getParserProperty, NULL, ZEND_ACC_PUBLIC) - PHP_ME(xmlreader, isValid, NULL, ZEND_ACC_PUBLIC) - PHP_ME(xmlreader, lookupNamespace, NULL, ZEND_ACC_PUBLIC) - PHP_ME(xmlreader, moveToAttributeNo, NULL, ZEND_ACC_PUBLIC) - PHP_ME(xmlreader, moveToAttribute, NULL, ZEND_ACC_PUBLIC) - PHP_ME(xmlreader, moveToAttributeNs, NULL, ZEND_ACC_PUBLIC) - PHP_ME(xmlreader, moveToElement, NULL, ZEND_ACC_PUBLIC) - PHP_ME(xmlreader, moveToFirstAttribute, NULL, ZEND_ACC_PUBLIC) - PHP_ME(xmlreader, moveToNextAttribute, NULL, ZEND_ACC_PUBLIC) - PHP_ME(xmlreader, open, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_ALLOW_STATIC) - PHP_ME(xmlreader, read, NULL, ZEND_ACC_PUBLIC) - PHP_ME(xmlreader, next, NULL, ZEND_ACC_PUBLIC) -/* Not Yet Implemented though defined in libxml as of 2.6.9dev - PHP_ME(xmlreader, readInnerXml, NULL, ZEND_ACC_PUBLIC) - PHP_ME(xmlreader, readOuterXml, NULL, ZEND_ACC_PUBLIC) - PHP_ME(xmlreader, readString, NULL, ZEND_ACC_PUBLIC) - PHP_ME(xmlreader, resetState, NULL, ZEND_ACC_PUBLIC) -*/ - PHP_ME(xmlreader, setParserProperty, NULL, ZEND_ACC_PUBLIC) - PHP_ME(xmlreader, setRelaxNGSchema, NULL, ZEND_ACC_PUBLIC) - PHP_ME(xmlreader, setRelaxNGSchemaSource, NULL, ZEND_ACC_PUBLIC) - PHP_ME(xmlreader, XML, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_ALLOW_STATIC) - PHP_ME(xmlreader, expand, NULL, ZEND_ACC_PUBLIC) - {NULL, NULL, NULL} -}; - -/* {{{ PHP_MINIT_FUNCTION - */ -PHP_MINIT_FUNCTION(xmlreader) -{ - - zend_class_entry ce; - - memcpy(&xmlreader_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - xmlreader_object_handlers.read_property = xmlreader_read_property; - xmlreader_object_handlers.write_property = xmlreader_write_property; - xmlreader_object_handlers.get_property_ptr_ptr = NULL; - - INIT_CLASS_ENTRY(ce, "XMLReader", xmlreader_functions); - ce.create_object = xmlreader_objects_new; - xmlreader_class_entry = zend_register_internal_class(&ce TSRMLS_CC); - - zend_hash_init(&xmlreader_prop_handlers, 0, NULL, NULL, 1); - xmlreader_register_prop_handler(&xmlreader_prop_handlers, "attributeCount", xmlTextReaderAttributeCount, NULL, IS_LONG TSRMLS_CC); - xmlreader_register_prop_handler(&xmlreader_prop_handlers, "baseURI", NULL, xmlTextReaderBaseUri, IS_STRING TSRMLS_CC); - xmlreader_register_prop_handler(&xmlreader_prop_handlers, "depth", xmlTextReaderDepth, NULL, IS_LONG TSRMLS_CC); - xmlreader_register_prop_handler(&xmlreader_prop_handlers, "hasAttributes", xmlTextReaderHasAttributes, NULL, IS_BOOL TSRMLS_CC); - xmlreader_register_prop_handler(&xmlreader_prop_handlers, "hasValue", xmlTextReaderHasValue, NULL, IS_BOOL TSRMLS_CC); - xmlreader_register_prop_handler(&xmlreader_prop_handlers, "isDefault", xmlTextReaderIsDefault, NULL, IS_BOOL TSRMLS_CC); - xmlreader_register_prop_handler(&xmlreader_prop_handlers, "isEmptyElement", xmlTextReaderIsEmptyElement, NULL, IS_BOOL TSRMLS_CC); - xmlreader_register_prop_handler(&xmlreader_prop_handlers, "localName", NULL, xmlTextReaderLocalName, IS_STRING TSRMLS_CC); - xmlreader_register_prop_handler(&xmlreader_prop_handlers, "name", NULL, xmlTextReaderName, IS_STRING TSRMLS_CC); - xmlreader_register_prop_handler(&xmlreader_prop_handlers, "namespaceURI", NULL, xmlTextReaderNamespaceUri, IS_STRING TSRMLS_CC); - xmlreader_register_prop_handler(&xmlreader_prop_handlers, "nodeType", xmlTextReaderNodeType, NULL, IS_LONG TSRMLS_CC); - xmlreader_register_prop_handler(&xmlreader_prop_handlers, "prefix", NULL, xmlTextReaderPrefix, IS_STRING TSRMLS_CC); - xmlreader_register_prop_handler(&xmlreader_prop_handlers, "value", NULL, xmlTextReaderValue, IS_STRING TSRMLS_CC); - xmlreader_register_prop_handler(&xmlreader_prop_handlers, "xmlLang", NULL, xmlTextReaderXmlLang, IS_STRING TSRMLS_CC); - - /* Constants for NodeType - cannot define common types to share with dom as there are differences in these types */ - REGISTER_LONG_CONSTANT("XMLREADER_NONE", XML_READER_TYPE_NONE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("XMLREADER_ELEMENT", XML_READER_TYPE_ELEMENT, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("XMLREADER_ATTRIBUTE", XML_READER_TYPE_ATTRIBUTE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("XMLREADER_TEXT", XML_READER_TYPE_TEXT, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("XMLREADER_CDATA", XML_READER_TYPE_CDATA, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("XMLREADER_ENTITY_REF", XML_READER_TYPE_ENTITY_REFERENCE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("XMLREADER_ENTITY", XML_READER_TYPE_ENTITY, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("XMLREADER_PI", XML_READER_TYPE_PROCESSING_INSTRUCTION, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("XMLREADER_COMMENT", XML_READER_TYPE_COMMENT, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("XMLREADER_DOC", XML_READER_TYPE_DOCUMENT, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("XMLREADER_DOC_TYPE", XML_READER_TYPE_DOCUMENT_TYPE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("XMLREADER_DOC_FRAGMENT", XML_READER_TYPE_DOCUMENT_FRAGMENT, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("XMLREADER_NOTATION", XML_READER_TYPE_NOTATION, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("XMLREADER_WHITESPACE", XML_READER_TYPE_WHITESPACE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("XMLREADER_SIGNIFICANT_WHITESPACE", XML_READER_TYPE_SIGNIFICANT_WHITESPACE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("XMLREADER_END_ELEMENT", XML_READER_TYPE_END_ELEMENT, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("XMLREADER_END_ENTITY", XML_READER_TYPE_END_ENTITY, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("XMLREADER_XML_DECLARATION", XML_READER_TYPE_XML_DECLARATION, CONST_CS | CONST_PERSISTENT); - - /* Constants for Parser options */ - REGISTER_LONG_CONSTANT("XMLREADER_LOADDTD", XML_PARSER_LOADDTD, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("XMLREADER_DEFAULTATTRS", XML_PARSER_DEFAULTATTRS, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("XMLREADER_VALIDATE", XML_PARSER_VALIDATE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("XMLREADER_SUBST_ENTITIES", XML_PARSER_SUBST_ENTITIES, CONST_CS | CONST_PERSISTENT); - - /* Constants for Errors when loading - not yet used until we implement custom error handling - REGISTER_LONG_CONSTANT("XMLREADER_VALIDITY_WARNING", XML_PARSER_SEVERITY_VALIDITY_WARNING, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("XMLREADER_VALIDITY_ERROR", XML_PARSER_SEVERITY_VALIDITY_ERROR, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("XMLREADER_WARNING", XML_PARSER_SEVERITY_WARNING, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("XMLREADER_ERROR", XML_PARSER_SEVERITY_ERROR, CONST_CS | CONST_PERSISTENT); - */ - - return SUCCESS; -} -/* }}} */ - - -/* {{{ PHP_MSHUTDOWN_FUNCTION - */ -PHP_MSHUTDOWN_FUNCTION(xmlreader) -{ - zend_hash_destroy(&xmlreader_prop_handlers); - return SUCCESS; -} -/* }}} */ - -/* {{{ PHP_MINFO_FUNCTION - */ -PHP_MINFO_FUNCTION(xmlreader) -{ - php_info_print_table_start(); - { - php_info_print_table_row(2, "XMLReader", "enabled"); - } - php_info_print_table_end(); - - /* Remove comments if you have entries in php.ini - DISPLAY_INI_ENTRIES(); - */ -} -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/xmlreader/php_xmlreader.h b/ext/xmlreader/php_xmlreader.h deleted file mode 100644 index 2a753efe4fa9..000000000000 --- a/ext/xmlreader/php_xmlreader.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Rob Richards | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifndef PHP_XMLREADER_H -#define PHP_XMLREADER_H - -extern zend_module_entry xmlreader_module_entry; -#define phpext_xmlreader_ptr &xmlreader_module_entry - -#ifdef PHP_WIN32 -#define PHP_XMLREADER_API __declspec(dllexport) -#else -#define PHP_XMLREADER_API -#endif - -#ifdef ZTS -#include "TSRM.h" -#endif - -#include "ext/libxml/php_libxml.h" -#include - -typedef struct _xmlreader_object { - zend_object std; - xmlTextReaderPtr ptr; - /* input is used to allow strings to be loaded under libxml 2.5.x - must manually allocate and de-allocate these - can be refactored when - libxml 2.6.x becomes minimum version */ - xmlParserInputBufferPtr input; - void *schema; - HashTable *prop_handler; - zend_object_handle handle; -} xmlreader_object; - -PHP_MINIT_FUNCTION(xmlreader); -PHP_MSHUTDOWN_FUNCTION(xmlreader); -PHP_MINFO_FUNCTION(xmlreader); - - -#ifdef ZTS -#define XMLREADER_G(v) TSRMG(xmlreader_globals_id, zend_xmlreader_globals *, v) -#else -#define XMLREADER_G(v) (xmlreader_globals.v) -#endif - -#endif /* PHP_XMLREADER_H */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/xmlreader/xmlreader.dsp b/ext/xmlreader/xmlreader.dsp deleted file mode 100644 index 7b21518ba319..000000000000 --- a/ext/xmlreader/xmlreader.dsp +++ /dev/null @@ -1,114 +0,0 @@ -# Microsoft Developer Studio Project File - Name="xmlreader" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 - -CFG=xmlreader - Win32 Release_TS -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "xmlreader.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "xmlreader.mak" CFG="xmlreader - Win32 Release_TS" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "xmlreader - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "xmlreader - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "xmlreader - Win32 Debug_TS" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "xmlreader___Win32_Debug_TS" -# PROP BASE Intermediate_Dir "xmlreader___Win32_Debug_TS" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug_TS" -# PROP Intermediate_Dir "Debug_TS" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "XMLREADER_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\.." /I "..\..\Zend" /I "..\..\TSRM" /I "..\..\main" /D ZEND_DEBUG=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "XMLREADER_EXPORTS" /D "COMPILE_DL_XMLREADER" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D "LIBXML_THREAD_ENABLED" /FR /YX /FD /GZ /c -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 php5ts_debug.lib resolv.lib kernel32.lib user32.lib gdi32.lib winspool.lib /nologo /dll /debug /machine:I386 /nodefaultlib:"msvcrt" /out:"..\..\Debug_TS/php_xmlreader.dll" /libpath:"..\..\Debug_TS" /libpath:"..\..\..\bindlib_w32\Release" - -!ELSEIF "$(CFG)" == "xmlreader - Win32 Release_TS" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "xmlreader___Win32_Release_TS0" -# PROP BASE Intermediate_Dir "xmlreader___Win32_Release_TS0" -# PROP BASE Ignore_Export_Lib 0 -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Release_TS" -# PROP Intermediate_Dir "Release_TS" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\.." /I "..\..\Zend" /I "..\..\TSRM" /I "..\..\main" /D ZEND_DEBUG=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "XMLREADER_EXPORTS" /D "COMPILE_DL_XSL" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D "LIBXML_THREAD_ENABLED" /FR /YX /FD /GZ /c -# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\.." /I "..\..\Zend" /I "..\..\TSRM" /I "..\..\main" /D ZEND_DEBUG=0 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "XMLREADER_EXPORTS" /D "COMPILE_DL_XSL" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D "LIBXML_THREAD_ENABLED" /YX /FD /GZ /c -# SUBTRACT CPP /Fr -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 php5ts_debug.lib resolv.lib kernel32.lib user32.lib gdi32.lib winspool.lib /nologo /dll /debug /machine:I386 /nodefaultlib:"msvcrt" /out:"..\..\Debug_TS/php_xmlreader.dll" /libpath:"..\..\Debug_TS" /libpath:"..\..\..\bindlib_w32\Release" -# ADD LINK32 php5ts.lib resolv.lib kernel32.lib user32.lib gdi32.lib winspool.lib /nologo /dll /incremental:no /machine:I386 /out:"..\..\Release_TS/php_xmlreader.dll" /libpath:"..\..\Debug_TS" /libpath:"..\..\..\bindlib_w32\Release" -# SUBTRACT LINK32 /debug - -!ENDIF - -# Begin Target - -# Name "xmlreader - Win32 Debug_TS" -# Name "xmlreader - Win32 Release_TS" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\php_xmlreader.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=.\php_xmlreader.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/ext/xmlrpc/libxmlrpc/acinclude.m4 b/ext/xmlrpc/libxmlrpc/acinclude.m4 index 07bf4f0b0776..49b6090f6b06 100644 --- a/ext/xmlrpc/libxmlrpc/acinclude.m4 +++ b/ext/xmlrpc/libxmlrpc/acinclude.m4 @@ -1,6 +1,6 @@ # Local macros for automake & autoconf -AC_DEFUN(XMLRPC_FUNCTION_CHECKS,[ +AC_DEFUN([XMLRPC_FUNCTION_CHECKS],[ # Standard XMLRPC list AC_CHECK_FUNCS( \ @@ -10,12 +10,12 @@ AC_CHECK_FUNCS( \ ]) -AC_DEFUN(XMLRPC_HEADER_CHECKS,[ +AC_DEFUN([XMLRPC_HEADER_CHECKS],[ AC_HEADER_STDC AC_CHECK_HEADERS(xmlparse.h xmltok.h stdlib.h strings.h string.h) ]) -AC_DEFUN(XMLRPC_TYPE_CHECKS,[ +AC_DEFUN([XMLRPC_TYPE_CHECKS],[ AC_REQUIRE([AC_C_CONST]) AC_REQUIRE([AC_C_INLINE]) diff --git a/ext/xmlrpc/libxmlrpc/xml_element.c b/ext/xmlrpc/libxmlrpc/xml_element.c index 5fee23959cfc..e3906bb0e70d 100644 --- a/ext/xmlrpc/libxmlrpc/xml_element.c +++ b/ext/xmlrpc/libxmlrpc/xml_element.c @@ -44,6 +44,11 @@ static const char rcsid[] = "#(@) $Id$"; * 06/2000 * HISTORY * $Log$ + * Revision 1.6 2004/06/01 20:16:06 iliaa + * Fixed bug #28597 (xmlrpc_encode_request() incorrectly encodes chars in + * 200-210 range). + * Patch by: fernando dot nemec at folha dot com dot br + * * Revision 1.5 2003/12/16 21:00:21 sniper * Fix some compile warnings (patch by Joe Orton) * @@ -108,7 +113,7 @@ static const char rcsid[] = "#(@) $Id$"; #include "expat.h" #include "encodings.h" -#define my_free(thing) if(thing) {free(thing); thing = 0;} +#define my_free(thing) if(thing) {free(thing); thing = NULL;} #define XML_DECL_START "children); Q_Destroy(&root->attrs); - my_free((char*)root->name); + if(root->name) { + free((char *)root->name); + root->name = NULL; + } simplestring_free(&root->text); my_free(root); } diff --git a/ext/xmlrpc/libxmlrpc/xmlrpc.m4 b/ext/xmlrpc/libxmlrpc/xmlrpc.m4 index e89c245f0253..87da92db8a67 100644 --- a/ext/xmlrpc/libxmlrpc/xmlrpc.m4 +++ b/ext/xmlrpc/libxmlrpc/xmlrpc.m4 @@ -1,4 +1,4 @@ -AC_DEFUN(XMLRPC_CHECKS,[ +AC_DEFUN([XMLRPC_CHECKS],[ AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_PROG_LN_S]) diff --git a/ext/xmlwriter/CREDITS b/ext/xmlwriter/CREDITS deleted file mode 100644 index 08ab51b32b55..000000000000 --- a/ext/xmlwriter/CREDITS +++ /dev/null @@ -1,2 +0,0 @@ -XMLWriter -Rob Richards diff --git a/ext/xmlwriter/EXPERIMENTAL b/ext/xmlwriter/EXPERIMENTAL deleted file mode 100644 index dfa49ae4967b..000000000000 --- a/ext/xmlwriter/EXPERIMENTAL +++ /dev/null @@ -1,4 +0,0 @@ -this module is experimental, -its functions may change their names -so do not rely to much on them -you have been warned! diff --git a/ext/xmlwriter/TODO b/ext/xmlwriter/TODO deleted file mode 100644 index 97ebcb580132..000000000000 --- a/ext/xmlwriter/TODO +++ /dev/null @@ -1,5 +0,0 @@ -- Decide on function naming for xmlwriter creation -- Fix up config file for PHP 5 to use libxml extension configuration -- Add OOP support - - diff --git a/ext/xmlwriter/config.m4 b/ext/xmlwriter/config.m4 deleted file mode 100644 index 18d630482c13..000000000000 --- a/ext/xmlwriter/config.m4 +++ /dev/null @@ -1,61 +0,0 @@ -dnl -dnl $Id$ -dnl - -AC_DEFUN(PHP_XMLWRITER_CHECK_VERSION,[ - old_CPPFLAGS=$CPPFLAGS - CPPFLAGS=-I$XMLWRITER_DIR/include$XMLWRITER_DIR_ADD - AC_MSG_CHECKING(for libxml version) - AC_EGREP_CPP(yes,[ -#include -#if LIBXML_VERSION >= 20600 - yes -#endif - ],[ - AC_MSG_RESULT(>= 2.6.0) - ],[ - AC_MSG_ERROR(libxml version 2.6.0 or greater required.) - ]) - CPPFLAGS=$old_CPPFLAGS -]) - -PHP_ARG_WITH(xmlwriter, for XMLWriter support, -[ --with-xmlwriter Include XMLWriter support.]) - -if test "$PHP_XMLWRITER" != "no"; then - - XMLWRITER_DIR_ADD="" - if test -r $PHP_XMLWRITER/include/libxml2/libxml/xmlwriter.h; then - XMLWRITER_DIR=$PHP_XMLWRITER - XMLWRITER_DIR_ADD="/libxml2" - elif test -r $PHP_XMLWRITER/include/libxml/xmlwriter.h; then - XMLWRITER_DIR=$PHP_XMLWRITER - else - for i in /usr/local /usr; do - test -r $i/include/libxml/xmlwriter.h && XMLWRITER_DIR=$i - test -r $i/include/libxml2/libxml/xmlwriter.h && XMLWRITER_DIR=$i && XMLWRITER_DIR_ADD="/libxml2" - done - fi - - if test -z "$XMLWRITER_DIR"; then - AC_MSG_RESULT(not found) - AC_MSG_ERROR(Please reinstall the libxml >= 2.6.0 distribution) - fi - - PHP_XMLWRITER_CHECK_VERSION - - XML2_CONFIG=$XMLWRITER_DIR/bin/xml2-config - - if test -x $XML2_CONFIG; then - XMLWRITER_LIBS=`$XML2_CONFIG --libs` - PHP_EVAL_LIBLINE($XMLWRITER_LIBS, XMLWRITER_SHARED_LIBADD) - else - PHP_ADD_LIBRARY_WITH_PATH($XMLWRITER_LIBNAME, $XMLWRITER_DIR/lib, XMLWRITER_SHARED_LIBADD) - fi - - PHP_ADD_INCLUDE($XMLWRITER_DIR/include$XMLWRITER_DIR_ADD) - - AC_DEFINE(HAVE_XMLWRITER,1,[ ]) - PHP_NEW_EXTENSION(xmlwriter, php_xmlwriter.c, $ext_shared) - PHP_SUBST(XMLWRITER_SHARED_LIBADD) -fi diff --git a/ext/xmlwriter/config.w32 b/ext/xmlwriter/config.w32 deleted file mode 100644 index 72dc218c5db5..000000000000 --- a/ext/xmlwriter/config.w32 +++ /dev/null @@ -1,14 +0,0 @@ -// $Id$ -// vim:ft=javascript - -ARG_WITH("xmlwriter", "XMLWriter support", "yes"); - -if (PHP_XMLWRITER == "yes" && PHP_LIBXML == "yes") { - EXTENSION("xmlwriter", "php_xmlwriter.c"); - AC_DEFINE("HAVE_XMLWRITER", 1, "XMLWriter support"); - if (!PHP_XMLWRITER_SHARED) { - ADD_FLAG("CFLAGS_XMLWRITER", "/D LIBXML_STATIC"); - } - ADD_EXTENSION_DEP('xmlwriter', 'libxml'); -} - diff --git a/ext/xmlwriter/package.xml b/ext/xmlwriter/package.xml deleted file mode 100644 index d7cc5d2d48ab..000000000000 --- a/ext/xmlwriter/package.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - xmlwriter - Provides fast, non-cached, forward-only means to write XML data. - - This extension wraps the libxml xmlWriter API. Represents a writer that - provides a non-cached, forward-only means of generating streams or files - containing XML data. - - PHP License - - - rrichards - Rob Richards - rrichards@php.net - lead - - - - 0.1 - 2004-07-12 - beta - - - - - - - - - - - - - - - - diff --git a/ext/xmlwriter/php_xmlwriter.c b/ext/xmlwriter/php_xmlwriter.c deleted file mode 100644 index 9dcba9c9419e..000000000000 --- a/ext/xmlwriter/php_xmlwriter.c +++ /dev/null @@ -1,1314 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Rob Richards | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - - -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "php_xmlwriter.h" - -zend_class_entry *xmlwriter_class_entry; - -static zend_function_entry xmlwriter_functions[] = { - PHP_FE(xmlwriter_open_uri, NULL) - PHP_FE(xmlwriter_open_memory, NULL) -#if LIBXML_VERSION >= 20605 - PHP_FE(xmlwriter_set_indent, NULL) - PHP_FE(xmlwriter_set_indent_string, NULL) -#endif - PHP_FE(xmlwriter_start_attribute, NULL) - PHP_FE(xmlwriter_end_attribute, NULL) - PHP_FE(xmlwriter_start_attribute_ns, NULL) - PHP_FE(xmlwriter_write_attribute, NULL) - PHP_FE(xmlwriter_write_attribute_ns, NULL) - PHP_FE(xmlwriter_start_element, NULL) - PHP_FE(xmlwriter_end_element, NULL) - PHP_FE(xmlwriter_start_element_ns, NULL) - PHP_FE(xmlwriter_write_element, NULL) - PHP_FE(xmlwriter_write_element_ns, NULL) - PHP_FE(xmlwriter_start_pi, NULL) - PHP_FE(xmlwriter_end_pi, NULL) - PHP_FE(xmlwriter_write_pi, NULL) - PHP_FE(xmlwriter_start_cdata, NULL) - PHP_FE(xmlwriter_end_cdata, NULL) - PHP_FE(xmlwriter_write_cdata, NULL) - PHP_FE(xmlwriter_text, NULL) - PHP_FE(xmlwriter_start_document, NULL) - PHP_FE(xmlwriter_end_document, NULL) - PHP_FE(xmlwriter_write_comment, NULL) - PHP_FE(xmlwriter_start_dtd, NULL) - PHP_FE(xmlwriter_end_dtd, NULL) - PHP_FE(xmlwriter_write_dtd, NULL) - PHP_FE(xmlwriter_start_dtd_element, NULL) - PHP_FE(xmlwriter_end_dtd_element, NULL) - PHP_FE(xmlwriter_output_memory, NULL) - {NULL, NULL, NULL} -}; - -/* {{{ function prototypes */ -PHP_MINIT_FUNCTION(xmlwriter); -PHP_MSHUTDOWN_FUNCTION(xmlwriter); -PHP_MINFO_FUNCTION(xmlwriter); - -static int le_xmlwriter; - -/* _xmlwriter_get_valid_file_path should be made a - common function in libxml extension as code is common to a few xml extensions */ -char *_xmlwriter_get_valid_file_path(char *source, char *resolved_path, int resolved_path_len TSRMLS_DC) { - xmlURI *uri; - xmlChar *escsource; - char *file_dest; - int isFileUri = 0; - - uri = xmlCreateURI(); - escsource = xmlURIEscapeStr(source, ":"); - xmlParseURIReference(uri, escsource); - xmlFree(escsource); - - if (uri->scheme != NULL) { - /* absolute file uris - libxml only supports localhost or empty host */ - if (strncasecmp(source, "file:///",8) == 0) { - isFileUri = 1; -#ifdef PHP_WIN32 - source += 8; -#else - source += 7; -#endif - } else if (strncasecmp(source, "file://localhost/",17) == 0) { - isFileUri = 1; -#ifdef PHP_WIN32 - source += 17; -#else - source += 16; -#endif - } - } - - file_dest = source; - - if ((uri->scheme == NULL || isFileUri)) { - /* XXX possible buffer overflow if VCWD_REALPATH does not know size of resolved_path */ - if (! VCWD_REALPATH(source, resolved_path)) { - expand_filepath(source, resolved_path TSRMLS_CC); - } - file_dest = resolved_path; - } - - xmlFreeURI(uri); - - return file_dest; -} - -/* {{{ xmlwriter_module_entry - */ -zend_module_entry xmlwriter_module_entry = { - STANDARD_MODULE_HEADER, - "xmlwriter", - xmlwriter_functions, - PHP_MINIT(xmlwriter), - PHP_MSHUTDOWN(xmlwriter), - NULL, - NULL, - PHP_MINFO(xmlwriter), - "0.1", - STANDARD_MODULE_PROPERTIES -}; -/* }}} */ - -#ifdef COMPILE_DL_XMLWRITER -ZEND_GET_MODULE(xmlwriter) -#endif - -/* {{{ xmlwriter_objects_clone */ -void xmlwriter_objects_clone(void *object, void **object_clone TSRMLS_DC) -{ - /* TODO */ -} -/* }}} */ - -static void xmlwriter_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) { - xmlwriter_object *intern; - - intern = (xmlwriter_object *) rsrc->ptr; - if (intern) { - if (intern->ptr) { - xmlFreeTextWriter(intern->ptr); - intern->ptr = NULL; - } - if (intern->output) { - xmlBufferFree(intern->output); - intern->output = NULL; - } - efree(intern); - } -} - -#if LIBXML_VERSION >= 20605 -/* {{{ proto bool xmlwriter_set_indent(resource xmlwriter, bool) -Toggle indentation on/off - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_set_indent) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - int indent, retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rb", &pind, &indent) == FAILURE) { - return; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterSetIndent(ptr, indent); - if (retval == 0) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_set_indent_string(resource xmlwriter, string indentString) -Set string used for indenting - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_set_indent_string) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - char *indent; - int indent_len, retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pind, &indent, &indent_len) == FAILURE) { - return; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterSetIndentString(ptr, indent); - if (retval == 0) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} -#endif - -/* {{{ proto bool xmlwriter_start_attribute(resource xmlwriter, string name) -Create start attribute - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_start_attribute) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - char *name; - int name_len, retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pind, &name, &name_len) == FAILURE) { - return; - } - - retval = xmlValidateName((xmlChar *) name, 0); - if (retval != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Attribute Name"); - RETURN_FALSE; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterStartAttribute(ptr, name); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_end_attribute(resource xmlwriter) -End attribute - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_end_attribute) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - int retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pind) == FAILURE) { - return; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterEndAttribute(ptr); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_start_attribute_ns(resource xmlwriter, string prefix, string name, string uri) -Create start namespaced attribute - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_start_attribute_ns) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - char *name, *prefix, *uri; - int name_len, prefix_len, uri_len, retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsss", &pind, - &prefix, &prefix_len, &name, &name_len, &uri, &uri_len) == FAILURE) { - return; - } - - retval = xmlValidateName((xmlChar *) name, 0); - if (retval != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Attribute Name"); - RETURN_FALSE; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterStartAttributeNS(ptr, prefix, name, uri); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_write_attribute(resource xmlwriter, string name, string content) -Write full attribute - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_write_attribute) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - char *name, *content; - int name_len, content_len, retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &pind, - &name, &name_len, &content, &content_len) == FAILURE) { - return; - } - - retval = xmlValidateName((xmlChar *) name, 0); - if (retval != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Attribute Name"); - RETURN_FALSE; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterWriteAttribute(ptr, name, content); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_write_attribute_ns(resource xmlwriter, string prefix, string name, string uri, string content) -Write full namespaced attribute - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_write_attribute_ns) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - char *name, *prefix, *uri, *content; - int name_len, prefix_len, uri_len, content_len, retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rssss", &pind, - &prefix, &prefix_len, &name, &name_len, &uri, &uri_len, &content, &content_len) == FAILURE) { - return; - } - - retval = xmlValidateName((xmlChar *) name, 0); - if (retval != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Attribute Name"); - RETURN_FALSE; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterWriteAttributeNS(ptr, prefix, name, uri, content); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_start_element(resource xmlwriter, string name) -Create start element tag - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_start_element) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - char *name; - int name_len, retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pind, &name, &name_len) == FAILURE) { - return; - } - - retval = xmlValidateName((xmlChar *) name, 0); - if (retval != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Element Name"); - RETURN_FALSE; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterStartElement(ptr, name); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_start_element_ns(resource xmlwriter, string prefix, string name, string uri) -Create start namespaced element tag - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_start_element_ns) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - char *name, *prefix, *uri; - int name_len, prefix_len, uri_len, retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsss", &pind, - &prefix, &prefix_len, &name, &name_len, &uri, &uri_len) == FAILURE) { - return; - } - - retval = xmlValidateName((xmlChar *) name, 0); - if (retval != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Element Name"); - RETURN_FALSE; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterStartElementNS(ptr, prefix, name, uri); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_end_element(resource xmlwriter) -End current element - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_end_element) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - int retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pind) == FAILURE) { - return; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterEndElement(ptr); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_write_element(resource xmlwriter, string name, string content) -Write full element tag - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_write_element) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - char *name, *content; - int name_len, content_len, retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &pind, - &name, &name_len, &content, &content_len) == FAILURE) { - return; - } - - retval = xmlValidateName((xmlChar *) name, 0); - if (retval != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Element Name"); - RETURN_FALSE; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterWriteElement(ptr, name, content); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_write_element_ns(resource xmlwriter, string prefix, string name, string uri, string content) -Write full namesapced element tag - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_write_element_ns) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - char *name, *prefix, *uri, *content; - int name_len, prefix_len, uri_len, content_len, retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rssss", &pind, - &prefix, &prefix_len, &name, &name_len, &uri, &uri_len, &content, &content_len) == FAILURE) { - return; - } - - retval = xmlValidateName((xmlChar *) name, 0); - if (retval != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Element Name"); - RETURN_FALSE; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterWriteElementNS(ptr, prefix, name, uri, content); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_start_pi(resource xmlwriter, string target) -Create start PI tag - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_start_pi) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - char *target; - int target_len, retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pind, &target, &target_len) == FAILURE) { - return; - } - - retval = xmlValidateName((xmlChar *) target, 0); - if (retval != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid PI Target"); - RETURN_FALSE; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterStartPI(ptr, target); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_end_pi(resource xmlwriter) -End current PI - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_end_pi) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - int retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pind) == FAILURE) { - return; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterEndPI(ptr); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_write_pi(resource xmlwriter, string target, string content) -Write full PI tag - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_write_pi) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - char *target, *content; - int target_len, content_len, retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &pind, - &target, &target_len, &content, &content_len) == FAILURE) { - return; - } - - retval = xmlValidateName((xmlChar *) target, 0); - if (retval != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid PI Target"); - RETURN_FALSE; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterWritePI(ptr, target, content); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_start_cdata(resource xmlwriter) -Create start CDATA tag - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_start_cdata) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - int retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pind) == FAILURE) { - return; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterStartCDATA(ptr); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_end_cdata(resource xmlwriter) -End current CDATA - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_end_cdata) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - int retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pind) == FAILURE) { - return; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterEndCDATA(ptr); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_write_cdata(resource xmlwriter, string content) -Write full CDATA tag - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_write_cdata) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - char *content; - int content_len, retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pind, - &content, &content_len) == FAILURE) { - return; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterWriteCDATA(ptr, content); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_text(resource xmlwriter, string content) -Write text - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_text) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - char *content; - int content_len, retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pind, &content, &content_len) == FAILURE) { - return; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterWriteString(ptr, content); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_write_comment(resource xmlwriter, string content) -Write full comment tag - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_write_comment) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - char *content; - int content_len, retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pind, - &content, &content_len) == FAILURE) { - return; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterWriteComment(ptr, content); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_start_document(resource xmlwriter, string version, string encoding, string standalone) -Create document tag - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_start_document) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - char *version, *enc, *alone; - int version_len, enc_len, alone_len, retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pind, &version, &version_len, &enc, &enc_len, &alone, &alone_len) == FAILURE) { - return; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterStartDocument(ptr, version, enc, alone); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_end_document(resource xmlwriter) -End current document - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_end_document) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - int retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pind) == FAILURE) { - return; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterEndDocument(ptr); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - - -/* {{{ proto bool xmlwriter_start_dtd(resource xmlwriter, string name, string pubid, string sysid) -Create start DTD tag - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_start_dtd) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - char *name, *pubid, *sysid; - int name_len, pubid_len, sysid_len, retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pind, &name, &name_len, &pubid, &pubid_len, &sysid, &sysid_len) == FAILURE) { - return; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterStartDTD(ptr, name, pubid, sysid); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_end_dtd(resource xmlwriter) -End current DTD - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_end_dtd) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - int retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pind) == FAILURE) { - return; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterEndDTD(ptr); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_write_dtd(resource xmlwriter, string name, string pubid, string sysid, string subset) -Write full DTD tag - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_write_dtd) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - char *name, *pubid, *sysid, *subset; - int name_len, pubid_len, sysid_len, subset_len, retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pind, &name, &name_len, &pubid, &pubid_len, &sysid, &sysid_len, &subset, &subset_len) == FAILURE) { - return; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterWriteDTD(ptr, name, pubid, sysid, subset); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_start_dtd_element(resource xmlwriter, string name) -Create start DTD element - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_start_dtd_element) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - char *name; - int name_len, retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pind, &name, &name_len) == FAILURE) { - return; - } - - retval = xmlValidateName((xmlChar *) name, 0); - if (retval != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Attribute Name"); - RETURN_FALSE; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterStartDTDElement(ptr, name); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_end_dtd_element(resource xmlwriter) -End current DTD element - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_end_dtd_element) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - int retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pind) == FAILURE) { - return; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterEndDTDElement(ptr); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_write_dtd_element(resource xmlwriter, string name, string content) -Write full DTD element tag - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_write_dtd_element) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - char *name, *content; - int name_len, content_len, retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &pind, - &name, &name_len, &content, &content_len) == FAILURE) { - return; - } - - retval = xmlValidateName((xmlChar *) name, 0); - if (retval != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Element Name"); - RETURN_FALSE; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterWriteDTDElement(ptr, name, content); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_start_dtd_attlist(resource xmlwriter, string name) -Create start DTD AttList - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_start_dtd_attlist) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - char *name; - int name_len, retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pind, &name, &name_len) == FAILURE) { - return; - } - - retval = xmlValidateName((xmlChar *) name, 0); - if (retval != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Attribute Name"); - RETURN_FALSE; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterStartDTDAttlist(ptr, name); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_end_dtd_attlist(resource xmlwriter) -End current DTD AttList - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_end_dtd_attlist) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - int retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pind) == FAILURE) { - return; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterEndDTDAttlist(ptr); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_write_dtd_attlist(resource xmlwriter, string name, string content) -Write full DTD AttList tag - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_write_dtd_attlist) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - char *name, *content; - int name_len, content_len, retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &pind, - &name, &name_len, &content, &content_len) == FAILURE) { - return; - } - - retval = xmlValidateName((xmlChar *) name, 0); - if (retval != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Element Name"); - RETURN_FALSE; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterWriteDTDAttlist(ptr, name, content); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_start_dtd_entity(resource xmlwriter, string name, bool isparam) -Create start DTD Entity - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_start_dtd_entity) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - char *name; - int name_len, isparm, retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pind, &name, &name_len, &isparm) == FAILURE) { - return; - } - - retval = xmlValidateName((xmlChar *) name, 0); - if (retval != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Attribute Name"); - RETURN_FALSE; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterStartDTDEntity(ptr, isparm, name); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_end_dtd_entity(resource xmlwriter) -End current DTD Entity - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_end_dtd_entity) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - int retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pind) == FAILURE) { - return; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterEndDTDEntity(ptr); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto bool xmlwriter_write_dtd_entity(resource xmlwriter, string name, string content) -Write full DTD Entity tag - returns FALSE on error */ -PHP_FUNCTION(xmlwriter_write_dtd_entity) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - char *name, *content; - int name_len, content_len, retval; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &pind, - &name, &name_len, &content, &content_len) == FAILURE) { - return; - } - - retval = xmlValidateName((xmlChar *) name, 0); - if (retval != 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Element Name"); - RETURN_FALSE; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - - if (ptr) { - retval = xmlTextWriterWriteDTDAttlist(ptr, name, content); - if (retval != -1) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} - -/* {{{ proto resource xmlwriter_open_uri(resource xmlwriter, string source) -Create new xmlwriter using source uri for output */ -PHP_FUNCTION(xmlwriter_open_uri) -{ - char *valid_file = NULL; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - char *source; - char resolved_path[MAXPATHLEN + 1]; - int source_len; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &source, &source_len) == FAILURE) { - WRONG_PARAM_COUNT; - return; - } - - valid_file = _xmlwriter_get_valid_file_path(source, resolved_path, MAXPATHLEN TSRMLS_CC); - if (!valid_file) { - RETURN_FALSE; - } - - ptr = xmlNewTextWriterFilename(valid_file, 0); - if (! ptr) { - RETURN_FALSE; - } - - intern = emalloc(sizeof(xmlwriter_object)); - intern->ptr = ptr; - intern->output = NULL; - - ZEND_REGISTER_RESOURCE(return_value,intern,le_xmlwriter); - -} - -/* {{{ proto resource xmlwriter_open_memory() -Create new xmlwriter using memory for string output */ -PHP_FUNCTION(xmlwriter_open_memory) -{ - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - xmlBufferPtr buffer; - - buffer = xmlBufferCreate(); - - if (buffer == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create output buffer"); - RETURN_FALSE; - } - - ptr = xmlNewTextWriterMemory(buffer, 0); - if (! ptr) { - xmlBufferFree(buffer); - RETURN_FALSE; - } - - intern = emalloc(sizeof(xmlwriter_object)); - intern->ptr = ptr; - intern->output = buffer; - - ZEND_REGISTER_RESOURCE(return_value,intern,le_xmlwriter); - -} - -/* {{{ proto string xmlwriter_output_memory(resource xmlwriter) -Output current buffer as string */ -PHP_FUNCTION(xmlwriter_output_memory) -{ - zval *pind; - xmlwriter_object *intern; - xmlTextWriterPtr ptr; - xmlBufferPtr buffer; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pind) == FAILURE) { - return; - } - - ZEND_FETCH_RESOURCE(intern,xmlwriter_object *, &pind, -1, "XMLWriter", le_xmlwriter); - ptr = intern->ptr; - buffer = intern->output; - - if (ptr && buffer) { - xmlTextWriterFlush(ptr); - RETVAL_STRING(buffer->content, 1); - xmlBufferEmpty(buffer); - return; - } - - RETURN_EMPTY_STRING() -} - -/* {{{ PHP_MINIT_FUNCTION - */ -PHP_MINIT_FUNCTION(xmlwriter) -{ - - le_xmlwriter = zend_register_list_destructors_ex(xmlwriter_dtor, NULL, "xmlwriter", module_number); - - return SUCCESS; -} -/* }}} */ - - -/* {{{ PHP_MSHUTDOWN_FUNCTION - */ -PHP_MSHUTDOWN_FUNCTION(xmlwriter) -{ - return SUCCESS; -} -/* }}} */ - -/* {{{ PHP_MINFO_FUNCTION - */ -PHP_MINFO_FUNCTION(xmlwriter) -{ - php_info_print_table_start(); - { - php_info_print_table_row(2, "XMLWriter", "enabled"); - } - php_info_print_table_end(); -} -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/xmlwriter/php_xmlwriter.h b/ext/xmlwriter/php_xmlwriter.h deleted file mode 100644 index c0b4ea5ba0ea..000000000000 --- a/ext/xmlwriter/php_xmlwriter.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Rob Richards | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifndef PHP_XMLWRITER_H -#define PHP_XMLWRITER_H - -extern zend_module_entry xmlwriter_module_entry; -#define phpext_xmlwriter_ptr &xmlwriter_module_entry - -#ifdef PHP_WIN32 -#define PHP_XMLWRITER_API __declspec(dllexport) -#else -#define PHP_XMLWRITER_API -#endif - -#ifdef ZTS -#include "TSRM.h" -#endif - -#include -#include -#include - -typedef struct _xmlwriter_object { - xmlTextWriterPtr ptr; - xmlBufferPtr output; -} xmlwriter_object; - -#if LIBXML_VERSION >= 20605 -PHP_FUNCTION(xmlwriter_set_indent); -PHP_FUNCTION(xmlwriter_set_indent_string); -#endif -PHP_FUNCTION(xmlwriter_start_attribute); -PHP_FUNCTION(xmlwriter_end_attribute); -PHP_FUNCTION(xmlwriter_start_attribute_ns); -PHP_FUNCTION(xmlwriter_write_attribute); -PHP_FUNCTION(xmlwriter_write_attribute_ns); -PHP_FUNCTION(xmlwriter_start_element); -PHP_FUNCTION(xmlwriter_end_element); -PHP_FUNCTION(xmlwriter_start_element_ns); -PHP_FUNCTION(xmlwriter_write_element); -PHP_FUNCTION(xmlwriter_write_element_ns); -PHP_FUNCTION(xmlwriter_start_pi); -PHP_FUNCTION(xmlwriter_end_pi); -PHP_FUNCTION(xmlwriter_write_pi); -PHP_FUNCTION(xmlwriter_start_cdata); -PHP_FUNCTION(xmlwriter_end_cdata); -PHP_FUNCTION(xmlwriter_write_cdata); -PHP_FUNCTION(xmlwriter_text); -PHP_FUNCTION(xmlwriter_start_document); -PHP_FUNCTION(xmlwriter_end_document); -PHP_FUNCTION(xmlwriter_write_comment); -PHP_FUNCTION(xmlwriter_start_dtd); -PHP_FUNCTION(xmlwriter_end_dtd); -PHP_FUNCTION(xmlwriter_write_dtd); -PHP_FUNCTION(xmlwriter_start_dtd_element); -PHP_FUNCTION(xmlwriter_end_dtd_element); -PHP_FUNCTION(xmlwriter_open_uri); -PHP_FUNCTION(xmlwriter_open_memory); -PHP_FUNCTION(xmlwriter_output_memory); - -#ifdef ZTS -#define XMLWRITER_G(v) TSRMG(xmlwriter_globals_id, zend_xmlwriter_globals *, v) -#else -#define XMLWRITER_G(v) (xmlwriter_globals.v) -#endif - -#endif /* PHP_XMLWRITER_H */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/ext/xsl/EXPERIMENTAL b/ext/xsl/EXPERIMENTAL deleted file mode 100644 index 293159a693de..000000000000 --- a/ext/xsl/EXPERIMENTAL +++ /dev/null @@ -1,5 +0,0 @@ -this module is experimental, -its functions may change their names -or move to extension all together -so do not rely to much on them -you have been warned! diff --git a/ext/xsl/config.m4 b/ext/xsl/config.m4 index 13290409ac29..da89b9df1815 100644 --- a/ext/xsl/config.m4 +++ b/ext/xsl/config.m4 @@ -6,12 +6,16 @@ PHP_ARG_WITH(xsl, for XSL support, [ --with-xsl[=DIR] Include new XSL support (requires libxslt >= 1.0.18). DIR is the libxslt install directory.]) -if test "$PHP_XSL" != "no" -a "$PHP_DOM" = "no"; then - AC_MSG_ERROR([XSL extension requires DOM extension, add --enable-dom.]) -fi - if test "$PHP_XSL" != "no"; then + if test "$PHP_LIBXML" = "no"; then + AC_MSG_ERROR([XSL extension requires LIBXML extension, add --enable-libxml]) + fi + + if test "$PHP_DOM" = "no"; then + AC_MSG_ERROR([XSL extension requires DOM extension, add --enable-dom]) + fi + for i in $PHP_XSL /usr/local /usr; do if test -x "$i/bin/xslt-config"; then XSLT_CONFIG=$i/bin/xslt-config diff --git a/ext/xsl/config.w32 b/ext/xsl/config.w32 index 2a92a7b0375d..37da4bd630d1 100644 --- a/ext/xsl/config.w32 +++ b/ext/xsl/config.w32 @@ -6,16 +6,28 @@ ARG_WITH("xsl", "xsl support", "no"); if (PHP_XSL != "no") { if (PHP_DOM == "yes" && PHP_LIBXML == "yes") { var ext_xsl_lib_found = false; + var ext_exslt_lib_found = false; if (CHECK_LIB("libxslt_a.lib", "xsl", PHP_XSL)) { - ADD_FLAG("CFLAGS_XSL", "/D LIBXSLT_STATIC "); ext_xsl_lib_found = true; + ADD_FLAG("CFLAGS_XSL", "/D LIBXSLT_STATIC "); + if (CHECK_LIB("libexslt_a.lib", "xsl", PHP_XSL)) { + ADD_FLAG("CFLAGS_XSL", "/D LIBEXSLT_STATIC "); + ext_exslt_lib_found = true; + } } else if (CHECK_LIB("libxslt.lib", "xsl", PHP_XSL)) { ext_xsl_lib_found = true; + if (CHECK_LIB("libexslt.lib", "xsl", PHP_XSL)) { + ext_exslt_lib_found = true; + } } if (ext_xsl_lib_found && CHECK_HEADER_ADD_INCLUDE("libxslt\\xslt.h", "CFLAGS_XSL")) { - + if (ext_exslt_lib_found) { + if (CHECK_HEADER_ADD_INCLUDE("libexslt\\exslt.h", "CFLAGS_XSL")) { + AC_DEFINE("HAVE_XSL_EXSLT", 1, ""); + } + } EXTENSION("xsl", "php_xsl.c xsltprocessor.c", PHP_XSL_SHARED); AC_DEFINE("HAVE_XSL", 1, "Define if xsl extension is enabled"); if (! PHP_XSL_SHARED) { diff --git a/ext/xsl/php_xsl.c b/ext/xsl/php_xsl.c index 44908be596da..904739a2656e 100644 --- a/ext/xsl/php_xsl.c +++ b/ext/xsl/php_xsl.c @@ -67,60 +67,6 @@ zend_module_entry xsl_module_entry = { ZEND_GET_MODULE(xsl) #endif -/* {{{ xsl_objects_clone */ -void xsl_objects_clone(void *object, void **object_clone TSRMLS_DC) -{ - xsl_object *intern = (xsl_object *) object; - xsl_object *clone; - zval *tmp; - zend_class_entry *class_type; - - class_type = intern->std.ce; - - clone = emalloc(sizeof(xsl_object)); - clone->std.ce = class_type; - clone->std.in_get = 0; - clone->std.in_set = 0; - clone->ptr = NULL; - clone->prop_handler = NULL; - clone->parameter = NULL; - clone->hasKeys = intern->hasKeys; - clone->registerPhpFunctions = 0; - - ALLOC_HASHTABLE(clone->std.properties); - zend_hash_init(clone->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0); - zend_hash_copy(clone->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); - ALLOC_HASHTABLE(clone->parameter); - zend_hash_init(clone->parameter, 0, NULL, ZVAL_PTR_DTOR, 0); - - *object_clone = (void *) clone; -} -/* }}} */ - -zend_object_value xsl_objects_store_clone_obj(zval *zobject TSRMLS_DC) -{ - zend_object_value retval; - void *new_object; - xsl_object *intern; - struct _store_object *obj; - zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); - - obj = &EG(objects_store).object_buckets[handle].bucket.obj; - - if (obj->clone == NULL) { - zend_error(E_CORE_ERROR, "Trying to clone uncloneable object of class %s", Z_OBJCE_P(zobject)->name); - } - - obj->clone(obj->object, &new_object TSRMLS_CC); - - retval.handle = zend_objects_store_put(new_object, obj->dtor, obj->free_storage, obj->clone TSRMLS_CC); - intern = (xsl_object *) new_object; - intern->handle = retval.handle; - retval.handlers = Z_OBJ_HT_P(zobject); - - return retval; -} - /* {{{ xsl_objects_free_storage */ void xsl_objects_free_storage(void *object TSRMLS_DC) { @@ -132,6 +78,11 @@ void xsl_objects_free_storage(void *object TSRMLS_DC) zend_hash_destroy(intern->parameter); FREE_HASHTABLE(intern->parameter); + if (intern->node_list) { + zend_hash_destroy(intern->node_list); + FREE_HASHTABLE(intern->node_list); + } + if (intern->ptr) { /* free wrapper */ if (((xsltStylesheetPtr) intern->ptr)->_private != NULL) { @@ -160,13 +111,14 @@ zend_object_value xsl_objects_new(zend_class_entry *class_type TSRMLS_DC) intern->parameter = NULL; intern->hasKeys = 0; intern->registerPhpFunctions = 0; + intern->node_list = NULL; ALLOC_HASHTABLE(intern->std.properties); zend_hash_init(intern->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0); zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); ALLOC_HASHTABLE(intern->parameter); zend_hash_init(intern->parameter, 0, NULL, ZVAL_PTR_DTOR, 0); - retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t) xsl_objects_free_storage, xsl_objects_clone TSRMLS_CC); + retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t) xsl_objects_free_storage, NULL TSRMLS_CC); intern->handle = retval.handle; retval.handlers = &xsl_object_handlers; return retval; @@ -181,13 +133,20 @@ PHP_MINIT_FUNCTION(xsl) zend_class_entry ce; memcpy(&xsl_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - xsl_object_handlers.clone_obj = xsl_objects_store_clone_obj; + xsl_object_handlers.clone_obj = NULL; REGISTER_XSL_CLASS(ce, "XSLTProcessor", NULL, php_xsl_xsltprocessor_class_functions, xsl_xsltprocessor_class_entry); #if HAVE_XSL_EXSLT exsltRegisterAll(); #endif + xsltRegisterExtModuleFunction ((const xmlChar *) "functionString", + (const xmlChar *) "http://php.net/xsl", + xsl_ext_function_string_php); + xsltRegisterExtModuleFunction ((const xmlChar *) "function", + (const xmlChar *) "http://php.net/xsl", + xsl_ext_function_object_php); + REGISTER_LONG_CONSTANT("XSL_CLONE_AUTO", 0, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("XSL_CLONE_NEVER", -1, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("XSL_CLONE_ALWAYS", 1, CONST_CS | CONST_PERSISTENT); @@ -274,6 +233,12 @@ PHP_MSHUTDOWN_FUNCTION(xsl) /* uncomment this line if you have INI entries UNREGISTER_INI_ENTRIES(); */ + + xsltUnregisterExtModuleFunction ((const xmlChar *) "functionString", + (const xmlChar *) "http://php.net/xsl"); + xsltUnregisterExtModuleFunction ((const xmlChar *) "function", + (const xmlChar *) "http://php.net/xsl"); + xsltCleanupGlobals(); return SUCCESS; @@ -285,6 +250,7 @@ PHP_MSHUTDOWN_FUNCTION(xsl) */ PHP_RINIT_FUNCTION(xsl) { + xsltSetGenericErrorFunc(NULL, php_libxml_error_handler); return SUCCESS; } /* }}} */ @@ -294,6 +260,7 @@ PHP_RINIT_FUNCTION(xsl) */ PHP_RSHUTDOWN_FUNCTION(xsl) { + xsltSetGenericErrorFunc(NULL, NULL); return SUCCESS; } /* }}} */ diff --git a/ext/xsl/php_xsl.h b/ext/xsl/php_xsl.h index bd71315932ef..fb607659d704 100644 --- a/ext/xsl/php_xsl.h +++ b/ext/xsl/php_xsl.h @@ -57,12 +57,16 @@ typedef struct _xsl_object { HashTable *parameter; int hasKeys; int registerPhpFunctions; + HashTable *node_list; } xsl_object; void php_xsl_set_object(zval *wrapper, void *obj TSRMLS_DC); void xsl_objects_free_storage(void *object TSRMLS_DC); zval *php_xsl_create_object(xsltStylesheetPtr obj, int *found, zval *wrapper_in, zval *return_value TSRMLS_DC); +void xsl_ext_function_string_php(xmlXPathParserContextPtr ctxt, int nargs); +void xsl_ext_function_object_php(xmlXPathParserContextPtr ctxt, int nargs); + #define REGISTER_XSL_CLASS(ce, name, parent_ce, funcs, entry) \ INIT_CLASS_ENTRY(ce, name, funcs); \ ce.create_object = xsl_objects_new; \ diff --git a/ext/xsl/tests/bug33853.phpt b/ext/xsl/tests/bug33853.phpt new file mode 100755 index 000000000000..bcf30f65a36a --- /dev/null +++ b/ext/xsl/tests/bug33853.phpt @@ -0,0 +1,33 @@ +--TEST-- +Bug #33853 (php:function call __autoload with lowercase param) +--SKIPIF-- + +--FILE-- +loadXML(' + + + + +'); +$inputdom = new DomDocument(); +$inputdom->loadXML(' +'); + +$proc = new XsltProcessor(); +$proc->registerPhpFunctions(); +$xsl = $proc->importStylesheet($xsl); +$newdom = $proc->transformToDoc($inputdom); +?> +===DONE=== +--EXPECT-- +string(4) "TeSt" diff --git a/ext/xsl/tests/exslt.xml b/ext/xsl/tests/exslt.xml index 0d9c8eb75be0..54913c6f5d83 100644 --- a/ext/xsl/tests/exslt.xml +++ b/ext/xsl/tests/exslt.xml @@ -1,10 +1,9 @@ - - - - - - - - - - + + + + + + + + + diff --git a/ext/xsl/tests/exslt.xsl b/ext/xsl/tests/exslt.xsl index 06ffd8d60d03..8f0baef6ca8f 100644 --- a/ext/xsl/tests/exslt.xsl +++ b/ext/xsl/tests/exslt.xsl @@ -1,46 +1,45 @@ - - - - - - - Test Date : - - year : - - leap-year : - - month-in-year : - - month-name : - - month-abbreviation : - - week-in-year : - - day-in-year : - - day-in-month : - - day-of-week-in-month : - - day-in-week : - - day-name : - - day-abbreviation : - - time : - - hour-in-day : - - minute-in-hour : - - second-in-minute : - - - - + + + + + + + Test Date : + + year : + + leap-year : + + month-in-year : + + month-name : + + month-abbreviation : + + week-in-year : + + day-in-year : + + day-in-month : + + day-of-week-in-month : + + day-in-week : + + day-name : + + day-abbreviation : + + time : + + hour-in-day : + + minute-in-hour : + + second-in-minute : + + + diff --git a/ext/xsl/xsltprocessor.c b/ext/xsl/xsltprocessor.c index a331df7df666..9f29436adeda 100644 --- a/ext/xsl/xsltprocessor.c +++ b/ext/xsl/xsltprocessor.c @@ -27,9 +27,6 @@ #include "php_xsl.h" #include "ext/libxml/php_libxml.h" -static void xsl_ext_function_string_php(xmlXPathParserContextPtr ctxt, int nargs); -static void xsl_ext_function_object_php(xmlXPathParserContextPtr ctxt, int nargs); - /* * class xsl_xsltprocessor * @@ -76,13 +73,6 @@ static char *php_xsl_xslt_string_to_xpathexpr(const char *str TSRMLS_DC) return (char *) value; } -static void php_xsl_unregister_php_functions() { - xsltUnregisterExtModuleFunction ((const xmlChar *) "functionString", - (const xmlChar *) "http://php.net/xsl"); - xsltUnregisterExtModuleFunction ((const xmlChar *) "function", - (const xmlChar *) "http://php.net/xsl"); -} - /* {{{ php_xsl_xslt_make_params() Translates a PHP array to a libxslt parameters array */ @@ -139,25 +129,54 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t zval **args; zval *retval; int result, i, ret; + int error = 0; zend_fcall_info fci; zval handler; xmlXPathObjectPtr obj; char *str; char *callable = NULL; + xsl_object *intern; TSRMLS_FETCH(); + if (! zend_is_executing(TSRMLS_C)) { + xsltGenericError(xsltGenericErrorContext, + "xsltExtFunctionTest: Function called from outside of PHP\n"); + error = 1; + } else { tctxt = xsltXPathGetTransformContext(ctxt); if (tctxt == NULL) { xsltGenericError(xsltGenericErrorContext, "xsltExtFunctionTest: failed to get the transformation context\n"); + error = 1; + } else { + intern = (xsl_object *) tctxt->_private; + if (intern == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xsltExtFunctionTest: failed to get the internal object\n"); + error = 1; + } + else if (intern->registerPhpFunctions == 0) { + xsltGenericError(xsltGenericErrorContext, + "xsltExtFunctionTest: PHP Object did not register PHP functions\n"); + error = 1; + } + } + } + + if (error == 1) { + for (i = nargs - 1; i >= 0; i--) { + obj = valuePop(ctxt); + xmlXPathFreeObject(obj); + } return; } fci.param_count = nargs - 1; - fci.params = safe_emalloc(fci.param_count, sizeof(zval**), 0); - - args = safe_emalloc(nargs - 1, sizeof(zval *), 0); + if (fci.param_count > 0) { + fci.params = safe_emalloc(fci.param_count, sizeof(zval**), 0); + args = safe_emalloc(fci.param_count, sizeof(zval *), 0); + } /* Reverse order to pop values off ctxt stack */ for (i = nargs - 2; i >= 0; i--) { obj = valuePop(ctxt); @@ -179,10 +198,10 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t xmlFree(str); } else if (type == 2) { int j; - dom_object *intern; + dom_object *domintern; array_init(args[i]); - if (obj->nodesetval->nodeNr > 0) { - intern = (dom_object *) php_dom_object_get_data((void *) obj->nodesetval->nodeTab[0]->doc); + if (obj->nodesetval && obj->nodesetval->nodeNr > 0) { + domintern = (dom_object *) php_dom_object_get_data((void *) obj->nodesetval->nodeTab[0]->doc); for (j = 0; j < obj->nodesetval->nodeNr; j++) { xmlNodePtr node = obj->nodesetval->nodeTab[j]; zval *child; @@ -207,7 +226,7 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t node->parent = nsparent; node->ns = curns; } - child = php_dom_create_object(node, &ret, NULL, child, intern TSRMLS_CC); + child = php_dom_create_object(node, &ret, NULL, child, domintern TSRMLS_CC); add_next_index_zval(args[i], child); } } @@ -228,11 +247,13 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t if (obj->stringval == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Handler name must be a string"); xmlXPathFreeObject(obj); - for (i = 0; i < nargs - 1; i++) { - zval_ptr_dtor(&args[i]); + if (fci.param_count > 0) { + for (i = 0; i < nargs - 1; i++) { + zval_ptr_dtor(&args[i]); + } + efree(args); + efree(fci.params); } - efree(args); - efree(fci.params); return; } INIT_PZVAL(&handler); @@ -253,11 +274,19 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t if (result == FAILURE) { if (Z_TYPE(handler) == IS_STRING) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call handler %s()", Z_STRVAL_P(&handler)); - } + } + /* retval is == NULL, when an exception occured, don't report anything, because PHP itself will handle that */ + } else if (retval == NULL) { } else { if (retval->type == IS_OBJECT && instanceof_function( Z_OBJCE_P(retval), dom_node_class_entry TSRMLS_CC)) { xmlNode *nodep; dom_object *obj; + if (intern->node_list == NULL) { + ALLOC_HASHTABLE(intern->node_list); + zend_hash_init(intern->node_list, 0, NULL, ZVAL_PTR_DTOR, 0); + } + zval_add_ref(&retval); + zend_hash_next_index_insert(intern->node_list, &retval, sizeof(zval *), NULL); obj = (dom_object *)zend_object_store_get_object(retval TSRMLS_CC); nodep = dom_object_get_node(obj); valuePush(ctxt, xmlXPathNewNodeSet(nodep)); @@ -275,25 +304,27 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t } efree(callable); zval_dtor(&handler); - for (i = 0; i < nargs - 1; i++) { - zval_ptr_dtor(&args[i]); + if (fci.param_count > 0) { + for (i = 0; i < nargs - 1; i++) { + zval_ptr_dtor(&args[i]); + } + efree(args); + efree(fci.params); } - efree(args); - efree(fci.params); } -static void xsl_ext_function_string_php(xmlXPathParserContextPtr ctxt, int nargs) +void xsl_ext_function_string_php(xmlXPathParserContextPtr ctxt, int nargs) { xsl_ext_function_php(ctxt, nargs, 1); } -static void xsl_ext_function_object_php(xmlXPathParserContextPtr ctxt, int nargs) +void xsl_ext_function_object_php(xmlXPathParserContextPtr ctxt, int nargs) { xsl_ext_function_php(ctxt, nargs, 2); } -/* {{{ proto xsl_xsltdocucument xsl_xsltprocessor_import_stylesheet(node index); +/* {{{ proto void xsl_xsltprocessor_import_stylesheet(domdocument doc); URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html# Since: */ @@ -378,7 +409,55 @@ PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet) /* }}} end xsl_xsltprocessor_import_stylesheet */ -/* {{{ proto xsl_document xsl_xsltprocessor_transform_to_doc(node doc [,boolean clone]); +static xmlDocPtr php_xsl_apply_stylesheet(xsl_object *intern, xsltStylesheetPtr style, xmlDocPtr doc TSRMLS_DC) +{ + xmlDocPtr newdocp; + xsltTransformContextPtr ctxt; + char **params = NULL; + int clone; + + if (style == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "No stylesheet associated to this object"); + return NULL; + } + if (intern->parameter) { + params = php_xsl_xslt_make_params(intern->parameter, 0 TSRMLS_CC); + } + + if (intern->hasKeys == 1) { + doc = xmlCopyDoc(doc, 1); + } + + ctxt = xsltNewTransformContext(style, doc); + ctxt->_private = (void *) intern; + + newdocp = xsltApplyStylesheetUser(style, doc, (const char**) params, NULL, NULL, ctxt); + + xsltFreeTransformContext(ctxt); + + if (intern->node_list != NULL) { + zend_hash_destroy(intern->node_list); + FREE_HASHTABLE(intern->node_list); + intern->node_list = NULL; + } + + if (intern->hasKeys == 1) { + xmlFreeDoc(doc); + } + + if (params) { + clone = 0; + while(params[clone]) { + efree(params[clone++]); + } + efree(params); + } + + return newdocp; + +} + +/* {{{ proto domdocument xsl_xsltprocessor_transform_to_doc(domnode doc); URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html# Since: */ @@ -389,8 +468,7 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_doc) xmlNodePtr node = NULL; xmlDoc *newdocp; xsltStylesheetPtr sheetp; - int ret, clone; - char **params = NULL; + int ret; xsl_object *intern; id = getThis(); @@ -411,30 +489,7 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_doc) RETURN_NULL(); } - if (intern->parameter) { - params = php_xsl_xslt_make_params(intern->parameter, 0 TSRMLS_CC); - } - - if (intern->hasKeys == 1) { - doc = xmlCopyDoc(doc, 1); - } - newdocp = xsltApplyStylesheet(sheetp, doc, (const char**) params); - - if (intern->registerPhpFunctions == 1) { - php_xsl_unregister_php_functions(); - } - - if (intern->hasKeys == 1) { - xmlFreeDoc(doc); - } - - if (params) { - clone = 0; - while(params[clone]) { - efree(params[clone++]); - } - efree(params); - } + newdocp = php_xsl_apply_stylesheet(intern, sheetp, doc TSRMLS_CC); if (newdocp) { DOM_RET_OBJ(rv, (xmlNodePtr) newdocp, &ret, NULL); @@ -446,7 +501,7 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_doc) /* }}} end xsl_xsltprocessor_transform_to_doc */ -/* {{{ proto xsl_ xsl_xsltprocessor_transform_to_uri(node doc, string uri [,boolean clone]); +/* {{{ proto int xsl_xsltprocessor_transform_to_uri(domdocument doc, string uri); */ PHP_FUNCTION(xsl_xsltprocessor_transform_to_uri) { @@ -455,8 +510,8 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_uri) xmlDoc *newdocp; xmlNodePtr node = NULL; xsltStylesheetPtr sheetp; - int ret, uri_len, clone; - char **params = NULL, *uri; + int ret, uri_len; + char *uri; xsl_object *intern; id = getThis(); @@ -477,31 +532,7 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_uri) RETURN_NULL(); } - if (intern->parameter) { - params = php_xsl_xslt_make_params(intern->parameter, 0 TSRMLS_CC); - } - - if (intern->hasKeys == 1) { - doc = xmlCopyDoc(doc, 1); - } - - newdocp = xsltApplyStylesheet(sheetp, doc, (const char**)params); - - if (intern->registerPhpFunctions == 1) { - php_xsl_unregister_php_functions(); - } - - if (intern->hasKeys == 1) { - xmlFreeDoc(doc); - } - - if (params) { - clone = 0; - while(params[clone]) { - efree(params[clone++]); - } - efree(params); - } + newdocp = php_xsl_apply_stylesheet(intern, sheetp, doc TSRMLS_CC); ret = -1; if (newdocp) { @@ -514,7 +545,7 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_uri) /* }}} end xsl_xsltprocessor_transform_to_uri */ -/* {{{ proto xsl_string xsl_xsltprocessor_transform_to_xml(node doc [,boolean clone]); +/* {{{ proto string xsl_xsltprocessor_transform_to_xml(domdocument doc); */ PHP_FUNCTION(xsl_xsltprocessor_transform_to_xml) { @@ -523,10 +554,9 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_xml) xmlDoc *newdocp; xmlNodePtr node = NULL; xsltStylesheetPtr sheetp; - int ret, clone; + int ret; xmlChar *doc_txt_ptr; int doc_txt_len; - char **params = NULL; xsl_object *intern; id = getThis(); @@ -547,31 +577,7 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_xml) RETURN_NULL(); } - if (intern->parameter) { - params = php_xsl_xslt_make_params(intern->parameter, 0 TSRMLS_CC); - } - - if (intern->hasKeys == 1) { - doc = xmlCopyDoc(doc, 1); - } - - newdocp = xsltApplyStylesheet(sheetp, doc, (const char**)params); - - if (intern->registerPhpFunctions == 1) { - php_xsl_unregister_php_functions(); - } - - if (intern->hasKeys == 1) { - xmlFreeDoc(doc); - } - - if (params) { - clone = 0; - while(params[clone]) { - efree(params[clone++]); - } - efree(params); - } + newdocp = php_xsl_apply_stylesheet(intern, sheetp, doc TSRMLS_CC); ret = -1; if (newdocp) { @@ -615,7 +621,7 @@ PHP_FUNCTION(xsl_xsltprocessor_set_parameter) } /* }}} end xsl_xsltprocessor_set_parameter */ -/* {{{ proto xsl_ xsl_xsltprocessor_get_parameter(string namespace, string name); +/* {{{ proto string xsl_xsltprocessor_get_parameter(string namespace, string name); */ PHP_FUNCTION(xsl_xsltprocessor_get_parameter) { @@ -640,7 +646,7 @@ PHP_FUNCTION(xsl_xsltprocessor_get_parameter) } /* }}} end xsl_xsltprocessor_get_parameter */ -/* {{{ proto xsl_ xsl_xsltprocessor_remove_parameter(string namespace, string name); +/* {{{ proto bool xsl_xsltprocessor_remove_parameter(string namespace, string name); */ PHP_FUNCTION(xsl_xsltprocessor_remove_parameter) { @@ -663,7 +669,7 @@ PHP_FUNCTION(xsl_xsltprocessor_remove_parameter) } /* }}} end xsl_xsltprocessor_remove_parameter */ -/* {{{ proto xsl_xsltprocessor_register_php_functions(); +/* {{{ proto void xsl_xsltprocessor_register_php_functions(); */ PHP_FUNCTION(xsl_xsltprocessor_register_php_functions) { @@ -676,16 +682,10 @@ PHP_FUNCTION(xsl_xsltprocessor_register_php_functions) intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC); intern->registerPhpFunctions = 1; - xsltRegisterExtModuleFunction ((const xmlChar *) "functionString", - (const xmlChar *) "http://php.net/xsl", - xsl_ext_function_string_php); - xsltRegisterExtModuleFunction ((const xmlChar *) "function", - (const xmlChar *) "http://php.net/xsl", - xsl_ext_function_object_php); } /* }}} end xsl_xsltprocessor_register_php_functions(); */ -/* {{{ proto xsl_xsltprocessor_has_exslt_support(); +/* {{{ proto bool xsl_xsltprocessor_has_exslt_support(); */ PHP_FUNCTION(xsl_xsltprocessor_has_exslt_support) { diff --git a/ext/zlib/php_zlib.def b/ext/zlib/php_zlib.def index 7c4ce9263540..b166331fa9a6 100644 --- a/ext/zlib/php_zlib.def +++ b/ext/zlib/php_zlib.def @@ -3,6 +3,7 @@ EXPORTS compress2 deflate deflateEnd + deflateInit_ deflateInit2_ uncompress inflateInit_ @@ -11,4 +12,4 @@ EXPORTS inflateEnd crc32 inflateReset - \ No newline at end of file + deflateReset diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index a3ae1e438148..0566412d700d 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -640,6 +640,7 @@ static int php_do_deflate(uint str_length, Bytef **p_buffer, uint *p_buffer_len, if (do_end) { err = deflate(&ZLIBG(stream), Z_FINISH); + buffer[outlen + start_offset - ZLIBG(stream).avail_out] = '\0'; } *p_buffer = buffer; diff --git a/ext/zlib/zlib_fopen_wrapper.c b/ext/zlib/zlib_fopen_wrapper.c index a1e897b7afe9..69a5a9a09e4c 100644 --- a/ext/zlib/zlib_fopen_wrapper.c +++ b/ext/zlib/zlib_fopen_wrapper.c @@ -27,6 +27,7 @@ struct php_gz_stream_data_t { gzFile gz_file; + php_stream *stream; }; static size_t php_gziop_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) @@ -74,6 +75,10 @@ static int php_gziop_close(php_stream *stream, int close_handle TSRMLS_DC) ret = gzclose(self->gz_file); self->gz_file = NULL; } + if (self->stream) { + php_stream_close(self->stream); + self->stream = NULL; + } } efree(self); @@ -100,7 +105,7 @@ php_stream_ops php_stream_gzio_ops = { php_stream *php_stream_gzopen(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) { - struct php_gz_stream_data_t *self; + struct php_gz_stream_data_t *self = {0}; php_stream *stream = NULL, *innerstream = NULL; /* sanity check the stream: it can be either read-only or write-only */ @@ -124,8 +129,9 @@ php_stream *php_stream_gzopen(php_stream_wrapper *wrapper, char *path, char *mod if (innerstream) { int fd; - if (SUCCESS == php_stream_cast(innerstream, PHP_STREAM_AS_FD | PHP_STREAM_CAST_RELEASE, (void **) &fd, REPORT_ERRORS)) { + if (SUCCESS == php_stream_cast(innerstream, PHP_STREAM_AS_FD, (void **) &fd, REPORT_ERRORS)) { self->gz_file = gzdopen(fd, mode); + self->stream = innerstream; if (self->gz_file) { stream = php_stream_alloc_rel(&php_stream_gzio_ops, self, 0, mode); if (stream) { diff --git a/ltmain.sh b/ltmain.sh index 7e0c9f487c83..dd490ba90bd1 100644 --- a/ltmain.sh +++ b/ltmain.sh @@ -48,6 +48,9 @@ EOF exit 0 fi +# define SED for historic ltconfig's generated by Libtool 1.3 +test -z "$SED" && SED=sed + # The name of this program. progname=`$echo "$0" | ${SED} 's%^.*/%%'` modename="$progname" @@ -56,7 +59,7 @@ modename="$progname" PROGRAM=ltmain.sh PACKAGE=libtool VERSION=1.4.3 -TIMESTAMP=" (1.922.2.110 2002/10/23 01:39:54)" +TIMESTAMP=" (1.922.2.111 2002/10/23 02:54:36)" default_mode= help="Try \`$progname --help' for more information." @@ -768,6 +771,7 @@ compiler." linker_flags= dllsearchpath= lib_search_path=`pwd` + inst_prefix_dir= avoid_version=no dlfiles= @@ -898,6 +902,11 @@ compiler." prev= continue ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; release) release="-$arg" prev= @@ -999,6 +1008,11 @@ compiler." continue ;; + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) @@ -1893,7 +1907,16 @@ compiler." if test "$hardcode_direct" = yes; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then - add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + add_dir= + if test -n "$inst_prefix_dir"; then + case "$libdir" in + [\\/]*) + add_dir="-L$inst_prefix_dir$libdir" + ;; + esac + fi + add_dir="$add_dir -L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in @@ -1903,7 +1926,16 @@ compiler." add="-l$name" else # We cannot seem to hardcode it, guess we'll fake it. - add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + add_dir= + if test -n "$inst_prefix_dir"; then + case "$libdir" in + [\\/]*) + add_dir="-L$inst_prefix_dir$libdir" + ;; + esac + fi + add_dir="$add_dir -L$libdir" add="-l$name" fi @@ -2236,7 +2268,7 @@ compiler." # Check that each of the things are valid numbers. case $current in - 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; + [0-9]*) ;; *) $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 @@ -2245,7 +2277,7 @@ compiler." esac case $revision in - 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; + [0-9]*) ;; *) $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 @@ -2254,7 +2286,7 @@ compiler." esac case $age in - 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; + [0-9]*) ;; *) $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 @@ -3928,7 +3960,7 @@ fi\ fi done # Quote the link command for shipping. - relink_command="(cd `pwd`; $SHELL $0 --mode=relink $libtool_args)" + relink_command="(cd `pwd`; $SHELL $0 --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` # Only create the output if not a dry run. @@ -4229,12 +4261,30 @@ relink_command=\"$relink_command\"" dir="$dir$objdir" if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$echo "$destdir" | sed "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + if test "$inst_prefix_dir" = "$destdir"; then + $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2 + exit 1 + fi + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$echo "$relink_command" | sed "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$echo "$relink_command" | sed "s%@inst_prefix_dir@%%"` + fi + $echo "$modename: warning: relinking \`$file'" 1>&2 $show "$relink_command" if $run eval "$relink_command"; then : else $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 - continue + exit 1 fi fi @@ -4397,7 +4447,13 @@ relink_command=\"$relink_command\"" if test "$finalize" = yes && test -z "$run"; then tmpdir="/tmp" test -n "$TMPDIR" && tmpdir="$TMPDIR" - tmpdir="$tmpdir/libtool-$$" + tmpdir_mktemp=`mktemp -d $tmpdir/libtool-XXXXXX 2> /dev/null` + if test $? = 0 ; then + tmpdir="$tmpdir_mktemp" + unset tmpdir_mktemp + else + tmpdir="$tmpdir/libtool-$$" + fi if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then : else $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2 diff --git a/main/SAPI.c b/main/SAPI.c index b1e3488f0652..3f695aa731ca 100644 --- a/main/SAPI.c +++ b/main/SAPI.c @@ -290,9 +290,13 @@ SAPI_API void sapi_activate_headers_only(TSRMLS_D) /* SG(sapi_headers).http_response_code = 200; */ SG(sapi_headers).http_status_line = NULL; + SG(read_post_bytes) = 0; + SG(request_info).post_data = NULL; + SG(request_info).raw_post_data = NULL; SG(request_info).current_user = NULL; SG(request_info).current_user_length = 0; SG(request_info).no_headers = 0; + SG(request_info).post_entry = NULL; /* * It's possible to override this general case in the activate() callback, @@ -331,6 +335,7 @@ SAPI_API void sapi_activate(TSRMLS_D) SG(request_info).current_user = NULL; SG(request_info).current_user_length = 0; SG(request_info).no_headers = 0; + SG(request_info).post_entry = NULL; /* It's possible to override this general case in the activate() callback, if * necessary. @@ -387,6 +392,7 @@ SAPI_API void sapi_deactivate(TSRMLS_D) zend_llist_destroy(&SG(sapi_headers).headers); if (SG(request_info).post_data) { efree(SG(request_info).post_data); + SG(request_info).post_data = NULL; } else if (SG(server_context)) { if(sapi_module.read_post) { /* make sure we've consumed all request input data */ @@ -400,18 +406,23 @@ SAPI_API void sapi_deactivate(TSRMLS_D) } if (SG(request_info).raw_post_data) { efree(SG(request_info).raw_post_data); + SG(request_info).raw_post_data = NULL; } if (SG(request_info).auth_user) { efree(SG(request_info).auth_user); + SG(request_info).auth_user = NULL; } if (SG(request_info).auth_password) { efree(SG(request_info).auth_password); + SG(request_info).auth_password = NULL; } if (SG(request_info).content_type_dup) { efree(SG(request_info).content_type_dup); + SG(request_info).content_type_dup = NULL; } if (SG(request_info).current_user) { efree(SG(request_info).current_user); + SG(request_info).current_user = NULL; } if (sapi_module.deactivate) { sapi_module.deactivate(TSRMLS_C); @@ -594,8 +605,6 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC) sapi_update_response_code(302 TSRMLS_CC); } } else if (!STRCASECMP(header_line, "WWW-Authenticate")) { /* HTTP Authentication */ - int newlen; - char *result, *newheader; sapi_update_response_code(401 TSRMLS_CC); /* authentication-required */ @@ -603,8 +612,8 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC) #if (HAVE_PCRE || HAVE_BUNDLED_PCRE) && !defined(COMPILE_DL_PCRE) { zval *repl_temp; - char *ptr = colon_offset+1; - int ptr_len=0, result_len = 0; + char *ptr = colon_offset+1, *result, *newheader; + int ptr_len=0, result_len = 0, newlen = 0; /* skip white space */ while (isspace(*ptr)) { diff --git a/main/alloca.c b/main/alloca.c index ae28159913ae..401649cee091 100644 --- a/main/alloca.c +++ b/main/alloca.c @@ -23,7 +23,7 @@ /* $Id$ */ -#include "php_config.h" +#include #if !HAVE_ALLOCA diff --git a/main/config.nw.h b/main/config.nw.h deleted file mode 100644 index 1329c4f244c7..000000000000 --- a/main/config.nw.h +++ /dev/null @@ -1,316 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -/* config.nw.h. Configure file for NetWare platform */ - - -/* Define if PHP to setup it's own SIGCHLD handler (not needed on NetWare) */ -#define PHP_SIGCHILD 0 - -/* dns functions found in resolv.lib */ -#define HAVE_LIBBIND 1 - -#define HAVE_GETSERVBYNAME 1 -#define HAVE_GETSERVBYPORT 1 -#define HAVE_GETPROTOBYNAME 1 -#define HAVE_GETPROTOBYNUMBER 1 - -/* set to enable bcmath */ -#define HAVE_BCMATH 1 - -/* set to enable mysql */ -#define HAVE_MYSQL 1 - -/* set to enable FTP support */ -#define HAVE_FTP 1 - -/* set to enable SNMP */ -/*#define HAVE_SNMP 1*/ - -/* defines for PostgreSQL extension */ -#define HAVE_PGSQL 1 -#define PHP_PGSQL_PRIVATE 1 -#define HAVE_PGSQL_WITH_MULTIBYTE_SUPPORT 1 -#define HAVE_PQCLIENTENCODING 1 -#define HAVE_PQCMDTUPLES 1 -#define HAVE_PQOIDVALUE 1 - -/* set to enable bundled PCRE library */ -#define HAVE_BUNDLED_PCRE 1 - -/* set to enable bundled expat library */ -/* #define HAVE_LIBEXPAT 1 */ /* For now */ -#define HAVE_WDDX 0 - -/* set to enable the crypt command */ -/* #define HAVE_CRYPT 1 */ -/* #define HAVE_CRYPT_H 1 */ - -/* set to enable force cgi redirect */ -#define FORCE_CGI_REDIRECT 0 - -/* should be added to runtime config*/ -#define PHP_URL_FOPEN 1 - -#define STDIN_FILENO 0 -#define STDOUT_FILENO 1 -#define STDERR_FILENO 2 - -/* ---------------------------------------------------------------- - The following are defaults for run-time configuration - ---------------------------------------------------------------*/ - -#define PHP_SAFE_MODE 0 -#define MAGIC_QUOTES 0 - - -/* Undefine if you want stricter XML/SGML compliance by default */ -/* this disables "" and "" */ -#define DEFAULT_SHORT_OPEN_TAG "1" - - -/* ---------------------------------------------------------------- - The following defines are for those modules which require - external libraries to compile. These will be removed from - here in a future beta, as these modules will be moved out to dll's - ---------------------------------------------------------------*/ -#define HAVE_ERRMSG_H 0 /*needed for mysql 3.21.17 and up*/ -#undef HAVE_ADABAS -#undef HAVE_SOLID - - -/* ---------------------------------------------------------------- - The following may or may not be (or need to be) ported to the - windows environment. - ---------------------------------------------------------------*/ - -/* Define if you have the link function. */ -#undef HAVE_LINK - -/* Define if you have the symlink function. */ -#undef HAVE_SYMLINK - -/* Define if you have the usleep function. */ -#undef HAVE_USLEEP - -#define HAVE_GETCWD 1 -/* #define HAVE_POSIX_READDIR_R 1 */ /* We will use readdir() from LibC */ - -#define NEED_ISBLANK 1 - -/* ---------------------------------------------------------------- - The following should never need to be played with - Functions defined to 0 or remarked out are either already - handled by the standard VC libraries, or are no longer needed, or - simply will/can not be ported. - - DONT TOUCH!!!!! Unless you realy know what your messing with! - ---------------------------------------------------------------*/ - -#define DISCARD_PATH 0 -#undef HAVE_SETITIMER -#undef HAVE_IODBC -#define HAVE_UODBC 1 -#define HAVE_LIBDL 1 -#define HAVE_SENDMAIL 1 - -/* Define if you have the gettimeofday function. */ -#define HAVE_GETTIMEOFDAY 1 - -/* Define if you have the putenv function. */ -#define HAVE_PUTENV 1 - -#define HAVE_LIMITS_H 1 - -#define HAVE_TZSET 1 -#define HAVE_TZNAME 1 - -/* Define if you have the flock function. */ -#undef HAVE_FLOCK - -/* Define if you have alloca, as a function or macro. */ -/* Though we have alloca(), this seems to be causing some problem with the stack pointer -- hence not using it */ -/* #define HAVE_ALLOCA 1 */ - -/* Define if you have */ -#undef HAVE_SYS_TIME_H - -/* Define if you have */ -#define HAVE_SIGNAL_H 1 - -/* Define if your struct stat has st_blksize. */ -#define HAVE_ST_BLKSIZE - -/* Define if your struct stat has st_blocks. */ -#define HAVE_ST_BLOCKS - -/* Define if your struct stat has st_rdev. */ -#define HAVE_ST_RDEV 1 - -/* Define if utime(file, NULL) sets file's timestamp to the present. */ -#define HAVE_UTIME_NULL 1 - -/* Define if you have the vprintf function. */ -#define HAVE_VPRINTF 1 - -/* Define if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define both of these if you want the bundled REGEX library */ -#define REGEX 1 -#define HSREGEX 1 - -#define HAVE_PCRE 1 - -#define HAVE_LDAP 1 - -/* Define if you have the gcvt function. */ -/* #define HAVE_GCVT 1 */ - -/* Define if you have the getlogin function. */ -/* #define HAVE_GETLOGIN 1 */ - -/* Define if you have the memcpy function. */ -#define HAVE_MEMCPY 1 - -/* Define if you have the memmove function. */ -#define HAVE_MEMMOVE 1 - -/* Define if you have the regcomp function. */ -#define HAVE_REGCOMP 1 - -/* Define if you have the setlocale function. */ -/* #define HAVE_SETLOCALE 1 */ /* LibC doesn't seem to be supporting fully -- hence commenting for now */ - -#define HAVE_LOCALECONV 1 - -#define HAVE_LOCALE_H 1 - -/* Define if you have the setvbuf function. */ -#ifndef HAVE_LIBBIND -#define HAVE_SETVBUF 1 -#endif - -/* Define if you have the snprintf function. */ -#define HAVE_SNPRINTF 1 -#define HAVE_VSNPRINTF 1 -/* Define if you have the strcasecmp function. */ -#define HAVE_STRCASECMP 1 - -/* Define if you have the strdup function. */ -#define HAVE_STRDUP 1 - -/* Define if you have the strerror function. */ -#define HAVE_STRERROR 1 - -/* Define if you have the strstr function. */ -#define HAVE_STRSTR 1 - -/* Define if you have the tempnam function. */ -#define HAVE_TEMPNAM 1 - -/* Define if you have the utime function. */ -#define HAVE_UTIME 1 - -/* Define if you have the header file. */ -#define HAVE_DIRENT_H 1 - -/* Define if you have the header file. */ -#define HAVE_FCNTL_H 1 - -/* Define if you have the header file. */ -#define HAVE_GRP_H 0 - -/* Define if you have the header file. */ -#define HAVE_PWD_H 1 - -/* Define if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define if you have the header file. */ -#undef HAVE_SYS_FILE_H - -/* Define if you have the header file. */ -#ifdef USE_WINSOCK -#undef HAVE_SYS_SOCKET_H -#else -#define HAVE_SYS_SOCKET_H 1 /* Added '1' for '#if' to work */ -#endif - -/* Define if you have the header file. */ -#undef HAVE_SYS_WAIT_H - -/* Define if you have the header file. */ -/* #define HAVE_SYSLOG_H 1 */ - -/* Define if you have the header file. */ -#define HAVE_UNISTD_H 1 /* Added '1' for '#if' to work */ - -/* Define if you have the dl library (-ldl). */ -#define HAVE_LIBDL 1 - -/* Define if you have the m library (-lm). */ -#define HAVE_LIBM 1 - -/* Define if you have the cuserid function. */ -#define HAVE_CUSERID 0 - -/* Define if you have the rint function. */ -#undef HAVE_RINT - -#define HAVE_STRFTIME 1 - -/* Defined since unsetenv function is defined in LibC. - * This is used to destroy env values in the function php_putenv_destructor. - * If we do not use unsetenv, then the environment variables are directlt manipulated. - * This will then result in LibC not being able to do the maintenance - * that is required for NetWare. - */ -#define HAVE_UNSETENV 1 - -/* Default directory for loading extensions. */ -#define PHP_EXTENSION_DIR "sys:/php/ext" - -#define SIZEOF_INT 4 - -/* Define directory constants for PHP and PEAR */ - -/* This is the default configuration file to read */ -#define CONFIGURATION_FILE_PATH "php.ini" - -#define APACHE_MODULE_DIR "sys:/apache/modules" -#define PHP_BINDIR "sys:/php" -#define PHP_LIBDIR PHP_BINDIR -#define PHP_DATADIR PHP_BINDIR -#define PHP_SYSCONFDIR PHP_BINDIR -#define PHP_LOCALSTATEDIR PHP_BINDIR -#define PHP_CONFIG_FILE_PATH "sys:/php" -#define PEAR_INSTALLDIR "sys:/php/pear" - -#define PHP_CONFIG_FILE_SCAN_DIR NULL -#define PHP_EXTENSION_DIR "sys:/php/ext" - -#define PHP_INCLUDE_PATH NULL - -#define PHP_PREFIX "sys:/php" -#define PHP_SHLIB_SUFFIX "nlm" - -#define USE_CONFIG_FILE 1 - diff --git a/main/config.w32.h b/main/config.w32.h index 6bfe3879a67f..8c2336553c05 100644 --- a/main/config.w32.h +++ b/main/config.w32.h @@ -1,26 +1,20 @@ /* - Build Configuration for Win32. - This has only been tested with MS VisualC++ 6 (and later). - + Build Configuration Template for Win32. $Id$ */ /* Default PHP / PEAR directories */ -#define CONFIGURATION_FILE_PATH "php.ini" -#define PEAR_INSTALLDIR "c:\\php5\\pear" -#define PHP_BINDIR "c:\\php5" #define PHP_CONFIG_FILE_PATH (getenv("SystemRoot"))?getenv("SystemRoot"):"" -#define PHP_CONFIG_FILE_SCAN_DIR "" -#define PHP_DATADIR "c:\\php5" -#define PHP_EXTENSION_DIR "c:\\php5" -#define PHP_INCLUDE_PATH ".;c:\\php5\\pear" -#define PHP_LIBDIR "c:\\php5" -#define PHP_LOCALSTATEDIR "c:\\php5" -#define PHP_PREFIX "c:\\php5" -#define PHP_SYSCONFDIR "c:\\php5" - -/* Enable / Disable BCMATH extension (default: enabled) */ -#define HAVE_BCMATH 1 +#define CONFIGURATION_FILE_PATH "php.ini" +#define PEAR_INSTALLDIR "C:\\php5\\pear" +#define PHP_BINDIR "C:\\php5" +#define PHP_DATADIR "C:\\php5" +#define PHP_EXTENSION_DIR "C:\\php5" +#define PHP_INCLUDE_PATH ".;C:\\php5\\pear" +#define PHP_LIBDIR "C:\\php5" +#define PHP_LOCALSTATEDIR "C:\\php5" +#define PHP_PREFIX "C:\\php5" +#define PHP_SYSCONFDIR "C:\\php5" /* Enable / Disable crypt() function (default: enabled) */ #define HAVE_CRYPT 1 @@ -29,64 +23,12 @@ #define PHP_MD5_CRYPT 1 #define PHP_BLOWFISH_CRYPT 0 -/* Enable / Disable CALENDAR extension (default: enabled) */ -#define HAVE_CALENDAR 1 - -/* Enable / Disable CTYPE extension (default: enabled) */ -#define HAVE_CTYPE 1 - -/* Enable / Disable FTP extension (default: enabled) */ -#define HAVE_FTP 1 - -/* Enable / Disable MBSTRING extension (default: disabled) */ -/* #define HAVE_MBSTRING 0 */ -/* #define HAVE_MBREGEX 0 */ -/* #define HAVE_MBSTR_CN 0 */ -/* #define HAVE_MBSTR_JA 0 */ -/* #define HAVE_MBSTR_KR 0 */ -/* #define HAVE_MBSTR_RU 0 */ -/* #define HAVE_MBSTR_TW 0 */ - -/* If you have the .Net SDK in your include path, define this - * to compile .Net support into your COM extension. */ -#define HAVE_MSCOREE_H 0 - -/* Enable / Disable ODBC extension (default: enabled) */ -#define HAVE_UODBC 1 - -/* Enable / Disable PCRE extension (default: enabled) */ -#define HAVE_BUNDLED_PCRE 1 -#define HAVE_PCRE 1 - -/* Enable / Disable SESSION extension (default: enabled) */ -#define HAVE_PHP_SESSION 1 - -/* Enable / Disable TOKENIZER extension (default: enabled) */ -#define HAVE_TOKENIZER 1 - -/* Enable / Disable WDDX extension (default: enabled) */ -#define HAVE_WDDX 1 - -/* Enable / Disable XML extensions (default: enabled) */ -#define HAVE_LIBXML 1 -#define HAVE_DOM 1 -#define HAVE_SIMPLEXML 1 -#define HAVE_XML 1 - -/* Enable / Disable ZLIB extension (default: enabled) */ -#define HAVE_ZLIB 1 - -/* Enable / Disable SQLite extension (default: enabled) */ -#define HAVE_SQLITE 1 - /* PHP Runtime Configuration */ -#define FORCE_CGI_REDIRECT 1 #define PHP_URL_FOPEN 1 #define PHP_SAFE_MODE 0 #define MAGIC_QUOTES 0 #define USE_CONFIG_FILE 1 #define DEFAULT_SHORT_OPEN_TAG "1" -#define ENABLE_PATHINFO_CHECK 1 /* Platform-Specific Configuration. Should not be changed. */ #define PHP_SIGCHILD 0 @@ -143,7 +85,7 @@ #define HAVE_LOCALECONV 1 #define HAVE_LOCALE_H 1 #ifndef HAVE_LIBBIND -#define HAVE_SETVBUF 1 +# define HAVE_SETVBUF 1 #endif #define HAVE_SHUTDOWN 1 #define HAVE_SNPRINTF 1 @@ -188,13 +130,6 @@ #define HAVE_GLOB #define PHP_SHLIB_SUFFIX "dll" #define HAVE_SQLDATASOURCES -#define POSIX_MALLOC_THRESHOLD 10 - - -/* - * defining HAVE_SOCKLEN_T prevents PHP from building with the latest platform SDK... - * #define HAVE_SOCKLEN_T - */ /* Win32 supports strcoll */ #define HAVE_STRCOLL 1 @@ -203,3 +138,129 @@ #define PHP_CAN_SUPPORT_PROC_OPEN 1 #define HAVE_MBLEN + +#undef HAVE_ATOF_ACCEPTS_NAN +#undef HAVE_ATOF_ACCEPTS_INF +#define HAVE_HUGE_VAL_NAN 1 + +/* values determined by configure.js */ + +/* undefined */ +#define CONFIGURE_COMMAND "cscript /nologo configure.js " + +/* undefined */ +#define HAVE_ARPA_NAMESER_H 1 + +/* undefined */ +#define HAVE_WSPIAPI_H 1 + +/* undefined */ +#define HAVE_GETADDRINFO 1 + +/* undefined */ +#define HAVE_GAI_STRERROR 1 + +/* undefined */ +#define HAVE_IPV6 1 + +/* undefined */ +#define MEMORY_LIMIT 0 + +/* undefined */ +#define HAVE_NEWAPIS_H 1 + +/* CGI redirect mode */ +#define FORCE_CGI_REDIRECT 1 + +/* Pathinfo check */ +#define ENABLE_PATHINFO_CHECK 1 + +/* undefined */ +#define PHP_FASTCGI 1 + +/* Have BCMATH library */ +#define HAVE_BCMATH 1 + +/* Have calendar */ +#define HAVE_CALENDAR 1 + +/* Have COM_DOTNET support */ +#define HAVE_COM_DOTNET 1 + +/* undefined */ +#define HAVE_MSCOREE_H 1 + +/* Have ctype */ +#define HAVE_CTYPE 1 + +/* Have FTP support */ +#define HAVE_FTP 1 + +/* undefined */ +#define HAVE_GD_H 1 + +/* GD support */ +#define HAVE_LIBGD 1 + +/* undefined */ +#define HAVE_ICONV_H 1 + +/* Define if iconv extension is enabled */ +#define HAVE_ICONV 1 + +/* Define if libiconv is available */ +#define HAVE_LIBICONV 1 + +/* Which iconv implementation to use */ +#define PHP_ICONV_IMPL "\"libiconv\"" + +/* Whether iconv supports errno or not */ +#define ICONV_SUPPORTS_ERRNO 1 + +/* undefined */ +#define HAVE_LIBXML_PARSER_H 1 + +/* LibXML support */ +#define HAVE_LIBXML 1 + +/* ODBC support */ +#define HAVE_UODBC 1 + +/* Using bundled PCRE library */ +#define HAVE_BUNDLED_PCRE 1 + +/* Have PCRE library */ +#define HAVE_PCRE 1 + +/* Session support */ +#define HAVE_PHP_SESSION 1 + +/* undefined */ +#define HAVE_SPL 1 + +/* SQLite support */ +#define HAVE_SQLITE 1 + +/* undefined */ +#define PHP_CONFIG_FILE_SCAN_DIR "" + +/* Tokenizer support */ +#define HAVE_TOKENIZER 1 + +/* ZLIB support */ +#define HAVE_ZLIB 1 + +/* undefined */ +#define HAVE_ZLIB_H 1 + +/* DOM support */ +#define HAVE_DOM 1 + +/* Simple XML support */ +#define HAVE_SIMPLEXML 1 + +/* WDDX support */ +#define HAVE_WDDX 1 + +/* XML support */ +#define HAVE_XML 1 diff --git a/main/fopen_wrappers.c b/main/fopen_wrappers.c index d29a33b5b7c2..a31a63472d0b 100644 --- a/main/fopen_wrappers.c +++ b/main/fopen_wrappers.c @@ -35,14 +35,6 @@ #ifdef PHP_WIN32 #define O_RDONLY _O_RDONLY #include "win32/param.h" -#elif defined(NETWARE) -/*#include */ -/*#include */ -#ifdef NEW_LIBC -#include -#else -#include "netware/param.h" -#endif #else #include #endif @@ -56,8 +48,6 @@ #if HAVE_PWD_H #ifdef PHP_WIN32 #include "win32/pwd.h" -#elif defined(NETWARE) -#include "netware/pwd.h" #else #include #endif @@ -105,24 +95,11 @@ PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path char resolved_name[MAXPATHLEN]; char resolved_basedir[MAXPATHLEN]; char local_open_basedir[MAXPATHLEN]; - int local_open_basedir_pos; int resolved_basedir_len; int resolved_name_len; /* Special case basedir==".": Use script-directory */ - if ((strcmp(basedir, ".") == 0) && - SG(request_info).path_translated && - *SG(request_info).path_translated - ) { - strlcpy(local_open_basedir, SG(request_info).path_translated, sizeof(local_open_basedir)); - local_open_basedir_pos = strlen(local_open_basedir) - 1; - - /* Strip filename */ - while (!IS_SLASH(local_open_basedir[local_open_basedir_pos]) - && (local_open_basedir_pos >= 0)) { - local_open_basedir[local_open_basedir_pos--] = 0; - } - } else { + if (strcmp(basedir, ".") || !VCWD_GETCWD(local_open_basedir, MAXPATHLEN)) { /* Else use the unmodified path */ strlcpy(local_open_basedir, basedir, sizeof(local_open_basedir)); } @@ -147,7 +124,7 @@ PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path } /* Check the path */ -#ifdef PHP_WIN32 +#if defined(PHP_WIN32) || defined(NETWARE) if (strncasecmp(resolved_basedir, resolved_name, resolved_basedir_len) == 0) { #else if (strncmp(resolved_basedir, resolved_name, resolved_basedir_len) == 0) { diff --git a/main/logos.h b/main/logos.h index a67ee2d7621e..6841b426ef80 100644 --- a/main/logos.h +++ b/main/logos.h @@ -706,609 +706,647 @@ unsigned char php_logo[] = { unsigned char php_egg_logo[] = { 71, 73, 70, 56, 57, 97, 120, 0, 67, 0, - 247, 255, 0, 0, 0, 0, 177, 156, 157, 205, - 169, 172, 148, 134, 135, 134, 109, 112, 169, 155, - 157, 182, 169, 171, 165, 153, 155, 119, 79, 87, - 167, 152, 155, 167, 157, 159, 195, 159, 167, 170, - 156, 161, 160, 150, 154, 153, 129, 143, 118, 109, - 115, 3, 1, 3, 74, 60, 74, 6, 5, 6, - 183, 173, 184, 101, 93, 102, 148, 142, 150, 5, - 3, 6, 9, 7, 10, 83, 74, 88, 168, 159, - 174, 156, 150, 166, 222, 219, 229, 172, 166, 187, - 215, 212, 225, 206, 203, 220, 123, 120, 139, 134, - 132, 155, 195, 193, 216, 182, 181, 209, 187, 186, - 214, 174, 173, 208, 1, 1, 3, 3, 3, 5, - 11, 11, 16, 14, 14, 20, 7, 7, 10, 34, - 34, 48, 22, 22, 31, 28, 28, 39, 85, 85, - 115, 153, 153, 205, 153, 153, 203, 9, 9, 12, - 156, 156, 205, 160, 160, 206, 170, 170, 206, 177, - 177, 208, 142, 144, 195, 149, 150, 202, 150, 151, - 199, 157, 158, 202, 161, 162, 201, 165, 166, 204, - 80, 82, 122, 75, 77, 112, 112, 115, 165, 97, - 99, 143, 91, 93, 134, 69, 71, 102, 105, 107, - 154, 41, 42, 60, 127, 130, 185, 86, 88, 125, - 51, 52, 74, 136, 139, 192, 133, 135, 184, 146, - 148, 197, 153, 155, 199, 155, 157, 200, 119, 123, - 178, 61, 63, 90, 16, 17, 24, 192, 192, 192, - 132, 89, 62, 139, 94, 66, 143, 105, 82, 222, - 180, 157, 132, 77, 50, 113, 74, 54, 115, 87, - 73, 125, 66, 39, 126, 83, 64, 122, 82, 63, - 102, 71, 57, 113, 85, 72, 197, 160, 142, 204, - 168, 152, 89, 54, 39, 93, 57, 42, 82, 50, - 37, 121, 75, 56, 95, 60, 45, 105, 68, 53, - 89, 58, 45, 97, 67, 55, 113, 79, 65, 104, - 73, 60, 99, 70, 58, 111, 81, 69, 118, 88, - 75, 115, 85, 73, 115, 87, 75, 116, 90, 79, - 181, 143, 127, 207, 174, 160, 94, 51, 35, 78, - 45, 33, 105, 62, 47, 98, 62, 48, 100, 65, - 52, 107, 71, 58, 108, 74, 62, 216, 182, 170, - 210, 177, 165, 227, 193, 180, 219, 188, 177, 118, - 60, 40, 106, 56, 39, 111, 62, 45, 68, 39, - 29, 55, 34, 27, 83, 53, 43, 71, 45, 37, - 94, 64, 54, 10, 7, 6, 93, 67, 59, 116, - 85, 75, 149, 110, 97, 12, 9, 8, 111, 84, - 75, 102, 66, 56, 101, 69, 60, 103, 71, 62, - 93, 65, 57, 95, 67, 59, 99, 70, 62, 91, - 65, 58, 117, 88, 80, 118, 93, 86, 183, 150, - 140, 188, 158, 149, 236, 203, 194, 198, 171, 163, - 190, 164, 157, 41, 26, 22, 91, 61, 53, 98, - 66, 58, 95, 65, 57, 84, 59, 53, 114, 82, - 74, 109, 81, 74, 102, 79, 73, 158, 127, 119, - 123, 100, 94, 163, 133, 126, 194, 167, 160, 204, - 179, 173, 171, 159, 156, 95, 65, 59, 71, 49, - 44, 97, 67, 61, 93, 65, 59, 76, 54, 49, - 126, 91, 83, 19, 14, 13, 112, 86, 80, 87, - 69, 65, 133, 107, 101, 144, 119, 114, 137, 114, - 109, 177, 150, 144, 164, 139, 134, 181, 155, 149, - 209, 183, 177, 200, 176, 171, 223, 197, 191, 211, - 187, 182, 167, 157, 155, 165, 155, 153, 32, 20, - 18, 82, 55, 50, 90, 63, 58, 119, 83, 77, - 94, 66, 61, 60, 43, 40, 95, 74, 70, 171, - 145, 140, 247, 212, 206, 235, 209, 204, 167, 155, - 153, 255, 244, 242, 86, 61, 57, 247, 220, 216, - 155, 142, 140, 170, 157, 155, 149, 124, 121, 187, - 160, 157, 172, 149, 146, 216, 192, 189, 147, 131, - 129, 147, 138, 137, 91, 65, 63, 46, 33, 32, - 155, 132, 130, 157, 137, 135, 181, 159, 157, 224, - 202, 200, 132, 121, 120, 248, 228, 226, 165, 152, - 151, 140, 130, 129, 156, 145, 144, 162, 151, 150, - 151, 141, 140, 186, 176, 175, 103, 85, 84, 174, - 156, 155, 163, 147, 146, 176, 151, 150, 166, 143, - 142, 188, 165, 164, 194, 171, 170, 198, 177, 176, - 210, 189, 188, 229, 207, 206, 236, 215, 214, 22, - 17, 17, 176, 153, 153, 203, 181, 181, 174, 159, - 159, 168, 153, 153, 169, 155, 155, 171, 157, 157, - 191, 177, 177, 176, 163, 163, 169, 157, 157, 167, - 155, 155, 165, 153, 153, 171, 159, 159, 158, 148, - 148, 169, 159, 159, 165, 155, 155, 163, 153, 153, - 161, 153, 153, 3, 3, 3, 1, 1, 1, 255, - 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 33, 249, 4, 1, 0, 0, 78, 0, 44, - 0, 0, 0, 0, 120, 0, 67, 0, 64, 8, - 255, 0, 157, 8, 28, 72, 176, 160, 193, 131, + 247, 0, 0, 0, 0, 0, 255, 255, 255, 153, + 153, 205, 135, 111, 114, 110, 103, 104, 185, 161, + 165, 182, 176, 177, 178, 169, 171, 22, 18, 19, + 43, 39, 40, 217, 151, 172, 233, 184, 199, 196, + 168, 177, 253, 219, 230, 207, 179, 188, 252, 202, + 219, 216, 178, 191, 254, 231, 239, 123, 120, 121, + 240, 190, 209, 144, 141, 143, 99, 92, 97, 91, + 87, 90, 6, 5, 6, 189, 187, 189, 93, 92, + 93, 170, 162, 172, 5, 3, 6, 103, 101, 104, + 33, 29, 36, 3, 2, 4, 203, 199, 209, 215, + 211, 222, 9, 8, 11, 107, 106, 109, 116, 115, + 118, 221, 219, 228, 206, 203, 218, 174, 171, 194, + 191, 188, 210, 195, 193, 215, 191, 190, 202, 159, + 158, 168, 168, 167, 182, 185, 184, 211, 172, 171, + 207, 1, 1, 2, 11, 11, 16, 14, 14, 20, + 7, 7, 10, 34, 34, 48, 28, 28, 39, 22, + 22, 30, 153, 153, 203, 156, 156, 205, 160, 160, + 205, 133, 133, 163, 148, 148, 178, 178, 178, 208, + 182, 182, 194, 79, 79, 82, 66, 66, 68, 33, + 33, 34, 111, 111, 114, 46, 46, 47, 76, 76, + 77, 84, 85, 121, 142, 144, 194, 149, 150, 202, + 153, 154, 205, 154, 155, 205, 150, 151, 199, 157, + 158, 202, 161, 162, 200, 165, 166, 203, 75, 77, + 111, 115, 118, 170, 97, 99, 143, 91, 93, 134, + 105, 107, 154, 41, 42, 60, 51, 52, 74, 129, + 132, 182, 136, 139, 191, 146, 148, 196, 153, 155, + 199, 155, 157, 200, 65, 67, 96, 174, 175, 184, + 16, 17, 24, 147, 149, 161, 68, 69, 73, 53, + 54, 57, 132, 133, 136, 139, 143, 153, 93, 96, + 102, 97, 100, 106, 71, 73, 77, 98, 99, 101, + 82, 85, 90, 86, 89, 94, 90, 93, 98, 131, + 137, 146, 104, 109, 116, 109, 114, 121, 119, 124, + 131, 101, 105, 110, 123, 129, 136, 74, 78, 82, + 61, 64, 67, 115, 120, 125, 80, 83, 86, 56, + 58, 60, 35, 36, 37, 48, 49, 50, 50, 51, + 52, 60, 61, 62, 41, 42, 42, 39, 40, 40, + 37, 38, 38, 136, 164, 159, 4, 5, 3, 176, + 173, 166, 192, 189, 183, 180, 174, 163, 194, 187, + 177, 181, 175, 166, 178, 172, 163, 176, 170, 161, + 182, 166, 144, 179, 164, 143, 179, 168, 153, 121, + 116, 109, 186, 180, 172, 184, 178, 170, 191, 185, + 177, 201, 195, 187, 198, 193, 186, 138, 117, 91, + 154, 135, 111, 181, 163, 140, 160, 144, 124, 187, + 170, 149, 184, 168, 148, 189, 178, 164, 186, 175, + 162, 203, 198, 192, 203, 199, 194, 202, 198, 193, + 200, 196, 191, 133, 108, 79, 144, 126, 105, 195, + 180, 163, 176, 163, 148, 201, 187, 171, 202, 190, + 177, 179, 169, 158, 205, 194, 182, 197, 188, 178, + 200, 192, 183, 180, 173, 165, 178, 171, 163, 177, + 170, 162, 175, 168, 160, 189, 182, 174, 197, 190, + 182, 206, 199, 191, 203, 197, 190, 3, 2, 1, + 111, 96, 81, 173, 157, 140, 164, 151, 138, 181, + 171, 161, 178, 170, 162, 173, 166, 159, 195, 188, + 181, 214, 207, 200, 211, 204, 197, 200, 194, 188, + 197, 191, 185, 192, 186, 180, 207, 201, 195, 205, + 199, 193, 202, 197, 192, 196, 192, 188, 197, 194, + 191, 64, 63, 62, 84, 83, 82, 122, 83, 48, + 193, 175, 158, 188, 171, 155, 198, 182, 167, 194, + 183, 173, 88, 55, 28, 210, 198, 188, 201, 193, + 186, 204, 196, 189, 204, 197, 191, 115, 103, 94, + 204, 194, 186, 204, 195, 188, 205, 200, 196, 100, + 89, 81, 105, 98, 93, 175, 168, 163, 202, 195, + 190, 196, 193, 191, 95, 82, 74, 123, 109, 100, + 165, 157, 152, 177, 170, 166, 199, 192, 188, 202, + 197, 194, 201, 196, 193, 199, 194, 191, 13, 11, + 10, 61, 55, 52, 130, 126, 124, 69, 67, 66, + 81, 79, 78, 200, 196, 194, 193, 189, 187, 82, + 67, 60, 149, 136, 130, 79, 74, 72, 198, 193, + 191, 40, 29, 25, 62, 48, 43, 74, 58, 52, + 87, 73, 68, 138, 130, 127, 10, 7, 6, 201, + 195, 193, 195, 192, 191, 199, 189, 186, 19, 15, + 14, 88, 84, 83, 196, 188, 186, 201, 197, 196, + 185, 181, 180, 31, 22, 20, 198, 193, 192, 51, + 39, 37, 47, 34, 33, 183, 156, 154, 168, 162, + 162, 157, 151, 151, 196, 190, 190, 189, 184, 184, + 57, 56, 56, 193, 190, 190, 72, 71, 71, 53, + 53, 53, 44, 44, 44, 29, 29, 29, 255, 255, + 255, 33, 249, 4, 1, 0, 0, 255, 0, 44, + 0, 0, 0, 0, 120, 0, 67, 0, 0, 8, + 255, 0, 255, 9, 28, 72, 176, 160, 193, 131, 8, 19, 42, 92, 200, 176, 161, 195, 135, 16, - 9, 186, 112, 177, 164, 133, 144, 20, 48, 78, - 160, 64, 209, 100, 197, 10, 22, 44, 84, 64, - 243, 229, 171, 20, 170, 82, 38, 53, 53, 130, - 180, 173, 94, 182, 1, 216, 176, 57, 203, 182, - 141, 102, 180, 100, 174, 114, 186, 218, 118, 108, - 219, 54, 103, 206, 154, 37, 147, 38, 205, 83, - 178, 106, 213, 30, 40, 85, 234, 35, 72, 143, - 37, 80, 163, 70, 29, 98, 4, 201, 68, 23, - 17, 19, 78, 252, 193, 2, 128, 87, 0, 130, - 114, 149, 68, 117, 9, 211, 25, 50, 166, 26, - 169, 29, 116, 234, 212, 32, 76, 138, 234, 208, - 17, 51, 71, 140, 24, 58, 117, 204, 32, 42, - 3, 233, 27, 55, 122, 217, 142, 101, 203, 118, - 11, 215, 60, 109, 223, 200, 217, 42, 103, 142, - 153, 55, 109, 218, 188, 81, 35, 102, 141, 90, - 57, 101, 201, 142, 221, 26, 134, 172, 29, 50, - 119, 237, 66, 15, 19, 141, 203, 240, 129, 210, - 134, 33, 107, 171, 183, 13, 91, 181, 15, 75, - 140, 200, 150, 109, 21, 235, 65, 23, 71, 84, - 124, 69, 87, 82, 211, 174, 94, 167, 122, 177, - 117, 107, 74, 145, 153, 185, 115, 146, 7, 202, - 132, 41, 19, 25, 51, 104, 228, 120, 153, 62, - 134, 250, 152, 49, 156, 164, 113, 91, 39, 205, - 85, 44, 74, 121, 236, 216, 255, 185, 227, 166, - 252, 150, 72, 231, 183, 216, 169, 197, 158, 82, - 44, 88, 162, 68, 77, 187, 229, 142, 158, 253, - 251, 244, 220, 233, 119, 135, 172, 127, 231, 97, - 240, 192, 3, 26, 59, 184, 92, 115, 13, 62, - 249, 36, 168, 32, 100, 245, 56, 3, 194, 13, - 72, 68, 248, 2, 86, 46, 148, 240, 149, 47, - 168, 236, 210, 72, 34, 136, 32, 50, 7, 25, - 129, 44, 34, 98, 38, 153, 244, 178, 200, 37, - 151, 236, 130, 162, 138, 127, 124, 1, 7, 32, - 128, 244, 97, 73, 46, 52, 230, 98, 137, 31, - 125, 0, 114, 73, 35, 191, 60, 82, 8, 40, - 177, 172, 195, 205, 59, 234, 148, 67, 141, 57, - 212, 28, 73, 13, 37, 161, 76, 70, 12, 51, - 145, 180, 17, 73, 37, 148, 208, 66, 78, 37, - 110, 228, 33, 201, 43, 159, 180, 66, 64, 53, - 205, 28, 115, 205, 48, 244, 172, 99, 102, 126, - 241, 32, 168, 224, 154, 108, 174, 169, 77, 54, - 57, 228, 128, 3, 14, 87, 229, 246, 85, 46, - 168, 20, 179, 203, 41, 142, 56, 178, 139, 138, - 41, 234, 185, 75, 159, 142, 160, 168, 137, 46, - 46, 194, 161, 168, 162, 95, 52, 242, 9, 27, - 99, 244, 225, 7, 32, 186, 112, 146, 204, 50, - 202, 136, 35, 78, 56, 201, 180, 210, 202, 43, - 159, 70, 3, 76, 44, 192, 68, 19, 77, 56, - 227, 216, 66, 11, 45, 204, 48, 99, 11, 53, - 181, 168, 255, 51, 142, 56, 202, 216, 145, 199, - 29, 177, 180, 162, 198, 38, 155, 160, 225, 171, - 175, 106, 4, 171, 134, 22, 196, 22, 107, 108, - 21, 105, 176, 193, 6, 36, 173, 184, 146, 1, - 13, 52, 144, 48, 67, 12, 19, 21, 116, 149, - 11, 92, 73, 144, 130, 70, 43, 248, 162, 73, - 32, 152, 32, 114, 87, 28, 111, 132, 241, 72, - 42, 96, 232, 161, 238, 186, 234, 242, 225, 110, - 24, 127, 232, 162, 231, 42, 175, 184, 18, 77, - 58, 182, 24, 99, 141, 40, 146, 84, 178, 76, - 52, 177, 132, 179, 204, 52, 227, 88, 41, 142, - 58, 204, 144, 163, 169, 56, 149, 204, 210, 42, - 123, 179, 132, 71, 137, 39, 88, 80, 97, 49, - 21, 117, 148, 161, 49, 26, 85, 84, 97, 172, - 177, 205, 76, 224, 193, 200, 30, 132, 48, 195, - 181, 89, 9, 116, 109, 157, 62, 0, 81, 196, - 203, 76, 196, 204, 4, 16, 52, 99, 16, 193, - 51, 113, 88, 49, 133, 206, 86, 232, 241, 134, - 28, 127, 168, 98, 73, 41, 159, 128, 2, 75, - 191, 253, 82, 162, 76, 40, 149, 244, 27, 138, - 40, 118, 48, 89, 229, 44, 179, 208, 66, 235, - 52, 203, 120, 18, 5, 20, 133, 120, 2, 140, - 1, 35, 144, 236, 65, 7, 100, 111, 176, 129, - 7, 35, 232, 176, 114, 181, 41, 183, 205, 208, - 218, 112, 199, 45, 247, 220, 107, 187, 109, 247, - 221, 78, 92, 107, 68, 16, 68, 184, 255, 172, - 194, 223, 66, 4, 254, 242, 224, 50, 199, 76, - 51, 205, 60, 36, 206, 195, 14, 59, 16, 225, - 248, 15, 144, 255, 224, 195, 228, 148, 55, 229, - 212, 18, 84, 217, 128, 50, 222, 17, 77, 116, - 4, 16, 77, 120, 181, 143, 62, 22, 92, 128, - 142, 37, 36, 153, 164, 139, 38, 197, 44, 114, - 70, 94, 89, 40, 66, 71, 25, 117, 100, 113, - 198, 28, 89, 96, 17, 133, 43, 246, 208, 211, - 83, 54, 165, 93, 131, 152, 58, 230, 156, 51, - 139, 44, 223, 8, 47, 252, 52, 204, 192, 90, - 139, 40, 210, 124, 51, 204, 60, 243, 224, 194, - 206, 245, 6, 30, 184, 26, 77, 206, 184, 246, - 90, 15, 67, 132, 47, 254, 17, 53, 104, 110, - 91, 67, 91, 161, 240, 149, 33, 168, 163, 194, - 250, 158, 167, 48, 146, 8, 236, 89, 32, 98, - 134, 34, 152, 144, 66, 74, 38, 243, 203, 17, - 134, 28, 0, 12, 131, 23, 252, 39, 135, 58, - 188, 130, 27, 127, 105, 70, 43, 32, 209, 137, - 95, 116, 131, 0, 201, 136, 6, 40, 218, 192, - 5, 41, 72, 193, 13, 118, 192, 131, 6, 241, - 240, 42, 106, 144, 3, 28, 236, 216, 207, 125, - 244, 227, 159, 208, 20, 102, 24, 195, 144, 71, - 1, 218, 177, 153, 234, 29, 96, 30, 248, 192, - 135, 54, 26, 224, 146, 1, 124, 128, 124, 53, - 200, 161, 249, 6, 226, 2, 30, 124, 69, 21, - 24, 218, 5, 41, 255, 24, 209, 139, 33, 50, - 130, 20, 110, 89, 4, 255, 200, 240, 63, 57, - 4, 226, 137, 39, 186, 206, 24, 200, 224, 5, - 69, 245, 161, 15, 46, 186, 226, 23, 90, 241, - 141, 111, 28, 163, 27, 225, 96, 134, 40, 142, - 100, 11, 74, 72, 34, 18, 89, 194, 195, 36, - 172, 193, 70, 125, 25, 35, 26, 24, 8, 71, - 45, 66, 65, 9, 46, 68, 2, 24, 253, 241, - 76, 104, 218, 193, 142, 121, 92, 99, 30, 163, - 185, 94, 59, 214, 65, 143, 118, 76, 47, 134, - 106, 106, 83, 130, 86, 179, 13, 13, 36, 33, - 9, 55, 152, 80, 15, 119, 83, 138, 214, 93, - 226, 137, 80, 60, 17, 138, 46, 33, 34, 66, - 237, 66, 19, 39, 241, 3, 52, 44, 1, 141, - 43, 94, 145, 81, 95, 248, 2, 235, 52, 129, - 134, 84, 184, 226, 27, 177, 0, 85, 50, 194, - 17, 142, 128, 197, 34, 26, 210, 8, 71, 0, - 188, 1, 143, 105, 80, 98, 18, 198, 8, 198, - 36, 134, 57, 76, 246, 144, 131, 18, 179, 168, - 132, 39, 30, 181, 138, 67, 112, 130, 19, 135, - 88, 5, 36, 32, 161, 172, 106, 118, 233, 83, - 174, 104, 134, 52, 234, 145, 15, 68, 186, 169, - 30, 25, 208, 129, 56, 233, 164, 178, 244, 121, - 165, 4, 64, 244, 205, 160, 254, 4, 63, 253, - 97, 2, 19, 115, 8, 195, 30, 248, 176, 135, - 55, 4, 34, 13, 105, 160, 103, 28, 246, 25, - 255, 7, 39, 106, 226, 18, 157, 72, 198, 56, - 200, 65, 14, 90, 0, 195, 40, 177, 144, 5, - 40, 94, 129, 75, 105, 12, 12, 107, 211, 80, - 135, 58, 86, 85, 14, 87, 169, 67, 28, 1, - 80, 198, 29, 194, 195, 5, 46, 84, 194, 21, - 179, 43, 131, 175, 54, 65, 172, 52, 120, 236, - 99, 40, 45, 86, 43, 50, 16, 130, 17, 140, - 64, 4, 106, 187, 138, 66, 86, 118, 132, 22, - 168, 224, 35, 33, 81, 129, 16, 124, 241, 135, - 61, 176, 235, 167, 244, 244, 169, 207, 190, 80, - 10, 64, 148, 68, 23, 207, 40, 198, 47, 46, - 129, 138, 222, 116, 130, 89, 205, 114, 5, 1, - 90, 1, 48, 89, 60, 205, 22, 182, 112, 85, - 86, 153, 81, 11, 102, 172, 138, 18, 176, 40, - 196, 21, 192, 0, 134, 43, 60, 225, 172, 80, - 184, 2, 22, 202, 80, 5, 72, 36, 195, 0, - 30, 48, 155, 92, 59, 48, 2, 25, 172, 140, - 115, 183, 153, 91, 13, 134, 208, 131, 32, 248, - 32, 114, 147, 11, 130, 96, 123, 64, 216, 169, - 136, 111, 54, 57, 172, 1, 18, 110, 112, 131, - 36, 40, 1, 7, 113, 18, 231, 12, 102, 64, - 2, 18, 208, 64, 4, 34, 120, 105, 180, 116, - 64, 173, 185, 225, 245, 179, 90, 89, 153, 17, - 150, 208, 215, 191, 18, 161, 5, 60, 56, 156, - 106, 19, 215, 56, 34, 72, 206, 41, 79, 57, - 66, 85, 234, 6, 218, 218, 255, 90, 107, 34, - 70, 104, 153, 16, 154, 208, 17, 156, 254, 77, - 167, 129, 19, 2, 225, 48, 64, 92, 226, 118, - 131, 2, 200, 77, 110, 55, 126, 225, 192, 228, - 38, 183, 5, 174, 13, 172, 96, 167, 75, 216, - 234, 86, 23, 115, 70, 48, 223, 249, 108, 155, - 215, 32, 20, 225, 2, 16, 48, 129, 182, 50, - 130, 130, 21, 144, 114, 44, 154, 208, 196, 24, - 22, 65, 134, 58, 212, 46, 17, 115, 16, 23, - 21, 90, 113, 0, 120, 208, 100, 27, 218, 40, - 208, 60, 190, 33, 11, 101, 208, 18, 24, 217, - 80, 13, 100, 194, 1, 139, 101, 0, 163, 18, - 178, 144, 134, 106, 190, 225, 18, 154, 192, 196, - 53, 74, 249, 192, 83, 196, 71, 225, 217, 110, - 215, 110, 184, 97, 130, 4, 190, 2, 0, 11, - 160, 99, 36, 170, 43, 134, 35, 22, 193, 167, - 224, 20, 199, 12, 102, 200, 66, 22, 240, 50, - 23, 15, 209, 1, 10, 187, 235, 29, 77, 128, - 231, 199, 121, 28, 163, 18, 141, 153, 133, 56, - 178, 87, 15, 120, 152, 195, 26, 231, 48, 71, - 45, 100, 17, 141, 107, 176, 3, 133, 9, 64, - 161, 146, 135, 129, 26, 234, 169, 198, 37, 221, - 123, 205, 7, 168, 34, 27, 217, 150, 143, 109, - 111, 115, 65, 11, 82, 240, 21, 9, 136, 37, - 37, 187, 144, 159, 123, 109, 151, 8, 69, 40, - 194, 20, 192, 33, 69, 34, 204, 32, 23, 49, - 200, 161, 255, 159, 97, 136, 51, 34, 32, 225, - 10, 120, 24, 0, 30, 245, 104, 70, 53, 64, - 245, 9, 2, 96, 35, 26, 234, 96, 15, 51, - 40, 1, 142, 79, 124, 98, 25, 204, 56, 135, - 49, 144, 36, 142, 8, 126, 102, 63, 252, 233, - 207, 10, 219, 113, 0, 20, 150, 38, 201, 46, - 44, 205, 97, 182, 231, 140, 215, 144, 111, 54, - 181, 185, 13, 18, 138, 240, 21, 65, 180, 207, - 55, 109, 73, 53, 35, 226, 146, 226, 44, 176, - 217, 12, 137, 216, 223, 115, 162, 211, 196, 56, - 199, 121, 12, 114, 64, 195, 91, 233, 113, 141, - 106, 124, 162, 27, 171, 104, 69, 44, 36, 113, - 30, 244, 108, 129, 11, 110, 232, 40, 23, 204, - 8, 11, 101, 136, 2, 171, 228, 128, 71, 59, - 234, 115, 166, 252, 236, 167, 132, 74, 38, 36, - 50, 10, 32, 15, 234, 193, 16, 31, 13, 104, - 64, 62, 86, 211, 32, 16, 40, 22, 9, 138, - 101, 155, 11, 110, 160, 27, 175, 136, 37, 79, - 142, 56, 133, 254, 136, 216, 22, 37, 134, 11, - 17, 115, 113, 226, 19, 81, 36, 135, 249, 133, - 33, 149, 169, 244, 66, 42, 199, 16, 6, 78, - 28, 3, 30, 195, 24, 128, 43, 68, 49, 9, - 97, 8, 163, 22, 228, 73, 246, 29, 236, 144, - 165, 96, 0, 185, 22, 230, 48, 71, 124, 200, - 1, 139, 54, 180, 33, 22, 200, 40, 147, 153, - 206, 100, 38, 253, 216, 199, 29, 220, 255, 14, - 144, 126, 228, 97, 24, 111, 182, 137, 145, 21, - 96, 44, 99, 175, 210, 21, 175, 64, 163, 20, - 154, 144, 31, 38, 200, 240, 78, 83, 152, 130, - 45, 74, 236, 69, 32, 80, 20, 8, 21, 45, - 34, 16, 99, 72, 37, 28, 146, 110, 69, 63, - 56, 221, 18, 80, 167, 17, 52, 88, 241, 12, - 175, 85, 98, 162, 161, 144, 69, 179, 199, 40, - 12, 99, 212, 98, 22, 212, 176, 6, 63, 4, - 64, 0, 165, 72, 34, 235, 176, 176, 195, 36, - 66, 177, 140, 145, 187, 157, 29, 94, 140, 9, - 54, 182, 49, 140, 2, 204, 67, 145, 120, 31, - 119, 61, 42, 128, 3, 37, 40, 33, 9, 19, - 169, 57, 0, 160, 145, 161, 76, 4, 34, 57, - 115, 200, 228, 37, 73, 172, 34, 118, 166, 87, - 19, 95, 144, 20, 41, 161, 126, 35, 28, 153, - 242, 15, 43, 49, 244, 43, 248, 248, 13, 3, - 188, 99, 26, 233, 16, 199, 52, 100, 65, 139, - 139, 18, 204, 26, 196, 8, 134, 48, 55, 136, - 135, 86, 205, 34, 20, 119, 184, 3, 40, 216, - 128, 6, 78, 160, 65, 11, 107, 88, 22, 36, - 62, 241, 10, 109, 74, 35, 26, 3, 104, 73, - 55, 19, 153, 247, 25, 234, 32, 78, 116, 90, - 119, 187, 1, 128, 167, 98, 112, 178, 147, 187, - 208, 228, 37, 244, 228, 201, 98, 232, 226, 36, - 49, 2, 196, 23, 152, 190, 168, 62, 252, 161, - 19, 214, 239, 69, 255, 29, 90, 33, 141, 100, - 36, 131, 0, 246, 74, 198, 43, 112, 98, 175, - 88, 132, 94, 83, 179, 146, 69, 37, 242, 144, - 7, 53, 178, 39, 73, 234, 144, 133, 40, 106, - 33, 9, 79, 164, 226, 16, 107, 112, 8, 209, - 36, 128, 2, 152, 82, 90, 48, 44, 90, 80, - 5, 202, 178, 126, 216, 16, 38, 217, 0, 78, - 210, 50, 3, 49, 149, 55, 46, 48, 106, 165, - 6, 13, 190, 65, 40, 126, 34, 40, 131, 66, - 98, 164, 48, 116, 213, 225, 5, 111, 80, 79, - 93, 64, 6, 108, 176, 10, 97, 240, 6, 113, - 32, 6, 152, 144, 34, 189, 64, 0, 239, 87, - 48, 178, 224, 9, 174, 224, 9, 92, 146, 12, - 224, 144, 14, 211, 224, 13, 58, 8, 127, 171, - 242, 108, 18, 37, 81, 227, 176, 52, 226, 225, - 6, 146, 208, 10, 104, 16, 44, 248, 164, 6, - 29, 131, 79, 6, 248, 132, 4, 192, 1, 152, - 37, 2, 39, 35, 83, 229, 52, 17, 91, 86, - 2, 226, 165, 10, 24, 168, 39, 245, 198, 8, - 247, 22, 7, 244, 84, 46, 132, 128, 46, 236, - 226, 46, 251, 4, 47, 48, 242, 11, 4, 128, - 42, 3, 197, 12, 93, 39, 12, 202, 16, 11, - 160, 0, 48, 164, 50, 13, 4, 101, 37, 138, - 193, 12, 229, 80, 14, 234, 160, 48, 226, 32, - 10, 26, 20, 30, 110, 64, 9, 192, 160, 49, - 136, 184, 49, 183, 247, 132, 32, 35, 2, 33, - 255, 240, 136, 35, 80, 133, 88, 150, 87, 158, - 3, 58, 28, 225, 17, 44, 192, 83, 95, 224, - 5, 106, 96, 134, 63, 197, 46, 123, 48, 79, - 124, 240, 6, 128, 80, 10, 108, 129, 18, 157, - 208, 37, 16, 20, 13, 203, 240, 14, 192, 144, - 19, 67, 17, 65, 225, 0, 14, 224, 48, 122, - 176, 208, 48, 88, 213, 42, 92, 85, 11, 182, - 64, 127, 238, 81, 8, 103, 165, 86, 88, 48, - 140, 136, 136, 44, 198, 210, 10, 242, 48, 54, - 100, 211, 1, 30, 32, 2, 118, 101, 133, 157, - 179, 50, 61, 0, 4, 128, 35, 56, 47, 19, - 1, 197, 32, 79, 235, 18, 138, 62, 101, 5, - 86, 192, 7, 47, 226, 7, 55, 226, 11, 78, - 119, 9, 175, 96, 20, 157, 178, 64, 244, 2, - 48, 192, 0, 11, 148, 32, 53, 161, 64, 11, - 207, 214, 42, 170, 34, 14, 76, 2, 12, 133, - 0, 5, 83, 176, 143, 251, 8, 6, 84, 16, - 5, 209, 96, 0, 29, 32, 87, 4, 25, 2, - 36, 64, 91, 181, 21, 55, 53, 208, 3, 62, - 192, 3, 51, 3, 4, 172, 213, 56, 144, 67, - 57, 126, 229, 3, 15, 64, 1, 76, 80, 4, - 66, 128, 1, 4, 112, 42, 177, 64, 42, 145, - 32, 11, 253, 162, 12, 153, 34, 14, 6, 96, - 0, 25, 144, 1, 28, 176, 146, 58, 96, 89, - 151, 149, 89, 35, 240, 136, 143, 72, 50, 45, - 69, 2, 207, 136, 144, 220, 255, 229, 16, 116, - 179, 50, 232, 86, 101, 20, 22, 62, 178, 133, - 88, 138, 197, 88, 143, 244, 88, 115, 130, 3, - 49, 208, 89, 59, 57, 137, 57, 217, 148, 78, - 249, 148, 80, 217, 54, 75, 57, 149, 208, 24, - 149, 86, 73, 129, 19, 241, 2, 71, 208, 3, - 63, 208, 2, 46, 99, 141, 48, 83, 56, 171, - 165, 56, 140, 211, 90, 174, 21, 57, 63, 48, - 88, 67, 64, 62, 119, 117, 149, 110, 115, 21, - 72, 208, 3, 45, 192, 4, 55, 5, 18, 191, - 21, 92, 194, 69, 56, 98, 121, 56, 100, 201, - 56, 142, 115, 150, 19, 89, 57, 211, 53, 152, - 176, 181, 4, 228, 163, 93, 110, 25, 90, 72, - 16, 4, 212, 168, 17, 188, 133, 137, 57, 5, - 92, 36, 49, 22, 172, 240, 0, 72, 177, 20, - 72, 129, 20, 174, 65, 0, 211, 180, 10, 159, - 144, 153, 151, 169, 20, 4, 64, 0, 199, 117, - 145, 129, 101, 93, 215, 37, 21, 228, 35, 73, - 110, 57, 17, 65, 192, 4, 43, 160, 45, 23, - 112, 2, 142, 233, 17, 208, 48, 18, 48, 130, - 10, 186, 112, 9, 100, 112, 73, 188, 153, 5, - 104, 224, 10, 247, 0, 24, 206, 208, 18, 135, - 129, 15, 199, 64, 42, 18, 20, 11, 10, 214, - 69, 245, 80, 15, 176, 244, 145, 71, 35, 13, - 62, 177, 13, 3, 0, 19, 161, 249, 0, 151, - 35, 21, 83, 97, 97, 23, 134, 87, 19, 209, - 3, 76, 255, 112, 1, 0, 16, 94, 22, 128, - 17, 232, 144, 11, 35, 129, 94, 129, 112, 6, - 103, 113, 6, 89, 64, 59, 41, 70, 6, 89, - 64, 5, 79, 224, 10, 246, 49, 99, 213, 99, - 32, 223, 64, 11, 126, 168, 12, 0, 38, 67, - 252, 57, 13, 171, 50, 14, 148, 176, 12, 217, - 224, 71, 217, 35, 60, 136, 225, 18, 63, 1, - 97, 15, 32, 97, 63, 25, 62, 22, 198, 57, - 91, 177, 124, 0, 80, 2, 166, 179, 158, 165, - 176, 58, 130, 18, 63, 172, 166, 98, 179, 83, - 7, 116, 33, 46, 79, 16, 5, 175, 160, 0, - 240, 240, 59, 193, 131, 24, 228, 80, 60, 162, - 128, 60, 6, 162, 13, 215, 160, 14, 194, 144, - 113, 194, 64, 9, 209, 160, 13, 236, 96, 100, - 76, 134, 26, 168, 97, 32, 50, 212, 96, 81, - 246, 1, 83, 118, 4, 72, 74, 161, 53, 192, - 148, 58, 233, 2, 65, 32, 4, 28, 182, 15, - 66, 211, 27, 68, 135, 9, 62, 7, 28, 38, - 22, 23, 42, 150, 5, 25, 67, 59, 30, 130, - 6, 108, 16, 13, 132, 244, 156, 131, 81, 24, - 6, 146, 13, 227, 208, 85, 230, 160, 14, 217, - 243, 13, 234, 192, 70, 141, 1, 61, 210, 192, - 14, 134, 20, 26, 157, 97, 72, 40, 36, 15, - 167, 241, 66, 48, 244, 100, 52, 225, 26, 31, - 0, 2, 179, 1, 106, 76, 138, 16, 88, 168, - 62, 162, 243, 97, 71, 21, 102, 102, 255, 134, - 8, 103, 80, 102, 141, 192, 8, 108, 33, 63, - 178, 99, 23, 136, 39, 7, 115, 96, 6, 101, - 176, 9, 159, 192, 14, 127, 193, 26, 63, 241, - 19, 197, 121, 12, 228, 128, 48, 204, 160, 99, - 205, 208, 12, 211, 16, 118, 196, 112, 14, 229, - 32, 11, 174, 32, 13, 121, 164, 31, 5, 144, - 71, 158, 65, 32, 184, 112, 11, 7, 192, 167, - 243, 192, 167, 218, 195, 26, 216, 16, 168, 131, - 90, 161, 161, 181, 101, 165, 134, 58, 29, 234, - 133, 98, 246, 94, 177, 163, 8, 140, 112, 68, - 204, 145, 5, 117, 33, 6, 112, 246, 63, 113, - 102, 41, 239, 112, 103, 199, 144, 20, 144, 192, - 9, 157, 208, 10, 213, 16, 13, 88, 130, 108, - 110, 176, 5, 82, 34, 9, 121, 224, 112, 73, - 50, 14, 209, 112, 12, 252, 1, 105, 145, 38, - 105, 120, 154, 167, 120, 154, 0, 168, 17, 67, - 228, 214, 26, 55, 148, 88, 233, 246, 157, 121, - 211, 3, 130, 103, 8, 35, 225, 62, 131, 162, - 106, 141, 128, 98, 42, 102, 63, 137, 144, 63, - 96, 24, 159, 4, 100, 107, 182, 54, 7, 193, - 121, 146, 237, 224, 107, 221, 192, 10, 191, 64, - 103, 19, 20, 37, 91, 96, 65, 228, 42, 5, - 244, 231, 48, 150, 49, 14, 157, 81, 31, 1, - 178, 14, 240, 106, 66, 184, 192, 100, 183, 144, - 31, 161, 113, 26, 212, 163, 61, 13, 192, 105, - 251, 154, 88, 59, 255, 84, 78, 68, 240, 21, - 16, 240, 110, 168, 54, 8, 195, 49, 8, 98, - 102, 6, 201, 129, 8, 89, 144, 8, 11, 235, - 28, 208, 33, 29, 183, 54, 29, 94, 64, 112, - 157, 208, 12, 127, 113, 12, 10, 244, 10, 183, - 24, 123, 201, 198, 5, 91, 144, 181, 89, 203, - 5, 118, 48, 11, 134, 8, 10, 149, 176, 113, - 210, 134, 31, 249, 97, 109, 36, 100, 171, 0, - 178, 14, 119, 106, 24, 7, 2, 110, 226, 166, - 119, 229, 22, 33, 232, 182, 67, 88, 120, 129, - 201, 26, 111, 189, 32, 28, 109, 65, 10, 166, - 192, 102, 114, 129, 120, 251, 22, 8, 100, 160, - 8, 209, 225, 5, 93, 112, 184, 134, 251, 7, - 4, 103, 112, 6, 224, 14, 199, 224, 10, 202, - 48, 76, 120, 64, 136, 87, 219, 81, 89, 50, - 9, 65, 38, 12, 212, 224, 85, 161, 32, 14, - 109, 0, 12, 131, 52, 114, 35, 68, 66, 212, - 134, 178, 237, 160, 114, 160, 113, 72, 196, 183, - 32, 46, 81, 1, 139, 21, 33, 55, 112, 21, - 65, 208, 101, 55, 167, 9, 142, 144, 183, 241, - 195, 8, 169, 38, 34, 240, 21, 6, 128, 187, - 28, 129, 240, 63, 207, 33, 112, 139, 2, 112, - 93, 224, 5, 144, 192, 14, 240, 96, 15, 15, - 144, 12, 173, 66, 13, 231, 0, 113, 87, 107, - 43, 233, 138, 122, 15, 103, 12, 202, 144, 10, - 148, 192, 127, 230, 234, 9, 223, 112, 11, 237, - 255, 48, 15, 117, 186, 14, 240, 64, 72, 244, - 176, 109, 5, 160, 31, 229, 11, 26, 187, 234, - 114, 138, 180, 26, 174, 11, 73, 145, 52, 17, - 164, 230, 110, 56, 151, 187, 207, 122, 165, 245, - 134, 22, 193, 171, 111, 33, 178, 8, 99, 240, - 7, 2, 124, 9, 93, 208, 125, 112, 32, 142, - 52, 226, 11, 197, 128, 177, 189, 0, 14, 76, - 226, 42, 180, 112, 70, 145, 112, 7, 195, 164, - 104, 194, 112, 14, 98, 119, 14, 14, 240, 3, - 20, 240, 142, 178, 64, 9, 120, 96, 7, 178, - 48, 10, 110, 103, 109, 143, 54, 10, 222, 112, - 61, 246, 209, 14, 215, 144, 119, 47, 183, 119, - 127, 247, 72, 19, 113, 2, 95, 65, 120, 97, - 150, 8, 100, 144, 195, 152, 176, 8, 67, 52, - 8, 74, 100, 10, 39, 130, 73, 68, 215, 34, - 138, 66, 196, 226, 8, 117, 78, 55, 41, 165, - 88, 10, 204, 226, 9, 177, 16, 0, 228, 48, - 43, 3, 85, 14, 139, 65, 13, 194, 224, 181, - 181, 64, 12, 252, 176, 0, 169, 128, 0, 174, - 64, 71, 162, 87, 9, 33, 12, 11, 201, 227, - 69, 122, 6, 154, 153, 137, 13, 199, 160, 13, - 171, 235, 194, 9, 178, 119, 114, 210, 119, 51, - 124, 33, 25, 130, 9, 70, 155, 28, 32, 34, - 34, 79, 148, 9, 167, 32, 125, 42, 146, 94, - 45, 34, 41, 71, 76, 121, 78, 167, 69, 142, - 144, 177, 169, 64, 126, 215, 255, 224, 121, 125, - 88, 170, 125, 216, 60, 204, 160, 12, 148, 128, - 122, 193, 244, 112, 183, 210, 181, 170, 18, 10, - 118, 192, 5, 133, 112, 8, 93, 18, 65, 210, - 16, 48, 223, 192, 14, 200, 176, 14, 163, 48, - 10, 225, 27, 67, 110, 252, 77, 113, 18, 39, - 244, 251, 21, 150, 80, 120, 152, 148, 120, 33, - 50, 116, 151, 212, 199, 41, 242, 39, 135, 210, - 84, 148, 55, 74, 78, 7, 8, 112, 224, 34, - 49, 162, 11, 187, 192, 9, 188, 208, 10, 205, - 240, 13, 55, 161, 75, 233, 64, 75, 181, 212, - 95, 59, 56, 13, 12, 167, 122, 171, 167, 70, - 147, 192, 139, 227, 224, 6, 119, 16, 9, 173, - 64, 128, 0, 184, 10, 202, 210, 76, 186, 215, - 37, 189, 151, 13, 223, 192, 198, 238, 203, 38, - 245, 160, 1, 226, 36, 39, 174, 217, 101, 222, - 178, 11, 153, 20, 125, 210, 71, 125, 125, 114, - 10, 214, 23, 74, 133, 28, 35, 166, 100, 74, - 95, 240, 11, 154, 96, 10, 169, 208, 123, 191, - 199, 37, 0, 99, 126, 166, 130, 75, 225, 0, - 15, 11, 227, 108, 181, 160, 65, 196, 52, 9, - 248, 39, 14, 182, 48, 11, 192, 208, 10, 185, - 167, 44, 222, 236, 205, 196, 226, 43, 196, 178, - 44, 93, 146, 77, 45, 129, 206, 50, 212, 0, - 28, 48, 89, 156, 117, 21, 45, 176, 62, 241, - 76, 98, 139, 64, 40, 155, 196, 78, 236, 84, - 12, 187, 255, 188, 40, 193, 28, 204, 169, 212, - 5, 207, 164, 11, 57, 210, 161, 173, 80, 75, - 191, 39, 20, 173, 240, 9, 58, 225, 80, 203, - 0, 14, 71, 29, 122, 6, 106, 11, 181, 64, - 127, 176, 194, 135, 228, 48, 13, 110, 128, 7, - 148, 0, 10, 221, 124, 8, 104, 176, 9, 206, - 100, 123, 9, 216, 49, 8, 248, 49, 195, 178, - 6, 187, 23, 210, 209, 80, 15, 28, 80, 89, - 51, 112, 147, 19, 145, 179, 94, 1, 1, 208, - 32, 47, 158, 212, 39, 187, 192, 129, 169, 102, - 203, 4, 220, 5, 111, 144, 215, 112, 240, 125, - 144, 80, 7, 111, 240, 5, 127, 224, 27, 189, - 112, 104, 211, 32, 14, 228, 32, 10, 224, 16, - 13, 245, 226, 10, 205, 178, 12, 71, 93, 75, - 224, 32, 14, 5, 19, 10, 161, 224, 122, 125, - 40, 43, 211, 80, 9, 226, 177, 205, 173, 64, - 8, 75, 168, 5, 139, 232, 132, 140, 88, 44, - 29, 179, 44, 3, 128, 89, 208, 114, 147, 88, - 9, 176, 63, 20, 207, 114, 45, 211, 125, 44, - 111, 134, 231, 63, 94, 16, 138, 111, 208, 5, - 104, 208, 215, 111, 224, 5, 98, 24, 7, 153, - 64, 211, 191, 144, 12, 146, 173, 48, 164, 226, - 9, 70, 241, 10, 175, 16, 11, 203, 16, 14, - 58, 152, 14, 224, 160, 12, 227, 80, 14, 94, - 235, 159, 229, 64, 80, 179, 2, 123, 20, 183, - 5, 71, 88, 7, 192, 114, 128, 7, 255, 104, - 82, 163, 253, 49, 43, 229, 82, 34, 96, 147, - 208, 120, 45, 198, 170, 133, 233, 228, 133, 241, - 182, 183, 153, 224, 33, 98, 56, 138, 111, 80, - 7, 169, 128, 5, 235, 194, 7, 189, 29, 6, - 171, 115, 10, 166, 208, 10, 80, 172, 14, 241, - 161, 52, 89, 229, 9, 173, 32, 139, 225, 16, - 81, 82, 44, 217, 70, 194, 12, 127, 56, 13, - 1, 48, 127, 147, 171, 108, 160, 128, 136, 104, - 32, 82, 30, 125, 82, 225, 253, 10, 28, 0, - 137, 105, 179, 57, 18, 161, 210, 40, 32, 94, - 179, 121, 115, 122, 178, 8, 239, 212, 33, 98, - 32, 223, 244, 125, 5, 159, 168, 7, 104, 232, - 5, 49, 162, 9, 135, 224, 86, 233, 16, 122, - 112, 24, 12, 2, 112, 96, 176, 192, 156, 31, - 25, 122, 214, 109, 36, 213, 253, 135, 12, 195, - 42, 15, 77, 127, 81, 3, 10, 254, 104, 49, - 238, 149, 49, 30, 205, 136, 159, 208, 0, 35, - 35, 147, 146, 232, 175, 60, 36, 187, 69, 64, - 94, 29, 113, 115, 114, 96, 23, 134, 75, 7, - 144, 192, 226, 45, 174, 7, 161, 248, 46, 127, - 64, 41, 157, 192, 9, 191, 176, 10, 177, 26, - 0, 197, 195, 12, 227, 0, 11, 160, 96, 224, - 71, 13, 221, 146, 173, 12, 178, 0, 14, 31, - 204, 212, 236, 209, 85, 189, 120, 7, 253, 55, - 140, 254, 152, 136, 34, 133, 44, 24, 78, 44, - 175, 0, 15, 100, 255, 67, 50, 29, 238, 225, - 51, 117, 45, 62, 80, 4, 143, 105, 151, 190, - 240, 11, 101, 16, 230, 103, 40, 84, 127, 221, - 161, 165, 128, 33, 191, 112, 230, 13, 228, 64, - 29, 9, 139, 191, 23, 65, 31, 9, 14, 149, - 32, 143, 21, 149, 139, 187, 72, 53, 179, 160, - 12, 254, 247, 4, 80, 0, 235, 87, 48, 235, - 107, 197, 86, 105, 96, 232, 5, 16, 87, 27, - 176, 140, 6, 217, 150, 16, 177, 54, 211, 168, - 2, 57, 21, 92, 69, 128, 10, 181, 253, 137, - 99, 174, 46, 123, 208, 5, 146, 66, 18, 128, - 112, 18, 190, 0, 80, 233, 197, 10, 172, 208, - 13, 157, 160, 9, 159, 48, 77, 201, 45, 146, - 241, 40, 10, 179, 128, 85, 91, 165, 42, 239, - 216, 127, 81, 208, 143, 83, 64, 86, 96, 0, - 232, 173, 80, 163, 4, 105, 54, 29, 96, 50, - 56, 153, 50, 112, 35, 151, 26, 153, 151, 69, - 32, 51, 17, 16, 1, 151, 80, 79, 35, 168, - 7, 222, 184, 51, 111, 32, 35, 183, 105, 35, - 154, 224, 10, 237, 40, 11, 178, 0, 12, 7, - 207, 36, 90, 23, 182, 110, 64, 217, 242, 40, - 10, 167, 74, 11, 67, 104, 231, 90, 3, 5, - 177, 62, 5, 92, 19, 14, 34, 179, 140, 4, - 249, 238, 7, 25, 239, 22, 186, 54, 55, 192, - 149, 64, 176, 151, 17, 121, 90, 20, 208, 13, - 155, 0, 6, 59, 51, 5, 124, 128, 192, 190, - 139, 208, 10, 70, 35, 11, 145, 16, 9, 146, - 144, 243, 103, 247, 142, 180, 64, 30, 76, 19, - 143, 180, 160, 12, 142, 157, 0, 9, 208, 0, - 12, 48, 1, 49, 41, 147, 98, 147, 232, 6, - 169, 148, 140, 238, 148, 114, 131, 4, 67, 16, - 4, 63, 176, 3, 139, 35, 145, 129, 73, 93, - 133, 5, 21, 21, 38, 27, 57, 36, 183, 141, - 245, 88, 145, 165, 3, 147, 229, 146, 152, 229, - 82, 73, 223, 82, 52, 48, 45, 114, 147, 152, - 6, 177, 148, 53, 112, 4, 164, 213, 87, 131, - 181, 245, 152, 115, 88, 66, 9, 187, 142, 165, - 4, 173, 44, 89, 147, 37, 129, 50, 224, 244, - 109, 239, 246, 191, 78, 149, 134, 127, 248, 34, - 79, 248, 35, 143, 248, 134, 239, 246, 1, 1, - 0, 59 }; + 35, 50, 20, 64, 177, 162, 197, 139, 24, 51, + 82, 148, 200, 177, 163, 71, 131, 24, 167, 48, + 97, 242, 164, 137, 19, 33, 66, 150, 92, 89, + 201, 242, 202, 146, 37, 40, 133, 56, 105, 242, + 100, 36, 19, 41, 83, 168, 96, 252, 200, 179, + 39, 65, 139, 53, 164, 48, 57, 121, 37, 10, + 20, 40, 81, 146, 70, 105, 233, 82, 229, 203, + 167, 49, 99, 58, 153, 58, 245, 73, 77, 41, + 82, 134, 92, 244, 201, 181, 161, 197, 41, 79, + 132, 20, 149, 65, 246, 40, 82, 165, 75, 139, + 22, 21, 242, 229, 41, 212, 168, 84, 103, 54, + 153, 75, 215, 234, 72, 156, 68, 44, 118, 221, + 43, 176, 34, 21, 38, 98, 101, 208, 152, 49, + 131, 172, 12, 179, 103, 147, 170, 101, 218, 20, + 102, 84, 153, 84, 233, 206, 181, 74, 153, 178, + 205, 41, 67, 242, 110, 228, 235, 177, 226, 148, + 38, 87, 160, 100, 201, 66, 99, 112, 225, 178, + 102, 149, 126, 35, 180, 139, 14, 144, 126, 236, + 216, 205, 153, 211, 134, 13, 155, 47, 101, 198, + 168, 1, 83, 65, 12, 135, 223, 40, 229, 86, + 182, 59, 178, 166, 205, 155, 83, 52, 11, 224, + 12, 145, 34, 149, 39, 87, 100, 188, 128, 49, + 186, 52, 97, 195, 71, 201, 105, 127, 246, 108, + 117, 107, 57, 64, 98, 207, 255, 145, 211, 38, + 204, 237, 47, 186, 213, 140, 9, 3, 6, 76, + 25, 17, 35, 8, 88, 200, 80, 161, 130, 132, + 17, 147, 139, 235, 191, 123, 119, 72, 141, 205, + 204, 37, 68, 17, 96, 80, 196, 16, 194, 116, + 212, 89, 87, 216, 60, 227, 52, 24, 140, 55, + 170, 168, 146, 137, 119, 116, 128, 39, 30, 121, + 182, 125, 129, 158, 26, 90, 156, 209, 198, 22, + 106, 156, 129, 134, 27, 101, 180, 55, 70, 27, + 186, 100, 19, 141, 57, 44, 154, 99, 15, 77, + 54, 9, 117, 19, 86, 200, 233, 4, 96, 128, + 125, 9, 0, 29, 13, 23, 24, 248, 194, 116, + 164, 209, 48, 15, 131, 229, 4, 99, 164, 145, + 150, 68, 168, 202, 55, 95, 108, 177, 5, 25, + 235, 181, 1, 7, 16, 92, 144, 241, 5, 24, + 95, 168, 129, 134, 25, 104, 108, 193, 198, 110, + 96, 208, 209, 70, 25, 101, 192, 177, 204, 62, + 111, 184, 193, 204, 48, 179, 36, 82, 136, 31, + 209, 216, 131, 3, 127, 119, 9, 133, 85, 78, + 21, 225, 72, 209, 19, 81, 132, 224, 130, 7, + 61, 30, 8, 3, 13, 226, 48, 72, 206, 34, + 150, 88, 194, 203, 145, 193, 240, 34, 161, 42, + 25, 124, 24, 198, 24, 99, 176, 241, 6, 148, + 147, 150, 33, 226, 150, 107, 168, 23, 70, 27, + 149, 126, 9, 6, 15, 109, 136, 73, 199, 54, + 230, 28, 51, 12, 50, 136, 52, 51, 205, 30, + 134, 184, 255, 34, 231, 156, 118, 98, 101, 43, + 158, 203, 241, 53, 224, 21, 33, 0, 224, 129, + 7, 27, 24, 136, 0, 60, 227, 120, 83, 142, + 42, 171, 52, 114, 137, 37, 138, 44, 106, 36, + 47, 188, 52, 162, 10, 33, 83, 250, 16, 135, + 28, 112, 212, 70, 134, 26, 106, 144, 177, 173, + 23, 94, 152, 97, 198, 25, 99, 244, 192, 197, + 22, 116, 176, 49, 6, 25, 111, 176, 177, 69, + 16, 97, 108, 67, 72, 41, 195, 16, 211, 106, + 51, 178, 200, 162, 78, 59, 6, 212, 163, 133, + 25, 56, 224, 96, 235, 192, 184, 114, 69, 145, + 20, 87, 100, 1, 0, 0, 127, 110, 16, 2, + 2, 243, 144, 83, 142, 50, 153, 60, 178, 138, + 34, 137, 42, 234, 236, 179, 141, 52, 2, 206, + 28, 253, 204, 177, 30, 27, 97, 96, 59, 198, + 166, 106, 164, 225, 133, 22, 94, 172, 81, 198, + 22, 61, 192, 60, 198, 23, 103, 188, 241, 198, + 23, 111, 240, 16, 68, 6, 246, 116, 66, 204, + 207, 196, 156, 114, 203, 41, 167, 52, 163, 206, + 43, 253, 134, 27, 240, 192, 88, 101, 118, 35, + 71, 20, 57, 33, 195, 194, 11, 187, 240, 112, + 177, 207, 168, 50, 72, 47, 190, 168, 114, 9, + 180, 96, 55, 122, 164, 37, 171, 64, 211, 67, + 27, 92, 176, 65, 134, 166, 109, 248, 0, 68, + 109, 103, 184, 33, 174, 25, 43, 123, 193, 174, + 26, 91, 132, 113, 70, 167, 106, 88, 255, 138, + 222, 22, 207, 92, 146, 136, 41, 63, 23, 125, + 138, 36, 69, 87, 98, 205, 52, 179, 28, 114, + 128, 61, 94, 44, 61, 5, 78, 56, 105, 149, + 43, 212, 8, 95, 64, 53, 0, 27, 32, 0, + 68, 57, 169, 100, 2, 9, 38, 144, 244, 226, + 72, 35, 205, 130, 29, 118, 163, 151, 52, 146, + 1, 29, 159, 182, 177, 173, 148, 113, 68, 65, + 105, 26, 107, 164, 161, 197, 191, 102, 116, 161, + 134, 25, 120, 168, 193, 195, 109, 96, 168, 81, + 6, 15, 233, 110, 147, 202, 34, 145, 152, 226, + 124, 49, 167, 152, 98, 75, 49, 136, 227, 91, + 73, 46, 221, 224, 211, 175, 22, 146, 79, 225, + 189, 211, 151, 59, 180, 39, 20, 155, 187, 176, + 142, 56, 222, 164, 178, 10, 36, 165, 251, 226, + 203, 35, 140, 52, 178, 8, 198, 204, 50, 171, + 8, 198, 173, 55, 18, 4, 28, 108, 144, 138, + 30, 28, 117, 32, 3, 151, 246, 230, 5, 52, + 212, 205, 13, 106, 248, 129, 27, 220, 112, 6, + 247, 80, 170, 12, 95, 8, 3, 29, 246, 17, + 134, 103, 40, 98, 17, 144, 112, 158, 243, 108, + 193, 65, 91, 220, 2, 29, 205, 104, 70, 53, + 20, 135, 11, 237, 249, 75, 96, 222, 75, 161, + 141, 28, 130, 143, 168, 205, 96, 115, 231, 32, + 150, 50, 26, 49, 8, 247, 57, 194, 17, 129, + 16, 4, 35, 118, 200, 195, 27, 114, 173, 23, + 64, 52, 221, 8, 255, 96, 134, 37, 32, 128, + 97, 12, 65, 168, 67, 25, 208, 128, 134, 53, + 152, 97, 13, 77, 252, 215, 8, 212, 32, 130, + 31, 212, 204, 102, 37, 226, 86, 25, 216, 144, + 174, 32, 88, 98, 17, 140, 16, 70, 45, 198, + 72, 198, 49, 74, 130, 24, 183, 184, 5, 37, + 170, 49, 194, 87, 109, 15, 133, 42, 124, 26, + 66, 40, 34, 4, 24, 80, 205, 5, 16, 75, + 223, 42, 4, 241, 136, 62, 62, 226, 134, 238, + 115, 95, 16, 7, 57, 72, 115, 144, 33, 8, + 109, 56, 3, 27, 228, 144, 155, 125, 140, 1, + 75, 96, 24, 209, 2, 113, 103, 134, 31, 136, + 33, 68, 25, 88, 215, 25, 202, 144, 38, 55, + 160, 161, 12, 251, 232, 193, 62, 150, 183, 136, + 94, 192, 34, 22, 168, 76, 165, 25, 37, 97, + 139, 73, 76, 130, 26, 149, 184, 94, 9, 15, + 176, 59, 156, 196, 49, 124, 7, 161, 99, 12, + 168, 118, 1, 98, 61, 99, 0, 170, 8, 68, + 32, 252, 24, 200, 98, 6, 242, 134, 200, 116, + 196, 35, 84, 177, 12, 54, 100, 203, 13, 176, + 171, 84, 27, 218, 67, 179, 6, 58, 49, 13, + 104, 56, 131, 111, 212, 192, 1, 68, 206, 33, + 31, 61, 160, 131, 39, 63, 121, 196, 125, 40, + 195, 18, 151, 232, 133, 48, 80, 9, 139, 118, + 158, 50, 22, 101, 108, 229, 244, 110, 97, 13, + 117, 224, 227, 113, 56, 200, 1, 102, 188, 183, + 255, 194, 57, 10, 64, 8, 187, 92, 216, 57, + 196, 65, 14, 101, 44, 66, 21, 124, 244, 99, + 31, 135, 41, 204, 133, 10, 243, 161, 60, 100, + 132, 42, 36, 224, 36, 77, 177, 225, 120, 164, + 138, 100, 184, 184, 37, 183, 113, 37, 48, 13, + 105, 56, 67, 24, 182, 240, 154, 48, 4, 193, + 55, 71, 156, 212, 27, 44, 216, 136, 94, 252, + 226, 23, 154, 208, 196, 38, 58, 209, 9, 97, + 208, 180, 22, 206, 195, 169, 45, 78, 81, 9, + 124, 169, 195, 113, 42, 200, 39, 102, 134, 48, + 132, 126, 22, 36, 106, 118, 92, 216, 53, 208, + 7, 141, 70, 100, 66, 16, 57, 124, 104, 14, + 117, 40, 8, 29, 70, 244, 170, 59, 84, 133, + 57, 44, 21, 6, 44, 178, 161, 7, 108, 56, + 3, 238, 200, 244, 5, 38, 186, 225, 7, 85, + 212, 210, 168, 182, 193, 3, 53, 160, 135, 82, + 60, 0, 3, 27, 62, 4, 14, 75, 52, 2, + 24, 49, 141, 233, 75, 49, 129, 137, 94, 240, + 245, 165, 50, 221, 132, 96, 61, 81, 138, 82, + 120, 130, 20, 173, 240, 151, 62, 137, 10, 62, + 144, 48, 225, 133, 74, 157, 71, 57, 46, 177, + 199, 170, 78, 181, 170, 85, 101, 132, 85, 119, + 40, 204, 171, 6, 34, 171, 223, 120, 3, 23, + 122, 240, 6, 80, 189, 11, 12, 32, 93, 15, + 25, 80, 139, 6, 14, 72, 64, 4, 22, 216, + 214, 110, 200, 144, 129, 53, 255, 144, 136, 102, + 111, 200, 77, 169, 118, 97, 140, 69, 24, 2, + 25, 166, 16, 6, 49, 108, 218, 9, 193, 106, + 226, 23, 124, 37, 221, 95, 127, 1, 140, 230, + 2, 163, 16, 204, 80, 129, 22, 114, 192, 216, + 198, 14, 68, 0, 84, 136, 2, 213, 6, 90, + 14, 115, 84, 22, 179, 152, 213, 44, 84, 165, + 10, 81, 172, 74, 244, 27, 187, 128, 3, 88, + 185, 128, 188, 39, 173, 237, 74, 213, 156, 228, + 8, 68, 32, 55, 52, 100, 64, 12, 95, 24, + 193, 26, 206, 64, 6, 49, 240, 23, 93, 186, + 80, 94, 83, 61, 97, 138, 90, 116, 240, 20, + 197, 0, 154, 170, 62, 177, 9, 77, 56, 215, + 185, 164, 32, 133, 33, 162, 59, 221, 162, 82, + 193, 168, 116, 164, 154, 7, 224, 209, 93, 173, + 101, 226, 169, 224, 37, 175, 84, 253, 56, 204, + 62, 226, 240, 161, 230, 104, 82, 222, 232, 96, + 129, 225, 245, 224, 12, 102, 192, 102, 3, 197, + 218, 187, 46, 184, 161, 120, 98, 200, 89, 2, + 71, 128, 192, 117, 125, 193, 93, 219, 120, 70, + 42, 190, 24, 9, 98, 216, 34, 25, 173, 164, + 158, 208, 208, 193, 228, 91, 224, 107, 24, 137, + 152, 69, 97, 95, 241, 138, 67, 144, 194, 0, + 209, 205, 65, 14, 46, 108, 93, 1, 72, 97, + 106, 11, 67, 128, 55, 160, 17, 141, 65, 152, + 249, 204, 103, 102, 133, 47, 34, 193, 230, 210, + 141, 14, 255, 19, 47, 141, 243, 94, 251, 58, + 136, 111, 228, 56, 102, 104, 250, 129, 134, 246, + 91, 60, 8, 186, 33, 13, 189, 203, 198, 89, + 221, 106, 179, 148, 217, 118, 4, 95, 232, 47, + 24, 50, 64, 0, 99, 48, 107, 17, 131, 248, + 196, 145, 57, 56, 9, 73, 72, 34, 141, 78, + 70, 135, 53, 172, 17, 142, 105, 224, 194, 211, + 184, 232, 70, 55, 246, 64, 139, 119, 28, 64, + 5, 91, 190, 48, 21, 254, 243, 143, 12, 11, + 84, 30, 202, 88, 197, 40, 56, 65, 235, 90, + 115, 130, 21, 184, 230, 131, 31, 12, 97, 136, + 8, 247, 225, 21, 165, 248, 132, 176, 59, 113, + 140, 78, 48, 216, 19, 192, 136, 4, 5, 56, + 96, 129, 30, 140, 129, 7, 91, 16, 3, 160, + 113, 22, 210, 109, 121, 50, 13, 223, 144, 192, + 56, 23, 216, 5, 52, 224, 238, 172, 173, 253, + 194, 125, 151, 225, 232, 11, 102, 226, 21, 182, + 24, 35, 7, 45, 125, 233, 52, 50, 89, 22, + 211, 136, 55, 46, 230, 61, 111, 125, 140, 250, + 29, 89, 62, 194, 133, 143, 80, 145, 35, 128, + 25, 0, 28, 254, 134, 43, 254, 208, 138, 130, + 135, 34, 20, 173, 8, 197, 31, 254, 0, 10, + 80, 236, 186, 16, 133, 32, 197, 33, 104, 65, + 139, 82, 168, 67, 29, 195, 56, 6, 49, 144, + 81, 92, 79, 176, 194, 28, 34, 24, 195, 22, + 74, 155, 129, 50, 136, 193, 137, 33, 255, 2, + 147, 136, 70, 144, 13, 180, 146, 43, 146, 182, + 245, 141, 8, 50, 16, 132, 55, 176, 99, 27, + 224, 88, 6, 179, 46, 177, 136, 76, 0, 163, + 24, 181, 72, 6, 146, 43, 109, 105, 76, 107, + 90, 22, 156, 166, 55, 46, 238, 145, 14, 123, + 155, 112, 203, 71, 136, 122, 69, 158, 192, 75, + 121, 24, 35, 26, 204, 144, 6, 40, 14, 126, + 112, 81, 36, 92, 225, 14, 55, 4, 196, 37, + 78, 11, 96, 207, 98, 26, 33, 68, 134, 218, + 135, 81, 10, 87, 100, 163, 111, 147, 154, 230, + 241, 190, 208, 133, 150, 161, 65, 75, 55, 230, + 64, 54, 152, 205, 95, 53, 184, 161, 11, 93, + 144, 128, 4, 44, 185, 139, 32, 20, 158, 29, + 67, 86, 68, 235, 124, 126, 138, 160, 7, 125, + 18, 182, 104, 247, 45, 70, 168, 56, 78, 59, + 35, 23, 244, 102, 122, 58, 178, 119, 234, 28, + 84, 33, 234, 255, 17, 192, 18, 168, 182, 142, + 114, 124, 35, 235, 210, 232, 186, 40, 86, 15, + 8, 174, 135, 125, 236, 135, 48, 251, 217, 67, + 120, 138, 159, 33, 227, 21, 209, 24, 129, 24, + 186, 186, 158, 16, 173, 171, 12, 245, 253, 115, + 26, 52, 244, 131, 76, 122, 178, 12, 63, 208, + 130, 61, 150, 111, 14, 193, 103, 96, 23, 187, + 8, 242, 163, 27, 33, 8, 96, 32, 98, 140, + 66, 95, 183, 36, 170, 145, 198, 17, 110, 58, + 28, 224, 119, 134, 255, 248, 197, 223, 116, 12, + 188, 67, 3, 42, 168, 194, 231, 67, 175, 221, + 133, 193, 227, 234, 122, 72, 189, 52, 68, 17, + 138, 213, 219, 255, 224, 127, 216, 181, 216, 201, + 94, 138, 89, 204, 66, 22, 205, 128, 96, 197, + 64, 56, 133, 96, 15, 63, 80, 46, 149, 66, + 90, 8, 20, 55, 221, 52, 60, 75, 148, 1, + 28, 240, 3, 189, 177, 64, 35, 192, 1, 35, + 64, 1, 20, 96, 14, 217, 64, 0, 203, 192, + 14, 1, 54, 100, 211, 55, 8, 192, 128, 12, + 100, 116, 100, 149, 70, 9, 148, 208, 125, 149, + 199, 105, 185, 208, 130, 226, 167, 121, 250, 112, + 79, 42, 96, 5, 234, 87, 5, 20, 1, 89, + 0, 32, 15, 208, 80, 15, 241, 215, 117, 204, + 0, 8, 64, 120, 127, 12, 247, 112, 100, 247, + 10, 109, 2, 128, 205, 80, 12, 182, 96, 10, + 211, 0, 10, 223, 32, 2, 35, 181, 30, 97, + 240, 5, 43, 163, 5, 35, 192, 14, 86, 82, + 46, 219, 176, 11, 247, 101, 1, 236, 80, 1, + 14, 48, 1, 5, 0, 120, 18, 64, 8, 26, + 104, 12, 236, 96, 1, 28, 96, 12, 208, 240, + 104, 170, 192, 10, 125, 208, 12, 216, 151, 125, + 236, 182, 70, 105, 100, 13, 185, 176, 105, 226, + 23, 15, 241, 240, 130, 250, 160, 15, 24, 96, + 0, 42, 128, 4, 86, 64, 131, 20, 241, 2, + 84, 35, 15, 230, 224, 10, 210, 208, 136, 162, + 255, 240, 131, 65, 184, 122, 173, 32, 10, 127, + 160, 107, 251, 55, 113, 192, 150, 8, 0, 136, + 96, 75, 88, 10, 163, 64, 1, 145, 50, 41, + 100, 128, 6, 42, 176, 2, 90, 112, 31, 85, + 232, 6, 186, 192, 14, 102, 96, 138, 4, 240, + 12, 244, 208, 0, 15, 208, 0, 12, 144, 13, + 128, 135, 129, 18, 0, 13, 131, 103, 12, 247, + 195, 115, 170, 16, 9, 165, 208, 120, 115, 120, + 130, 147, 151, 130, 43, 24, 14, 185, 112, 121, + 201, 248, 130, 24, 96, 126, 42, 144, 4, 72, + 64, 136, 2, 48, 4, 46, 192, 48, 215, 224, + 13, 246, 192, 136, 243, 7, 132, 220, 200, 141, + 244, 23, 10, 175, 87, 132, 254, 55, 12, 33, + 68, 61, 166, 240, 10, 204, 32, 1, 224, 0, + 7, 91, 80, 86, 110, 112, 104, 93, 80, 138, + 43, 96, 6, 106, 176, 15, 96, 176, 2, 41, + 128, 2, 102, 96, 15, 17, 240, 0, 179, 216, + 0, 244, 144, 13, 18, 96, 139, 230, 192, 134, + 26, 72, 8, 138, 39, 45, 145, 32, 105, 216, + 23, 116, 145, 103, 105, 41, 88, 13, 32, 100, + 13, 124, 136, 140, 125, 72, 126, 127, 232, 140, + 73, 0, 141, 72, 48, 141, 189, 2, 0, 165, + 151, 141, 210, 192, 12, 144, 216, 141, 222, 8, + 142, 68, 136, 137, 254, 151, 8, 205, 64, 12, + 212, 99, 11, 123, 16, 13, 98, 0, 7, 92, + 16, 6, 119, 119, 37, 63, 255, 64, 1, 42, + 32, 93, 120, 144, 6, 100, 160, 13, 216, 2, + 86, 22, 0, 2, 253, 232, 143, 17, 0, 1, + 223, 64, 1, 246, 160, 2, 107, 32, 6, 25, + 48, 2, 130, 71, 8, 173, 163, 10, 144, 48, + 13, 233, 22, 116, 66, 231, 74, 69, 199, 70, + 232, 176, 130, 185, 16, 15, 203, 152, 14, 98, + 233, 116, 207, 184, 145, 73, 48, 141, 52, 0, + 0, 168, 176, 14, 216, 72, 146, 36, 9, 8, + 111, 217, 141, 171, 87, 137, 41, 89, 118, 254, + 39, 11, 136, 32, 128, 167, 96, 8, 230, 176, + 13, 252, 64, 7, 200, 151, 1, 106, 48, 144, + 20, 192, 50, 42, 16, 82, 104, 192, 5, 64, + 0, 78, 216, 64, 0, 13, 16, 1, 13, 208, + 0, 19, 208, 0, 11, 112, 129, 209, 176, 2, + 88, 64, 1, 63, 128, 86, 203, 112, 9, 139, + 7, 12, 199, 80, 70, 201, 160, 149, 146, 128, + 130, 108, 52, 66, 95, 9, 150, 96, 233, 12, + 98, 217, 116, 128, 248, 14, 245, 160, 4, 74, + 0, 141, 211, 72, 62, 107, 233, 13, 217, 224, + 10, 110, 9, 8, 163, 208, 155, 114, 169, 112, + 150, 8, 113, 152, 216, 127, 154, 88, 123, 197, + 32, 11, 210, 64, 8, 251, 144, 15, 209, 86, + 69, 93, 96, 15, 24, 88, 119, 94, 192, 6, + 110, 160, 2, 110, 64, 82, 116, 0, 14, 236, + 48, 1, 17, 0, 153, 11, 240, 0, 16, 32, + 1, 93, 255, 160, 148, 24, 128, 5, 35, 192, + 3, 187, 144, 10, 208, 176, 120, 125, 0, 116, + 100, 148, 149, 39, 104, 154, 222, 247, 149, 200, + 152, 140, 99, 105, 111, 129, 168, 1, 178, 169, + 4, 29, 73, 5, 87, 192, 48, 235, 32, 7, + 100, 182, 155, 188, 233, 155, 220, 8, 156, 250, + 23, 113, 177, 183, 146, 155, 40, 9, 137, 224, + 10, 34, 160, 13, 116, 192, 3, 98, 144, 147, + 20, 48, 158, 20, 32, 1, 91, 196, 5, 123, + 163, 5, 62, 57, 6, 101, 80, 1, 32, 16, + 153, 15, 160, 0, 223, 80, 1, 63, 208, 5, + 34, 96, 14, 94, 128, 5, 6, 88, 31, 235, + 233, 84, 158, 64, 12, 115, 248, 120, 174, 180, + 70, 167, 121, 61, 120, 232, 130, 172, 57, 150, + 205, 104, 0, 43, 176, 159, 253, 233, 4, 12, + 51, 80, 202, 176, 136, 36, 57, 10, 5, 106, + 146, 8, 202, 107, 10, 106, 132, 184, 144, 8, + 61, 117, 56, 165, 16, 13, 28, 160, 13, 61, + 192, 3, 28, 176, 6, 94, 208, 5, 217, 96, + 15, 18, 144, 1, 100, 128, 54, 108, 144, 6, + 101, 224, 3, 65, 176, 3, 37, 192, 0, 178, + 248, 0, 19, 48, 0, 240, 192, 15, 99, 192, + 1, 236, 64, 0, 24, 170 , + 162, 25, 144, 10, 139, 231, 9, 238, 41, 116, + 240, 57, 9, 56, 74, 13, 222, 7, 150, 95, + 105, 159, 62, 138, 15, 26, 96, 2, 45, 208, + 2, 74, 255, 96, 3, 2, 112, 4, 82, 240, + 66, 121, 128, 0, 216, 0, 13, 217, 152, 164, + 189, 169, 164, 65, 8, 118, 9, 42, 113, 70, + 152, 8, 44, 25, 128, 167, 240, 10, 246, 176, + 12, 65, 176, 5, 109, 213, 5, 226, 130, 129, + 22, 16, 4, 65, 0, 50, 239, 50, 90, 100, + 224, 0, 1, 16, 0, 17, 176, 0, 11, 240, + 13, 243, 224, 15, 218, 0, 125, 219, 144, 1, + 18, 144, 6, 227, 153, 1, 219, 160, 12, 230, + 214, 158, 239, 57, 154, 55, 74, 13, 130, 202, + 70, 215, 211, 130, 203, 216, 163, 127, 168, 61, + 43, 176, 168, 140, 90, 17, 67, 112, 5, 46, + 128, 10, 3, 197, 14, 3, 16, 13, 174, 144, + 169, 6, 90, 127, 156, 234, 164, 164, 80, 118, + 165, 0, 170, 178, 112, 56, 163, 106, 15, 4, + 176, 13, 251, 160, 165, 194, 58, 158, 3, 0, + 14, 218, 192, 15, 117, 112, 7, 116, 48, 7, + 91, 128, 6, 99, 96, 1, 26, 224, 0, 223, + 48, 0, 21, 144, 0, 29, 0, 7, 59, 83, + 1, 224, 176, 15, 217, 144, 6, 226, 153, 1, + 227, 48, 100, 148, 69, 10, 146, 224, 167, 240, + 137, 130, 204, 138, 163, 207, 250, 149, 228, 119, + 159, 6, 144, 168, 214, 122, 3, 253, 198, 4, + 29, 224, 2, 121, 112, 13, 242, 176, 12, 171, + 16, 174, 153, 202, 155, 173, 167, 112, 67, 88, + 151, 159, 186, 174, 67, 179, 7, 246, 255, 192, + 26, 241, 154, 95, 105, 48, 2, 230, 64, 0, + 186, 48, 7, 252, 144, 15, 117, 192, 5, 114, + 224, 108, 194, 138, 6, 21, 208, 142, 95, 64, + 7, 116, 0, 7, 60, 176, 13, 98, 176, 11, + 218, 112, 31, 131, 183, 5, 17, 203, 44, 141, + 80, 8, 149, 128, 149, 89, 137, 130, 242, 201, + 149, 60, 218, 177, 25, 89, 15, 43, 96, 2, + 58, 192, 168, 142, 106, 17, 66, 80, 141, 39, + 75, 14, 100, 214, 178, 7, 10, 179, 97, 119, + 137, 118, 169, 137, 162, 186, 7, 174, 32, 1, + 236, 32, 74, 178, 5, 6, 35, 176, 12, 252, + 32, 7, 116, 0, 78, 251, 48, 27, 101, 154, + 153, 90, 178, 6, 96, 0, 7, 180, 65, 115, + 63, 96, 1, 251, 48, 120, 217, 80, 1, 62, + 32, 14, 188, 128, 78, 141, 96, 8, 149, 224, + 167, 174, 244, 74, 24, 43, 168, 76, 70, 145, + 227, 215, 154, 127, 24, 131, 137, 170, 3, 168, + 43, 178, 27, 225, 28, 81, 176, 173, 121, 176, + 14, 110, 11, 174, 65, 8, 8, 223, 184, 112, + 150, 184, 127, 180, 176, 160, 118, 123, 105, 137, + 160, 7, 217, 208, 26, 89, 218, 95, 100, 176, + 12, 202, 144, 15, 115, 16, 4, 251, 32, 161, + 112, 144, 15, 187, 32, 2, 176, 101, 1, 190, + 193, 14, 21, 242, 46, 187, 32, 1, 21, 192, + 14, 34, 32, 158, 186, 128, 0, 98, 102, 12, + 148, 101, 8, 214, 255, 48, 154, 202, 250, 74, + 205, 202, 149, 207, 218, 177, 247, 105, 126, 88, + 128, 186, 44, 208, 2, 122, 81, 17, 143, 181, + 48, 30, 32, 102, 111, 203, 141, 173, 64, 187, + 149, 248, 122, 10, 74, 11, 123, 112, 132, 205, + 112, 11, 146, 144, 11, 134, 144, 13, 224, 192, + 15, 234, 21, 6, 153, 100, 1, 219, 240, 33, + 52, 71, 7, 61, 160, 11, 249, 176, 15, 18, + 188, 133, 203, 192, 133, 251, 128, 45, 20, 42, + 2, 191, 145, 189, 98, 128, 0, 235, 224, 15, + 228, 160, 167, 171, 96, 8, 179, 80, 13, 238, + 48, 154, 146, 240, 74, 92, 137, 14, 213, 192, + 13, 220, 16, 182, 98, 137, 11, 128, 136, 1, + 59, 176, 3, 58, 208, 190, 170, 123, 57, 21, + 225, 4, 73, 181, 1, 240, 48, 102, 43, 27, + 174, 38, 153, 127, 98, 23, 113, 252, 59, 179, + 105, 36, 9, 149, 96, 8, 18, 160, 13, 64, + 32, 7, 92, 160, 11, 72, 196, 3, 218, 160, + 11, 101, 64, 6, 61, 64, 37, 249, 160, 11, + 92, 188, 133, 65, 112, 115, 82, 59, 27, 99, + 48, 95, 28, 64, 0, 4, 176, 11, 254, 112, + 13, 48, 224, 15, 216, 32, 194, 210, 176, 7, + 185, 64, 13, 238, 0, 168, 107, 212, 149, 76, + 198, 13, 59, 58, 186, 165, 11, 136, 53, 204, + 2, 44, 160, 3, 74, 160, 23, 57, 66, 71, + 189, 226, 2, 62, 172, 13, 198, 240, 13, 224, + 255, 170, 169, 64, 72, 151, 151, 104, 118, 154, + 88, 9, 0, 92, 9, 122, 32, 2, 66, 91, + 7, 79, 252, 46, 76, 203, 5, 110, 181, 5, + 179, 193, 5, 116, 192, 197, 251, 32, 181, 219, + 16, 27, 247, 218, 15, 111, 144, 6, 101, 108, + 1, 218, 128, 0, 215, 128, 0, 254, 208, 15, + 216, 240, 12, 132, 240, 13, 163, 240, 14, 179, + 192, 13, 238, 64, 13, 107, 84, 9, 161, 11, + 173, 201, 40, 195, 174, 217, 13, 205, 184, 3, + 39, 112, 2, 126, 28, 200, 121, 242, 19, 21, + 33, 4, 126, 2, 44, 240, 32, 15, 207, 144, + 200, 209, 192, 200, 161, 160, 7, 157, 170, 146, + 145, 140, 14, 178, 160, 7, 25, 208, 15, 113, + 112, 7, 117, 96, 7, 113, 192, 5, 179, 113, + 7, 99, 178, 5, 92, 0, 7, 116, 192, 15, + 218, 240, 206, 91, 176, 13, 242, 220, 26, 115, + 0, 4, 25, 32, 2, 21, 160, 13, 249, 224, + 15, 89, 224, 15, 117, 0, 180, 186, 240, 12, + 208, 160, 200, 134, 64, 11, 225, 224, 14, 220, + 64, 13, 31, 180, 105, 208, 10, 150, 245, 38, + 106, 196, 140, 1, 41, 112, 2, 40, 128, 204, + 238, 187, 204, 71, 213, 204, 48, 176, 1, 23, + 16, 2, 89, 16, 49, 71, 90, 205, 65, 168, + 107, 50, 155, 174, 249, 130, 47, 209, 160, 13, + 113, 224, 3, 44, 125, 7, 62, 224, 15, 52, + 224, 15, 118, 32, 7, 114, 255, 224, 76, 179, + 81, 180, 251, 96, 175, 251, 176, 133, 219, 160, + 11, 225, 12, 6, 63, 208, 3, 129, 91, 207, + 92, 80, 212, 85, 92, 14, 203, 64, 8, 171, + 0, 8, 239, 208, 14, 232, 224, 194, 215, 19, + 15, 245, 233, 130, 246, 38, 106, 123, 128, 15, + 18, 141, 2, 90, 141, 2, 23, 45, 71, 215, + 181, 195, 51, 112, 14, 49, 48, 29, 29, 48, + 14, 229, 0, 13, 43, 203, 9, 128, 0, 10, + 193, 73, 118, 125, 16, 108, 120, 137, 8, 179, + 32, 1, 64, 224, 210, 254, 112, 7, 114, 112, + 7, 118, 125, 215, 119, 0, 7, 97, 48, 30, + 64, 48, 82, 116, 160, 13, 134, 151, 134, 115, + 224, 15, 114, 160, 6, 35, 16, 4, 251, 42, + 38, 112, 208, 15, 67, 171, 11, 224, 160, 12, + 181, 28, 13, 6, 176, 7, 211, 192, 13, 108, + 84, 168, 47, 56, 111, 163, 70, 113, 248, 144, + 2, 31, 80, 2, 37, 160, 213, 93, 141, 75, + 32, 49, 117, 81, 240, 35, 212, 225, 15, 242, + 16, 194, 223, 48, 8, 173, 112, 187, 10, 250, + 107, 193, 150, 8, 136, 128, 8, 135, 176, 13, + 253, 144, 0, 118, 224, 54, 117, 224, 15, 62, + 224, 210, 119, 16, 7, 194, 205, 15, 115, 64, + 147, 92, 176, 63, 89, 58, 31, 235, 1, 59, + 143, 11, 4, 236, 200, 15, 53, 7, 4, 117, + 240, 151, 189, 106, 12, 95, 58, 10, 123, 16, + 14, 220, 255, 16, 75, 22, 233, 12, 184, 224, + 12, 247, 48, 106, 123, 176, 7, 24, 48, 218, + 164, 93, 2, 44, 160, 204, 24, 45, 32, 21, + 129, 48, 89, 144, 32, 52, 80, 214, 2, 189, + 10, 173, 16, 9, 69, 124, 8, 135, 96, 219, + 159, 144, 8, 108, 103, 14, 186, 112, 221, 43, + 13, 30, 113, 96, 7, 118, 48, 180, 98, 178, + 210, 253, 32, 206, 236, 117, 54, 60, 160, 134, + 33, 199, 3, 20, 78, 7, 254, 176, 5, 112, + 32, 7, 204, 235, 196, 236, 172, 13, 57, 87, + 203, 174, 112, 8, 184, 80, 121, 60, 42, 195, + 184, 112, 222, 7, 240, 1, 32, 176, 226, 164, + 205, 2, 57, 140, 218, 240, 93, 17, 77, 16, + 5, 213, 49, 3, 29, 0, 4, 176, 157, 9, + 172, 176, 127, 125, 208, 7, 132, 21, 108, 85, + 186, 11, 186, 208, 15, 224, 65, 147, 175, 81, + 7, 227, 252, 207, 83, 2, 4, 32, 243, 207, + 253, 229, 170, 206, 43, 60, 18, 52, 7, 62, + 80, 7, 174, 17, 180, 131, 157, 15, 40, 34, + 217, 202, 48, 208, 245, 240, 14, 137, 240, 212, + 132, 202, 154, 161, 214, 13, 6, 80, 2, 36, + 64, 2, 43, 14, 2, 92, 189, 21, 205, 97, + 17, 82, 32, 4, 130, 225, 15, 167, 49, 7, + 233, 67, 89, 131, 80, 8, 61, 254, 227, 137, + 80, 10, 202, 57, 184, 176, 83, 42, 68, 123, + 7, 64, 144, 224, 175, 65, 206, 118, 255, 208, + 224, 114, 16, 109, 98, 224, 170, 95, 88, 6, + 252, 208, 15, 253, 144, 15, 249, 48, 184, 219, + 160, 207, 92, 220, 3, 15, 188, 15, 236, 96, + 12, 139, 88, 8, 184, 240, 212, 20, 137, 121, + 206, 240, 14, 103, 158, 230, 168, 14, 2, 46, + 238, 230, 17, 129, 17, 76, 16, 29, 215, 113, + 20, 163, 53, 205, 151, 192, 9, 164, 224, 227, + 192, 86, 8, 132, 64, 7, 65, 48, 6, 111, + 192, 184, 52, 253, 26, 64, 80, 232, 76, 254, + 196, 80, 140, 45, 14, 252, 58, 76, 206, 216, + 114, 96, 7, 9, 80, 42, 140, 189, 13, 61, + 144, 15, 200, 27, 4, 85, 172, 13, 211, 172, + 34, 160, 46, 145, 241, 224, 194, 6, 160, 14, + 168, 158, 234, 109, 206, 234, 80, 115, 17, 175, + 142, 29, 80, 192, 5, 73, 1, 14, 137, 236, + 10, 164, 224, 7, 230, 96, 1, 116, 0, 202, + 174, 1, 4, 61, 32, 65, 116, 144, 175, 253, + 224, 54, 197, 125, 236, 115, 160, 11, 235, 28, + 6, 92, 224, 236, 138, 9, 148, 225, 140, 176, + 217, 210, 15, 109, 112, 115, 100, 176, 156, 216, + 238, 233, 209, 32, 226, 186, 124, 15, 248, 176, + 226, 225, 158, 230, 227, 46, 200, 60, 145, 17, + 128, 97, 20, 137, 145, 22, 79, 75, 8, 98, + 128, 46, 104, 19, 202, 111, 112, 170, 53, 217, + 15, 9, 126, 224, 9, 222, 15, 195, 78, 233, + 66, 139, 45, 224, 255, 28, 7, 9, 80, 33, + 197, 125, 46, 167, 154, 15, 45, 166, 11, 91, + 224, 240, 236, 224, 229, 248, 112, 15, 241, 160, + 222, 32, 16, 238, 108, 126, 218, 239, 221, 19, + 25, 33, 5, 160, 129, 22, 87, 176, 5, 45, + 145, 189, 246, 224, 6, 218, 144, 55, 22, 176, + 5, 68, 46, 7, 117, 32, 233, 146, 158, 232, + 65, 59, 7, 43, 77, 3, 117, 192, 184, 117, + 224, 54, 243, 62, 236, 254, 160, 11, 28, 176, + 11, 111, 48, 2, 25, 128, 13, 252, 208, 3, + 216, 174, 12, 217, 80, 15, 59, 32, 218, 31, + 160, 226, 22, 79, 2, 236, 237, 222, 26, 175, + 43, 24, 113, 4, 67, 193, 24, 111, 161, 5, + 187, 0, 6, 18, 112, 34, 215, 157, 15, 118, + 192, 206, 114, 80, 207, 253, 192, 197, 90, 255, + 219, 137, 94, 7, 90, 111, 30, 98, 18, 6, + 64, 16, 7, 97, 64, 15, 171, 176, 10, 246, + 16, 39, 246, 144, 168, 88, 80, 195, 39, 80, + 2, 68, 15, 2, 165, 221, 2, 105, 75, 238, + 1, 162, 17, 67, 48, 20, 42, 177, 18, 47, + 17, 19, 102, 176, 147, 108, 240, 239, 234, 220, + 15, 234, 149, 15, 252, 128, 220, 132, 205, 15, + 9, 176, 10, 170, 64, 15, 244, 224, 11, 198, + 95, 0, 5, 112, 0, 7, 160, 1, 26, 176, + 2, 208, 175, 4, 45, 128, 186, 55, 236, 199, + 199, 124, 204, 235, 141, 2, 56, 172, 17, 56, + 251, 146, 75, 176, 47, 5, 79, 112, 18, 142, + 33, 4, 77, 144, 3, 249, 212, 148, 25, 16, + 78, 131, 45, 207, 21, 40, 2, 236, 128, 13, + 41, 68, 84, 170, 118, 4, 85, 96, 5, 72, + 176, 145, 178, 105, 173, 236, 91, 253, 44, 0, + 16, 40, 4, 178, 208, 209, 194, 134, 0, 132, + 9, 19, 254, 99, 216, 208, 225, 67, 136, 17, + 37, 74, 84, 88, 17, 225, 16, 41, 76, 158, + 52, 113, 210, 177, 9, 14, 51, 88, 204, 124, + 25, 243, 35, 199, 59, 21, 43, 188, 4, 81, + 49, 197, 229, 16, 152, 84, 142, 28, 169, 98, + 5, 73, 146, 36, 74, 148, 180, 224, 217, 66, + 135, 14, 22, 65, 11, 42, 57, 104, 81, 225, + 68, 164, 73, 149, 70, 52, 106, 17, 35, 19, + 168, 94, 64, 164, 88, 99, 70, 138, 148, 41, + 34, 119, 96, 208, 225, 242, 229, 16, 42, 50, + 107, 90, 193, 153, 115, 103, 79, 37, 55, 138, + 54, 93, 184, 212, 237, 91, 165, 108, 43, 86, + 81, 130, 132, 10, 154, 21, 87, 175, 106, 65, + 241, 211, 235, 148, 152, 51, 171, 212, 68, 82, + 24, 137, 141, 181, 114, 219, 194, 101, 220, 120, + 162, 226, 34, 70, 146, 236, 184, 33, 128, 200, + 229, 200, 69, 20, 111, 102, 235, 216, 243, 231, + 199, 156, 69, 143, 94, 12, 218, 244, 105, 166, + 164, 85, 35, 68, 221, 218, 245, 107, 216, 174, + 3, 2, 0, 59 }; + diff --git a/main/main.c b/main/main.c index 9b0a3c9701ad..d96d437f8360 100644 --- a/main/main.c +++ b/main/main.c @@ -32,14 +32,7 @@ #include "win32/signal.h" #include #elif defined(NETWARE) -#ifdef NEW_LIBC #include -#else -#include "netware/time_nw.h" -#endif -/*#include "netware/signal_nw.h"*/ -/*#include "netware/env.h"*/ /* Temporary */ -/*#include */ #ifdef USE_WINSOCK #include #endif @@ -229,7 +222,7 @@ static PHP_INI_MH(OnUpdateTimeout) # define PHP_SAFE_MODE_EXEC_DIR "" #endif -#ifdef PHP_PROG_SENDMAIL +#if defined(PHP_PROG_SENDMAIL) && !defined(NETWARE) # define DEFAULT_SENDMAIL_PATH PHP_PROG_SENDMAIL " -t -i " #else # define DEFAULT_SENDMAIL_PATH NULL @@ -305,6 +298,7 @@ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("file_uploads", "1", PHP_INI_SYSTEM, OnUpdateBool, file_uploads, php_core_globals, core_globals) STD_PHP_INI_ENTRY("upload_max_filesize", "2M", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, upload_max_filesize, php_core_globals, core_globals) + PHP_INI_ENTRY("max_multipart_body_parts", "-1", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL) STD_PHP_INI_ENTRY("post_max_size", "8M", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, post_max_size, sapi_globals_struct,sapi_globals) STD_PHP_INI_ENTRY("upload_tmp_dir", NULL, PHP_INI_SYSTEM, OnUpdateStringUnempty, upload_tmp_dir, php_core_globals, core_globals) @@ -549,9 +543,9 @@ PHPAPI void php_verror(const char *docref, const char *params, int type, const c } /* }}} */ -/* {{{ php_error_docref */ +/* {{{ php_error_docref0 */ /* See: CODING_STANDARDS for details. */ -PHPAPI void php_error_docref(const char *docref TSRMLS_DC, int type, const char *format, ...) +PHPAPI void php_error_docref0(const char *docref TSRMLS_DC, int type, const char *format, ...) { va_list args; @@ -655,16 +649,21 @@ static void php_error_cb(int type, const char *error_filename, const uint error_ /* according to error handling mode, suppress error, throw exception or show it */ if (PG(error_handling) != EH_NORMAL) { switch (type) { - case E_ERROR: case E_CORE_ERROR: case E_COMPILE_ERROR: - case E_USER_ERROR: case E_PARSE: /* fatal errors are real errors and cannot be made exceptions */ break; + case E_STRICT: + /* for the sake of BC to old damaged code */ + break; + case E_NOTICE: + case E_USER_NOTICE: + /* notices are no errors and are not treated as such like E_WARNINGS */ + break; default: /* throw an exception if we are in EH_THROW mode - * but DO NOT overwrite a pending excepption + * but DO NOT overwrite a pending exception */ if (PG(error_handling) == EH_THROW && !EG(exception)) { zend_throw_exception(PG(exception_class), buffer, 0 TSRMLS_CC); @@ -776,8 +775,8 @@ static void php_error_cb(int type, const char *error_filename, const uint error_ /* restore memory limit */ AG(memory_limit) = PG(memory_limit); #endif - zend_bailout(); efree(buffer); + zend_bailout(); return; } break; @@ -1135,11 +1134,12 @@ void php_request_shutdown_for_hook(void *dummy) { TSRMLS_FETCH(); if (PG(modules_activated)) zend_try { - php_call_shutdown_functions(); + php_call_shutdown_functions(TSRMLS_C); } zend_end_try(); if (PG(modules_activated)) { zend_deactivate_modules(TSRMLS_C); + php_free_shutdown_functions(TSRMLS_C); } zend_try { @@ -1148,6 +1148,8 @@ void php_request_shutdown_for_hook(void *dummy) for (i = 0; i < NUM_TRACK_VARS; i++) { if (PG(http_globals)[i]) { zval_ptr_dtor(&PG(http_globals)[i]); + /* May be accessed before php_request_startup() */ + PG(http_globals)[i] = NULL; } } } zend_end_try(); @@ -1158,6 +1160,10 @@ void php_request_shutdown_for_hook(void *dummy) sapi_deactivate(TSRMLS_C); } zend_end_try(); + zend_try { + php_shutdown_stream_hashes(TSRMLS_C); + } zend_end_try(); + zend_try { shutdown_memory_manager(CG(unclean_shutdown), 0 TSRMLS_CC); } zend_end_try(); @@ -1181,6 +1187,7 @@ void php_request_shutdown(void *dummy) * inside zend_executor callback functions. */ EG(opline_ptr) = NULL; + EG(active_op_array) = NULL; zend_try { php_end_ob_buffers((zend_bool)(SG(request_info).headers_only?0:1) TSRMLS_CC); @@ -1190,12 +1197,17 @@ void php_request_shutdown(void *dummy) sapi_send_headers(TSRMLS_C); } zend_end_try(); + zend_try { + zend_call_destructors(TSRMLS_C); + } zend_end_try(); + if (PG(modules_activated)) zend_try { - php_call_shutdown_functions(); + php_call_shutdown_functions(TSRMLS_C); } zend_end_try(); if (PG(modules_activated)) { zend_deactivate_modules(TSRMLS_C); + php_free_shutdown_functions(TSRMLS_C); } zend_try { @@ -1204,6 +1216,8 @@ void php_request_shutdown(void *dummy) for (i=0; i /* Includes definition for u_char */ #endif -#if defined(NETWARE) && !defined(NEW_LIBC) -/*#include */ -#include -#endif - static void setup(u_char *list1, u_char *list2, size_t n, size_t size, int (*cmp)(const void *, const void * TSRMLS_DC) TSRMLS_DC); static void insertionsort(u_char *a, size_t n, size_t size, int (*cmp)(const void *, const void * TSRMLS_DC) TSRMLS_DC); diff --git a/main/network.c b/main/network.c index ee8567967f5c..189d3aa8a855 100644 --- a/main/network.c +++ b/main/network.c @@ -28,13 +28,6 @@ #ifdef PHP_WIN32 #define O_RDONLY _O_RDONLY #include "win32/param.h" -#elif defined(NETWARE) -#ifdef NEW_LIBC -#include -#include -#else -#include "netware/time_nw.h" -#endif #else #include #endif @@ -57,15 +50,11 @@ #if defined(NETWARE) #ifdef USE_WINSOCK -/*#include */ #include #else -/* New headers for socket stuff */ -#ifdef NEW_LIBC #include #include #include -#endif #include #endif #elif !defined(PHP_WIN32) @@ -295,9 +284,6 @@ PHPAPI int php_network_connect_socket(php_socket_t sockfd, int error = 0; socklen_t len; int ret = 0; - fd_set rset; - fd_set wset; - fd_set eset; SET_SOCKET_BLOCKING_MODE(sockfd, orig_flags); @@ -325,18 +311,11 @@ PHPAPI int php_network_connect_socket(php_socket_t sockfd, goto ok; } - FD_ZERO(&rset); - FD_ZERO(&eset); - FD_SET(sockfd, &rset); - FD_SET(sockfd, &eset); - - wset = rset; - - if ((n = select(sockfd + 1, &rset, &wset, &eset, timeout)) == 0) { + if ((n = php_pollfd_for(sockfd, PHP_POLLREADABLE|POLLOUT, timeout)) == 0) { error = PHP_TIMEOUT_ERROR_VALUE; } - if(FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) { + if (n > 0) { len = sizeof(error); /* BSD-derived systems set errno correctly @@ -495,12 +474,15 @@ PHPAPI int php_network_parse_network_address_with_port(const char *addr, long ad if (*addr == '[') { colon = memchr(addr + 1, ']', addrlen-1); if (!colon || colon[1] != ':') { - return 0; + return FAILURE; } port = atoi(colon + 2); addr++; } else { colon = memchr(addr, ':', addrlen); + if (!colon) { + return FAILURE; + } port = atoi(colon + 1); } @@ -589,8 +571,8 @@ PHPAPI void php_network_populate_name_from_sockaddr( /* generally not thread safe, but it *is* thread safe under win32 */ buf = inet_ntoa(((struct sockaddr_in*)sa)->sin_addr); if (buf) { - *textaddrlen = strlen(buf); - *textaddr = estrndup(buf, *textaddrlen); + *textaddrlen = spprintf(textaddr, 0, "%s:%d", + buf, ntohs(((struct sockaddr_in*)sa)->sin_port)); } break; @@ -599,8 +581,8 @@ PHPAPI void php_network_populate_name_from_sockaddr( case AF_INET6: buf = (char*)inet_ntop(sa->sa_family, &((struct sockaddr_in6*)sa)->sin6_addr, (char *)&abuf, sizeof(abuf)); if (buf) { - *textaddrlen = strlen(buf); - *textaddr = estrndup(buf, *textaddrlen); + *textaddrlen = spprintf(textaddr, 0, "%s:%d", + buf, ntohs(((struct sockaddr_in6*)sa)->sin6_port)); } break; @@ -689,21 +671,17 @@ PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock, TSRMLS_DC) { php_socket_t clisock = -1; - fd_set rset; int error = 0, n; php_sockaddr_storage sa; socklen_t sl; - - FD_ZERO(&rset); - FD_SET(srvsock, &rset); - n = select(srvsock + 1, &rset, NULL, NULL, timeout); + n = php_pollfd_for(srvsock, PHP_POLLREADABLE, timeout); if (n == 0) { error = PHP_TIMEOUT_ERROR_VALUE; } else if (n == -1) { error = php_socket_errno(); - } else if (FD_ISSET(srvsock, &rset)) { + } else { sl = sizeof(sa); clisock = accept(srvsock, (struct sockaddr*)&sa, &sl); @@ -802,8 +780,13 @@ php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short } if (sa) { + /* free error string recieved during previous iteration (if any) */ + if (error_string && *error_string) { + efree(*error_string); + *error_string = NULL; + } + /* make a connection attempt */ - n = php_network_connect_socket(sock, sa, socklen, asynchronous, timeout ? &working_timeout : NULL, error_string, error_code); @@ -1023,6 +1006,93 @@ PHPAPI int php_set_sock_blocking(int socketd, int block TSRMLS_DC) return ret; } +PHPAPI void _php_emit_fd_setsize_warning(int max_fd) +{ + TSRMLS_FETCH(); + +#ifdef PHP_WIN32 + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "PHP needs to be recompiled with a larger value of FD_SETSIZE.\n" + "If this binary is from an official www.php.net package, file a bug report\n" + "at http://bugs.php.net, including the following information:\n" + "FD_SETSIZE=%d, but you are using %d.\n" + " --enable-fd-setsize=%d is recommended, but you may want to set it\n" + "to match to maximum number of sockets each script will work with at\n" + "one time, in order to avoid seeing this error again at a later date.", + FD_SETSIZE, max_fd, (max_fd + 128) & ~127); +#else + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "You MUST recompile PHP with a larger value of FD_SETSIZE.\n" + "It is set to %d, but you have descriptors numbered at least as high as %d.\n" + " --enable-fd-setsize=%d is recommended, but you may want to set it\n" + "to equal the maximum number of open files supported by your system,\n" + "in order to avoid seeing this error again at a later date.", + FD_SETSIZE, max_fd, (max_fd + 1024) & ~1023); +#endif +} + +#if defined(PHP_USE_POLL_2_EMULATION) + +/* emulate poll(2) using select(2), safely. */ + +PHPAPI int php_poll2(php_pollfd *ufds, unsigned int nfds, int timeout) +{ + fd_set rset, wset, eset; + php_socket_t max_fd = SOCK_ERR; + unsigned int i, n; + struct timeval tv; + + /* check the highest numbered descriptor */ + for (i = 0; i < nfds; i++) { + if (ufds[i].fd > max_fd) + max_fd = ufds[i].fd; + } + + PHP_SAFE_MAX_FD(max_fd, nfds + 1); + + FD_ZERO(&rset); + FD_ZERO(&wset); + FD_ZERO(&eset); + + for (i = 0; i < nfds; i++) { + if (ufds[i].events & PHP_POLLREADABLE) { + PHP_SAFE_FD_SET(ufds[i].fd, &rset); + } + if (ufds[i].events & POLLOUT) { + PHP_SAFE_FD_SET(ufds[i].fd, &wset); + } + if (ufds[i].events & POLLPRI) { + PHP_SAFE_FD_SET(ufds[i].fd, &eset); + } + } + + if (timeout >= 0) { + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout - (tv.tv_sec * 1000)) * 1000; + } + n = select(max_fd + 1, &rset, &wset, &eset, timeout >= 0 ? &tv : NULL); + + if (n >= 0) { + for (i = 0; i < nfds; i++) { + ufds[i].revents = 0; + + if (PHP_SAFE_FD_ISSET(ufds[i].fd, &rset)) { + /* could be POLLERR or POLLHUP but can't tell without probing */ + ufds[i].revents |= POLLIN; + } + if (PHP_SAFE_FD_ISSET(ufds[i].fd, &wset)) { + ufds[i].revents |= POLLOUT; + } + if (PHP_SAFE_FD_ISSET(ufds[i].fd, &eset)) { + ufds[i].revents |= POLLPRI; + } + } + } + return n; +} + +#endif + /* * Local variables: diff --git a/main/output.c b/main/output.c index 750506619690..b503680f73eb 100644 --- a/main/output.c +++ b/main/output.c @@ -238,7 +238,7 @@ PHPAPI void php_end_ob_buffer(zend_bool send_buffer, zend_bool just_flush TSRMLS OG(ob_lock) = 1; if (call_user_function_ex(CG(function_table), NULL, OG(active_ob_buffer).output_handler, &alternate_buffer, 2, params, 1, NULL TSRMLS_CC)==SUCCESS) { - if (!(Z_TYPE_P(alternate_buffer)==IS_BOOL && Z_BVAL_P(alternate_buffer)==0)) { + if (alternate_buffer && !(Z_TYPE_P(alternate_buffer)==IS_BOOL && Z_BVAL_P(alternate_buffer)==0)) { convert_to_string_ex(&alternate_buffer); final_buffer = Z_STRVAL_P(alternate_buffer); final_buffer_length = Z_STRLEN_P(alternate_buffer); @@ -294,6 +294,9 @@ PHPAPI void php_end_ob_buffer(zend_bool send_buffer, zend_bool just_flush TSRMLS OG(ob_nesting_level)--; if (send_buffer) { + if (just_flush) { /* if flush is called prior to proper end, ensure presence of NUL */ + final_buffer[final_buffer_length] = '\0'; + } OG(php_body_write)(final_buffer, final_buffer_length TSRMLS_CC); } diff --git a/main/php.h b/main/php.h index f19affd17836..3866582b5f58 100644 --- a/main/php.h +++ b/main/php.h @@ -37,10 +37,8 @@ #include "zend_API.h" -#if PHP_BROKEN_SPRINTF #undef sprintf #define sprintf php_sprintf -#endif /* PHP's DEBUG value must match Zend's ZEND_DEBUG value */ #undef PHP_DEBUG @@ -67,16 +65,6 @@ #endif #endif -#ifdef NETWARE -/* For php_get_uname() function */ -#define PHP_UNAME "NetWare" -/* - * This is obtained using uname(2) on Unix and assigned in the case of Windows; - * we'll do it this way at least for now. - */ -#define PHP_OS PHP_UNAME -#endif - #include "php_regex.h" #if HAVE_ASSERT_H @@ -103,7 +91,7 @@ #endif #if HAVE_BUILD_DEFS_H -#include "build-defs.h" +#include #endif /* @@ -207,13 +195,6 @@ char *strerror(int); # ifdef PHP_WIN32 #include "win32/pwd.h" #include "win32/param.h" -#elif defined(NETWARE) -#ifdef NEW_LIBC -#include -#else -#include "NetWare/param.h" -#endif -#include "NetWare/pwd.h" # else #include #include @@ -232,13 +213,21 @@ char *strerror(int); #define LONG_MIN (- LONG_MAX - 1) #endif +#ifndef INT_MAX +#define INT_MAX 2147483647 +#endif + +#ifndef INT_MIN +#define INT_MIN (- INT_MAX - 1) +#endif + #define PHP_GCC_VERSION ZEND_GCC_VERSION #define PHP_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_MALLOC #define PHP_ATTRIBUTE_FORMAT ZEND_ATTRIBUTE_FORMAT -#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) || PHP_BROKEN_SPRINTF || PHP_BROKEN_SNPRINTF || PHP_BROKEN_VSNPRINTF +BEGIN_EXTERN_C() #include "snprintf.h" -#endif +END_EXTERN_C() #include "spprintf.h" #define EXEC_INPUT_BUF 4096 @@ -258,20 +247,10 @@ char *strerror(int); /* global variables */ -extern pval *data; #if !defined(PHP_WIN32) -#ifdef NETWARE -#ifdef NEW_LIBC -#define php_sleep sleep -#else /* NEW_LIBC */ -#define php_sleep delay /* sleep() and usleep() are not available */ -#define usleep delay -#endif /* NEW_LIBC */ -extern char **environ; -#else /* NETWARE */ extern char **environ; #define php_sleep sleep -#endif /* NETWARE */ +#define PHP_SLEEP_NON_VOID #endif /* !defined(PHP_WIN32) */ #ifdef PHP_PWRITE_64 diff --git a/main/php_compat.h b/main/php_compat.h index 4645feaa987d..134328cc50f7 100644 --- a/main/php_compat.h +++ b/main/php_compat.h @@ -23,10 +23,8 @@ #ifdef PHP_WIN32 #include "config.w32.h" -#elif defined(NETWARE) -#include "config.nw.h" #else -#include "php_config.h" +#include #endif #if defined(HAVE_BUNDLED_PCRE) || !defined(PHP_VERSION) diff --git a/main/php_ini.c b/main/php_ini.c index 5fb95c71d82b..ec2cdd16d418 100644 --- a/main/php_ini.c +++ b/main/php_ini.c @@ -534,9 +534,11 @@ int php_shutdown_config(void) zend_hash_destroy(&configuration_hash); if (php_ini_opened_path) { free(php_ini_opened_path); + php_ini_opened_path = NULL; } if (php_ini_scanned_files) { free(php_ini_scanned_files); + php_ini_scanned_files = NULL; } return SUCCESS; } diff --git a/main/php_main.h b/main/php_main.h index 01656e5d24e3..883953643f58 100644 --- a/main/php_main.h +++ b/main/php_main.h @@ -48,7 +48,8 @@ PHPAPI int php_handle_auth_data(const char *auth TSRMLS_DC); PHPAPI void php_html_puts(const char *str, uint siz TSRMLS_DC); -extern void php_call_shutdown_functions(void); +extern void php_call_shutdown_functions(TSRMLS_D); +extern void php_free_shutdown_functions(TSRMLS_D); /* environment module */ extern int php_init_environ(void); diff --git a/main/php_network.h b/main/php_network.h index 3d791e8fa73d..d88fbc890dfe 100644 --- a/main/php_network.h +++ b/main/php_network.h @@ -106,6 +106,104 @@ typedef int php_socket_t; # define SOCK_RECV_ERR -1 #endif +/* uncomment this to debug poll(2) emulation on systems that have poll(2) */ +/* #define PHP_USE_POLL_2_EMULATION 1 */ + +#if defined(HAVE_SYS_POLL_H) && defined(HAVE_POLL) +# include +typedef struct pollfd php_pollfd; +#else +typedef struct _php_pollfd { + php_socket_t fd; + short events; + short revents; +} php_pollfd; + +PHPAPI int php_poll2(php_pollfd *ufds, unsigned int nfds, int timeout); + +# define POLLIN 0x0001 /* There is data to read */ +# define POLLPRI 0x0002 /* There is urgent data to read */ +# define POLLOUT 0x0004 /* Writing now will not block */ +# define POLLERR 0x0008 /* Error condition */ +# define POLLHUP 0x0010 /* Hung up */ +# define POLLNVAL 0x0020 /* Invalid request: fd not open */ + +# ifndef PHP_USE_POLL_2_EMULATION +# define PHP_USE_POLL_2_EMULATION 1 +# endif +#endif + +#define PHP_POLLREADABLE (POLLIN|POLLERR|POLLHUP) + +#ifndef PHP_USE_POLL_2_EMULATION +# define php_poll2(ufds, nfds, timeout) poll(ufds, nfds, timeout) +#endif + +/* timeval-to-timeout (for poll(2)) */ +static inline int php_tvtoto(struct timeval *timeouttv) +{ + if (timeouttv) { + return (timeouttv->tv_sec * 1000) + (timeouttv->tv_usec / 1000); + } + return -1; +} + +/* hybrid select(2)/poll(2) for a single descriptor. + * timeouttv follows same rules as select(2), but is reduced to millisecond accuracy. + * Returns 0 on timeout, -1 on error, or the event mask (ala poll(2)). + */ +static inline int php_pollfd_for(php_socket_t fd, int events, struct timeval *timeouttv) +{ + php_pollfd p; + int n; + + p.fd = fd; + p.events = events; + p.revents = 0; + + n = php_poll2(&p, 1, php_tvtoto(timeouttv)); + + if (n > 0) { + return p.revents; + } + + return n; +} + +static inline int php_pollfd_for_ms(php_socket_t fd, int events, int timeout) +{ + php_pollfd p; + int n; + + p.fd = fd; + p.events = events; + p.revents = 0; + + n = php_poll2(&p, 1, timeout); + + if (n > 0) { + return p.revents; + } + + return n; +} + +/* emit warning and suggestion for unsafe select(2) usage */ +PHPAPI void _php_emit_fd_setsize_warning(int max_fd); + +#ifdef PHP_WIN32 +/* it is safe to FD_SET too many fd's under win32; the macro will simply ignore + * descriptors that go beyond the default FD_SETSIZE */ +# define PHP_SAFE_FD_SET(fd, set) FD_SET(fd, set) +# define PHP_SAFE_FD_ISSET(fd, set) FD_ISSET(fd, set) +# define PHP_SAFE_MAX_FD(m, n) do { if (n + 1 >= FD_SETSIZE) { _php_emit_fd_setsize_warning(n); }} while(0) +#else +# define PHP_SAFE_FD_SET(fd, set) do { if (fd < FD_SETSIZE) FD_SET(fd, set); } while(0) +# define PHP_SAFE_FD_ISSET(fd, set) ((fd < FD_SETSIZE) && FD_ISSET(fd, set)) +# define PHP_SAFE_MAX_FD(m, n) do { if (m >= FD_SETSIZE) { _php_emit_fd_setsize_warning(m); m = FD_SETSIZE - 1; }} while(0) +#endif + + #define PHP_SOCK_CHUNK_SIZE 8192 #ifdef HAVE_SOCKADDR_STORAGE diff --git a/main/php_open_temporary_file.c b/main/php_open_temporary_file.c index b8c94528cd40..0134623b14c2 100644 --- a/main/php_open_temporary_file.c +++ b/main/php_open_temporary_file.c @@ -31,18 +31,12 @@ #include "win32/winutil.h" #elif defined(NETWARE) #ifdef USE_WINSOCK -/*#include */ #include #else #include #endif -#ifdef NEW_LIBC #include #else -#include "netware/param.h" -#endif -#include "netware/mktemp.h" -#else #include #include #include @@ -104,6 +98,7 @@ static int php_do_open_temporary_file(const char *path, const char *pfx, char ** { char *trailing_slash; char *opened_path; + int path_len = 0; int fd = -1; #ifndef HAVE_MKSTEMP int open_flags = O_CREAT | O_TRUNC | O_RDWR @@ -112,19 +107,17 @@ static int php_do_open_temporary_file(const char *path, const char *pfx, char ** #endif ; #endif -#ifdef NETWARE - char *file_path = NULL; -#endif - if (!path) { return -1; } + path_len = strlen(path); + if (!(opened_path = emalloc(MAXPATHLEN))) { return -1; } - if (IS_SLASH(path[strlen(path)-1])) { + if (!path_len || IS_SLASH(path[path_len - 1])) { trailing_slash = ""; } else { trailing_slash = "/"; @@ -139,12 +132,6 @@ static int php_do_open_temporary_file(const char *path, const char *pfx, char ** VCWD_CHMOD(opened_path, 0600); fd = VCWD_OPEN_MODE(opened_path, open_flags, 0600); } -#elif defined(NETWARE) - /* Using standard mktemp() implementation for NetWare */ - file_path = mktemp(opened_path); - if (file_path) { - fd = VCWD_OPEN(file_path, open_flags); - } #elif defined(HAVE_MKSTEMP) fd = mkstemp(opened_path); #else diff --git a/main/php_realpath.c b/main/php_realpath.c deleted file mode 100644 index 0607e91cc481..000000000000 --- a/main/php_realpath.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Sander Steffann (sander@steffann.nl) | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#include "php.h" - -#if HAVE_UNISTD_H -#include -#endif -#include - -#ifndef MAXSYMLINKS -#define MAXSYMLINKS 32 -#endif - -#ifndef S_ISDIR -#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR) -#endif - -char *php_realpath(char *path, char resolved_path[]); - -#ifdef PHP_WIN32 -#define IS_SLASH(p) ((p) == '/' || (p) == '\\') -#else -#define IS_SLASH(p) ((p) == '/') -#endif - -char *php_realpath(char *path, char resolved_path []) { - char path_construction[MAXPATHLEN]; /* We build the result in here */ - char *writepos; /* Position to write next char */ - - char path_copy[MAXPATHLEN]; /* A work-copy of the path */ - char *workpos; /* working position in *path */ - -#if !defined(PHP_WIN32) - char buf[MAXPATHLEN]; /* Buffer for readlink */ - int linklength; /* The result from readlink */ -#endif - int linkcount = 0; /* Count symlinks to avoid loops */ - - struct stat filestat; /* result from stat */ - -#ifdef PHP_WIN32 - char *temppos; /* position while counting '.' */ - int dotcount; /* number of '.' */ - int t; /* counter */ -#endif - - /* Set the work-position to the beginning of the given path */ - strcpy(path_copy, path); - workpos = path_copy; - -#ifdef PHP_WIN32 - /* Find out where we start - Windows version */ - if (IS_SLASH(*workpos)) { - /* We start at the root of the current drive */ - /* Get the current directory */ - if (V_GETCWD(path_construction, MAXPATHLEN-1) == NULL) { - /* Unable to get cwd */ - resolved_path[0] = 0; - return NULL; - } - /* We only need the first three chars (for example "C:\") */ - path_construction[3] = 0; - workpos++; - } else if (workpos[1] == ':') { - /* A drive-letter is specified, copy it */ - strncpy(path_construction, path, 2); - strcat(path_construction, "\\"); - workpos++; - workpos++; - } else { - /* Use the current directory */ - if (V_GETCWD(path_construction, MAXPATHLEN-1) == NULL) { - /* Unable to get cwd */ - resolved_path[0] = 0; - return NULL; - } - strcat(path_construction, "\\"); - } -#else - /* Find out where we start - Unix version */ - if (*workpos == '/') { - /* We start at the root */ - strcpy(path_construction, "/"); - workpos++; - } else { - /* Use the current directory */ - if (V_GETCWD(path_construction, MAXPATHLEN-1) == NULL) { - /* Unable to get cwd */ - resolved_path[0] = 0; - return NULL; - } - strcat(path_construction, "/"); - } -#endif - - /* Set the next-char-position */ - writepos = &path_construction[strlen(path_construction)]; - - /* Go to the end, then stop */ - while(*workpos != 0) { - /* Strip (back)slashes */ - while(IS_SLASH(*workpos)) workpos++; - -#ifdef PHP_WIN32 - /* reset dotcount */ - dotcount = 0; - - /* Look for .. */ - if ((workpos[0] == '.') && (workpos[1] != 0)) { - /* Windows accepts \...\ as \..\..\, \....\ as \..\..\..\, etc */ - /* At least Win98 does */ - - temppos = workpos; - while(*temppos++ == '.') { - dotcount++; - if (!IS_SLASH(*temppos) && (*temppos != 0) && (*temppos != '.')) { - /* This is not a /../ component, but a filename that starts with '.' */ - dotcount = 0; - } - } - - /* Go back dotcount-1 times */ - for (t=0 ; t<(dotcount-1) ; t++) { - workpos++; /* move to next '.' */ - - /* Can we still go back? */ - if ((writepos-3) <= path_construction) return NULL; - - /* Go back */ - writepos--; /* move to '\' */ - writepos--; - while(!IS_SLASH(*writepos)) writepos--; /* skip until previous '\\' */ - } - workpos++; - } - - /* No special case */ - if (dotcount == 0) { - /* Append */ - while(!IS_SLASH(*workpos) && (*workpos != 0)) { - *writepos++ = *workpos++; - } - } - - /* Just one '.', go to next element */ - if (dotcount == 1) { - while(!IS_SLASH(*workpos) && (*workpos != 0)) { - *workpos++; - } - - /* Avoid double \ in the result */ - writepos--; - } - - /* If it was a directory, append a slash */ - if (IS_SLASH(*workpos)) { - *writepos++ = *workpos++; - } - *writepos = 0; -#else /* defined(PHP_WIN32) */ - /* Look for .. */ - if ((workpos[0] == '.') && (workpos[1] != 0)) { - if ((workpos[1] == '.') && ((workpos[2] == '/') || (workpos[2] == 0))) { - /* One directory back */ - /* Set pointers to right position */ - workpos++; /* move to second '.' */ - workpos++; /* move to '/' */ - - /* Only apply .. if not in root */ - if ((writepos-1) > path_construction) { - writepos--; /* move to '/' */ - while(*--writepos != '/') ; /* skip until previous '/' */ - } - } else { - if (workpos[1] == '/') { - /* Found a /./ skip it */ - workpos++; /* move to '/' */ - - /* Avoid double / in the result */ - writepos--; - } else { - /* No special case, the name just started with a . */ - /* Append */ - while((*workpos != '/') && (*workpos != 0)) { - *writepos++ = *workpos++; - } - } - } - } else { - /* No special case */ - /* Append */ - while((*workpos != '/') && (*workpos != 0)) { - *writepos++ = *workpos++; - } - } - -#if HAVE_SYMLINK - /* We are going to use path_construction, so close it */ - *writepos = 0; - - /* Check the current location to see if it is a symlink */ - if((linklength = readlink(path_construction, buf, MAXPATHLEN)) != -1) { - /* Check linkcount */ - if (linkcount > MAXSYMLINKS) return NULL; - - /* Count this symlink */ - linkcount++; - - /* Set end of buf */ - buf[linklength] = 0; - - /* Check for overflow */ - if ((strlen(workpos) + strlen(buf) + 1) >= MAXPATHLEN) return NULL; - - /* Remove the symlink-component wrom path_construction */ - writepos--; /* move to '/' */ - while(*--writepos != '/') ; /* skip until previous '/' */ - *++writepos = 0; /* end of string after '/' */ - - /* If the symlink starts with a '/', empty path_construction */ - if (*buf == '/') { - *path_construction = 0; - writepos = path_construction; - } - - /* Insert symlink into path_copy */ - strcat(buf, workpos); - strcpy(path_copy, buf); - workpos = path_copy; - } -#endif /* HAVE_SYMLINK */ - - /* If it was a directory, append a slash */ - if (*workpos == '/') { - *writepos++ = *workpos++; - } - *writepos = 0; -#endif /* defined(PHP_WIN32) */ - } - - /* Check if the resolved path is a directory */ - if (V_STAT(path_construction, &filestat) != 0) { - if (errno != ENOENT) return NULL; - } else { - if (S_ISDIR(filestat.st_mode)) { - /* It's a directory, append a / if needed */ - if (*(writepos-1) != '/') { - /* Check for overflow */ - if ((strlen(workpos) + 2) >= MAXPATHLEN) { - return NULL; - } - *writepos++ = '/'; - *writepos = 0; - } - } - } - - strcpy(resolved_path, path_construction); - return resolved_path; -} - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - */ diff --git a/main/php_scandir.c b/main/php_scandir.c index e24b4137f594..63b6a65b5a73 100644 --- a/main/php_scandir.c +++ b/main/php_scandir.c @@ -22,7 +22,7 @@ #ifdef PHP_WIN32 #include "config.w32.h" #else -#include "php_config.h" +#include #endif #include "php_scandir.h" @@ -42,7 +42,10 @@ #endif #include + +#ifndef NETWARE #include +#endif #endif /* HAVE_SCANDIR */ diff --git a/main/php_scandir.h b/main/php_scandir.h index 0ff56ebbc2c3..755fe43cc52d 100644 --- a/main/php_scandir.h +++ b/main/php_scandir.h @@ -32,7 +32,7 @@ #include "config.w32.h" #include "win32/readdir.h" #else -#include "php_config.h" +#include #endif #ifdef HAVE_DIRENT_H diff --git a/main/php_sprintf.c b/main/php_sprintf.c index f7daab2952d7..7e6e9ecf2381 100644 --- a/main/php_sprintf.c +++ b/main/php_sprintf.c @@ -20,19 +20,18 @@ #include #include -#ifdef NETWARE -#include "config.nw.h" +#include "php.h" +#ifdef PHP_WIN32 +#include "config.w32.h" #else -#include "php_config.h" +#include #endif -#if PHP_BROKEN_SPRINTF - -int +PHPAPI int php_sprintf (char*s, const char* format, ...) { va_list args; - char *ret; + int ret; va_start (args, format); s[0] = '\0'; @@ -43,8 +42,6 @@ php_sprintf (char*s, const char* format, ...) return strlen (s); } -#endif /* PHP_BROKEN_SPRINTF */ - /* * Local variables: * tab-width: 4 diff --git a/main/php_streams.h b/main/php_streams.h index 000b4291c3ec..fdf5a1fe6103 100755 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -103,11 +103,7 @@ typedef struct _php_stream_filter php_stream_filter; #include "streams/php_stream_filter_api.h" typedef struct _php_stream_statbuf { -#if defined(NETWARE) && defined(CLIB_STAT_PATCH) - struct stat_libc sb; /* regular info */ -#else struct stat sb; /* regular info */ -#endif /* extended info to go here some day: content-type etc. etc. */ } php_stream_statbuf; @@ -331,11 +327,11 @@ PHPAPI php_stream_dirent *_php_stream_readdir(php_stream *dirstream, php_stream_ #define php_stream_closedir(dirstream) php_stream_close((dirstream)) #define php_stream_rewinddir(dirstream) php_stream_rewind((dirstream)) -PHPAPI int php_stream_dirent_alphasort(const php_stream_dirent **a, const php_stream_dirent **b); -PHPAPI int php_stream_dirent_alphasortr(const php_stream_dirent **a, const php_stream_dirent **b); +PHPAPI int php_stream_dirent_alphasort(const char **a, const char **b); +PHPAPI int php_stream_dirent_alphasortr(const char **a, const char **b); -PHPAPI int _php_stream_scandir(char *dirname, php_stream_dirent **namelist[], int flags, php_stream_context *context, - int (*compare) (const php_stream_dirent **a, const php_stream_dirent **b) TSRMLS_DC); +PHPAPI int _php_stream_scandir(char *dirname, char **namelist[], int flags, php_stream_context *context, + int (*compare) (const char **a, const char **b) TSRMLS_DC); #define php_stream_scandir(dirname, namelist, context, compare) _php_stream_scandir((dirname), (namelist), 0, (context), (compare) TSRMLS_CC) PHPAPI int _php_stream_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC); @@ -411,7 +407,8 @@ END_EXTERN_C() /* copy up to maxlen bytes from src to dest. If maxlen is PHP_STREAM_COPY_ALL, copy until eof(src). * Uses mmap if the src is a plain file and at offset 0 */ -#define PHP_STREAM_COPY_ALL -1 +#define PHP_STREAM_COPY_ALL ((size_t)-1) + BEGIN_EXTERN_C() PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size_t maxlen STREAMS_DC TSRMLS_DC); #define php_stream_copy_to_stream(src, dest, maxlen) _php_stream_copy_to_stream((src), (dest), (maxlen) STREAMS_CC TSRMLS_CC) @@ -504,6 +501,7 @@ END_EXTERN_C() int php_init_stream_wrappers(int module_number TSRMLS_DC); int php_shutdown_stream_wrappers(int module_number TSRMLS_DC); +void php_shutdown_stream_hashes(TSRMLS_D); PHP_RSHUTDOWN_FUNCTION(streams); BEGIN_EXTERN_C() diff --git a/main/php_syslog.h b/main/php_syslog.h index 3f93f28ee1f5..a80067033cf7 100644 --- a/main/php_syslog.h +++ b/main/php_syslog.h @@ -23,13 +23,8 @@ #ifdef PHP_WIN32 #include "win32/syslog.h" -#elif defined(NETWARE) -# include "config.nw.h" -#ifdef HAVE_SYSLOG_H -#include -#endif #else -#include "php_config.h" +#include #ifdef HAVE_SYSLOG_H #include #endif diff --git a/main/php_variables.c b/main/php_variables.c index 498d4b173d81..95b1818454b6 100644 --- a/main/php_variables.c +++ b/main/php_variables.c @@ -36,6 +36,19 @@ void _php_import_environment_variables(zval *array_ptr TSRMLS_DC); PHPAPI void (*php_import_environment_variables)(zval *array_ptr TSRMLS_DC) = _php_import_environment_variables; +/* Input arrays start with a single hash bucket instead of the default of 8, + * to limit the memory used by deeply nested input. */ +static void array_init_singleton(zval *arg) +{ + HashTable *ht; + + array_init(arg); + ht = Z_ARRVAL_P(arg); + ht->arBuckets = (Bucket **) erealloc(ht->arBuckets, sizeof(Bucket *)); + ht->nTableSize = 1; + ht->nTableMask = 0; +} + PHPAPI void php_register_variable(char *var, char *strval, zval *track_vars_array TSRMLS_DC) { php_register_variable_safe(var, strval, strlen(strval), track_vars_array TSRMLS_CC); @@ -133,7 +146,11 @@ PHPAPI void php_register_variable_ex(char *var, zval *val, pval *track_vars_arra if (!ip) { /* PHP variables cannot contain '[' in their names, so we replace the character with a '_' */ *(index_s - 1) = '_'; - index_len = var_len = strlen(var); + + index_len = var_len = 0; + if (index) { + index_len = var_len = strlen(index); + } goto plain_var; return; } @@ -143,7 +160,7 @@ PHPAPI void php_register_variable_ex(char *var, zval *val, pval *track_vars_arra if (!index) { MAKE_STD_ZVAL(gpc_element); - array_init(gpc_element); + array_init_singleton(gpc_element); zend_hash_next_index_insert(symtable1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p); } else { if (PG(magic_quotes_gpc) && (index!=var)) { @@ -155,7 +172,7 @@ PHPAPI void php_register_variable_ex(char *var, zval *val, pval *track_vars_arra if (zend_symtable_find(symtable1, escaped_index, index_len+1, (void **) &gpc_element_p)==FAILURE || Z_TYPE_PP(gpc_element_p) != IS_ARRAY) { MAKE_STD_ZVAL(gpc_element); - array_init(gpc_element); + array_init_singleton(gpc_element); zend_symtable_update(symtable1, escaped_index, index_len+1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p); } if (index!=escaped_index) { @@ -182,7 +199,19 @@ PHPAPI void php_register_variable_ex(char *var, zval *val, pval *track_vars_arra if (!index) { zend_hash_next_index_insert(symtable1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p); } else { + zval **tmp; char *escaped_index = php_addslashes(index, index_len, &index_len, 0 TSRMLS_CC); + /* + * According to rfc2965, more specific paths are listed above the less specific ones. + * If we encounter a duplicate cookie name, we should skip it, since it is not possible + * to have the same (plain text) cookie name for the same path and we should not overwrite + * more specific cookies with the less specific ones. + */ + if (PG(http_globals)[TRACK_VARS_COOKIE] && symtable1 == Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_COOKIE]) && + zend_symtable_find(symtable1, escaped_index, index_len+1, (void **) &tmp) != FAILURE) { + efree(escaped_index); + break; + } zend_symtable_update(symtable1, escaped_index, index_len+1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p); efree(escaped_index); } @@ -242,16 +271,25 @@ SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data) case PARSE_GET: case PARSE_COOKIE: ALLOC_ZVAL(array_ptr); - array_init(array_ptr); + array_init_singleton(array_ptr); INIT_PZVAL(array_ptr); switch (arg) { case PARSE_POST: + if (PG(http_globals)[TRACK_VARS_POST]) { + zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_POST]); + } PG(http_globals)[TRACK_VARS_POST] = array_ptr; break; case PARSE_GET: + if (PG(http_globals)[TRACK_VARS_GET]) { + zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_GET]); + } PG(http_globals)[TRACK_VARS_GET] = array_ptr; break; case PARSE_COOKIE: + if (PG(http_globals)[TRACK_VARS_COOKIE]) { + zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_COOKIE]); + } PG(http_globals)[TRACK_VARS_COOKIE] = array_ptr; break; } @@ -496,6 +534,9 @@ static inline void php_register_server_variables(TSRMLS_D) ALLOC_ZVAL(array_ptr); array_init(array_ptr); INIT_PZVAL(array_ptr); + if (PG(http_globals)[TRACK_VARS_SERVER]) { + zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_SERVER]); + } PG(http_globals)[TRACK_VARS_SERVER] = array_ptr; PG(magic_quotes_gpc) = 0; @@ -527,6 +568,7 @@ static void php_autoglobal_merge(HashTable *dest, HashTable *src TSRMLS_DC) ulong num_key; HashPosition pos; int key_type; + int globals_check = (PG(register_globals) && (dest == (&EG(symbol_table)))); zend_hash_internal_pointer_reset_ex(src, &pos); while (zend_hash_get_current_data_ex(src, (void **)&src_entry, &pos) == SUCCESS) { @@ -537,7 +579,12 @@ static void php_autoglobal_merge(HashTable *dest, HashTable *src TSRMLS_DC) || Z_TYPE_PP(dest_entry) != IS_ARRAY) { (*src_entry)->refcount++; if (key_type == HASH_KEY_IS_STRING) { - zend_hash_update(dest, string_key, strlen(string_key)+1, src_entry, sizeof(zval *), NULL); + /* if register_globals is on and working with main symbol table, prevent overwriting of GLOBALS */ + if (!globals_check || string_key_len != sizeof("GLOBALS") || memcmp(string_key, "GLOBALS", sizeof("GLOBALS") - 1)) { + zend_hash_update(dest, string_key, string_key_len, src_entry, sizeof(zval *), NULL); + } else { + (*src_entry)->refcount--; + } } else { zend_hash_index_update(dest, num_key, src_entry, sizeof(zval *), NULL); } @@ -665,8 +712,8 @@ int php_hash_environment(TSRMLS_D) PG(http_globals)[i] = dummy_track_vars_array; } - zend_hash_update(&EG(symbol_table), auto_global_records[i].name, auto_global_records[i].name_len, &PG(http_globals)[i], sizeof(zval *), NULL); PG(http_globals)[i]->refcount++; + zend_hash_update(&EG(symbol_table), auto_global_records[i].name, auto_global_records[i].name_len, &PG(http_globals)[i], sizeof(zval *), NULL); if (PG(register_long_arrays)) { zend_hash_update(&EG(symbol_table), auto_global_records[i].long_name, auto_global_records[i].long_name_len, &PG(http_globals)[i], sizeof(zval *), NULL); PG(http_globals)[i]->refcount++; @@ -686,7 +733,18 @@ int php_hash_environment(TSRMLS_D) static zend_bool php_auto_globals_create_server(char *name, uint name_len TSRMLS_DC) { - php_register_server_variables(TSRMLS_C); + if (PG(variables_order) && (strchr(PG(variables_order),'S') || strchr(PG(variables_order),'s'))) { + php_register_server_variables(TSRMLS_C); + } else { + zval *server_vars=NULL; + ALLOC_ZVAL(server_vars); + array_init(server_vars); + INIT_PZVAL(server_vars); + if (PG(http_globals)[TRACK_VARS_SERVER]) { + zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_SERVER]); + } + PG(http_globals)[TRACK_VARS_SERVER] = server_vars; + } zend_hash_update(&EG(symbol_table), name, name_len+1, &PG(http_globals)[TRACK_VARS_SERVER], sizeof(zval *), NULL); PG(http_globals)[TRACK_VARS_SERVER]->refcount++; @@ -706,9 +764,14 @@ static zend_bool php_auto_globals_create_env(char *name, uint name_len TSRMLS_DC ALLOC_ZVAL(env_vars); array_init(env_vars); INIT_PZVAL(env_vars); + if (PG(http_globals)[TRACK_VARS_ENV]) { + zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_ENV]); + } PG(http_globals)[TRACK_VARS_ENV] = env_vars; - php_import_environment_variables(PG(http_globals)[TRACK_VARS_ENV] TSRMLS_CC); + if (PG(variables_order) && (strchr(PG(variables_order),'E') || strchr(PG(variables_order),'e'))) { + php_import_environment_variables(PG(http_globals)[TRACK_VARS_ENV] TSRMLS_CC); + } zend_hash_update(&EG(symbol_table), name, name_len+1, &PG(http_globals)[TRACK_VARS_ENV], sizeof(zval *), NULL); PG(http_globals)[TRACK_VARS_ENV]->refcount++; diff --git a/main/php_version.h b/main/php_version.h index 651a74426255..230cb41b1d66 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -2,6 +2,6 @@ /* edit configure.in to change version number */ #define PHP_MAJOR_VERSION 5 #define PHP_MINOR_VERSION 0 -#define PHP_RELEASE_VERSION 1 -#define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "5.0.1-dev" +#define PHP_RELEASE_VERSION 5 +#define PHP_EXTRA_VERSION "-p1" +#define PHP_VERSION "5.0.5-p1" diff --git a/main/reentrancy.c b/main/reentrancy.c index 8d7a7ff2bb93..ce8f698208f5 100644 --- a/main/reentrancy.c +++ b/main/reentrancy.c @@ -29,11 +29,6 @@ #include "win32/readdir.h" #endif -#if defined(NETWARE) && !(NEW_LIBC) -/*#include */ -#include -#endif - #include "php_reentrancy.h" #include "ext/standard/php_rand.h" /* for PHP_RAND_MAX */ @@ -120,51 +115,6 @@ PHPAPI struct tm *php_gmtime_r(const time_t *const timep, struct tm *p_tm) #endif -#if defined(NETWARE) -/* - Re-entrant versions of functions seem to be better for loading NLMs in different address space. - Since we have them now in LibC, we might as well make use of them. -*/ - -#define HAVE_LOCALTIME_R 1 -#define HAVE_CTIME_R 1 -#define HAVE_ASCTIME_R 1 -#define HAVE_GMTIME_R 1 - -PHPAPI struct tm *php_localtime_r(const time_t *const timep, struct tm *p_tm) -{ - /* Modified according to LibC definition */ - if (localtime_r(timep, p_tm) != NULL) - return (p_tm); - return (NULL); -} - -PHPAPI char *php_ctime_r(const time_t *clock, char *buf) -{ - /* Modified according to LibC definition */ - if (ctime_r(clock, buf) != NULL) - return (buf); - return (NULL); -} - -PHPAPI char *php_asctime_r(const struct tm *tm, char *buf) -{ - /* Modified according to LibC definition */ - if (asctime_r(tm, buf) != NULL) - return (buf); - return (NULL); -} - -PHPAPI struct tm *php_gmtime_r(const time_t *const timep, struct tm *p_tm) -{ - /* Modified according to LibC definition */ - if (gmtime_r(timep, p_tm) != NULL) - return (p_tm); - return (NULL); -} - -#endif /* NETWARE */ - #if defined(__BEOS__) PHPAPI struct tm *php_gmtime_r(const time_t *const timep, struct tm *p_tm) diff --git a/main/rfc1867.c b/main/rfc1867.c index c810688434ee..58f1d85409cd 100644 --- a/main/rfc1867.c +++ b/main/rfc1867.c @@ -32,6 +32,7 @@ #include "php_globals.h" #include "php_variables.h" #include "rfc1867.h" +#include "zend_ini.h" #define DEBUG_FILE_UPLOAD ZEND_DEBUG @@ -130,6 +131,8 @@ void php_mb_gpc_stack_variable(char *param, char *value, char ***pval_list, int #define UPLOAD_ERROR_B 2 /* Uploaded file exceeded MAX_FILE_SIZE */ #define UPLOAD_ERROR_C 3 /* Partially uploaded */ #define UPLOAD_ERROR_D 4 /* No file uploaded */ +#define UPLOAD_ERROR_E 6 /* Missing /tmp or similar directory */ +#define UPLOAD_ERROR_F 7 /* Failed to write file to disk */ void php_rfc1867_register_constants(TSRMLS_D) { @@ -138,6 +141,8 @@ void php_rfc1867_register_constants(TSRMLS_D) REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_FORM_SIZE", UPLOAD_ERROR_B, CONST_CS | CONST_PERSISTENT); REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_PARTIAL", UPLOAD_ERROR_C, CONST_CS | CONST_PERSISTENT); REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_NO_FILE", UPLOAD_ERROR_D, CONST_CS | CONST_PERSISTENT); + REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_NO_TMP_DIR", UPLOAD_ERROR_E, CONST_CS | CONST_PERSISTENT); + REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_CANT_WRITE", UPLOAD_ERROR_F, CONST_CS | CONST_PERSISTENT); } static void normalize_protected_variable(char *varname TSRMLS_DC) @@ -462,12 +467,21 @@ static int find_boundary(multipart_buffer *self, char *boundary TSRMLS_DC) } +static zend_bool php_mime_should_save_hdr(const char *name) +{ + return !strcasecmp(name, "Content-Disposition") + || !strcasecmp(name, "Content-Type"); +} + +static char *php_mime_get_hdr_value(zend_llist header, char *key); + /* parse headers */ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header TSRMLS_DC) { char *line; mime_header_entry prev_entry, entry; int prev_len, cur_len; + int skip_continuation = 0; /* didn't find boundary, abort */ if (!find_boundary(self, self->boundary TSRMLS_CC)) { @@ -490,12 +504,22 @@ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header T if (value) { *value = 0; - do { value++; } while(isspace(*value)); + + /* Keep only headers we use, and ignore duplicates */ + if (!php_mime_should_save_hdr(key) + || php_mime_get_hdr_value(*header, key)) { + /* also drop the continuation lines of this header */ + skip_continuation = 1; + continue; + } + skip_continuation = 0; + + do { value++; } while(isspace((unsigned char)*value)); entry.value = estrdup(value); entry.key = estrdup(key); - } else if (zend_llist_count(header)) { /* If no ':' on the line, add to previous line */ + } else if (zend_llist_count(header) && !skip_continuation) { /* If no ':' on the line, add to previous line */ prev_len = strlen(prev_entry.value); cur_len = strlen(line); @@ -579,11 +603,11 @@ static char *php_ap_getword(char **line, char stop) } -static char *substring_conf(char *start, int len, char quote TSRMLS_DC) +static char *substring_conf(char *start, size_t len, char quote TSRMLS_DC) { char *result = emalloc(len + 2); char *resp = result; - int i; + size_t i; for (i = 0; i < len; ++i) { if (start[i] == '\\' && (start[i + 1] == '\\' || (quote && start[i + 1] == quote))) { @@ -632,6 +656,7 @@ static char *php_ap_getword_conf(char **line TSRMLS_DC) if ((quote = *str) == '"' || quote == '\'') { strend = str + 1; +look_for_quote: while (*strend && *strend != quote) { if (*strend == '\\' && strend[1] && strend[1] == quote) { strend += 2; @@ -639,7 +664,15 @@ static char *php_ap_getword_conf(char **line TSRMLS_DC) ++strend; } } - res = substring_conf(str + 1, strend - str - 1, quote TSRMLS_CC); + if (*strend && *strend == quote) { + char p = *(strend + 1); + if (p != '\r' && p != '\n' && p != '\0') { + strend++; + goto look_for_quote; + } + } + + res = substring_conf(str + 1, (size_t)(strend - str - 1), quote TSRMLS_CC); if (*strend == quote) { ++strend; @@ -651,7 +684,7 @@ static char *php_ap_getword_conf(char **line TSRMLS_DC) while (*strend && !isspace(*strend)) { ++strend; } - res = substring_conf(str, strend - str, 0 TSRMLS_CC); + res = substring_conf(str, (size_t)(strend - str), 0 TSRMLS_CC); } while (*strend && isspace(*strend)) { @@ -693,7 +726,7 @@ static void *php_ap_memstr(char *haystack, int haystacklen, char *needle, int ne /* read until a boundary condition */ -static int multipart_buffer_read(multipart_buffer *self, char *buf, int bytes TSRMLS_DC) +static int multipart_buffer_read(multipart_buffer *self, char *buf, int bytes, int *end TSRMLS_DC) { int len, max; char *bound; @@ -706,6 +739,9 @@ static int multipart_buffer_read(multipart_buffer *self, char *buf, int bytes TS /* look for a potential boundary match, only read data up to that point */ if ((bound = php_ap_memstr(self->buf_begin, self->bytes_in_buffer, self->boundary_next, self->boundary_next_len, 1))) { max = bound - self->buf_begin; + if (end && php_ap_memstr(self->buf_begin, self->bytes_in_buffer, self->boundary_next, self->boundary_next_len, 0)) { + *end = 1; + } } else { max = self->bytes_in_buffer; } @@ -742,7 +778,7 @@ static char *multipart_buffer_read_body(multipart_buffer *self TSRMLS_DC) char buf[FILLUNIT], *out=NULL; int total_bytes=0, read_bytes=0; - while((read_bytes = multipart_buffer_read(self, buf, sizeof(buf) TSRMLS_CC))) { + while((read_bytes = multipart_buffer_read(self, buf, sizeof(buf), NULL TSRMLS_CC))) { out = erealloc(out, total_bytes + read_bytes + 1); memcpy(out + total_bytes, buf, read_bytes); total_bytes += read_bytes; @@ -773,14 +809,23 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) zend_bool magic_quotes_gpc; multipart_buffer *mbuff; zval *array_ptr = (zval *) arg; - FILE *fp; + int fd=-1; zend_llist header; + int body_parts_cnt = INI_INT("max_multipart_body_parts"); + int body_parts_limit; if (SG(request_info).content_length > SG(post_max_size)) { - sapi_module.sapi_error(E_WARNING, "POST Content-Length of %d bytes exceeds the limit of %d bytes", SG(request_info).content_length, SG(post_max_size)); + sapi_module.sapi_error(E_WARNING, "POST Content-Length of %ld bytes exceeds the limit of %ld bytes", SG(request_info).content_length, SG(post_max_size)); return; } + if (body_parts_cnt < 0) { + /* There is no max_input_vars or max_file_uploads to derive the limit + * from, so use their default sum (1000 + 20) */ + body_parts_cnt = 1020; + } + body_parts_limit = body_parts_cnt; + /* Get the boundary */ boundary = strstr(content_type_dup, "boundary"); if (!boundary || !(boundary=strchr(boundary, '='))) { @@ -847,6 +892,12 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) if ((cd = php_mime_get_hdr_value(header, "Content-Disposition"))) { char *pair=NULL; + int end=0; + + if (--body_parts_cnt < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Multipart body parts limit exceeded %d. To increase the limit change max_multipart_body_parts in php.ini.", body_parts_limit); + SAFE_RETURN; + } while (isspace(*cd)) { ++cd; @@ -930,13 +981,38 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) } else { is_anonymous = 0; } + + /* New Rule: never repair potential malicious user input */ + if (!skip_upload) { + char *tmp = param; + long c = 0; + + while (*tmp) { + if (*tmp == '[') { + c++; + } else if (*tmp == ']') { + c--; + if (tmp[1] && tmp[1] != '[') { + skip_upload = 1; + break; + } + } + if (c < 0) { + skip_upload = 1; + break; + } + tmp++; + } + } + + total_bytes = cancel_upload = 0; if (!skip_upload) { /* Handle file */ - fp = php_open_temporary_file(PG(upload_tmp_dir), "php", &temp_filename TSRMLS_CC); - if (!fp) { + fd = php_open_temporary_fd(PG(upload_tmp_dir), "php", &temp_filename TSRMLS_CC); + if (fd==-1) { sapi_module.sapi_error(E_WARNING, "File upload error - unable to create a temporary file"); - skip_upload = 1; + cancel_upload = UPLOAD_ERROR_E; } } if (skip_upload) { @@ -945,9 +1021,6 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) continue; } - total_bytes = 0; - cancel_upload = 0; - if(strlen(filename) == 0) { #if DEBUG_FILE_UPLOAD sapi_module.sapi_error(E_NOTICE, "No file uploaded"); @@ -955,7 +1028,8 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) cancel_upload = UPLOAD_ERROR_D; } - while (!cancel_upload && (blen = multipart_buffer_read(mbuff, buff, sizeof(buff) TSRMLS_CC))) + end = 0; + while (!cancel_upload && (blen = multipart_buffer_read(mbuff, buff, sizeof(buff), &end TSRMLS_CC))) { if (PG(upload_max_filesize) > 0 && total_bytes > PG(upload_max_filesize)) { #if DEBUG_FILE_UPLOAD @@ -968,22 +1042,29 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) #endif cancel_upload = UPLOAD_ERROR_B; } else if (blen > 0) { - wlen = fwrite(buff, 1, blen, fp); + wlen = write(fd, buff, blen); if (wlen < blen) { #if DEBUG_FILE_UPLOAD - sapi_module.sapi_error(E_NOTICE, "Only %d bytes were written, expected to write %ld", wlen, blen); + sapi_module.sapi_error(E_NOTICE, "Only %d bytes were written, expected to write %d", wlen, blen); #endif - cancel_upload = UPLOAD_ERROR_C; + cancel_upload = UPLOAD_ERROR_F; } else { total_bytes += wlen; } } - } - fclose(fp); - + } + if (fd!=-1) { /* may not be initialized if file could not be created */ + close(fd); + } + if (!cancel_upload && !end) { #if DEBUG_FILE_UPLOAD - if(strlen(filename) > 0 && total_bytes == 0) { + sapi_module.sapi_error(E_NOTICE, "Missing mime boundary at the end of the data for file %s", strlen(filename) > 0 ? filename : ""); +#endif + cancel_upload = UPLOAD_ERROR_C; + } +#if DEBUG_FILE_UPLOAD + if(strlen(filename) > 0 && total_bytes == 0 && !cancel_upload) { sapi_module.sapi_error(E_WARNING, "Uploaded file size 0 - file [%s=%s] not saved", param, filename); cancel_upload = 5; } @@ -991,7 +1072,9 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) if (cancel_upload) { if (temp_filename) { - unlink(temp_filename); + if (cancel_upload != UPLOAD_ERROR_E) { /* file creation failed */ + unlink(temp_filename); + } efree(temp_filename); } temp_filename=""; @@ -1004,10 +1087,6 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) * start_arr is set to point to 1st [ */ is_arr_upload = (start_arr = strchr(param,'[')) && (param[strlen(param)-1] == ']'); - /* handle unterminated [ */ - if (!is_arr_upload && start_arr) { - *start_arr = '_'; - } if (is_arr_upload) { array_len = strlen(start_arr); @@ -1049,18 +1128,29 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) s = tmp; } num_vars--; - } else { - s = strrchr(filename, '\\'); - if ((tmp = strrchr(filename, '/')) > s) { - s = tmp; - } + goto filedone; } -#else +#endif + s = strrchr(filename, '\\'); if ((tmp = strrchr(filename, '/')) > s) { s = tmp; } +#ifdef PHP_WIN32 + if (PG(magic_quotes_gpc)) { + s = s ? s : filename; + tmp = strrchr(s, '\''); + s = tmp > s ? tmp : s; + tmp = strrchr(s, '"'); + s = tmp > s ? tmp : s; + } #endif + +#if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING) +filedone: +#endif + + if (!is_anonymous) { if (s && s > filename) { safe_php_register_variable(lbuf, s+1, NULL, 0 TSRMLS_CC); diff --git a/main/safe_mode.c b/main/safe_mode.c index 9271610f9bdf..dac3ad452676 100644 --- a/main/safe_mode.c +++ b/main/safe_mode.c @@ -55,13 +55,16 @@ PHPAPI int php_checkuid_ex(const char *filename, char *fopen_mode, int mode, int php_stream_wrapper *wrapper = NULL; TSRMLS_FETCH(); - strlcpy(filenamecopy, filename, MAXPATHLEN); - filename=(char *)&filenamecopy; - if (!filename) { return 0; /* path must be provided */ } + if (strlcpy(filenamecopy, filename, MAXPATHLEN)>=MAXPATHLEN) { + return 0; + } + filename=(char *)&filenamecopy; + + if (fopen_mode) { if (fopen_mode[0] == 'r') { mode = CHECKUID_DISALLOW_FILE_NOT_EXISTS; @@ -187,7 +190,12 @@ PHPAPI int php_checkuid_ex(const char *filename, char *fopen_mode, int mode, int } PHPAPI int php_checkuid(const char *filename, char *fopen_mode, int mode) { +#ifdef NETWARE + /* NetWare don't have uid*/ + return 1; +#else return php_checkuid_ex(filename, fopen_mode, mode, 0); +#endif } PHPAPI char *php_get_current_user() diff --git a/main/snprintf.c b/main/snprintf.c index fa0e7f1e8815..4cb9b5c91c19 100644 --- a/main/snprintf.c +++ b/main/snprintf.c @@ -466,8 +466,6 @@ ap_php_gcvt(double number, int ndigit, char *buf, boolean_e altform) return (buf); } -#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) || PHP_BROKEN_SNPRINTF || PHP_BROKEN_VSNPRINTF - /* * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions * @@ -1137,7 +1135,7 @@ static void strx_printv(int *ccp, char *buf, size_t len, const char *format, } -int ap_php_snprintf(char *buf, size_t len, const char *format,...) +PHPAPI int ap_php_snprintf(char *buf, size_t len, const char *format,...) { int cc; va_list ap; @@ -1149,7 +1147,7 @@ int ap_php_snprintf(char *buf, size_t len, const char *format,...) } -int ap_php_vsnprintf(char *buf, size_t len, const char *format, va_list ap) +PHPAPI int ap_php_vsnprintf(char *buf, size_t len, const char *format, va_list ap) { int cc; @@ -1157,8 +1155,6 @@ int ap_php_vsnprintf(char *buf, size_t len, const char *format, va_list ap) return (cc); } -#endif /* HAVE_SNPRINTF */ - /* * Local variables: * tab-width: 4 diff --git a/main/snprintf.h b/main/snprintf.h index 76b7b6a6ca1a..f921ad14cd50 100644 --- a/main/snprintf.h +++ b/main/snprintf.h @@ -64,20 +64,26 @@ spprintf is the dynamical version of snprintf. It allocates the buffer in size #ifndef SNPRINTF_H #define SNPRINTF_H -#if !defined(HAVE_SNPRINTF) || PHP_BROKEN_SNPRINTF -int ap_php_snprintf(char *, size_t, const char *, ...) PHP_ATTRIBUTE_FORMAT(printf, 3, 4); -#define snprintf ap_php_snprintf +BEGIN_EXTERN_C() +PHPAPI int ap_php_snprintf(char *, size_t, const char *, ...) PHP_ATTRIBUTE_FORMAT(printf, 3, 4); +PHPAPI int ap_php_vsnprintf(char *, size_t, const char *, va_list ap) PHP_ATTRIBUTE_FORMAT(printf, 3, 0); +PHPAPI int php_sprintf (char* s, const char* format, ...) PHP_ATTRIBUTE_FORMAT(printf, 2, 3); +END_EXTERN_C() + +#ifdef snprintf +#undef snprintf #endif +#define snprintf ap_php_snprintf -#if !defined(HAVE_VSNPRINTF) || PHP_BROKEN_VSNPRINTF -int ap_php_vsnprintf(char *, size_t, const char *, va_list ap) PHP_ATTRIBUTE_FORMAT(printf, 3, 0); -#define vsnprintf ap_php_vsnprintf +#ifdef vsnprintf +#undef vsnprintf #endif +#define vsnprintf ap_php_vsnprintf -#if PHP_BROKEN_SPRINTF -int php_sprintf (char* s, const char* format, ...) PHP_ATTRIBUTE_FORMAT(printf, 2, 3); -#define sprintf php_sprintf +#ifdef sprintf +#undef sprintf #endif +#define sprintf php_sprintf typedef enum { NO = 0, YES = 1 diff --git a/main/streams/mmap.c b/main/streams/mmap.c index 82bfa623f10d..1cfa9b825842 100644 --- a/main/streams/mmap.c +++ b/main/streams/mmap.c @@ -31,9 +31,9 @@ PHPAPI char *_php_stream_mmap_range(php_stream *stream, size_t offset, size_t le range.mode = mode; range.mapped = NULL; - /* For now, we impose an arbitrary 1MB limit to avoid + /* For now, we impose an arbitrary 2MB limit to avoid * runaway swapping when large files are passed thru. */ - if (length > 1 * 1024 * 1024) { + if (length > 2 * 1024 * 1024) { return NULL; } diff --git a/main/streams/php_streams_int.h b/main/streams/php_streams_int.h index a75334346303..f5826b83967b 100644 --- a/main/streams/php_streams_int.h +++ b/main/streams/php_streams_int.h @@ -18,17 +18,23 @@ /* $Id$ */ + #if ZEND_DEBUG -#define emalloc_rel_orig(size) \ + +#if USE_ZEND_ALLOC +# define emalloc_rel_orig(size) \ ( __php_stream_call_depth == 0 \ ? _emalloc((size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_RELAY_CC) \ : _emalloc((size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC) ) -#define erealloc_rel_orig(ptr, size) \ +# define erealloc_rel_orig(ptr, size) \ ( __php_stream_call_depth == 0 \ ? _erealloc((ptr), (size), 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_RELAY_CC) \ : _erealloc((ptr), (size), 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC) ) - +#else +# define emalloc_rel_orig(size) emalloc(size) +# define erealloc_rel_orig(ptr, size) erealloc(ptr, size) +#endif #define pemalloc_rel_orig(size, persistent) ((persistent) ? malloc((size)) : emalloc_rel_orig((size))) #define perealloc_rel_orig(ptr, size, persistent) ((persistent) ? realloc((ptr), (size)) : erealloc_rel_orig((ptr), (size))) diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index c37f38221cb4..c20bec7786f7 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -83,93 +83,16 @@ PHPAPI int php_stream_parse_fopen_modes(const char *mode, int *open_flags) } -/* {{{ php_stream_fopen */ -PHPAPI php_stream *_php_stream_fopen(const char *filename, const char *mode, char **opened_path, int options STREAMS_DC TSRMLS_DC) -{ - char *realpath = NULL; - struct stat st; - int open_flags; - int fd; - php_stream *ret; - int persistent = options & STREAM_OPEN_PERSISTENT; - char *persistent_id = NULL; - - if (FAILURE == php_stream_parse_fopen_modes(mode, &open_flags)) { - if (options & REPORT_ERRORS) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "`%s' is not a valid mode for fopen", mode); - } - return NULL; - } - - if ((realpath = expand_filepath(filename, NULL TSRMLS_CC)) == NULL) { - return NULL; - } - - if (persistent) { - spprintf(&persistent_id, 0, "streams_stdio_%d_%s", open_flags, realpath); - switch (php_stream_from_persistent_id(persistent_id, &ret TSRMLS_CC)) { - case PHP_STREAM_PERSISTENT_SUCCESS: - if (opened_path) { - *opened_path = realpath; - realpath = NULL; - } - if (realpath) { - efree(realpath); - } - /* fall through */ - - case PHP_STREAM_PERSISTENT_FAILURE: - efree(persistent_id);; - return ret; - } - } - - fd = open(realpath, open_flags, 0666); - - if (fd != -1) { - /* sanity checks for include/require */ - if (options & STREAM_OPEN_FOR_INCLUDE && (fstat(fd, &st) == -1 || !S_ISREG(st.st_mode))) { -#ifdef PHP_WIN32 - /* skip the sanity check; fstat doesn't appear to work on - * UNC paths */ - if (!IS_UNC_PATH(filename, strlen(filename))) -#endif - goto err; - } - - ret = php_stream_fopen_from_fd_rel(fd, mode, persistent_id); - - if (ret) { - if (opened_path) { - *opened_path = realpath; - realpath = NULL; - } - if (realpath) { - efree(realpath); - } - if (persistent_id) { - efree(persistent_id); - } - return ret; - } -err: - close(fd); - } - efree(realpath); - if (persistent_id) { - efree(persistent_id); - } - return NULL; -} -/* }}} */ - /* {{{ ------- STDIO stream implementation -------*/ typedef struct { FILE *file; int fd; /* underlying file descriptor */ - int is_process_pipe; /* use pclose instead of fclose */ - int is_pipe; /* don't try and seek */ + unsigned is_process_pipe:1; /* use pclose instead of fclose */ + unsigned is_pipe:1; /* don't try and seek */ + unsigned cached_fstat:1; /* sb is valid */ + unsigned _reserved:29; + int lock_flag; /* stores the lock state */ char *temp_file_name; /* if non-null, this is the path to a temporary file that * is to be deleted when the stream is closed */ @@ -185,7 +108,25 @@ typedef struct { char *last_mapped_addr; HANDLE file_mapping; #endif + + struct stat sb; } php_stdio_stream_data; +#define PHP_STDIOP_GET_FD(anfd, data) anfd = (data)->file ? fileno((data)->file) : (data)->fd + +static int do_fstat(php_stdio_stream_data *d, int force) +{ + if (!d->cached_fstat || force) { + int fd; + int r; + + PHP_STDIOP_GET_FD(fd, d); + r = fstat(fd, &d->sb); + d->cached_fstat = r == 0; + + return r; + } + return 0; +} PHPAPI php_stream *_php_stream_fopen_temporary_file(const char *dir, const char *pfx, char **opened_path STREAMS_DC TSRMLS_DC) { @@ -214,6 +155,7 @@ PHPAPI php_stream *_php_stream_fopen_tmpfile(int dummy STREAMS_DC TSRMLS_DC) php_stream *stream = php_stream_fopen_from_fd_rel(fd, "r+b", NULL); if (stream) { php_stdio_stream_data *self = (php_stdio_stream_data*)stream->abstract; + stream->wrapper = &php_plain_files_wrapper; self->temp_file_name = opened_path; self->lock_flag = LOCK_UN; @@ -246,8 +188,7 @@ PHPAPI php_stream *_php_stream_fopen_from_fd(int fd, const char *mode, const cha #ifdef S_ISFIFO /* detect if this is a pipe */ if (self->fd >= 0) { - struct stat sb; - self->is_pipe = (fstat(self->fd, &sb) == 0 && S_ISFIFO(sb.st_mode)) ? 1 : 0; + self->is_pipe = (do_fstat(self, 0) == 0 && S_ISFIFO(self->sb.st_mode)) ? 1 : 0; } #elif defined(PHP_WIN32) { @@ -290,8 +231,7 @@ PHPAPI php_stream *_php_stream_fopen_from_file(FILE *file, const char *mode STRE #ifdef S_ISFIFO /* detect if this is a pipe */ if (self->fd >= 0) { - struct stat sb; - self->is_pipe = (fstat(self->fd, &sb) == 0 && S_ISFIFO(sb.st_mode)) ? 1 : 0; + self->is_pipe = (do_fstat(self, 0) == 0 && S_ISFIFO(self->sb.st_mode)) ? 1 : 0; } #elif defined(PHP_WIN32) { @@ -336,8 +276,6 @@ PHPAPI php_stream *_php_stream_fopen_from_pipe(FILE *file, const char *mode STRE return stream; } -#define PHP_STDIOP_GET_FD(anfd, data) anfd = (data)->file ? fileno((data)->file) : (data)->fd - static size_t php_stdiop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC) { php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract; @@ -524,6 +462,9 @@ static int php_stdiop_cast(php_stream *stream, int castas, void **ret TSRMLS_DC) /* we were opened as a plain file descriptor, so we * need fdopen now */ data->file = fdopen(data->fd, stream->mode); + if (data->file == NULL) { + return FAILURE; + } } *(FILE**)ret = data->file; @@ -561,14 +502,14 @@ static int php_stdiop_cast(php_stream *stream, int castas, void **ret TSRMLS_DC) static int php_stdiop_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC) { - int fd; + int ret; php_stdio_stream_data *data = (php_stdio_stream_data*) stream->abstract; assert(data != NULL); - PHP_STDIOP_GET_FD(fd, data); - - return fstat(fd, &ssb->sb); + ret = do_fstat(data, 1); + memcpy(&ssb->sb, &data->sb, sizeof(ssb->sb)); + return ret; } static int php_stdiop_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC) @@ -641,7 +582,7 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void return 0; } - if (!flock(fd, value) || (errno == EWOULDBLOCK && value & LOCK_NB)) { + if (!flock(fd, value)) { data->lock_flag = value; return 0; } else { @@ -653,7 +594,6 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void #if HAVE_MMAP { php_stream_mmap_range *range = (php_stream_mmap_range*)ptrparam; - struct stat sbuf; int prot, flags; switch (value) { @@ -661,9 +601,9 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void return fd == -1 ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK; case PHP_STREAM_MMAP_MAP_RANGE: - fstat(fd, &sbuf); - if (range->length == 0 || range->length > sbuf.st_size) { - range->length = sbuf.st_size; + do_fstat(data, 1); + if (range->length == 0 || range->length > data->sb.st_size) { + range->length = data->sb.st_size; } switch (range->mode) { case PHP_STREAM_MAP_MODE_READONLY: @@ -888,6 +828,94 @@ static php_stream *php_plain_files_dir_opener(php_stream_wrapper *wrapper, char } /* }}} */ +/* {{{ php_stream_fopen */ +PHPAPI php_stream *_php_stream_fopen(const char *filename, const char *mode, char **opened_path, int options STREAMS_DC TSRMLS_DC) +{ + char *realpath = NULL; + int open_flags; + int fd; + php_stream *ret; + int persistent = options & STREAM_OPEN_PERSISTENT; + char *persistent_id = NULL; + + if (FAILURE == php_stream_parse_fopen_modes(mode, &open_flags)) { + if (options & REPORT_ERRORS) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "`%s' is not a valid mode for fopen", mode); + } + return NULL; + } + + if ((realpath = expand_filepath(filename, NULL TSRMLS_CC)) == NULL) { + return NULL; + } + + if (persistent) { + spprintf(&persistent_id, 0, "streams_stdio_%d_%s", open_flags, realpath); + switch (php_stream_from_persistent_id(persistent_id, &ret TSRMLS_CC)) { + case PHP_STREAM_PERSISTENT_SUCCESS: + if (opened_path) { + *opened_path = realpath; + realpath = NULL; + } + if (realpath) { + efree(realpath); + } + /* fall through */ + + case PHP_STREAM_PERSISTENT_FAILURE: + efree(persistent_id);; + return ret; + } + } + + fd = open(realpath, open_flags, 0666); + + if (fd != -1) { + + ret = php_stream_fopen_from_fd_rel(fd, mode, persistent_id); + + if (ret) { + if (opened_path) { + *opened_path = realpath; + realpath = NULL; + } + if (realpath) { + efree(realpath); + } + if (persistent_id) { + efree(persistent_id); + } + + /* sanity checks for include/require. + * We check these after opening the stream, so that we save + * on fstat() syscalls */ + if (options & STREAM_OPEN_FOR_INCLUDE) { + php_stdio_stream_data *self = (php_stdio_stream_data*)ret->abstract; + int r; + + r = do_fstat(self, 0); + if ( +#ifndef PHP_WIN32 + (r != 0) || /* it is OK for fstat to fail under win32 */ +#endif + (r == 0 && !S_ISREG(self->sb.st_mode))) { + php_stream_close(ret); + return NULL; + } + } + + return ret; + } + close(fd); + } + efree(realpath); + if (persistent_id) { + efree(persistent_id); + } + return NULL; +} +/* }}} */ + static php_stream *php_plain_files_stream_opener(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) @@ -997,10 +1025,35 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, char *url_from, c if (ret == -1) { #ifdef EXDEV if (errno == EXDEV) { + struct stat sb; if (php_copy_file(url_from, url_to TSRMLS_CC) == SUCCESS) { - VCWD_UNLINK(url_from); - return 1; + if (VCWD_STAT(url_from, &sb) == 0) { +#if !defined(TSRM_WIN32) && !defined(NETWARE) + if (VCWD_CHMOD(url_to, sb.st_mode)) { + if (errno == EPERM) { + php_error_docref2(NULL TSRMLS_CC, url_from, url_to, E_WARNING, "%s", strerror(errno)); + VCWD_UNLINK(url_from); + return 1; + } + php_error_docref2(NULL TSRMLS_CC, url_from, url_to, E_WARNING, "%s", strerror(errno)); + return 0; + } + if (VCWD_CHOWN(url_to, sb.st_uid, sb.st_gid)) { + if (errno == EPERM) { + php_error_docref2(NULL TSRMLS_CC, url_from, url_to, E_WARNING, "%s", strerror(errno)); + VCWD_UNLINK(url_from); + return 1; + } + php_error_docref2(NULL TSRMLS_CC, url_from, url_to, E_WARNING, "%s", strerror(errno)); + return 0; + } +#endif + VCWD_UNLINK(url_from); + return 1; + } } + php_error_docref2(NULL TSRMLS_CC, url_from, url_to, E_WARNING, "%s", strerror(errno)); + return 0; } #endif php_error_docref2(NULL TSRMLS_CC, url_from, url_to, E_WARNING, "%s", strerror(errno)); diff --git a/main/streams/streams.c b/main/streams/streams.c index fc3d893e095b..3fbca6d53822 100755 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -592,8 +592,9 @@ PHPAPI size_t _php_stream_read(php_stream *stream, char *buf, size_t size TSRMLS } /* just break anyway, to avoid greedy read */ - if (stream->wrapper != &php_plain_files_wrapper) + if (stream->wrapper != &php_plain_files_wrapper) { break; + } } if (didread > 0) { @@ -832,22 +833,24 @@ PHPAPI char *php_stream_get_record(php_stream *stream, size_t maxlen, size_t *re { char *e, *buf; size_t toread; + int skip = 0; php_stream_fill_read_buffer(stream, maxlen TSRMLS_CC); - if (delim_len == 0) { + if (delim_len == 0 || !delim) { toread = maxlen; } else { if (delim_len == 1) { - e = memchr(stream->readbuf, *delim, stream->readbuflen); + e = memchr(stream->readbuf + stream->readpos, *delim, stream->writepos - stream->readpos); } else { - e = php_memnstr(stream->readbuf, delim, delim_len, (stream->readbuf + stream->readbuflen)); + e = php_memnstr(stream->readbuf + stream->readpos, delim, delim_len, (stream->readbuf + stream->writepos)); } if (!e) { toread = maxlen; } else { - toread = e - (char *) stream->readbuf; + toread = e - (char *) stream->readbuf - stream->readpos; + skip = 1; } } @@ -857,8 +860,13 @@ PHPAPI char *php_stream_get_record(php_stream *stream, size_t maxlen, size_t *re buf = emalloc(toread + 1); *returned_len = php_stream_read(stream, buf, toread); - + if (*returned_len >= 0) { + if (skip) { + stream->readpos += delim_len; + stream->position += delim_len; + } + buf[*returned_len] = '\0'; return buf; } else { efree(buf); @@ -1150,7 +1158,7 @@ PHPAPI size_t _php_stream_passthru(php_stream * stream STREAMS_DC TSRMLS_DC) char *p; size_t mapped; - p = php_stream_mmap_range(stream, php_stream_tell(stream), 0, PHP_STREAM_MAP_MODE_SHARED_READONLY, &mapped); + p = php_stream_mmap_range(stream, php_stream_tell(stream), PHP_STREAM_COPY_ALL, PHP_STREAM_MAP_MODE_SHARED_READONLY, &mapped); if (p) { PHPWRITE(p, mapped); @@ -1211,6 +1219,17 @@ PHPAPI size_t _php_stream_copy_to_mem(php_stream *src, char **buf, size_t maxlen } } + if (maxlen > 0) { + ptr = *buf = pemalloc_rel_orig(maxlen + 1, persistent); + while ((len < maxlen) & !php_stream_eof(src)) { + ret = php_stream_read(src, ptr, maxlen - len); + len += ret; + ptr += ret; + } + *ptr = '\0'; + return len; + } + /* avoid many reallocs by allocating a good sized chunk to begin with, if * we can. Note that the stream may be filtered, in which case the stat * result may be inaccurate, as the filter may inflate or deflate the @@ -1349,6 +1368,21 @@ static void stream_resource_persistent_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC FG(pclose_ret) = php_stream_free(stream, PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_RSRC_DTOR); } +void php_shutdown_stream_hashes(TSRMLS_D) +{ + if (FG(stream_wrappers)) { + zend_hash_destroy(FG(stream_wrappers)); + efree(FG(stream_wrappers)); + FG(stream_wrappers) = NULL; + } + + if (FG(stream_filters)) { + zend_hash_destroy(FG(stream_filters)); + efree(FG(stream_filters)); + FG(stream_filters) = NULL; + } +} + int php_init_stream_wrappers(int module_number TSRMLS_DC) { le_stream = zend_register_list_destructors_ex(stream_resource_regular_dtor, NULL, "stream", module_number); @@ -1384,7 +1418,18 @@ int php_shutdown_stream_wrappers(int module_number TSRMLS_DC) /* API for registering GLOBAL wrappers */ PHPAPI int php_register_url_stream_wrapper(char *protocol, php_stream_wrapper *wrapper TSRMLS_DC) { - return zend_hash_add(&url_stream_wrappers_hash, protocol, strlen(protocol), wrapper, sizeof(*wrapper), NULL); + int i, protocol_len = strlen(protocol); + + for(i = 0; i < protocol_len; i++) { + if (!isalnum((int)protocol[i]) && + protocol[i] != '+' && + protocol[i] != '-' && + protocol[i] != '.') { + return FAILURE; + } + } + + return zend_hash_add(&url_stream_wrappers_hash, protocol, protocol_len, wrapper, sizeof(*wrapper), NULL); } PHPAPI int php_unregister_url_stream_wrapper(char *protocol TSRMLS_DC) @@ -1395,6 +1440,17 @@ PHPAPI int php_unregister_url_stream_wrapper(char *protocol TSRMLS_DC) /* API for registering VOLATILE wrappers */ PHPAPI int php_register_url_stream_wrapper_volatile(char *protocol, php_stream_wrapper *wrapper TSRMLS_DC) { + int i, protocol_len = strlen(protocol); + + for(i = 0; i < protocol_len; i++) { + if (!isalnum((int)protocol[i]) && + protocol[i] != '+' && + protocol[i] != '-' && + protocol[i] != '.') { + return FAILURE; + } + } + if (!FG(stream_wrappers)) { php_stream_wrapper tmpwrapper; @@ -1403,7 +1459,7 @@ PHPAPI int php_register_url_stream_wrapper_volatile(char *protocol, php_stream_w zend_hash_copy(FG(stream_wrappers), &url_stream_wrappers_hash, NULL, &tmpwrapper, sizeof(php_stream_wrapper)); } - return zend_hash_add(FG(stream_wrappers), protocol, strlen(protocol), wrapper, sizeof(*wrapper), NULL); + return zend_hash_add(FG(stream_wrappers), protocol, protocol_len, wrapper, sizeof(*wrapper), NULL); } /* }}} */ @@ -1454,7 +1510,11 @@ PHPAPI php_stream_wrapper *php_stream_locate_url_wrapper(const char *path, char } /* TODO: curl based streams probably support file:// properly */ if (!protocol || !strncasecmp(protocol, "file", n)) { +#ifdef PHP_WIN32 + if (protocol && path[n+1] == '/' && path[n+2] == '/' && path[n+3] != '\0' && path[n+3] != '/' && path[n+4] != ':') { +#else if (protocol && path[n+1] == '/' && path[n+2] == '/' && path[n+3] != '/') { +#endif if (options & REPORT_ERRORS) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "remote host file access not supported, %s", path); } @@ -1867,28 +1927,28 @@ PHPAPI int php_stream_context_del_link(php_stream_context *context, /* {{{ php_stream_dirent_alphasort */ -PHPAPI int php_stream_dirent_alphasort(const php_stream_dirent **a, const php_stream_dirent **b) +PHPAPI int php_stream_dirent_alphasort(const char **a, const char **b) { - return strcoll((*a)->d_name,(*b)->d_name); + return strcoll(*a, *b); } /* }}} */ /* {{{ php_stream_dirent_alphasortr */ -PHPAPI int php_stream_dirent_alphasortr(const php_stream_dirent **a, const php_stream_dirent **b) +PHPAPI int php_stream_dirent_alphasortr(const char **a, const char **b) { - return strcoll((*b)->d_name,(*a)->d_name); + return strcoll(*b, *a); } /* }}} */ /* {{{ php_stream_scandir */ -PHPAPI int _php_stream_scandir(char *dirname, php_stream_dirent **namelist[], int flags, php_stream_context *context, - int (*compare) (const php_stream_dirent **a, const php_stream_dirent **b) TSRMLS_DC) +PHPAPI int _php_stream_scandir(char *dirname, char **namelist[], int flags, php_stream_context *context, + int (*compare) (const char **a, const char **b) TSRMLS_DC) { php_stream *stream; php_stream_dirent sdp; - php_stream_dirent **vector = NULL; + char **vector = NULL; int vector_size = 0; int nfiles = 0; @@ -1908,11 +1968,10 @@ PHPAPI int _php_stream_scandir(char *dirname, php_stream_dirent **namelist[], in } else { vector_size *= 2; } - vector = (php_stream_dirent **) erealloc(vector, vector_size * sizeof(php_stream_dirent *)); + vector = (char **) erealloc(vector, vector_size * sizeof(char *)); } - vector[nfiles] = emalloc(sizeof(php_stream_dirent)); - memcpy(vector[nfiles], &sdp, sizeof(sdp)); + vector[nfiles] = estrdup(sdp.d_name); nfiles++; } @@ -1921,7 +1980,7 @@ PHPAPI int _php_stream_scandir(char *dirname, php_stream_dirent **namelist[], in *namelist = vector; if (compare) { - qsort(*namelist, nfiles, sizeof(php_stream_dirent *), (int(*)(const void *, const void *))compare); + qsort(*namelist, nfiles, sizeof(char *), (int(*)(const void *, const void *))compare); } return nfiles; } diff --git a/main/streams/transports.c b/main/streams/transports.c index 04a4eccfbd3b..57cc0a6c5a4b 100644 --- a/main/streams/transports.c +++ b/main/streams/transports.c @@ -137,8 +137,8 @@ PHPAPI php_stream *_php_stream_xport_create(const char *name, long namelen, int /* client */ if (flags & STREAM_XPORT_CONNECT) { - if (0 != php_stream_xport_connect(stream, name, namelen, - flags & STREAM_XPORT_OP_CONNECT_ASYNC ? 1 : 0, + if (-1 == php_stream_xport_connect(stream, name, namelen, + flags & STREAM_XPORT_CONNECT_ASYNC ? 1 : 0, timeout, &error_text, error_code TSRMLS_CC)) { ERR_RETURN(error_string, error_text, "connect() failed: %s"); @@ -385,6 +385,7 @@ PHPAPI int php_stream_xport_recvfrom(php_stream *stream, char *buf, size_t bufle php_stream_xport_param param; int ret = 0; int recvd_len = 0; +#if 0 int oob; if (flags == 0 && addr == NULL) { @@ -416,6 +417,7 @@ PHPAPI int php_stream_xport_recvfrom(php_stream *stream, char *buf, size_t bufle return recvd_len; } } +#endif /* otherwise, we are going to bypass the buffer */ @@ -453,9 +455,11 @@ PHPAPI int php_stream_xport_sendto(php_stream *stream, const char *buf, size_t b int ret = 0; int oob; +#if 0 if (flags == 0 && addr == NULL) { return php_stream_write(stream, buf, buflen); } +#endif oob = (flags & STREAM_OOB) == STREAM_OOB; diff --git a/main/streams/userspace.c b/main/streams/userspace.c index 7bf7801d2f5a..e58eda0ca19e 100644 --- a/main/streams/userspace.c +++ b/main/streams/userspace.c @@ -445,15 +445,15 @@ static size_t php_userstreamop_write(php_stream *stream, const char *buf, size_t int call_result; php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; zval **args[1]; - zval zbuff, *zbufptr; + zval *zbufptr; size_t didwrite = 0; assert(us != NULL); ZVAL_STRINGL(&func_name, USERSTREAM_WRITE, sizeof(USERSTREAM_WRITE)-1, 0); - ZVAL_STRINGL(&zbuff, (char*)buf, count, 0); - zbufptr = &zbuff; + MAKE_STD_ZVAL(zbufptr); + ZVAL_STRINGL(zbufptr, (char*)buf, count, 1);; args[0] = &zbufptr; call_result = call_user_function_ex(NULL, @@ -463,6 +463,8 @@ static size_t php_userstreamop_write(php_stream *stream, const char *buf, size_t 1, args, 0, NULL TSRMLS_CC); + zval_ptr_dtor(&zbufptr); + didwrite = 0; if (call_result == SUCCESS && retval != NULL) { convert_to_long(retval); @@ -710,7 +712,7 @@ static int statbuf_from_array(zval *array, php_stream_statbuf *ssb TSRMLS_DC) STAT_PROP_ENTRY(rdev); #endif STAT_PROP_ENTRY(size); -#if defined(NETWARE) && defined(CLIB_STAT_PATCH) +#ifdef NETWARE STAT_PROP_ENTRY_EX(atime, atime.tv_sec); STAT_PROP_ENTRY_EX(mtime, mtime.tv_sec); STAT_PROP_ENTRY_EX(ctime, ctime.tv_sec); diff --git a/main/streams/xp_socket.c b/main/streams/xp_socket.c index d6fb72257e1f..f67161698c78 100644 --- a/main/streams/xp_socket.c +++ b/main/streams/xp_socket.c @@ -47,18 +47,48 @@ static size_t php_sockop_write(php_stream *stream, const char *buf, size_t count { php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract; int didwrite; + struct timeval *ptimeout; if (sock->socket == -1) { return 0; } + if (sock->timeout.tv_sec == -1) + ptimeout = NULL; + else + ptimeout = &sock->timeout; + +retry: didwrite = send(sock->socket, buf, count, 0); if (didwrite <= 0) { - char *estr = php_socket_strerror(php_socket_errno(), NULL, 0); + long err = php_socket_errno(); + char *estr; - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "send of %ld bytes failed with errno=%d %s", - (long)count, php_socket_errno(), estr); + if (sock->is_blocked && err == EWOULDBLOCK) { + int retval; + + sock->timeout_event = 0; + + do { + retval = php_pollfd_for(sock->socket, POLLOUT, ptimeout); + + if (retval == 0) { + sock->timeout_event = 1; + break; + } + + if (retval > 0) { + /* writable now; retry */ + goto retry; + } + + err = php_socket_errno(); + } while (err == EINTR); + } + estr = php_socket_strerror(err, NULL, 0); + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "send of %ld bytes failed with errno=%ld %s", + (long)count, err, estr); efree(estr); } @@ -75,35 +105,31 @@ static size_t php_sockop_write(php_stream *stream, const char *buf, size_t count static void php_sock_stream_wait_for_data(php_stream *stream, php_netstream_data_t *sock TSRMLS_DC) { - fd_set fdr, tfdr; int retval; - struct timeval timeout, *ptimeout; + struct timeval *ptimeout; if (sock->socket == -1) { return; } - FD_ZERO(&fdr); - FD_SET(sock->socket, &fdr); sock->timeout_event = 0; if (sock->timeout.tv_sec == -1) ptimeout = NULL; else - ptimeout = &timeout; - + ptimeout = &sock->timeout; while(1) { - tfdr = fdr; - timeout = sock->timeout; - - retval = select(sock->socket + 1, &tfdr, NULL, NULL, ptimeout); + retval = php_pollfd_for(sock->socket, PHP_POLLREADABLE, ptimeout); if (retval == 0) sock->timeout_event = 1; if (retval >= 0) break; + + if (php_socket_errno() != EINTR) + break; } } @@ -142,14 +168,12 @@ static int php_sockop_close(php_stream *stream, int close_handle TSRMLS_DC) { php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract; #ifdef PHP_WIN32 - fd_set wrfds, efds; int n; - struct timeval timeout; #endif if (close_handle) { - if (sock->socket != -1) { + if (sock->socket != SOCK_ERR) { #ifdef PHP_WIN32 /* prevent more data from coming in */ shutdown(sock->socket, SHUT_RD); @@ -161,19 +185,11 @@ static int php_sockop_close(php_stream *stream, int close_handle TSRMLS_DC) * but at the same time avoid hanging indefintely. * */ do { - FD_ZERO(&wrfds); - FD_SET(sock->socket, &wrfds); - efds = wrfds; - - timeout.tv_sec = 0; - timeout.tv_usec = 5000; /* arbitrary */ - - n = select(sock->socket + 1, NULL, &wrfds, &efds, &timeout); + n = php_pollfd_for_ms(sock->socket, POLLOUT, 500); } while (n == -1 && php_socket_errno() == EINTR); #endif - closesocket(sock->socket); - sock->socket = -1; + sock->socket = SOCK_ERR; } } @@ -185,8 +201,11 @@ static int php_sockop_close(php_stream *stream, int close_handle TSRMLS_DC) static int php_sockop_flush(php_stream *stream TSRMLS_DC) { +#if 0 php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract; return fsync(sock->socket); +#endif + return 0; } static int php_sockop_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC) @@ -195,6 +214,16 @@ static int php_sockop_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC return fstat(sock->socket, &ssb->sb); } +static inline int sock_sendto(php_netstream_data_t *sock, char *buf, size_t buflen, int flags, + struct sockaddr *addr, socklen_t addrlen + TSRMLS_DC) +{ + if (addr) { + return sendto(sock->socket, buf, buflen, flags, addr, addrlen); + } + return send(sock->socket, buf, buflen, flags); +} + static inline int sock_recvfrom(php_netstream_data_t *sock, char *buf, size_t buflen, int flags, char **textaddr, long *textaddrlen, struct sockaddr **addr, socklen_t *addrlen @@ -225,7 +254,6 @@ static int php_sockop_set_option(php_stream *stream, int option, int value, void switch(option) { case PHP_STREAM_OPTION_CHECK_LIVENESS: { - fd_set rfds; struct timeval tv; char buf; int alive = 1; @@ -233,23 +261,20 @@ static int php_sockop_set_option(php_stream *stream, int option, int value, void if (value == -1) { if (sock->timeout.tv_sec == -1) { tv.tv_sec = FG(default_socket_timeout); + tv.tv_usec = 0; } else { tv = sock->timeout; } } else { tv.tv_sec = value; + tv.tv_usec = 0; } if (sock->socket == -1) { alive = 0; - } else { - FD_ZERO(&rfds); - FD_SET(sock->socket, &rfds); - - if (select(sock->socket + 1, &rfds, NULL, NULL, &tv) > 0 && FD_ISSET(sock->socket, &rfds)) { - if (0 == recv(sock->socket, &buf, sizeof(buf), MSG_PEEK) && php_socket_errno() != EAGAIN) { - alive = 0; - } + } else if (php_pollfd_for(sock->socket, PHP_POLLREADABLE|POLLPRI, &tv) > 0) { + if (0 == recv(sock->socket, &buf, sizeof(buf), MSG_PEEK) && php_socket_errno() != EAGAIN) { + alive = 0; } } return alive ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR; @@ -312,11 +337,11 @@ static int php_sockop_set_option(php_stream *stream, int option, int value, void if ((xparam->inputs.flags & STREAM_OOB) == STREAM_OOB) { flags |= MSG_OOB; } - xparam->outputs.returncode = sendto(sock->socket, + xparam->outputs.returncode = sock_sendto(sock, xparam->inputs.buf, xparam->inputs.buflen, flags, xparam->inputs.addr, - xparam->inputs.addrlen); + xparam->inputs.addrlen TSRMLS_CC); if (xparam->outputs.returncode == -1) { char *err = php_socket_strerror(php_socket_errno(), NULL, 0); php_error_docref(NULL TSRMLS_CC, E_WARNING, diff --git a/netware/ApacheCore.imp b/netware/ApacheCore.imp deleted file mode 100644 index 3f7783797022..000000000000 --- a/netware/ApacheCore.imp +++ /dev/null @@ -1,365 +0,0 @@ - ap_MD5Final, - ap_MD5Init, - ap_MD5Update, - ap_acquire_mutex, - ap_add_cgi_vars, - ap_add_common_vars, - ap_add_loaded_module, - ap_add_module, - ap_add_named_module, - ap_add_per_dir_conf, - ap_add_per_url_conf, - ap_add_version_component, - ap_allow_options, - ap_allow_overrides, - ap_append_arrays, - ap_array_cat, - ap_auth_name, - ap_auth_type, - ap_basic_http_header, - ap_bclose, - ap_bcreate, - ap_bfilbuf, - ap_bfileno, - ap_bflsbuf, - ap_bflush, - ap_bgetopt, - ap_bgets, - ap_bhalfduplex, - ap_block_alarms, - ap_blookc, - ap_bnonblock, - ap_bonerror, - ap_bpushfd, - ap_bputs, - ap_bread, - ap_bsetflag, - ap_bsetopt, - ap_bskiplf, - ap_bspawn_child, - ap_bwrite, - ap_bytes_in_free_blocks, - ap_bytes_in_pool, - ap_call_exec, - ap_can_exec, - ap_cfg_closefile, - ap_cfg_getc, - ap_cfg_getline, - ap_chdir_file, - ap_check_alarm, - ap_check_cmd_context, - ap_checkmask, - ap_cleanup_for_exec, - ap_clear_module_list, - ap_clear_pool, - ap_clear_table, - ap_close_piped_log, - ap_construct_server, - ap_construct_url, - ap_content_type_tolower, - ap_copy_array, - ap_copy_array_hdr, - ap_copy_table, - ap_count_dirs, - ap_cpystrn, - ap_create_environment, - ap_create_mutex, - ap_create_per_dir_config, - ap_custom_response, - ap_default_port_for_request, - ap_default_port_for_scheme, - ap_default_type, - ap_destroy_mutex, - ap_destroy_pool, - ap_destroy_sub_req, - ap_die, - ap_discard_request_body, - ap_document_root, - ap_each_byterange, - ap_error_log2stderr, - ap_escape_html, - ap_escape_path_segment, - ap_escape_quotes, - ap_escape_shell_cmd, - ap_exists_scoreboard_image, - ap_finalize_request_protocol, - ap_find_command, - ap_find_command_in_modules, - ap_find_last_token, - ap_find_linked_module, - ap_find_module_name, - ap_find_path_info, - ap_find_token, - ap_get_basic_auth_pw, - ap_get_client_block, - ap_get_gmtoff, - ap_get_limit_req_body, - ap_get_remote_host, - ap_get_remote_logname, - ap_get_server_built, - ap_get_server_name, - ap_get_server_port, - ap_get_server_version, - ap_get_time, - ap_get_token, - ap_getparents, - ap_getword, - ap_getword_conf, - ap_getword_conf_nc, - ap_getword_nc, - ap_getword_nulls, - ap_getword_nulls_nc, - ap_getword_white, - ap_getword_white_nc, - ap_gm_timestr_822, - ap_gname2id, - ap_handle_command, - ap_hard_timeout, - ap_ht_time, - ap_ind, - ap_index_of_response, - ap_init_virtual_host, - ap_internal_redirect, - ap_internal_redirect_handler, - ap_is_directory, - ap_is_fnmatch, - ap_is_initial_req, - ap_is_matchexp, - ap_is_url, - ap_kill_cleanup, - ap_kill_cleanups_for_fd, - ap_kill_cleanups_for_socket, - ap_kill_timeout, - ap_log_assert, - ap_log_error_old, - ap_log_reason, - ap_log_unixerr, - ap_make_array, - ap_make_dirstr, - ap_make_dirstr_parent, - ap_make_dirstr_prefix, - ap_make_full_path, - ap_make_sub_pool, - ap_make_table, - ap_matches_request_vhost, - ap_md5, - ap_md5_binary, - ap_md5contextTo64, - ap_md5digest, - ap_meets_conditions, - ap_no2slash, - ap_note_auth_failure, - ap_note_basic_auth_failure, - ap_note_cleanups_for_fd, - ap_note_cleanups_for_file, - ap_note_cleanups_for_socket, - ap_note_digest_auth_failure, - ap_note_subprocess, - ap_open_mutex, - ap_open_piped_log, - ap_os_escape_path, - ap_overlap_tables, - ap_overlay_tables, - ap_palloc, - ap_parseHTTPdate, - ap_parse_hostinfo_components, - ap_parse_uri, - ap_parse_uri_components, - ap_pcalloc, - ap_pcfg_open_custom, - ap_pcfg_openfile, - ap_pclosedir, - ap_pclosef, - ap_pclosesocket, - ap_pduphostent, - ap_pfclose, - ap_pfdopen, - ap_pfopen, - ap_pgethostbyname, - ap_popendir, - ap_popenf, - ap_pregcomp, - ap_pregfree, - ap_pregsub, - ap_psignature, - ap_psocket, - ap_pstrdup, - ap_pstrndup, - ap_push_array, - ap_pvsprintf, - ap_rationalize_mtime, - ap_register_cleanup, - ap_release_mutex, - ap_remove_loaded_module, - ap_remove_module, - ap_requires, - ap_reset_timeout, - ap_rflush, - ap_rind, - ap_rputc, - ap_rputs, - ap_run_cleanup, - ap_run_sub_req, - ap_rwrite, - ap_satisfies, - ap_scan_script_header_err, - ap_scan_script_header_err_buff, - ap_scan_script_header_err_core, - ap_send_fb, - ap_send_fb_length, - ap_send_fd, - ap_send_fd_length, - ap_send_http_header, - ap_send_http_trace, - ap_send_mmap, - ap_send_size, - ap_server_root_relative, - ap_set_byterange, - ap_set_content_length, - ap_set_etag, - ap_set_keepalive, - ap_set_last_modified, - ap_setup_client_block, - ap_should_client_block, - ap_soft_timeout, - ap_some_auth_required, - ap_spawn_child, - ap_srm_command_loop, - ap_str_tolower, - ap_strcasecmp_match, - ap_strcmp_match, - ap_sub_req_lookup_file, - ap_sub_req_lookup_uri, - ap_sync_scoreboard_image, - ap_table_add, - ap_table_addn, - ap_table_get, - ap_table_merge, - ap_table_mergen, - ap_table_set, - ap_table_setn, - ap_table_unset, - ap_tm2sec, - ap_uname2id, - ap_unblock_alarms, - ap_unescape_url, - ap_unparse_uri_components, - ap_update_mtime, - ap_uudecode, - ap_uuencode, - ap_vbprintf, - ap_vformatter, - ap_vsnprintf, - regcomp, - regexec, - regfree, - access_module, - alias_module, - ap_bprintf, - ap_bvputs, - ap_day_snames, - ap_extended_status, - ap_limit_section, - ap_loaded_modules, - ap_log_error, - ap_log_printf, - ap_log_rerror, - ap_month_snames, - ap_null_cleanup, - ap_psprintf, - ap_pstrcat, - ap_restart_time, - ap_rprintf, - ap_rvputs, - ap_scoreboard_image, - ap_send_header_field, - ap_server_argv0, - ap_server_root, - ap_set_file_slot, - ap_set_flag_slot, - ap_set_string_slot, - ap_set_string_slot_lower, - ap_snprintf, - ap_suexec_enabled, - ap_table_do, - apache_main, - asis_module, - auth_module, - autoindex_module, - config_log_module, - core_module, - dir_module, - env_module, - imap_module, - includes_module, - mime_module, - negotiation_module, - setenvif_module, - so_module, - top_module, - ap_fnmatch, - ap_method_number_of, - ap_exists_config_define, - ap_single_module_configure, - ap_make_etag, - ap_array_pstrcat, - ap_find_list_item, - ap_MD5Encode, - ap_validate_password, - ap_size_list_item, - ap_get_list_item, - ap_scoreboard_fname, - ap_pid_fname, - ap_excess_requests_per_child, - ap_threads_per_child, - ap_max_requests_per_child, - ap_daemons_to_start, - ap_daemons_min_free, - ap_daemons_max_free, - ap_daemons_limit, - ap_user_name, - ap_user_id, - ap_group_id, - ap_standalone, - ap_server_confname, - ap_sub_req_method_uri, - ap_regerror, - ap_regexec, - ap_field_noparam, - ap_pbase64decode, - ap_pbase64encode, - ap_base64encode, - ap_base64encode_binary, - ap_base64encode_len, - ap_base64decode, - ap_base64decode_binary, - ap_base64decode_len, - ap_SHA1Init, - ap_SHA1Update_binary, - ap_SHA1Update, - ap_SHA1Final, - ap_sha1_base64, - ap_my_generation, - ap_get_virthost_addr, - ap_listeners, - ap_listenbacklog, - clean_parent_exit, - init_tsd, - ap_set_config_vectors, - ap_strcasestr, - ap_to64, - ap_vrprintf, - regerror, - ap_add_file_conf, - ap_configtestonly, - ap_is_rdirectory, - ap_remove_spaces, - ap_scan_script_header_err_strs, - ap_start_shutdown, - ap_start_restart, - ap_stripprefix, - ap_send_error_response, - ap_os_canonical_filename, - ap_os_http_method, - os_readdir, - os_opendir diff --git a/netware/BisonExtStandard.bat b/netware/BisonExtStandard.bat deleted file mode 100755 index 1a2e06950ade..000000000000 --- a/netware/BisonExtStandard.bat +++ /dev/null @@ -1,3 +0,0 @@ -@echo off - -bison --output=ext\standard\parsedate.c -v -d -p phplib ext\standard\parsedate.y diff --git a/netware/BisonFlexZend.bat b/netware/BisonFlexZend.bat deleted file mode 100755 index 5ed6aa3a18c8..000000000000 --- a/netware/BisonFlexZend.bat +++ /dev/null @@ -1,8 +0,0 @@ -@echo off - -bison --output=zend_ini_parser.c -v -d -p ini_ zend_ini_parser.y -flex -B -i -Sflex.skl -Pini_ -ozend_ini_scanner.c zend_ini_scanner.l -REM flex -i -Pini_ -ozend_ini_scanner.c zend_ini_scanner.l -bison --output=zend_language_parser.c -v -d -p zend zend_language_parser.y -flex -B -i -Sflex.skl -Pzend -ozend_language_scanner.c zend_language_scanner.l -REM flex -i -Pzend -ozend_language_scanner.c zend_language_scanner.l diff --git a/netware/ZendEngine2.mak b/netware/ZendEngine2.mak deleted file mode 100644 index effd309835ee..000000000000 --- a/netware/ZendEngine2.mak +++ /dev/null @@ -1,160 +0,0 @@ -# Temporarily here -- later may go into some batch file -# which will set this as an environment variable -PROJECT_ROOT = .. - -# Module details -MODULE_NAME = ZEND - -#include the common settings -include $(PROJECT_ROOT)/netware/common.mif - -# Extensions of all input and output files -.SUFFIXES: -.SUFFIXES: .nlm .lib .obj .cpp .c .msg .mlc .mdb .xdc .d - -C_SRC = zend.c \ - zend_alloc.c \ - zend_API.c \ - zend_builtin_functions.c \ - zend_compile.c \ - zend_constants.c \ - zend_dynamic_array.c \ - zend_execute.c \ - zend_execute_API.c \ - zend_extensions.c \ - zend_hash.c \ - zend_highlight.c \ - zend_indent.c \ - zend_ini.c \ - zend_ini_parser.c \ - zend_ini_scanner.c \ - zend_language_parser.c \ - zend_language_scanner.c \ - zend_list.c \ - zend_llist.c \ - zend_multibyte.c \ - zend_object_handlers.c \ - zend_objects.c \ - zend_opcode.c \ - zend_operators.c \ - zend_ptr_stack.c \ - zend_qsort.c \ - zend_sprintf.c \ - zend_stack.c \ - zend_static_allocator.c \ - zend_ts_hash.c \ - zend_variables.c - - -# Destination directories and files -OBJ_DIR = $(BUILD) -FINAL_DIR = $(BUILD) -OBJECTS = $(addprefix $(OBJ_DIR)/,$(CPP_SRC:.cpp=.obj) $(C_SRC:.c=.obj)) -DEPDS = $(addprefix $(OBJ_DIR)/,$(CPP_SRC:.cpp=.d) $(C_SRC:.c=.d)) - -# Binary file -ifndef BINARY - BINARY=$(FINAL_DIR)\$(MODULE_NAME).lib -endif - - -# Compile flags -C_FLAGS = -c -maxerrors 25 -msgstyle std -C_FLAGS += -wchar_t on -bool on -C_FLAGS += -processor Pentium -C_FLAGS += -nostdinc -C_FLAGS += -relax_pointers # To remove type-casting errors -C_FLAGS += -D__C9X_CMATH_INLINES_DEFINED -C_FLAGS += -DNETWARE -DZTS -C_FLAGS += -DNEW_LIBC -C_FLAGS += -DCLIB_STAT_PATCH -C_FLAGS += -DTHREAD_SWITCH - -# These are required to use dlclose so that the PHP extensions are automatically unloaded -# when apache is unloaded -C_FLAGS += -DHAVE_DLFCN_H -DHAVE_LIBDL - -C_FLAGS += -I. -I- -I../netware -I$(SDK_DIR)/include # ../netware added for special SYS/STAT.H -C_FLAGS += -I$(MWCIncludes) - - -# Link flags -LD_FLAGS = -type library -LD_FLAGS += -o $(BINARY) - - -# Extra stuff based on debug / release builds -ifeq '$(BUILD)' 'debug' - C_FLAGS += -DZEND_DEBUG=1 - C_FLAGS += -inline smart -sym on -sym codeview4 -sym internal -opt off -opt intrinsics - LD_FLAGS += -sym codeview4 -sym internal - export MWLibraryFiles=$(SDK_DIR)/imports/libcpre.o;mwcrtld.lib -else - C_FLAGS += -opt speed -inline on -inline auto -sym off - C_FLAGS += -DZEND_DEBUG=0 - LD_FLAGS += -sym off - export MWLibraryFiles=$(SDK_DIR)/imports/libcpre.o;mwcrtl.lib -endif - - -# Virtual paths -vpath %.cpp . -vpath %.c . -vpath %.obj $(OBJ_DIR) - - -all: prebuild project - -.PHONY: all - -prebuild: - @if not exist $(OBJ_DIR) md $(OBJ_DIR) - -project: $(BINARY) $(MESSAGE) - @echo Build complete. - - -$(OBJ_DIR)/%.d: %.c - @echo Building Dependencies for $( - -int *__get_errno_ptr(void) -{ - return ___errno(); -} - diff --git a/netware/grp.h b/netware/grp.h deleted file mode 100644 index e7a99327e2f5..000000000000 --- a/netware/grp.h +++ /dev/null @@ -1,31 +0,0 @@ -/* pwd.h - Try to approximate UN*X's getuser...() functions under MS-DOS. - Copyright (C) 1990 by Thorsten Ohl, td12@ddagsi3.bitnet - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 1, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Header$ - */ - -/* This 'implementation' is conjectured from the use of this functions in - the RCS and BASH distributions. Of course these functions don't do too - much useful things under MS-DOS, but using them avoids many "#ifdef - MSDOS" in ported UN*X code ... */ - -struct group { - char *gr_name; /* group name */ - char *gr_passwd; /* group password */ - int gr_gid; /* group id */ - char **gr_mem; /* group members */ -}; diff --git a/netware/libpq-fe.h b/netware/libpq-fe.h deleted file mode 100644 index 879a447091cd..000000000000 --- a/netware/libpq-fe.h +++ /dev/null @@ -1,378 +0,0 @@ -/*------------------------------------------------------------------------- - * - * libpq-fe.h - * This file contains definitions for structures and - * externs for functions used by frontend postgres applications. - * - * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * $Id$ - * - *------------------------------------------------------------------------- - */ - -#ifndef LIBPQ_FE_H -#define LIBPQ_FE_H - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include - -/* - * postgres_ext.h defines the backend's externally visible types, - * such as Oid. - */ -#include "postgres_ext.h" - -/* SSL type is needed here only to declare PQgetssl() */ -#ifdef USE_SSL -#include -#endif - -/* Application-visible enum types */ - -typedef enum -{ - /* - * Although you may decide to change this list in some way, values - * which become unused should never be removed, nor should constants - * be redefined - that would break compatibility with existing code. - */ - CONNECTION_OK, - CONNECTION_BAD, - /* Non-blocking mode only below here */ - - /* - * The existence of these should never be relied upon - they should - * only be used for user feedback or similar purposes. - */ - CONNECTION_STARTED, /* Waiting for connection to be made. */ - CONNECTION_MADE, /* Connection OK; waiting to send. */ - CONNECTION_AWAITING_RESPONSE, /* Waiting for a response from the - * postmaster. */ - CONNECTION_AUTH_OK, /* Received authentication; waiting for - * backend startup. */ - CONNECTION_SETENV /* Negotiating environment. */ -} ConnStatusType; - -typedef enum -{ - PGRES_POLLING_FAILED = 0, - PGRES_POLLING_READING, /* These two indicate that one may */ - PGRES_POLLING_WRITING, /* use select before polling again. */ - PGRES_POLLING_OK, - PGRES_POLLING_ACTIVE /* Can call poll function immediately. */ -} PostgresPollingStatusType; - -typedef enum -{ - PGRES_EMPTY_QUERY = 0, - PGRES_COMMAND_OK, /* a query command that doesn't return - * anything was executed properly by the - * backend */ - PGRES_TUPLES_OK, /* a query command that returns tuples was - * executed properly by the backend, - * PGresult contains the result tuples */ - PGRES_COPY_OUT, /* Copy Out data transfer in progress */ - PGRES_COPY_IN, /* Copy In data transfer in progress */ - PGRES_BAD_RESPONSE, /* an unexpected response was recv'd from - * the backend */ - PGRES_NONFATAL_ERROR, - PGRES_FATAL_ERROR -} ExecStatusType; - -/* PGconn encapsulates a connection to the backend. - * The contents of this struct are not supposed to be known to applications. - */ -typedef struct pg_conn PGconn; - -/* PGresult encapsulates the result of a query (or more precisely, of a single - * SQL command --- a query string given to PQsendQuery can contain multiple - * commands and thus return multiple PGresult objects). - * The contents of this struct are not supposed to be known to applications. - */ -typedef struct pg_result PGresult; - -/* PGnotify represents the occurrence of a NOTIFY message. - * Ideally this would be an opaque typedef, but it's so simple that it's - * unlikely to change. - * NOTE: in Postgres 6.4 and later, the be_pid is the notifying backend's, - * whereas in earlier versions it was always your own backend's PID. - */ -typedef struct pgNotify -{ - char relname[NAMEDATALEN]; /* name of relation containing - * data */ - int be_pid; /* process id of backend */ -} PGnotify; - -/* PQnoticeProcessor is the function type for the notice-message callback. - */ -typedef void (*PQnoticeProcessor) (void *arg, const char *message); - -/* Print options for PQprint() */ -typedef char pqbool; - -typedef struct _PQprintOpt -{ - pqbool header; /* print output field headings and row - * count */ - pqbool align; /* fill align the fields */ - pqbool standard; /* old brain dead format */ - pqbool html3; /* output html tables */ - pqbool expanded; /* expand tables */ - pqbool pager; /* use pager for output if needed */ - char *fieldSep; /* field separator */ - char *tableOpt; /* insert to HTML */ - char *caption; /* HTML
*/ - char **fieldName; /* null terminated array of repalcement - * field names */ -} PQprintOpt; - -/* ---------------- - * Structure for the conninfo parameter definitions returned by PQconndefaults - * - * All fields except "val" point at static strings which must not be altered. - * "val" is either NULL or a malloc'd current-value string. PQconninfoFree() - * will release both the val strings and the PQconninfoOption array itself. - * ---------------- - */ -typedef struct _PQconninfoOption -{ - char *keyword; /* The keyword of the option */ - char *envvar; /* Fallback environment variable name */ - char *compiled; /* Fallback compiled in default value */ - char *val; /* Option's current value, or NULL */ - char *label; /* Label for field in connect dialog */ - char *dispchar; /* Character to display for this field in - * a connect dialog. Values are: "" - * Display entered value as is "*" - * Password field - hide value "D" Debug - * option - don't show by default */ - int dispsize; /* Field size in characters for dialog */ -} PQconninfoOption; - -/* ---------------- - * PQArgBlock -- structure for PQfn() arguments - * ---------------- - */ -typedef struct -{ - int len; - int isint; - union - { - int *ptr; /* can't use void (dec compiler barfs) */ - int integer; - } u; -} PQArgBlock; - -/* ---------------- - * Exported functions of libpq - * ---------------- - */ - -/* === in fe-connect.c === */ - -/* make a new client connection to the backend */ -/* Asynchronous (non-blocking) */ -extern PGconn *PQconnectStart(const char *conninfo); -extern PostgresPollingStatusType PQconnectPoll(PGconn *conn); - -/* Synchronous (blocking) */ -extern PGconn *PQconnectdb(const char *conninfo); -extern PGconn *PQsetdbLogin(const char *pghost, const char *pgport, - const char *pgoptions, const char *pgtty, - const char *dbName, - const char *login, const char *pwd); - -#define PQsetdb(M_PGHOST,M_PGPORT,M_PGOPT,M_PGTTY,M_DBNAME) \ - PQsetdbLogin(M_PGHOST, M_PGPORT, M_PGOPT, M_PGTTY, M_DBNAME, NULL, NULL) - -/* close the current connection and free the PGconn data structure */ -extern void PQfinish(PGconn *conn); - -/* get info about connection options known to PQconnectdb */ -extern PQconninfoOption *PQconndefaults(void); - -/* free the data structure returned by PQconndefaults() */ -extern void PQconninfoFree(PQconninfoOption *connOptions); - -/* - * close the current connection and restablish a new one with the same - * parameters - */ -/* Asynchronous (non-blocking) */ -extern int PQresetStart(PGconn *conn); -extern PostgresPollingStatusType PQresetPoll(PGconn *conn); - -/* Synchronous (blocking) */ -extern void PQreset(PGconn *conn); - -/* issue a cancel request */ -extern int PQrequestCancel(PGconn *conn); - -/* Accessor functions for PGconn objects */ -extern char *PQdb(const PGconn *conn); -extern char *PQuser(const PGconn *conn); -extern char *PQpass(const PGconn *conn); -extern char *PQhost(const PGconn *conn); -extern char *PQport(const PGconn *conn); -extern char *PQtty(const PGconn *conn); -extern char *PQoptions(const PGconn *conn); -extern ConnStatusType PQstatus(const PGconn *conn); -extern char *PQerrorMessage(const PGconn *conn); -extern int PQsocket(const PGconn *conn); -extern int PQbackendPID(const PGconn *conn); -extern int PQclientEncoding(const PGconn *conn); -extern int PQsetClientEncoding(PGconn *conn, const char *encoding); - -#ifdef USE_SSL -/* Get the SSL structure associated with a connection */ -extern SSL *PQgetssl(PGconn *conn); -#endif - - -/* Enable/disable tracing */ -extern void PQtrace(PGconn *conn, FILE *debug_port); -extern void PQuntrace(PGconn *conn); - -/* Override default notice processor */ -extern PQnoticeProcessor PQsetNoticeProcessor(PGconn *conn, - PQnoticeProcessor proc, - void *arg); - -/* === in fe-exec.c === */ - -/* Quoting strings before inclusion in queries. */ -extern size_t PQescapeString(char *to, const char *from, size_t length); -extern unsigned char *PQescapeBytea(unsigned char *bintext, size_t binlen, - size_t *bytealen); - -/* Simple synchronous query */ -extern PGresult *PQexec(PGconn *conn, const char *query); -extern PGnotify *PQnotifies(PGconn *conn); -extern void PQfreeNotify(PGnotify *notify); - -/* Interface for multiple-result or asynchronous queries */ -extern int PQsendQuery(PGconn *conn, const char *query); -extern PGresult *PQgetResult(PGconn *conn); - -/* Routines for managing an asychronous query */ -extern int PQisBusy(PGconn *conn); -extern int PQconsumeInput(PGconn *conn); - -/* Routines for copy in/out */ -extern int PQgetline(PGconn *conn, char *string, int length); -extern int PQputline(PGconn *conn, const char *string); -extern int PQgetlineAsync(PGconn *conn, char *buffer, int bufsize); -extern int PQputnbytes(PGconn *conn, const char *buffer, int nbytes); -extern int PQendcopy(PGconn *conn); - -/* Set blocking/nonblocking connection to the backend */ -extern int PQsetnonblocking(PGconn *conn, int arg); -extern int PQisnonblocking(const PGconn *conn); - -/* Force the write buffer to be written (or at least try) */ -extern int PQflush(PGconn *conn); - -/* - * "Fast path" interface --- not really recommended for application - * use - */ -extern PGresult *PQfn(PGconn *conn, - int fnid, - int *result_buf, - int *result_len, - int result_is_int, - const PQArgBlock *args, - int nargs); - -/* Accessor functions for PGresult objects */ -extern ExecStatusType PQresultStatus(const PGresult *res); -extern char *PQresStatus(ExecStatusType status); -extern char *PQresultErrorMessage(const PGresult *res); -extern int PQntuples(const PGresult *res); -extern int PQnfields(const PGresult *res); -extern int PQbinaryTuples(const PGresult *res); -extern char *PQfname(const PGresult *res, int field_num); -extern int PQfnumber(const PGresult *res, const char *field_name); -extern Oid PQftype(const PGresult *res, int field_num); -extern int PQfsize(const PGresult *res, int field_num); -extern int PQfmod(const PGresult *res, int field_num); -extern char *PQcmdStatus(PGresult *res); -extern char *PQoidStatus(const PGresult *res); /* old and ugly */ -extern Oid PQoidValue(const PGresult *res); /* new and improved */ -extern char *PQcmdTuples(PGresult *res); -extern char *PQgetvalue(const PGresult *res, int tup_num, int field_num); -extern int PQgetlength(const PGresult *res, int tup_num, int field_num); -extern int PQgetisnull(const PGresult *res, int tup_num, int field_num); - -/* Delete a PGresult */ -extern void PQclear(PGresult *res); - -/* - * Make an empty PGresult with given status (some apps find this - * useful). If conn is not NULL and status indicates an error, the - * conn's errorMessage is copied. - */ -extern PGresult *PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status); - -/* === in fe-print.c === */ - -extern void -PQprint(FILE *fout, /* output stream */ - const PGresult *res, - const PQprintOpt *ps); /* option structure */ - -/* - * really old printing routines - */ -extern void -PQdisplayTuples(const PGresult *res, - FILE *fp, /* where to send the output */ - int fillAlign, /* pad the fields with spaces */ - const char *fieldSep, /* field separator */ - int printHeader, /* display headers? */ - int quiet); - -extern void -PQprintTuples(const PGresult *res, - FILE *fout, /* output stream */ - int printAttName, /* print attribute names */ - int terseOutput, /* delimiter bars */ - int width); /* width of column, if 0, use variable - * width */ - - -/* === in fe-lobj.c === */ - -/* Large-object access routines */ -extern int lo_open(PGconn *conn, Oid lobjId, int mode); -extern int lo_close(PGconn *conn, int fd); -extern int lo_read(PGconn *conn, int fd, char *buf, size_t len); -extern int lo_write(PGconn *conn, int fd, char *buf, size_t len); -extern int lo_lseek(PGconn *conn, int fd, int offset, int whence); -extern Oid lo_creat(PGconn *conn, int mode); -extern int lo_tell(PGconn *conn, int fd); -extern int lo_unlink(PGconn *conn, Oid lobjId); -extern Oid lo_import(PGconn *conn, const char *filename); -extern int lo_export(PGconn *conn, Oid lobjId, const char *filename); - -/* === in fe-misc.c === */ - -/* Determine length of multibyte encoded char at *s */ -extern int PQmblen(const unsigned char *s, int encoding); - -/* Get encoding id from environment variable PGCLIENTENCODING */ -extern int PQenv2encoding(void); - -#ifdef __cplusplus -} -#endif - -#endif /* LIBPQ_FE_H */ diff --git a/netware/libpq.imp b/netware/libpq.imp deleted file mode 100644 index 922679f07ec6..000000000000 --- a/netware/libpq.imp +++ /dev/null @@ -1,93 +0,0 @@ - lo_open, - lo_close, - lo_read, - lo_write, - lo_lseek, - lo_creat, - lo_tell, - lo_unlink, - lo_import, - lo_export, - PQconnectdb, - PQconnectStart, - PQconndefaults, - PQsetdbLogin, - PQconnectPoll, - PQfinish, - PQreset, - PQresetStart, - PQresetPoll, - PQrequestCancel, - PQconninfoFree, - PQdb, - PQuser, - PQpass, - PQhost, - PQport, - PQtty, - PQoptions, - PQstatus, - PQerrorMessage, - PQsocket, - PQbackendPID, - PQclientEncoding, - PQsetClientEncoding, - PQtrace, - PQuntrace, - PQsetNoticeProcessor, - PQmakeEmptyPGresult, - PQclear, - PQsendQuery, - PQconsumeInput, - PQisBusy, - PQgetResult, - PQexec, - PQnotifies, - PQgetline, - PQgetlineAsync, - PQputline, - PQputnbytes, - PQendcopy, - PQfn, - PQresultStatus, - PQresStatus, - PQresultErrorMessage, - PQntuples, - PQnfields, - PQbinaryTuples, - PQfname, - PQfnumber, - PQftype, - PQfsize, - PQfmod, - PQcmdStatus, - PQoidStatus, - PQoidValue, - PQcmdTuples, - PQgetvalue, - PQgetlength, - PQgetisnull, - PQsetnonblocking, - PQisnonblocking, - PQflush, - PQmblen, - PQenv2encoding, - PQprint, - PQdisplayTuples, - PQprintTuples, - pg_valid_client_encoding, - pg_valid_server_encoding, - pg_char_to_encname_struct, - pg_char_to_encoding, - pg_encoding_to_char, - createPQExpBuffer, - initPQExpBuffer, - destroyPQExpBuffer, - termPQExpBuffer, - resetPQExpBuffer, - enlargePQExpBuffer, - printfPQExpBuffer, - appendPQExpBuffer, - appendPQExpBufferStr, - appendPQExpBufferChar, - appendBinaryPQExpBuffer diff --git a/netware/libpq/libpq-fs.h b/netware/libpq/libpq-fs.h deleted file mode 100644 index d7436188951f..000000000000 --- a/netware/libpq/libpq-fs.h +++ /dev/null @@ -1,24 +0,0 @@ -/*------------------------------------------------------------------------- - * - * libpq-fs.h - * definitions for using Inversion file system routines (ie, large objects) - * - * - * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * $Id$ - * - *------------------------------------------------------------------------- - */ -#ifndef LIBPQ_FS_H -#define LIBPQ_FS_H - -/* - * Read/write mode flags for inversion (large object) calls - */ - -#define INV_WRITE 0x00020000 -#define INV_READ 0x00040000 - -#endif /* LIBPQ_FS_H */ diff --git a/netware/mktemp.c b/netware/mktemp.c deleted file mode 100644 index b6d8e9259353..000000000000 --- a/netware/mktemp.c +++ /dev/null @@ -1,87 +0,0 @@ - -#include -#include -#include - - -/* Based on standard ANSI C mktemp() for NetWare */ -char* mktemp(char* templateStr) -{ - char* pXs = NULL; - char numBuf[50] = {'\0'}; - int count = 0; - char* pPid = NULL; - - char termChar = '\0'; - char letter = 'a'; - char letter1 = 'a'; - - if (templateStr && (pXs = strstr(templateStr, "XXXXXX"))) - { - /* Generate temp name */ - termChar = pXs[6]; - ltoa(NXThreadGetId(), numBuf, 16); - numBuf[strlen(numBuf)-1] = '\0'; - - /* - Beware! thread IDs are 8 hex digits on NW 4.11 and only the - lower digits seem to change, whereas on NW 5 they are in the - range of < 1000 hex or 3 hex digits in length. So the following - logic ensures we use the least significant portion of the number.\ - */ - if (strlen(numBuf) > 5) - pPid = &numBuf[strlen(numBuf)-5]; - else - pPid = numBuf; - - /* - Temporary files, as the name suggests, are temporarily used and then - cleaned up after usage. In the case of complex scripts, new temp files - may be created before the old ones are deleted. So, we need to have - a provision to create many temp files. It is found that provision for - 26 files may not be enough in such cases. Hence the logic below. - - The logic below allows 26 files (like, pla00015.tmp through plz00015.tmp) - plus 6x26=676 (like, plaa0015.tmp through plzz0015.tmp) - */ - letter = 'a'; - do - { - sprintf(pXs, (char *)"%c%05.5s", letter, pPid); - pXs[6] = termChar; - - if (access(templateStr, 0) != 0) - return templateStr; /* File does not exist */ - - letter++; - } while (letter <= 'z'); - - letter1 = 'a'; - do - { - letter = 'a'; - - do - { - sprintf(pXs, (char *)"%c%c%04.5s", letter1, letter, pPid); - pXs[6] = termChar; - - if (access(templateStr, 0) != 0) - return templateStr; /* File does not exist */ - - letter++; - } while (letter <= 'z'); - - letter1++; - } while (letter1 <= 'z'); - - errno = ENOENT; - return NULL; - } - else - { - errno = EINVAL; - return NULL; - } -} - diff --git a/netware/mktemp.h b/netware/mktemp.h deleted file mode 100644 index b37043824683..000000000000 --- a/netware/mktemp.h +++ /dev/null @@ -1 +0,0 @@ -char* mktemp(char* templateStr); diff --git a/netware/param.h b/netware/param.h deleted file mode 100644 index aa879d035f27..000000000000 --- a/netware/param.h +++ /dev/null @@ -1,20 +0,0 @@ - -/***************************************************************************** - * * - * sys/param.c * - * * - * Freely redistributable and modifiable. Use at your own risk. * - * * - * Copyright 1994 The Downhill Project * - * * - *****************************************************************************/ -#ifndef MAXPATHLEN -/*#define MAXPATHLEN _MAX_PATH*/ -#define MAXPATHLEN 260 /* _MAX_PATH defined in STDLIB.H for Windows; picked up the value from there */ -#define _MAX_PATH 260 /* Defined since it is used in os.c while compiling apache */ -#endif -#define MAXHOSTNAMELEN 64 -#define howmany(x,y) (((x)+((y)-1))/(y)) -#define roundup(x,y) ((((x)+((y)-1))/(y))*(y)) - -#define _MAX_VOLUME 31 /* Defined since it is used in os.c while compiling apache. The value picked up from LibC */ diff --git a/netware/php-nw.bat b/netware/php-nw.bat deleted file mode 100755 index 3d2b59d8a85c..000000000000 --- a/netware/php-nw.bat +++ /dev/null @@ -1,10 +0,0 @@ -@echo off - -REM CodeWarrior stuff -set path=%path%;P:\APPS\SCRIPT\SW\CW71-4\BIN - -REM Tools for building Zend -set path=%path%;P:\APPS\SCRIPT\SW\GNUWIN32\BIN - -REM Build options -setbuild r 1 diff --git a/netware/php5apache.mak b/netware/php5apache.mak deleted file mode 100644 index d7d9342b139e..000000000000 --- a/netware/php5apache.mak +++ /dev/null @@ -1,165 +0,0 @@ -# Temporarily here -- later may go into some batch file -# which will set this as an environment variable -PROJECT_ROOT = ../.. - -# Module details -MODULE_NAME = mod_php -MODULE_DESC = "PHP 5 - Apache 1.3 Module" -VMAJ = 3 -VMIN = 0 -VREV = 0 - -#include the common settings -include $(PROJECT_ROOT)/netware/common.mif - -# Extensions of all input and output files -.SUFFIXES: -.SUFFIXES: .nlm .lib .obj .cpp .c .msg .mlc .mdb .xdc .d - -# Source files -C_SRC = mod_php5.c \ - php_apache.c \ - sapi_apache.c \ - libpre.c - -# Destination directories and files -OBJ_DIR = $(BUILD) -FINAL_DIR = $(BUILD) -MAP_FILE = $(FINAL_DIR)\$(MODULE_NAME).map -OBJECTS = $(addprefix $(OBJ_DIR)/,$(CPP_SRC:.cpp=.obj) $(C_SRC:.c=.obj)) -DEPDS = $(addprefix $(OBJ_DIR)/,$(CPP_SRC:.cpp=.d) $(C_SRC:.c=.d)) - -# Binary file -ifndef BINARY -BINARY=$(FINAL_DIR)\$(MODULE_NAME).nlm -endif - - -# Compile flags -C_FLAGS = -c -maxerrors 25 -msgstyle gcc -C_FLAGS += -wchar_t on -bool on -C_FLAGS += -processor Pentium -C_FLAGS += -w nounusedarg -msext on -C_FLAGS += -nostdinc -C_FLAGS += -relax_pointers # To remove type-casting errors -C_FLAGS += -DNETWARE -C_FLAGS += -DZTS -C_FLAGS += -DNLM_PLATFORM -C_FLAGS += -DN_PLAT_NLM -DNLM=1 -D__NO_MATH_OPS -C_FLAGS += -D__C9X_CMATH_INLINES_DEFINED -DAPACHE_OS_H -DNO_USE_SIGACTION -DMULTITHREAD -C_FLAGS += -DCLIB_STAT_PATCH -C_FLAGS += -DNEW_LIBC -C_FLAGS += -I. -I- -I. -I../../netware -I$(SDK_DIR)/include # ../../netware added for special SYS/STAT.H -C_FLAGS += -I$(MWCIncludes) -C_FLAGS += -I$(APACHE_DIR)/include -I$(APACHE_DIR)/os/netware -C_FLAGS += -I- -I../../main -I../../Zend -I../../TSRM -I../../ext/standard -C_FLAGS += -I../../ -I../../netware -I$(PROJECT_ROOT)/regex -C_FLAGS += -I$(WINSOCK_DIR)/include/nlm -I$(WINSOCK_DIR)/include - - -# Extra stuff based on debug / release builds -ifeq '$(BUILD)' 'debug' - SYM_FILE = $(FINAL_DIR)\$(MODULE_NAME).sym - C_FLAGS += -inline smart -sym on -sym codeview4 -opt off -opt intrinsics -sym internal -DDEBUGGING -DDKFBPON - C_FLAGS += -r -DZEND_DEBUG=1 - C_FLAGS += -exc cw - LD_FLAGS += -sym on -sym codeview4 -sym internal -osym $(SYM_FILE) - LD_FLAGS += -msgstyle std - export MWLibraryFiles=$(SDK_DIR)/imports/libcpre.o;mwcrtld.lib -else - C_FLAGS += -opt speed -inline on -inline smart -inline auto -sym off -DZEND_DEBUG=0 - C_FLAGS += -opt intrinsics - C_FLAGS += -opt level=4 - LD_FLAGS += -sym off - export MWLibraryFiles=$(SDK_DIR)/imports/libcpre.o;mwcrtl.lib -endif - -# Dependencies -MODULE = LibC \ - phplib -IMPORT = @$(SDK_DIR)/imports/libc.imp \ - @$(PROJECT_ROOT)/netware/apachecore.imp \ - @$(PROJECT_ROOT)/netware/phplib.imp -EXPORT = php5_module - - -# Virtual paths -vpath %.cpp . -vpath %.c . -vpath %.obj $(OBJ_DIR) - - -all: prebuild project - -.PHONY: all - -prebuild: - @if not exist $(OBJ_DIR) md $(OBJ_DIR) - -project: $(BINARY) $(MESSAGE) - @echo Build complete. - - -$(OBJ_DIR)/%.d: %.c - @echo Building Dependencies for $( $(basename $@).def -ifdef API - @echo Import $(API) >> $(basename $@).def -endif - @echo Module $(MODULE) >> $(basename $@).def -ifdef EXPORT - @echo Export $(EXPORT) >> $(basename $@).def -endif - @echo AutoUnload >> $(basename $@).def -ifeq '$(BUILD)' 'debug' - @echo Debug >> $(basename $@).def -endif - @echo Flag_On 0x00000008 >> $(basename $@).def - @echo Start _lib_start >> $(basename $@).def - @echo Exit _lib_stop >> $(basename $@).def - - $(MPKTOOL) $(XDCFLAGS) $(basename $@).xdc - @echo xdcdata $(basename $@).xdc >> $(basename $@).def - - @echo Linking $@... - @echo $(LD_FLAGS) -commandfile $(basename $@).def > $(basename $@).link -ifdef LIBRARY - @echo $(LIBRARY) >> $(basename $@).link -endif - @echo $(OBJECTS) >> $(basename $@).link - - @$(LINK) @$(basename $@).link - - -.PHONY: clean -clean: cleanobj cleanbin - -.PHONY: cleand -cleand: - @echo Deleting all dependency files... - -@del "$(OBJ_DIR)\*.d" - -.PHONY: cleanobj -cleanobj: - @echo Deleting all object files... - -@del "$(OBJ_DIR)\*.obj" - -.PHONY: cleanbin -cleanbin: - @echo Deleting binary files... - -@del "$(FINAL_DIR)\$(MODULE_NAME).nlm" - @echo Deleting MAP, DEF files, etc.... - -@del "$(FINAL_DIR)\$(MODULE_NAME).map" - -@del "$(FINAL_DIR)\$(MODULE_NAME).def" - -@del "$(FINAL_DIR)\$(MODULE_NAME).link" -ifeq '$(BUILD)' 'debug' - -@del $(FINAL_DIR)\$(MODULE_NAME).sym -endif diff --git a/netware/php5apache2filter.mak b/netware/php5apache2filter.mak deleted file mode 100644 index 7cc1a29192c4..000000000000 --- a/netware/php5apache2filter.mak +++ /dev/null @@ -1,166 +0,0 @@ -# Temporarily here -- later may go into some batch file -# which will set this as an environment variable -PROJECT_ROOT = ../.. - -# Module details -MODULE_NAME = mod_php -MODULE_DESC = "PHP 5 - Apache 2.0 Module" -VMAJ = 3 -VMIN = 0 -VREV = 0 - -#include the common settings -include $(PROJECT_ROOT)/netware/common.mif - -# Extensions of all input and output files -.SUFFIXES: -.SUFFIXES: .nlm .lib .obj .cpp .c .msg .mlc .mdb .xdc .d - -# Source files -C_SRC = apache_config.c \ - php_functions.c \ - sapi_apache2.c - -# Destination directories and files -OBJ_DIR = $(BUILD) -FINAL_DIR = $(BUILD) -MAP_FILE = $(FINAL_DIR)\$(MODULE_NAME).map -OBJECTS = $(addprefix $(OBJ_DIR)/,$(CPP_SRC:.cpp=.obj) $(C_SRC:.c=.obj)) -DEPDS = $(addprefix $(OBJ_DIR)/,$(CPP_SRC:.cpp=.d) $(C_SRC:.c=.d)) - -# Binary file -ifndef BINARY -BINARY=$(FINAL_DIR)\$(MODULE_NAME).nlm -endif - - -# Compile flags -C_FLAGS += -c -maxerrors 25 -msgstyle gcc -C_FLAGS += -wchar_t on -bool on -C_FLAGS += -processor Pentium -C_FLAGS += -w nounusedarg -msext on -C_FLAGS += -nostdinc -C_FLAGS += -relax_pointers # To remove type-casting errors -C_FLAGS += -DNETWARE -C_FLAGS += -DZTS -C_FLAGS += -DNLM_PLATFORM -C_FLAGS += -DN_PLAT_NLM -DNLM=1 -D__NO_MATH_OPS -C_FLAGS += -D__C9X_CMATH_INLINES_DEFINED -DAPACHE_OS_H -DNO_USE_SIGACTION -DMULTITHREAD -C_FLAGS += -DCLIB_STAT_PATCH -C_FLAGS += -DNEW_LIBC -C_FLAGS += -I. -I- -I. -I../../netware -I$(SDK_DIR)/include # ../../netware added for special SYS/STAT.H -C_FLAGS += -I$(SDK_DIR)/include/winsock # For Apache 2.0 headers -C_FLAGS += -I$(MWCIncludes) -C_FLAGS += -I$(APACHE_DIR)/include -C_FLAGS += -I- -I../../main -I../../Zend -I../../TSRM -I../../ext/standard -C_FLAGS += -I../../ -I../../netware -I$(PROJECT_ROOT)/regex -C_FLAGS += -I$(WINSOCK_DIR)/include/nlm -I$(WINSOCK_DIR)/include - - -# Extra stuff based on debug / release builds -ifeq '$(BUILD)' 'debug' - SYM_FILE = $(FINAL_DIR)\$(MODULE_NAME).sym - C_FLAGS += -inline smart -sym on -sym codeview4 -opt off -opt intrinsics -sym internal -DDEBUGGING -DDKFBPON - C_FLAGS += -r -DZEND_DEBUG=1 - C_FLAGS += -exc cw - LD_FLAGS += -sym on -sym codeview4 -sym internal -osym $(SYM_FILE) - LD_FLAGS += -msgstyle std - export MWLibraryFiles=$(SDK_DIR)/imports/libcpre.o;mwcrtld.lib -else - C_FLAGS += -opt speed -inline on -inline smart -inline auto -sym off -DZEND_DEBUG=0 - C_FLAGS += -opt intrinsics - C_FLAGS += -opt level=4 - LD_FLAGS += -sym off - export MWLibraryFiles=$(SDK_DIR)/imports/libcpre.o;mwcrtl.lib -endif - -# Dependencies -MODULE = LibC \ - phplib -IMPORT = @$(SDK_DIR)/imports/libc.imp \ - @$(APACHE_DIR)/lib/httpd.imp \ - @$(APACHE_DIR)/lib/aprlib.imp \ - @$(PROJECT_ROOT)/netware/phplib.imp -EXPORT = php5_module - - -# Virtual paths -vpath %.cpp . -vpath %.c . -vpath %.obj $(OBJ_DIR) - - -all: prebuild project - -.PHONY: all - -prebuild: - @if not exist $(OBJ_DIR) md $(OBJ_DIR) - -project: $(BINARY) $(MESSAGE) - @echo Build complete. - - -$(OBJ_DIR)/%.d: %.c - @echo Building Dependencies for $( $(basename $@).def -ifdef API - @echo Import $(API) >> $(basename $@).def -endif - @echo Module $(MODULE) >> $(basename $@).def -ifdef EXPORT - @echo Export $(EXPORT) >> $(basename $@).def -endif - @echo AutoUnload >> $(basename $@).def -ifeq '$(BUILD)' 'debug' - @echo Debug >> $(basename $@).def -endif - @echo Flag_On 0x00000008 >> $(basename $@).def - @echo Start _lib_start >> $(basename $@).def - @echo Exit _lib_stop >> $(basename $@).def - - $(MPKTOOL) $(XDCFLAGS) $(basename $@).xdc - @echo xdcdata $(basename $@).xdc >> $(basename $@).def - - @echo Linking $@... - @echo $(LD_FLAGS) -commandfile $(basename $@).def > $(basename $@).link -ifdef LIBRARY - @echo $(LIBRARY) >> $(basename $@).link -endif - @echo $(OBJECTS) $(APACHE_DIR)/lib/libpre.obj >> $(basename $@).link - - @$(LINK) @$(basename $@).link - - -.PHONY: clean -clean: cleanobj cleanbin - -.PHONY: cleand -cleand: - @echo Deleting all dependency files... - -@del "$(OBJ_DIR)\*.d" - -.PHONY: cleanobj -cleanobj: - @echo Deleting all object files... - -@del "$(OBJ_DIR)\*.obj" - -.PHONY: cleanbin -cleanbin: - @echo Deleting binary files... - -@del "$(FINAL_DIR)\$(MODULE_NAME).nlm" - @echo Deleting MAP, DEF files, etc.... - -@del "$(FINAL_DIR)\$(MODULE_NAME).map" - -@del "$(FINAL_DIR)\$(MODULE_NAME).def" - -@del "$(FINAL_DIR)\$(MODULE_NAME).link" -ifeq '$(BUILD)' 'debug' - -@del $(FINAL_DIR)\$(MODULE_NAME).sym -endif diff --git a/netware/php5cli.mak b/netware/php5cli.mak deleted file mode 100644 index 30a1896f20eb..000000000000 --- a/netware/php5cli.mak +++ /dev/null @@ -1,163 +0,0 @@ -# Temporarily here -- later may go into some batch file -# which will set this as an environment variable -PROJECT_ROOT = ../.. - -# Module details -MODULE_NAME = php -MODULE_DESC = "PHP 5 - Command Line Interface" -VMAJ = 2 -VMIN = 0 -VREV = 0 - -#include the common settings -include $(PROJECT_ROOT)/netware/common.mif - -# Extensions of all input and output files -.SUFFIXES: -.SUFFIXES: .nlm .lib .obj .cpp .c .msg .mlc .mdb .xdc .d - -# Source files -C_SRC = getopt.c \ - php_cli.c - -# Library files -LIBRARY = - -# Destination directories and files -OBJ_DIR = $(BUILD) -FINAL_DIR = $(BUILD) -MAP_FILE = $(FINAL_DIR)\$(MODULE_NAME).map -OBJECTS = $(addprefix $(OBJ_DIR)/,$(CPP_SRC:.cpp=.obj) $(C_SRC:.c=.obj)) -DEPDS = $(addprefix $(OBJ_DIR)/,$(CPP_SRC:.cpp=.d) $(C_SRC:.c=.d)) - -# Binary file -ifndef BINARY - BINARY=$(FINAL_DIR)\$(MODULE_NAME).nlm -endif - - -# Compile flags -C_FLAGS += -c -maxerrors 25 -msgstyle gcc -C_FLAGS += -wchar_t on -bool on -C_FLAGS += -processor Pentium -C_FLAGS += -w nounusedarg -msext on -C_FLAGS += -nostdinc -C_FLAGS += -relax_pointers # To remove type-casting errors -C_FLAGS += -DNETWARE -DTHREAD_SWITCH -C_FLAGS += -DZTS -C_FLAGS += -DNLM_PLATFORM -C_FLAGS += -DN_PLAT_NLM -DNLM=1 -D__NO_MATH_OPS -C_FLAGS += -D__C9X_CMATH_INLINES_DEFINED -DAPACHE_OS_H -DNO_USE_SIGACTION -DMULTITHREAD -C_FLAGS += -DNEW_LIBC -C_FLAGS += -I. -I- -I. -I../../netware -I$(SDK_DIR)/include # ../../netware added for special SYS/STAT.H -C_FLAGS += -I$(MWCIncludes) -C_FLAGS += -I- -I../../main -I../../Zend -I../../TSRM -I../../ext/standard -C_FLAGS += -I../../ -I../../netware -I$(PROJECT_ROOT)/regex -C_FLAGS += -I$(WINSOCK_DIR)/include/nlm -I$(WINSOCK_DIR)/include - -# Extra stuff based on debug / release builds -ifeq '$(BUILD)' 'debug' - SYM_FILE = $(FINAL_DIR)\$(MODULE_NAME).sym - C_FLAGS += -inline smart -sym on -sym codeview4 -opt off -opt intrinsics -sym internal -DDEBUGGING -DDKFBPON - C_FLAGS += -r -DZEND_DEBUG=1 - C_FLAGS += -exc cw - LD_FLAGS += -sym on -sym codeview4 -sym internal -osym $(SYM_FILE) - export MWLibraryFiles=$(SDK_DIR)/imports/libcpre.o;mwcrtld.lib -else - C_FLAGS += -opt speed -inline on -inline smart -inline auto -sym off -DZEND_DEBUG=0 - C_FLAGS += -opt intrinsics - C_FLAGS += -opt level=4 - LD_FLAGS += -sym off - export MWLibraryFiles=$(SDK_DIR)/imports/libcpre.o;mwcrtl.lib -endif - - -# Dependencies -MODULE = LibC \ - phplib -IMPORT = @$(SDK_DIR)/imports/libc.imp \ - @$(PROJECT_ROOT)/netware/phplib.imp -EXPORT = -API = - - -# Virtual paths -vpath %.cpp . -vpath %.c . -vpath %.obj $(OBJ_DIR) - - -all: prebuild project - -.PHONY: all - -prebuild: - @if not exist $(OBJ_DIR) md $(OBJ_DIR) - -project: $(BINARY) $(MESSAGE) - @echo Build complete. - - -$(OBJ_DIR)/%.d: %.c - @echo Building Dependencies for $( $(basename $@).def -ifdef API - @echo Import $(API) >> $(basename $@).def -endif - @echo Module $(MODULE) >> $(basename $@).def -ifdef EXPORT - @echo Export $(EXPORT) >> $(basename $@).def -endif - @echo AutoUnload >> $(basename $@).def -ifeq '$(BUILD)' 'debug' - @echo Debug >> $(basename $@).def -endif - @echo Flag_On 0x00000008 >> $(basename $@).def - @echo Start _LibCPrelude >> $(basename $@).def - @echo Exit _LibCPostlude >> $(basename $@).def - - $(MPKTOOL) $(XDCFLAGS) $(basename $@).xdc - @echo xdcdata $(basename $@).xdc >> $(basename $@).def - - @echo Linking $@... - @echo $(LD_FLAGS) -commandfile $(basename $@).def > $(basename $@).link -ifdef LIBRARY - @echo $(LIBRARY) >> $(basename $@).link -endif - @echo $(OBJECTS) >> $(basename $@).link - - @$(LINK) @$(basename $@).link - - -.PHONY: clean -clean: cleanobj cleanbin - -.PHONY: cleand -cleand: - @echo Deleting all dependency files... - -@del "$(OBJ_DIR)\*.d" - -.PHONY: cleanobj -cleanobj: - @echo Deleting all object files... - -@del "$(OBJ_DIR)\*.obj" - -.PHONY: cleanbin -cleanbin: - @echo Deleting binary files... - -@del "$(FINAL_DIR)\$(MODULE_NAME).nlm" - @echo Deleting MAP, DEF files, etc.... - -@del "$(FINAL_DIR)\$(MODULE_NAME).map" - -@del "$(FINAL_DIR)\$(MODULE_NAME).def" - -@del "$(FINAL_DIR)\$(MODULE_NAME).link" -ifeq '$(BUILD)' 'debug' - -@del $(FINAL_DIR)\$(MODULE_NAME).sym -endif diff --git a/netware/phplib.imp b/netware/phplib.imp deleted file mode 100644 index d1ecedc982b7..000000000000 --- a/netware/phplib.imp +++ /dev/null @@ -1,177 +0,0 @@ -_array_init, -_convert_to_string, -_ecalloc, -_efree, -_emalloc, -_erealloc, -_estrdup, -_estrndup, -_object_and_properties_init, -_object_init, -_object_init_ex, -_php_stream_cast, -_php_stream_free, -_php_stream_open_wrapper_ex, -_zend_get_parameters_array, -_zend_get_parameters_array_ex, -_zend_list_addref, -_zend_list_delete, -_zend_list_find, -_zval_copy_ctor, -_zval_dtor, -_zval_ptr_dtor, -add_assoc_bool_ex, -add_assoc_long_ex, -add_assoc_zval_ex, -add_index_null, -add_index_long, -add_index_zval, -add_assoc_string_ex, -add_assoc_stringl_ex, -add_assoc_null_ex, -add_index_string, -add_index_stringl, -add_next_index_bool, -add_next_index_long, -add_next_index_string, -add_next_index_stringl, -add_next_index_zval, -add_property_long_ex, -add_property_string_ex, -call_user_function, -compiler_globals_id, -convert_to_boolean, -convert_to_array, -convert_to_double, -convert_to_long, -core_globals_id, -display_ini_entries, -display_link_numbers, -empty_string, -executor_globals_id, -expand_filepath, -get_zend_version, -get_active_function_name, -highlight_file, -le_index_ptr, -module_registry, -multi_convert_to_long_ex, -open_file_for_scanning, -php_addslashes, -php_check_open_basedir, -php_checkuid, -php_execute_script, -php_fopen_primary_script, -php_handle_aborted_connection, -php_handle_special_queries, -php_body_write, -php_end_ob_buffers, -php_error_docref0, -php_get_current_user, -php_get_highlight_struct, -php_handle_auth_data, -php_header, -php_header_write, -php_import_environment_variables, -php_info_print_table_end, -php_info_print_table_colspan_header, -php_info_print_table_header, -php_info_print_table_row, -php_info_print_table_start, -php_lint_script, -php_log_err, -php_module_shutdown, -php_module_shutdown_for_exec, -php_module_shutdown_wrapper, -php_module_startup, -php_ob_set_internal_handler, -php_output_activate, -php_output_set_status, -php_output_startup, -php_print_info, -php_printf, -php_regcomp, -php_regexec, -php_regfree, -php_register_variable, -php_request_shutdown, -php_request_shutdown_for_exec, -php_request_startup, -php_sig_gif, -php_sig_jpg, -php_sig_png, -php_start_ob_buffer, -php_strip_tags, -php_strip_url_passwd, -php_stripslashes, -php_strlcpy, -php_strtolower, -php_strtoupper, -php_write, -sapi_add_header_ex, -sapi_free_header, -sapi_get_default_content_type, -sapi_globals_id, -sapi_shutdown, -sapi_startup, -second_arg_force_ref, -ts_allocate_id, -ts_resource_ex, -tsrm_shutdown, -tsrm_startup, -virtual_filepath, -virtual_fopen, -zend_alter_ini_entry, -zend_error, -zend_eval_string, -zend_execute_scripts, -zend_extensions, -zend_fetch_resource, -zend_get_parameters_ex, -zend_hash_add_or_update, -zend_hash_apply, -zend_hash_apply_with_argument, -zend_hash_clean, -zend_hash_del_key_or_index, -zend_hash_destroy, -zend_hash_exists, -zend_hash_find, -zend_hash_get_current_key_ex, -zend_hash_get_current_data_ex, -zend_hash_index_find, -zend_hash_index_update_or_next_insert, -zend_hash_init, -zend_hash_init_ex, -zend_hash_internal_pointer_reset_ex -zend_hash_merge_ex, -zend_hash_move_forward_ex, -zend_hash_num_elements, -zend_highlight, -zend_ini_deactivate, -zend_ini_boolean_displayer_cb, -zend_ini_string, -zend_list_insert, -zend_llist_add_element, -zend_llist_apply, -zend_llist_apply_with_argument, -zend_llist_destroy, -zend_llist_init, -zend_load_extension, -zend_parse_parameters, -zend_parse_parameters_ex, -zend_printf, -zend_register_ini_entries, -zend_register_internal_class, -zend_register_list_destructors_ex, -zend_register_long_constant, -zend_register_resource, -zend_startup_module, -zend_standard_class_def, -zend_strip, -zend_unregister_ini_entries, -zend_wrong_param_count, -zval_add_ref, -OnUpdateBool, -OnUpdateLong, -OnUpdateString, -OnUpdateStringUnempty diff --git a/netware/phplib.mak b/netware/phplib.mak deleted file mode 100644 index 90b6e674274b..000000000000 --- a/netware/phplib.mak +++ /dev/null @@ -1,404 +0,0 @@ -# Temporarily here -- later may go into some batch file -# which will set this as an environment variable -PROJECT_ROOT = . - -# Module details -MODULE_NAME = phplib -MODULE_DESC = "PHP 5 - Script Interpreter and Library" -VMAJ = 3 -VMIN = 0 -VREV = 0 - -#include the common settings -include $(PROJECT_ROOT)/netware/common.mif - - -# Extensions of all input and output files -.SUFFIXES: -.SUFFIXES: .nlm .lib .obj .cpp .c .msg .mlc .mdb .xdc .d - -# Source files -C_SRC = ext/bcmath/bcmath.c \ - ext/bcmath/libbcmath/src/add.c \ - ext/bcmath/libbcmath/src/compare.c \ - ext/bcmath/libbcmath/src/debug.c \ - ext/bcmath/libbcmath/src/div.c \ - ext/bcmath/libbcmath/src/divmod.c \ - ext/bcmath/libbcmath/src/doaddsub.c \ - ext/bcmath/libbcmath/src/init.c \ - ext/bcmath/libbcmath/src/int2num.c \ - ext/bcmath/libbcmath/src/nearzero.c \ - ext/bcmath/libbcmath/src/neg.c \ - ext/bcmath/libbcmath/src/num2long.c \ - ext/bcmath/libbcmath/src/num2str.c \ - ext/bcmath/libbcmath/src/outofmem.c \ - ext/bcmath/libbcmath/src/output.c \ - ext/bcmath/libbcmath/src/raise.c \ - ext/bcmath/libbcmath/src/raisemod.c \ - ext/bcmath/libbcmath/src/recmul.c \ - ext/bcmath/libbcmath/src/rmzero.c \ - ext/bcmath/libbcmath/src/rt.c \ - ext/bcmath/libbcmath/src/sqrt.c \ - ext/bcmath/libbcmath/src/str2num.c \ - ext/bcmath/libbcmath/src/sub.c \ - ext/bcmath/libbcmath/src/zero.c \ - ext/calendar/cal_unix.c \ - ext/calendar/calendar.c \ - ext/calendar/dow.c \ - ext/calendar/easter.c \ - ext/calendar/french.c \ - ext/calendar/gregor.c \ - ext/calendar/jewish.c \ - ext/calendar/julian.c \ - ext/ftp/ftp.c \ - ext/ftp/php_ftp.c \ - ext/mcal/php_mcal.c \ - ext/pcre/php_pcre.c \ - ext/pcre/pcrelib/chartables.c \ - ext/pcre/pcrelib/get.c \ - ext/pcre/pcrelib/maketables.c \ - ext/pcre/pcrelib/pcre.c \ - ext/pcre/pcrelib/pcreposix.c \ - ext/pcre/pcrelib/study.c \ - ext/session/mod_files.c \ - ext/session/mod_mm.c \ - ext/session/mod_user.c \ - ext/session/session.c \ - ext/snmp/snmp.c \ - ext/standard/aggregation.c \ - ext/standard/array.c \ - ext/standard/assert.c \ - ext/standard/base64.c \ - ext/standard/basic_functions.c \ - ext/standard/browscap.c \ - ext/standard/crc32.c \ - ext/standard/credits.c \ - ext/standard/css.c \ - ext/standard/cyr_convert.c \ - ext/standard/datetime.c \ - ext/standard/dir.c \ - ext/standard/dl.c \ - ext/standard/dns.c \ - ext/standard/exec.c \ - ext/standard/file.c \ - ext/standard/filestat.c \ - ext/standard/filters.c \ - ext/standard/flock_compat.c \ - ext/standard/formatted_print.c \ - ext/standard/fsock.c \ - ext/standard/ftok.c \ - ext/standard/ftp_fopen_wrapper.c \ - ext/standard/head.c \ - ext/standard/html.c \ - ext/standard/http_fopen_wrapper.c \ - ext/standard/image.c \ - ext/standard/incomplete_class.c \ - ext/standard/info.c \ - ext/standard/iptc.c \ - ext/standard/lcg.c \ - ext/standard/levenshtein.c \ - ext/standard/link.c \ - ext/standard/mail.c \ - ext/standard/math.c \ - ext/standard/md5.c \ - ext/standard/metaphone.c \ - ext/standard/microtime.c \ - ext/standard/pack.c \ - ext/standard/pageinfo.c \ - ext/standard/parsedate.c \ - ext/standard/php_fopen_wrapper.c \ - ext/standard/quot_print.c \ - ext/standard/rand.c \ - ext/standard/reg.c \ - ext/standard/scanf.c \ - ext/standard/sha1.c \ - ext/standard/soundex.c \ - ext/standard/string.c \ - ext/standard/strnatcmp.c \ - ext/standard/type.c \ - ext/standard/uniqid.c \ - ext/standard/url.c \ - ext/standard/url_scanner.c \ - ext/standard/url_scanner_ex.c \ - ext/standard/user_filters.c \ - ext/standard/var.c \ - ext/standard/var_unserializer.c \ - ext/standard/versioning.c \ - main/fopen_wrappers.c \ - main/internal_functions_nw.c \ - main/main.c \ - main/memory_streams.c \ - main/mergesort.c \ - main/network.c \ - main/output.c \ - main/php_content_types.c \ - main/php_ini.c \ - main/php_logos.c \ - main/php_open_temporary_file.c \ - main/php_sprintf.c \ - main/php_ticks.c \ - main/php_variables.c \ - main/reentrancy.c \ - main/rfc1867.c \ - main/safe_mode.c \ - main/SAPI.c \ - main/snprintf.c \ - main/spprintf.c \ - main/streams.c \ - main/strlcat.c \ - main/strlcpy.c \ - main/user_streams.c \ - netware/geterrnoptr.c \ - netware/mktemp.c \ - netware/pipe.c \ - netware/pwd.c \ - netware/start.c \ - netware/time_nw.c \ - netware/wfile.c \ - regex/regcomp.c \ - regex/regerror.c \ - regex/regexec.c \ - regex/regfree.c \ -# ext/standard/crypt.c \ -# ext/com/COM.c \ -# ext/com/conversion.c \ -# ext/odbc/php_odbc.c \ -# ext/snmp/winsnmp.c \ -# netware/winutil.c \ -# netware/registry.c \ -# main/alloca.c \ -# ext/wddx/wddx.c \ -# netware/readdir.c \ - -WIN32_C_SRC = sendmail.c \ - - -CPP_SRC_NODIR = $(notdir $(CPP_SRC)) -C_SRC_NODIR = $(notdir $(C_SRC)) -SRC_DIR = $(dir $(CPP_SRC) $(C_SRC)) - -# Library files -LIBRARY = $(PROJECT_ROOT)/Zend/$(BUILD)/Zend.lib $(PROJECT_ROOT)/TSRM/$(BUILD)/TSRM.lib - -# Destination directories and files -OBJ_DIR = $(BUILD) -FINAL_DIR = $(BUILD) -MAP_FILE = $(FINAL_DIR)\$(MODULE_NAME).map -OBJECTS = $(join $(SRC_DIR), $(addprefix $(OBJ_DIR)/,$(CPP_SRC_NODIR:.c=.obj) $(C_SRC_NODIR:.c=.obj))) -WIN32_OBJECTS = $(addprefix $(OBJ_DIR)/,$(WIN32_C_SRC:.c=.obj)) -DEPDS = $(join $(SRC_DIR), $(addprefix $(OBJ_DIR)/,$(CPP_SRC_NODIR:.c=.d) $(C_SRC_NODIR:.c=.d))) - -# Binary file -ifndef BINARY - BINARY=$(FINAL_DIR)\$(MODULE_NAME).nlm -endif - -# Compile flags -C_FLAGS += -c -maxerrors 25 -msgstyle gcc -C_FLAGS += -wchar_t on -bool on -C_FLAGS += -relax_pointers # To remove type-casting errors -C_FLAGS += -processor Pentium -C_FLAGS += -nostdinc -nosyspath -C_FLAGS += -DNETWARE -D__BIT_TYPES_DEFINED__ -DZTS -C_FLAGS += -DPHP5DLLTS_EXPORTS -DPHP_EXPORTS -DLIBZEND_EXPORTS -DTSRM_EXPORTS -DSAPI_EXPORTS -C_FLAGS += -DHAVE_SYS_TIME_H -DHAVE_STRUCT_FLOCK -DVIRTUAL_DIR -DHAVE_TZNAME -C_FLAGS += -DHAVE_DLFCN_H -DHAVE_LIBDL -C_FLAGS += -DCLIB_STAT_PATCH # stat patch -C_FLAGS += -DNEW_LIBC -DHAVE_ARPA_INET_H=1 -DHAVE_NETINET_IN_H=1 -DHAVE_INET_ATON=1 - -C_FLAGS += -DLINK_SIZE=2 # Added for the new definition in ext\pcre\pcrelib\internal.h -# Below added for the file ext\pcre\pcrelib\pcreposix.c and -# the default value is what is defined in the changelog file -C_FLAGS += -DPOSIX_MALLOC_THRESHOLD=5 - -C_FLAGS += -I. -Imain -Inetware -Iregex -IZend -ITSRM -C_FLAGS += -Iext/standard -Iext/mcal -Iext/pcre -Iext/pcre/pcrelib -C_FLAGS += -Iext/bcmath -Iext/bcmath/libbcmath/src -C_FLAGS += -Iext/odbc -Iext/session -Iext/ftp -Iext/wddx -Iext/calendar -Iext/snmp -C_FLAGS += -I- -Inetware -I$(SDK_DIR)/include -I$(MWCIncludes) # netware added for special SYS/STAT.H : Venkat(6/2/02) -C_FLAGS += -Iwin32 -C_FLAGS += -I$(SDK_DIR)/include/winsock # Added for socket calls - - -# Extra stuff based on debug / release builds -ifeq '$(BUILD)' 'debug' - SYM_FILE = $(FINAL_DIR)\$(MODULE_NAME).sym - C_FLAGS += -inline smart -sym on -sym codeview4 -sym internal -opt off -opt intrinsics - C_FLAGS += -D_DEBUG -DZEND_DEBUG=1 - LD_FLAGS += -sym codeview4 -sym internal -osym $(SYM_FILE) - export MWLibraryFiles=$(SDK_DIR)/imports/libcpre.o;mwcrtl.lib -else - C_FLAGS += -opt speed -inline on -inline auto -sym off -DZEND_DEBUG=0 - LD_FLAGS += -sym off - export MWLibraryFiles=$(SDK_DIR)/imports/libcpre.o;mwcrtl.lib -endif - -# Dependencies -MODULE = LibC -IMPORT = @$(SDK_DIR)/imports/libc.imp \ - @$(SDK_DIR)/imports/ws2nlm.imp \ - @$(MPK_DIR)/import/mpkOrg.imp -EXPORT = @$(PROJECT_ROOT)/netware/phplib.imp -API = NXGetEnvCount \ - NXCopyEnv \ - OutputToScreen \ - bsd_fd_set - - -# Virtual paths -vpath %.cpp . -vpath %.c . win32 -vpath %.obj $(OBJ_DIR) - - -all: prebuild project - -.PHONY: all - -prebuild: - @if not exist main\$(OBJ_DIR) md main\$(OBJ_DIR) - @if not exist regex\$(OBJ_DIR) md regex\$(OBJ_DIR) - @if not exist netware\$(OBJ_DIR) md netware\$(OBJ_DIR) - @if not exist ext\standard\$(OBJ_DIR) md ext\standard\$(OBJ_DIR) - @if not exist ext\bcmath\$(OBJ_DIR) md ext\bcmath\$(OBJ_DIR) - @if not exist ext\bcmath\libbcmath\src\$(OBJ_DIR) md ext\bcmath\libbcmath\src\$(OBJ_DIR) - @if not exist ext\mcal\$(OBJ_DIR) md ext\mcal\$(OBJ_DIR) - @if not exist ext\pcre\$(OBJ_DIR) md ext\pcre\$(OBJ_DIR) - @if not exist ext\pcre\pcrelib\$(OBJ_DIR) md ext\pcre\pcrelib\$(OBJ_DIR) - @if not exist ext\odbc\$(OBJ_DIR) md ext\odbc\$(OBJ_DIR) - @if not exist ext\session\$(OBJ_DIR) md ext\session\$(OBJ_DIR) - @if not exist ext\ftp\$(OBJ_DIR) md ext\ftp\$(OBJ_DIR) - @if not exist ext\wddx\$(OBJ_DIR) md ext\wddx\$(OBJ_DIR) - @if not exist ext\calendar\$(OBJ_DIR) md ext\calendar\$(OBJ_DIR) - @if not exist ext\snmp\$(OBJ_DIR) md ext\snmp\$(OBJ_DIR) - @if not exist $(FINAL_DIR) md $(FINAL_DIR) - -project: $(BINARY) $(MESSAGE) - @echo Build complete. - -%.d: ../%.c - @echo Building Dependencies for $( $(basename $(OBJ_DIR)\$(notdir $@)).cfg - @echo $(wordlist 21, 40, $(C_FLAGS)) >> $(basename $(OBJ_DIR)\$(notdir $@)).cfg - @echo $(wordlist 41, 60, $(C_FLAGS)) >> $(basename $(OBJ_DIR)\$(notdir $@)).cfg - @echo $(wordlist 61, 80, $(C_FLAGS)) >> $(basename $(OBJ_DIR)\$(notdir $@)).cfg - @$(CC) $< @$(basename $(OBJ_DIR)\$(notdir $@)).cfg -o $@ - @del $(basename $(OBJ_DIR)\$(notdir $@)).cfg - - -$(BINARY): $(OBJECTS) $(WIN32_OBJECTS) $(LIBRARY) - @echo Import $(IMPORT) > $(basename $@).def -ifdef API - @echo Import $(API) >> $(basename $@).def -endif - @echo Module $(MODULE) >> $(basename $@).def -ifdef EXPORT - @echo Export $(EXPORT) >> $(basename $@).def -endif - @echo AutoUnload >> $(basename $@).def -ifeq '$(BUILD)' 'debug' - @echo Debug >> $(basename $@).def -endif - @echo Flag_On 0x00000008 >> $(basename $@).def - @echo Start _LibCPrelude >> $(basename $@).def - @echo Exit _LibCPostlude >> $(basename $@).def - - $(MPKTOOL) $(XDCFLAGS) $(basename $@).xdc - @echo xdcdata $(basename $@).xdc >> $(basename $@).def - - @echo Linking $@... - @echo $(LD_FLAGS) -commandfile $(basename $@).def > $(basename $@).link -ifdef LIBRARY - @echo $(LIBRARY) >> $(basename $@).link -endif - @echo $(wordlist 1, 10, $(OBJECTS)) >> $(basename $@).link - @echo $(wordlist 11, 20, $(OBJECTS)) >> $(basename $@).link - @echo $(wordlist 21, 30, $(OBJECTS)) >> $(basename $@).link - @echo $(wordlist 31, 40, $(OBJECTS)) >> $(basename $@).link - @echo $(wordlist 41, 50, $(OBJECTS)) >> $(basename $@).link - @echo $(wordlist 51, 60, $(OBJECTS)) >> $(basename $@).link - @echo $(wordlist 61, 70, $(OBJECTS)) >> $(basename $@).link - @echo $(wordlist 71, 80, $(OBJECTS)) >> $(basename $@).link - @echo $(wordlist 81, 85, $(OBJECTS)) >> $(basename $@).link - @echo $(wordlist 86, 90, $(OBJECTS)) >> $(basename $@).link - @echo $(wordlist 91, 95, $(OBJECTS)) >> $(basename $@).link - @echo $(wordlist 96, 100, $(OBJECTS)) >> $(basename $@).link - @echo $(wordlist 101, 105, $(OBJECTS)) >> $(basename $@).link - @echo $(wordlist 106, 110, $(OBJECTS)) >> $(basename $@).link - @echo $(wordlist 111, 115, $(OBJECTS)) >> $(basename $@).link - @echo $(wordlist 116, 120, $(OBJECTS)) >> $(basename $@).link - @echo $(wordlist 121, 125, $(OBJECTS)) >> $(basename $@).link - @echo $(wordlist 126, 130, $(OBJECTS)) >> $(basename $@).link - @echo $(wordlist 131, 135, $(OBJECTS)) >> $(basename $@).link - @echo $(wordlist 136, 140, $(OBJECTS)) >> $(basename $@).link - @echo $(wordlist 141, 141, $(OBJECTS)) >> $(basename $@).link - - @echo $(wordlist 1, 2, $(WIN32_OBJECTS)) >> $(basename $@).link - - @$(LINK) @$(basename $@).link - - -.PHONY: clean -clean: cleansrc cleanobj cleanbin - -.PHONY: cleand -cleand: - @echo Deleting all dependency files... - -@del "main\$(OBJ_DIR)\*.d" - -@del "regex\$(OBJ_DIR)\*.d" - -@del "netware\$(OBJ_DIR)\*.d" - -@del "ext\standard\$(OBJ_DIR)\*.d" - -@del "ext\bcmath\$(OBJ_DIR)\*.d" - -@del "ext\bcmath\libbcmath\src\$(OBJ_DIR)\*.d" - -@del "ext\mcal\$(OBJ_DIR)\*.d" - -@del "ext\pcre\$(OBJ_DIR)\*.d" - -@del "ext\pcre\pcrelib\$(OBJ_DIR)\*.d" - -@del "ext\odbc\$(OBJ_DIR)\*.d" - -@del "ext\session\$(OBJ_DIR)\*.d" - -@del "ext\ftp\$(OBJ_DIR)\*.d" - -@del "ext\wddx\$(OBJ_DIR)\*.d" - -@del "ext\calendar\$(OBJ_DIR)\*.d" - -@del "ext\snmp\$(OBJ_DIR)\*.d" - -.PHONY: cleansrc -cleansrc: - @echo Deleting all generated source files... - -@del "ext\standard\parsedate.c" - -@del "ext\standard\parsedate.h" - -@del "ext\standard\parsedate.output" - -.PHONY: cleanobj -cleanobj: - @echo Deleting all object files... - -@del "main\$(OBJ_DIR)\*.obj" - -@del "regex\$(OBJ_DIR)\*.obj" - -@del "netware\$(OBJ_DIR)\*.obj" - -@del "ext\standard\$(OBJ_DIR)\*.obj" - -@del "ext\bcmath\$(OBJ_DIR)\*.obj" - -@del "ext\bcmath\libbcmath\src\$(OBJ_DIR)\*.obj" - -@del "ext\mcal\$(OBJ_DIR)\*.obj" - -@del "ext\pcre\$(OBJ_DIR)\*.obj" - -@del "ext\pcre\pcrelib\$(OBJ_DIR)\*.obj" - -@del "ext\odbc\$(OBJ_DIR)\*.obj" - -@del "ext\session\$(OBJ_DIR)\*.obj" - -@del "ext\ftp\$(OBJ_DIR)\*.obj" - -@del "ext\wddx\$(OBJ_DIR)\*.obj" - -@del "ext\calendar\$(OBJ_DIR)\*.obj" - -@del "ext\snmp\$(OBJ_DIR)\*.obj" - -.PHONY: cleanbin -cleanbin: - @echo Deleting binary files... - -@del "$(FINAL_DIR)\$(MODULE_NAME).nlm" - @echo Deleting MAP, DEF files, etc.... - -@del "$(FINAL_DIR)\$(MODULE_NAME).map" - -@del "$(FINAL_DIR)\$(MODULE_NAME).def" - -@del "$(FINAL_DIR)\$(MODULE_NAME).link" -ifeq '$(BUILD)' 'debug' - -@del $(FINAL_DIR)\$(MODULE_NAME).sym -endif diff --git a/netware/phptest.ncf b/netware/phptest.ncf deleted file mode 100644 index 9cb599e194e3..000000000000 --- a/netware/phptest.ncf +++ /dev/null @@ -1 +0,0 @@ -php -q run-tests.php > results.txt \ No newline at end of file diff --git a/netware/pipe.c b/netware/pipe.c deleted file mode 100644 index c302fdf3e0a9..000000000000 --- a/netware/pipe.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - * FILENAME : pipe.c - * DESCRIPTION : Functions to implement pipes on NetWare. - * Author : Anantha Kesari H Y, Venkat Raghavan S, Srivathsa M - * - */ - -#include -#include -#include - -#include "netware/pipe.h" -#include "netware/mktemp.h" - - -/* Following definitions unavailable in LibC, hence borrowed from CLib */ -#define P_WAIT 0 -#define P_NOWAIT 1 - -#define WHITESPACE " \t" -#define MAX_ARGS 10 - - -FILE* popen(const char* commandline, const char* mode) -{ - int err, count; - char pszPipestr[32] = {'\0'}; - char *command = NULL, *argv[MAX_ARGS] = {'\0'}; - int fd = -1; - fd_set myfds; - wiring_t wiring; - pid_t pid=0; - FILE *fp=NULL; - char *ptr = NULL; - int ptrLen = 0, argc = 0, i = 0; - - - /* Get a temporary name */ - (void) tmpnam(strecpy(pszPipestr, "PHP/php$pipe/")); - - wiring.infd=FD_UNUSED; - wiring.outfd=FD_UNUSED; - wiring.errfd=FD_UNUSED; - - /* Open a pipe */ - if ( *mode=='r') { - fd = pipe_open (pszPipestr, O_RDONLY); - if (fd == -1) - return NULL; - - wiring.outfd=fd; - } else if (*mode=='w') { - fd = pipe_open (pszPipestr, O_WRONLY); - if (fd == -1) - return NULL; - - wiring.infd=fd; - } else { - consoleprintf ("Unsupported pipe open mode \n"); - return NULL; - } - - /* Get the file pointer */ - fp = fdopen(fd, mode); - if (fp == NULL) { - consoleprintf ("Failure in fdopen \n"); - close (fd); - return NULL; - } - - /* Separate commandline string into words */ - ptr = strtok((char*)commandline, WHITESPACE); - ptrLen = strlen(ptr); - - /* Get the command */ - command = (char*)malloc(ptrLen + 1); - if(command == NULL) { - consoleprintf ("Failure in memory allocation \n"); - close (fd); - fclose (fp); - return NULL; - } - strcpy (command, ptr); - - /* Command as the first argument into prcessve */ - argv[argc] = (char*)malloc(ptrLen + 1); - if(argv[argc] == NULL) { - consoleprintf ("Failure in memory allocation \n"); - close (fd); - fclose (fp); - if(command) { - free(command); - command = NULL; - } - return NULL; - } - strcpy (argv[argc], ptr); - argc++; - - /* Get more arguments if any to be passed to prcessve */ - ptr = strtok(NULL, WHITESPACE); - while (ptr && (argc < MAX_ARGS)) - { - ptrLen = strlen(ptr); - - argv[argc] = (char*)malloc(ptrLen + 1); - if(argv[argc] == NULL) { - consoleprintf ("Failure in memory allocation \n"); - close (fd); - fclose (fp); - if(command) { - free(command); - command = NULL; - } - return NULL; - } - strcpy (argv[argc], ptr); - argc++; - - ptr = strtok(NULL, WHITESPACE); - } - argv[argc] = NULL; - - FD_ZERO(&myfds); - FD_SET(fd, &myfds); - - pid = processve(command, PROC_CURRENT_SPACE, NULL, &wiring, - &myfds, NULL, (const char **)argv ); - if (pid == -1) { - consoleprintf ("Failure in processve call \n"); - close (fd); - fclose(fp); - if(command) { - free(command); - command = NULL; - } - for(i=0; i*/ -#include -#include -#include - - -FILE* popen(const char* command, const char* mode); -int pclose(FILE* stream); diff --git a/netware/postgres_ext.h b/netware/postgres_ext.h deleted file mode 100644 index 9b79a23f15a0..000000000000 --- a/netware/postgres_ext.h +++ /dev/null @@ -1,45 +0,0 @@ -/*------------------------------------------------------------------------- - * - * postgres_ext.h - * - * This file contains declarations of things that are visible everywhere - * in PostgreSQL *and* are visible to clients of frontend interface libraries. - * For example, the Oid type is part of the API of libpq and other libraries. - * - * Declarations which are specific to a particular interface should - * go in the header file for that interface (such as libpq-fe.h). This - * file is only for fundamental Postgres declarations. - * - * User-written C functions don't count as "external to Postgres." - * Those function much as local modifications to the backend itself, and - * use header files that are otherwise internal to Postgres to interface - * with the backend. - * - * $Id$ - * - *------------------------------------------------------------------------- - */ - -#ifndef POSTGRES_EXT_H -#define POSTGRES_EXT_H - -/* - * Object ID is a fundamental type in Postgres. - */ -typedef unsigned int Oid; - -#define InvalidOid ((Oid) 0) - -#define OID_MAX UINT_MAX -/* you will need to include to use the above #define */ - - -/* - * NAMEDATALEN is the max length for system identifiers (e.g. table names, - * attribute names, function names, etc.) - * - * NOTE that databases with different NAMEDATALEN's cannot interoperate! - */ -#define NAMEDATALEN 32 - -#endif diff --git a/netware/pwd.c b/netware/pwd.c deleted file mode 100644 index 41861a054f90..000000000000 --- a/netware/pwd.c +++ /dev/null @@ -1,86 +0,0 @@ -/* pwd.c - Try to approximate UN*X's getuser...() functions under MS-DOS. - Copyright (C) 1990 by Thorsten Ohl, td12@ddagsi3.bitnet - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 1, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Header$ - */ - -/* This 'implementation' is conjectured from the use of this functions in - the RCS and BASH distributions. Of course these functions don't do too - much useful things under MS-DOS, but using them avoids many "#ifdef - MSDOS" in ported UN*X code ... */ - -#include "php.h" /*php specific */ -/* Need to take care of all the commented stuff later for NetWare */ -/* -#define WIN32_LEAN_AND_MEAN -#include -#include -*/ -#include -#include -#include -/*#include */ -#include "pwd.h" -#include "grp.h" - -#ifndef THREAD_SAFE -static struct passwd pw; /* should we return a malloc()'d structure */ -#endif -static char *home_dir = "."; /* we feel (no|every)where at home */ -static char *login_shell = "not command.com!"; - -struct passwd *getpwnam(char *name) -{ - return (struct passwd *) 0; -} - - -char *getlogin() -{ -/* - static char name[256]; - DWORD dw = 256; - GetUserName(name, &dw); - return name; -*/ - return NULL; /* For now */ -} - -struct passwd * - getpwuid(int uid) -{ - pw.pw_name = getlogin(); - pw.pw_dir = home_dir; - pw.pw_shell = login_shell; - pw.pw_uid = 0; - - return &pw; -} - -/* Implementation for now */ -int getpid() -{ - return -1; -} - -/* - * Local Variables: - * mode:C - * ChangeLog:ChangeLog - * compile-command:make - * End: - */ diff --git a/netware/pwd.h b/netware/pwd.h deleted file mode 100644 index 646d5f33ac0b..000000000000 --- a/netware/pwd.h +++ /dev/null @@ -1,54 +0,0 @@ -/* pwd.h - Try to approximate UN*X's getuser...() functions under MS-DOS. - Copyright (C) 1990 by Thorsten Ohl, td12@ddagsi3.bitnet - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 1, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - */ - -/* This 'implementation' is conjectured from the use of this functions in - the RCS and BASH distributions. Of course these functions don't do too - much useful things under MS-DOS, but using them avoids many "#ifdef - MSDOS" in ported UN*X code ... - */ - - -#ifndef PWD_H -#define PWD_H - -/* Not available in LibC / SDK header or CodeWarrior header files. - * So taking from Winsock definitions, which should be OK - */ -typedef unsigned int DWORD; - -struct passwd { - char *pw_name; /* user name */ - char *pw_passwd; /* encrypted password */ - int pw_uid; /* user uid */ - int pw_gid; /* user gid */ - char *pw_comment; /* comment */ - char *pw_gecos; /* Honeywell login info */ - char *pw_dir; /* home directory */ - char *pw_shell; /* default shell */ -}; - -extern struct passwd *getpwuid(int); -extern struct passwd *getpwnam(char *name); -extern char *getlogin(void); - -#ifndef NEW_LIBC -int getpid(); -#endif - -#endif diff --git a/netware/sendmail_nw.h b/netware/sendmail_nw.h index 9d0b7fb73c3a..b88f8e12a137 100644 --- a/netware/sendmail_nw.h +++ b/netware/sendmail_nw.h @@ -1,12 +1,14 @@ +#define closesocket close +#define LPCSTR char * +#define LPSTR char* +#define FAR #ifdef USE_WINSOCK -/*#include */ #include #else #include /* For struct sockaddr, 'PF_INET' and 'AF_INET' */ -#include /* For struct sockaddr_in */ +#include /* For struct sockaddr_in */ #include /* For struct hostent */ -/*#include */ #endif /* USE_WINSOCK */ typedef int SOCKET; /* Borrowed from winsock\novsock2.h */ diff --git a/netware/setbuild.bat b/netware/setbuild.bat deleted file mode 100755 index a1685624eda3..000000000000 --- a/netware/setbuild.bat +++ /dev/null @@ -1,19 +0,0 @@ -@echo off - -if "%1" == "/?" goto USAGE - -if "%1" == "d" set BUILD=debug -if "%1" == "r" set BUILD=release - -if "%2" == "1" set APACHE_VER=1.3 -if "%2" == "2" set APACHE_VER=2 - -goto EXIT - -:USAGE - @echo on - @echo Usage: setbuild d|r 1|2 - @echo set build type as 'debug' or 'release' - @echo set Web Server as Apache 1.3.x or Apache 2.0.x - -:EXIT \ No newline at end of file diff --git a/netware/sys/stat.h b/netware/sys/stat.h deleted file mode 100644 index e6f741cc5ea0..000000000000 --- a/netware/sys/stat.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Novell, Inc. | - +----------------------------------------------------------------------+ -*/ - - -#ifndef __sys_stat_h__ -#define __sys_stat_h__ - - -#include -#include -#include -#include - -#include - - -#ifdef CLIB_STAT_PATCH - -/***************** stat structure taken from CLib and modified ***************/ -struct stat -{ - long st_dev; /* volume number */ /* dev_t replaced by long */ - MACHINE_WORD st_ino; /* directory entry number of the st_name */ /* ino_t replaced by MACHINE_WORD */ - unsigned short st_mode; /* emulated file mode */ - unsigned short st_pad1; /* reserved for alignment */ - unsigned long st_nlink; /* count of hard links (always 1) */ - unsigned long st_uid; /* object id of owner */ - unsigned long st_gid; /* group-id (always 0) */ - long st_rdev; /* device type (always 0) */ /* dev_t replaced by long */ - off_t st_size; /* total file size--files only */ - time_t st_atime; /* last access date--files only */ - time_t st_mtime; /* last modify date and time */ - time_t st_ctime; /* POSIX: last status change time... */ - /* ...NetWare: creation date/time */ - time_t st_btime; /* last archived date and time */ - unsigned long st_attr; /* file attributes */ - unsigned long st_archivedID; /* user/object ID of last archive */ - unsigned long st_updatedID; /* user/object ID of last update */ - unsigned short st_inheritedRightsMask; /* inherited rights mask */ - unsigned short st_pad2; /* reserved for alignment */ - unsigned int st_originatingNameSpace; /* namespace of creation */ - size_t st_blksize; /* block size for allocation--files only */ - size_t st_blocks; /* count of blocks allocated to file */ - unsigned int st_flags; /* user-defined flags */ - unsigned long st_spare[4]; /* for future use */ - unsigned char st_name[255+1];/* TARGET_NAMESPACE name */ -}; -/***************** stat structure taken from CLib and modified ***************/ - -struct stat_libc -{ - uint32_t st_userspec; /* untouched by stat() */ - uint32_t st_flags; /* flags for this entry */ - mode_t st_mode; /* emulated file mode */ - uint32_t st_spare1; - uint64_t st_gen; /* generation number of inode */ - ino_t st_ino; /* directory entry number */ - dev_t st_dev; /* volume number */ - dev_t st_rdev; /* device type (always 0) */ - off64_t st_size; /* total file size */ - uint64_t st_spare2; - blkcnt_t st_blocks; /* count of blocks allocated to file */ - blksize_t st_blksize; /* block size for allocation--files only */ - nlink_t st_nlink; /* count of hard links (always 1) */ - uint32_t st_spare3[3]; - uid_t st_uid; /* owner (object) identity */ - gid_t st_gid; /* group-id (always 0) */ - uid_t st_bid; /* identity of last archiver */ - uid_t st_mid; /* identity of last updator */ - timespec_t st_atime; /* last access date--files only */ - timespec_t st_mtime; /* last modify date and time */ - timespec_t st_ctime; /* last file attributes modification */ - timespec_t st_btime; /* last archived date and time */ - uint64_t st_spare4[44]; -}; /* sizeof(struct dirent) == 0x200 (512.) */ - -#else /* CLIB_STAT_PATCH */ - -struct stat -{ - uint32_t st_userspec; /* untouched by stat() */ - uint32_t st_flags; /* flags for this entry */ - mode_t st_mode; /* emulated file mode */ - uint32_t st_spare1; - uint64_t st_gen; /* generation number of inode */ - ino_t st_ino; /* directory entry number */ - dev_t st_dev; /* volume number */ - dev_t st_rdev; /* device type (always 0) */ - off64_t st_size; /* total file size */ - uint64_t st_spare2; - blkcnt_t st_blocks; /* count of blocks allocated to file */ - blksize_t st_blksize; /* block size for allocation--files only */ - nlink_t st_nlink; /* count of hard links (always 1) */ - uint32_t st_spare3[3]; - uid_t st_uid; /* owner (object) identity */ - gid_t st_gid; /* group-id (always 0) */ - uid_t st_bid; /* identity of last archiver */ - uid_t st_mid; /* identity of last updator */ - timespec_t st_atime; /* last access date--files only */ - timespec_t st_mtime; /* last modify date and time */ - timespec_t st_ctime; /* last file attributes modification */ - timespec_t st_btime; /* last archived date and time */ - uint64_t st_spare4[44]; -}; /* sizeof(struct dirent) == 0x200 (512.) */ - -#endif /* CLIB_STAT_PATCH */ - - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -int chmod ( const char *path, mode_t mode ); -int fchmod( int fildes, mode_t mode ); -int fstat ( int fildes, struct stat *buf ); -int mkdir ( const char *pathname, mode_t mode ); -int mkfifo( const char *pathname, mode_t mode ); -int stat ( const char *path, struct stat *buf ); -mode_t umask ( mode_t cmask ); - -#ifdef __cplusplus -} -#endif - -#define stat64 stat /* same structure and function do both */ -#define fstat64 fstat /* same function does both */ - - -#endif /* __sys_stat_h__ */ diff --git a/netware/sysexits.h b/netware/sysexits.h deleted file mode 100644 index 37246b6e752f..000000000000 --- a/netware/sysexits.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 1987, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)sysexits.h 8.1 (Berkeley) 6/2/93 - */ - -#ifndef _SYSEXITS_H -#define _SYSEXITS_H 1 - -/* - * SYSEXITS.H -- Exit status codes for system programs. - * - * This include file attempts to categorize possible error - * exit statuses for system programs, notably delivermail - * and the Berkeley network. - * - * Error numbers begin at EX__BASE to reduce the possibility of - * clashing with other exit statuses that random programs may - * already return. The meaning of the codes is approximately - * as follows: - * - * EX_USAGE -- The command was used incorrectly, e.g., with - * the wrong number of arguments, a bad flag, a bad - * syntax in a parameter, or whatever. - * EX_DATAERR -- The input data was incorrect in some way. - * This should only be used for user's data & not - * system files. - * EX_NOINPUT -- An input file (not a system file) did not - * exist or was not readable. This could also include - * errors like "No message" to a mailer (if it cared - * to catch it). - * EX_NOUSER -- The user specified did not exist. This might - * be used for mail addresses or remote logins. - * EX_NOHOST -- The host specified did not exist. This is used - * in mail addresses or network requests. - * EX_UNAVAILABLE -- A service is unavailable. This can occur - * if a support program or file does not exist. This - * can also be used as a catchall message when something - * you wanted to do doesn't work, but you don't know - * why. - * EX_SOFTWARE -- An internal software error has been detected. - * This should be limited to non-operating system related - * errors as possible. - * EX_OSERR -- An operating system error has been detected. - * This is intended to be used for such things as "cannot - * fork", "cannot create pipe", or the like. It includes - * things like getuid returning a user that does not - * exist in the passwd file. - * EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp, - * etc.) does not exist, cannot be opened, or has some - * sort of error (e.g., syntax error). - * EX_CANTCREAT -- A (user specified) output file cannot be - * created. - * EX_IOERR -- An error occurred while doing I/O on some file. - * EX_TEMPFAIL -- temporary failure, indicating something that - * is not really an error. In sendmail, this means - * that a mailer (e.g.) could not create a connection, - * and the request should be reattempted later. - * EX_PROTOCOL -- the remote system returned something that - * was "not possible" during a protocol exchange. - * EX_NOPERM -- You did not have sufficient permission to - * perform the operation. This is not intended for - * file system problems, which should use NOINPUT or - * CANTCREAT, but rather for higher level permissions. - */ - -#define EX_OK 0 /* successful termination */ - -#define EX__BASE 64 /* base value for error messages */ - -#define EX_USAGE 64 /* command line usage error */ -#define EX_DATAERR 65 /* data format error */ -#define EX_NOINPUT 66 /* cannot open input */ -#define EX_NOUSER 67 /* addressee unknown */ -#define EX_NOHOST 68 /* host name unknown */ -#define EX_UNAVAILABLE 69 /* service unavailable */ -#define EX_SOFTWARE 70 /* internal software error */ -#define EX_OSERR 71 /* system error (e.g., can't fork) */ -#define EX_OSFILE 72 /* critical OS file missing */ -#define EX_CANTCREAT 73 /* can't create (user) output file */ -#define EX_IOERR 74 /* input/output error */ -#define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */ -#define EX_PROTOCOL 76 /* remote error in protocol */ -#define EX_NOPERM 77 /* permission denied */ -#define EX_CONFIG 78 /* configuration error */ - -#define EX__MAX 78 /* maximum listed value */ - -#endif /* sysexits.h */ diff --git a/netware/time_nw.c b/netware/time_nw.c deleted file mode 100644 index 195f18cdd96f..000000000000 --- a/netware/time_nw.c +++ /dev/null @@ -1,246 +0,0 @@ - -/***************************************************************************** - * * - * DH_TIME.C * - * * - * Freely redistributable and modifiable. Use at your own risk. * - * * - * Copyright 1994 The Downhill Project * - * - * Modified by Shane Caraveo for use with PHP - * - *****************************************************************************/ - -/* $Id$ */ - - /** - * - * 04-Feb-2001 - * - Added patch by "Vanhanen, Reijo" - * Improves accuracy of msec - */ - -/* Include stuff ************************************************************ */ - -#include "time_nw.h" -#include "unistd.h" -#include "signal.h" -/*#include -#include */ -#include -/* -int getfilesystemtime(struct timeval *time_Info) -{ -FILETIME ft; -__int64 ff; - - GetSystemTimeAsFileTime(&ft); *//* 100 ns blocks since 01-Jan-1641 *//* - *//* resolution seems to be 0.01 sec *//* - ff = *(__int64*)(&ft); - time_Info->tv_sec = (int)(ff/(__int64)10000000-(__int64)11644473600); - time_Info->tv_usec = (int)(ff % 10000000)/10; - return 0; -} -*/ - - -int gettimeofday(struct timeval *time_Info, struct timezone *timezone_Info) -{ -#ifdef NETWARE - return 0; -#else - static struct timeval starttime = {0, 0}; - static __int64 lasttime = 0; - static __int64 freq = 0; - __int64 timer; - LARGE_INTEGER li; - BOOL b; - double dt; - - /* Get the time, if they want it */ - if (time_Info != NULL) { - if (starttime.tv_sec == 0) { - b = QueryPerformanceFrequency(&li); - if (!b) { - starttime.tv_sec = -1; - } - else { - freq = li.QuadPart; - b = QueryPerformanceCounter(&li); - if (!b) { - starttime.tv_sec = -1; - } - else { - getfilesystemtime(&starttime); - timer = li.QuadPart; - dt = (double)timer/freq; - starttime.tv_usec -= (int)((dt-(int)dt)*1000000); - if (starttime.tv_usec < 0) { - starttime.tv_usec += 1000000; - --starttime.tv_sec; - } - starttime.tv_sec -= (int)dt; - } - } - } - if (starttime.tv_sec > 0) { - b = QueryPerformanceCounter(&li); - if (!b) { - starttime.tv_sec = -1; - } - else { - timer = li.QuadPart; - if (timer < lasttime) { - getfilesystemtime(time_Info); - dt = (double)timer/freq; - starttime = *time_Info; - starttime.tv_usec -= (int)((dt-(int)dt)*1000000); - if (starttime.tv_usec < 0) { - starttime.tv_usec += 1000000; - --starttime.tv_sec; - } - starttime.tv_sec -= (int)dt; - } - else { - lasttime = timer; - dt = (double)timer/freq; - time_Info->tv_sec = starttime.tv_sec + (int)dt; - time_Info->tv_usec = starttime.tv_usec + (int)((dt-(int)dt)*1000000); - if (time_Info->tv_usec > 1000000) { - time_Info->tv_usec -= 1000000; - ++time_Info->tv_sec; - } - } - } - } - if (starttime.tv_sec < 0) { - getfilesystemtime(time_Info); - } - - } - /* Get the timezone, if they want it */ - if (timezone_Info != NULL) { - _tzset(); - timezone_Info->tz_minuteswest = _timezone; - timezone_Info->tz_dsttime = _daylight; - } - /* And return */ - return 0; -#endif -} - - -/* this usleep isnt exactly accurate but should do ok */ -/* -void usleep(unsigned int useconds) -{ -struct timeval tnow, tthen, t0; - - gettimeofday(&tthen, NULL); - t0 = tthen; - tthen.tv_usec += useconds; - while (tthen.tv_usec > 1000000) { - tthen.tv_usec -= 1000000; - tthen.tv_sec++; - } - - if (useconds > 10000) { - useconds -= 10000; - Sleep(useconds/1000); - } - - while (1) { - gettimeofday(&tnow, NULL); - if (tnow.tv_sec > tthen.tv_sec) { - break; - } - if (tnow.tv_sec == tthen.tv_sec) { - if (tnow.tv_usec > tthen.tv_usec) { - break; - } - } - } -} -*/ - -#ifdef HAVE_SETITIMER - -/* -#ifndef THREAD_SAFE -unsigned int proftimer, virttimer, realtimer; -extern LPMSG phpmsg; -#endif - -struct timer_msg { - int signal; - unsigned int threadid; -}; - - -LPTIMECALLBACK setitimer_timeout(UINT uTimerID, UINT info, DWORD dwUser, DWORD dw1, DWORD dw2) -{ - struct timer_msg *msg = (struct timer_msg *) info; - - if (msg) { - raise((int) msg->signal); - PostThreadMessage(msg->threadid, - WM_NOTIFY, msg->signal, 0); - free(msg); - } - return 0; -} - -int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue) -{ - int timeout = value->it_value.tv_sec * 1000 + value->it_value.tv_usec; - int repeat = TIME_ONESHOT; -*/ - /*make sure the message queue is initialized *//* - PeekMessage(phpmsg, NULL, WM_USER, WM_USER, PM_NOREMOVE); - if (timeout > 0) { - struct timer_msg *msg = malloc(sizeof(struct timer_msg)); - msg->threadid = GetCurrentThreadId(); - if (!ovalue) { - repeat = TIME_PERIODIC; - } - switch (which) { - case ITIMER_REAL: - msg->signal = SIGALRM; - realtimer = timeSetEvent(timeout, 100, (LPTIMECALLBACK) setitimer_timeout, (UINT) msg, repeat); - break; - case ITIMER_VIRT: - msg->signal = SIGVTALRM; - virttimer = timeSetEvent(timeout, 100, (LPTIMECALLBACK) setitimer_timeout, (UINT) msg, repeat); - break; - case ITIMER_PROF: - msg->signal = SIGPROF; - proftimer = timeSetEvent(timeout, 100, (LPTIMECALLBACK) setitimer_timeout, (UINT) msg, repeat); - break; - default: - errno = EINVAL; - return -1; - break; - } - } else { - switch (which) { - case ITIMER_REAL: - timeKillEvent(realtimer); - break; - case ITIMER_VIRT: - timeKillEvent(virttimer); - break; - case ITIMER_PROF: - timeKillEvent(proftimer); - break; - default: - errno = EINVAL; - return -1; - break; - } - } - - - return 0; -} -*/ -#endif diff --git a/netware/time_nw.h b/netware/time_nw.h deleted file mode 100644 index c67065fdf276..000000000000 --- a/netware/time_nw.h +++ /dev/null @@ -1,57 +0,0 @@ -/***************************************************************************** - * * - * sys/time.h * - * * - * Freely redistributable and modifiable. Use at your own risk. * - * * - * Copyright 1994 The Downhill Project * - * - * Modified by Shane Caraveo for PHP - * - *****************************************************************************/ -#ifndef TIME_H -#define TIME_H - -/* Include stuff ************************************************************ */ -#ifdef USE_WINSOCK -/*#include */ -#include -#else -#include -#endif -#include - -/* -Commented out most of the stuff for now, since we dunno the utility right now -*/ - -/* Struct stuff ************************************************************* */ -/* -struct { - int tz_minuteswest; - int tz_dsttime; -} timezone; -*/ -/* -struct { - struct timeval it_interval; *//* next value *//* - struct timeval it_value; *//* current value *//* -} itimerval; -*/ -#define ITIMER_REAL 0 /*generates sigalrm */ -#define ITIMER_VIRTUAL 1 /*generates sigvtalrm */ -#define ITIMER_VIRT 1 /*generates sigvtalrm */ -#define ITIMER_PROF 2 /*generates sigprof */ - -/* Prototype stuff ********************************************************** */ -/* -extern int gettimeofday(struct timeval *time_Info, struct timezone *timezone_Info); -*/ - -/* setitimer operates at 100 millisecond resolution */ -/* -extern int setitimer(int which, const struct itimerval *value, - struct itimerval *ovalue); -*/ - -#endif diff --git a/netware/tsrm.mak b/netware/tsrm.mak deleted file mode 100644 index d0088ecb4a04..000000000000 --- a/netware/tsrm.mak +++ /dev/null @@ -1,109 +0,0 @@ -# Temporarily here -- later may go into some batch file -# which will set this as an environment variable -PROJECT_ROOT = .. - -# Module details -MODULE_NAME = TSRM - -#include the common settings -include $(PROJECT_ROOT)/netware/common.mif - -# Extensions of all input and output files -.SUFFIXES: -.SUFFIXES: .nlm .lib .obj .cpp .c .msg .mlc .mdb .xdc .d - -# Source files -CPP_SRC = -C_SRC = TSRM.c \ - tsrm_nw.c \ - tsrm_strtok_r.c \ - tsrm_virtual_cwd.c - -# Destination directories and files -OBJ_DIR = $(BUILD) -FINAL_DIR = $(BUILD) -OBJECTS = $(addprefix $(OBJ_DIR)/,$(CPP_SRC:.cpp=.obj) $(C_SRC:.c=.obj)) -DEPDS = $(addprefix $(OBJ_DIR)/,$(CPP_SRC:.cpp=.d) $(C_SRC:.c=.d)) - -# Binary file -ifndef BINARY - BINARY=$(FINAL_DIR)\$(MODULE_NAME).lib -endif - -# Compile flags -C_FLAGS = -c -maxerrors 25 -msgstyle gcc -C_FLAGS += -wchar_t on -bool on -C_FLAGS += -processor Pentium -C_FLAGS += -nostdinc -C_FLAGS += -relax_pointers # To remove type-casting errors -C_FLAGS += -DZTS -DNETWARE -DHAVE_DIRENT_H=1 -C_FLAGS += -DNEW_LIBC -C_FLAGS += -DUSE_MKFIFO -C_FLAGS += -DCLIB_STAT_PATCH -#C_FLAGS += -DUSE_MPK # To use the LibC recursive mutex locking -C_FLAGS += -I. -I- -I../netware -I$(SDK_DIR)/include # ../netware added for special SYS/STAT.H -C_FLAGS += -I$(MPK_DIR)/include1 -C_FLAGS += -I$(MWCIncludes) - - -# Link flags -LD_FLAGS = -type library -LD_FLAGS += -o $(BINARY) - -# Extra stuff based on debug / release builds -ifeq '$(BUILD)' 'debug' - C_FLAGS += -inline smart -sym on -sym codeview4 -sym internal -opt off -opt intrinsics -DTSRM_DEBUG=1 - LD_FLAGS += -sym codeview4 -sym internal - export MWLibraryFiles=$(SDK_DIR)/imports/libcpre.o;mwcrtld.lib -else - C_FLAGS += -opt speed -inline smart -inline auto -sym off -DTSRM_DEBUG=0 - LD_FLAGS += -sym off - export MWLibraryFiles=$(SDK_DIR)/imports/libcpre.o;mwcrtl.lib -endif - -# Virtual paths -vpath %.cpp . -vpath %.c . -vpath %.obj $(OBJ_DIR) - - -all: prebuild project - -.PHONY: all - -prebuild: - @if not exist $(OBJ_DIR) md $(OBJ_DIR) - -project: $(BINARY) $(MESSAGE) - @echo Build complete. - -$(OBJ_DIR)/%.d: %.c - @echo Building Dependencies for $( */ -#include -#include -#include - -#define access _access -#define X_OK 0 -#ifndef ENOENT -#define ENOENT 136 -#endif -#ifndef EINVAL -#define EINVAL 131 -#endif - -int readlink(char *, char *, int); -int checkroot(char *path); diff --git a/netware/zend.mak b/netware/zend.mak deleted file mode 100644 index 77b107480842..000000000000 --- a/netware/zend.mak +++ /dev/null @@ -1,158 +0,0 @@ -# Temporarily here -- later may go into some batch file -# which will set this as an environment variable -PROJECT_ROOT = .. - -# Module details -MODULE_NAME = ZEND - -#include the common settings -include $(PROJECT_ROOT)/netware/common.mif - -# Extensions of all input and output files -.SUFFIXES: -.SUFFIXES: .nlm .lib .obj .cpp .c .msg .mlc .mdb .xdc .d - -C_SRC = zend.c \ - zend_alloc.c \ - zend_API.c \ - zend_builtin_functions.c \ - zend_compile.c \ - zend_constants.c \ - zend_dynamic_array.c \ - zend_execute.c \ - zend_execute_API.c \ - zend_extensions.c \ - zend_hash.c \ - zend_highlight.c \ - zend_indent.c \ - zend_ini.c \ - zend_ini_parser.c \ - zend_ini_scanner.c \ - zend_language_parser.c \ - zend_language_scanner.c \ - zend_list.c \ - zend_llist.c \ - zend_multibyte.c \ - zend_opcode.c \ - zend_operators.c \ - zend_ptr_stack.c \ - zend_qsort.c \ - zend_sprintf.c \ - zend_stack.c \ - zend_static_allocator.c \ - zend_variables.c - - -# Destination directories and files -OBJ_DIR = $(BUILD) -FINAL_DIR = $(BUILD) -OBJECTS = $(addprefix $(OBJ_DIR)/,$(CPP_SRC:.cpp=.obj) $(C_SRC:.c=.obj)) -DEPDS = $(addprefix $(OBJ_DIR)/,$(CPP_SRC:.cpp=.d) $(C_SRC:.c=.d)) - -# Binary file -ifndef BINARY - BINARY=$(FINAL_DIR)\$(MODULE_NAME).lib -endif - - -# Compile flags -C_FLAGS = -c -maxerrors 25 -msgstyle std -C_FLAGS += -wchar_t on -bool on -C_FLAGS += -processor Pentium -C_FLAGS += -nostdinc -C_FLAGS += -relax_pointers # To remove type-casting errors -C_FLAGS += -D__C9X_CMATH_INLINES_DEFINED -C_FLAGS += -DNETWARE -DZTS -C_FLAGS += -DNEW_LIBC -C_FLAGS += -DCLIB_STAT_PATCH -C_FLAGS += -DTHREAD_SWITCH - -# These are required to use dlclose so that the PHP extensions are automatically unloaded -# when apache is unloaded -C_FLAGS += -DHAVE_DLFCN_H -DHAVE_LIBDL - -C_FLAGS += -I. -I- -I../netware -I$(SDK_DIR)/include # ../netware added for special SYS/STAT.H -C_FLAGS += -I$(MWCIncludes) - - -# Link flags -LD_FLAGS = -type library -LD_FLAGS += -o $(BINARY) - - -# Extra stuff based on debug / release builds -ifeq '$(BUILD)' 'debug' - C_FLAGS += -DZEND_DEBUG=1 - C_FLAGS += -inline smart -sym on -sym codeview4 -sym internal -opt off -opt intrinsics - LD_FLAGS += -sym codeview4 -sym internal - export MWLibraryFiles=$(SDK_DIR)/imports/libcpre.o;mwcrtld.lib -else - C_FLAGS += -opt speed -inline on -inline auto -sym off - C_FLAGS += -DZEND_DEBUG=0 - LD_FLAGS += -sym off - export MWLibraryFiles=$(SDK_DIR)/imports/libcpre.o;mwcrtl.lib -endif - - -# Virtual paths -vpath %.cpp . -vpath %.c . -vpath %.obj $(OBJ_DIR) - - -all: prebuild project - -.PHONY: all - -prebuild: - @if not exist $(OBJ_DIR) md $(OBJ_DIR) - -project: $(BINARY) $(MESSAGE) - @echo Build complete. - - -$(OBJ_DIR)/%.d: %.c - @echo Building Dependencies for $( 'hpux', 'IRIX64' => 'irix', - // Darwin? ); static $cpumap = array( 'i586' => 'i386', 'i686' => 'i386', + 'ppc' => 'powerpc', ); if ($uname === null) { $uname = php_uname(); @@ -138,6 +143,24 @@ function parseSignature($uname = null) // use only the first two digits from the kernel version $release = ereg_replace('^([[:digit:]]+\.[[:digit:]]+).*', '\1', $parts[2]); break; + case 'Mac' : + $sysname = 'darwin'; + $nodename = $parts[2]; + $release = $parts[3]; + if ($cpu == 'Macintosh') { + if ($parts[$n - 2] == 'Power') { + $cpu = 'powerpc'; + } + } + break; + case 'Darwin' : + if ($cpu == 'Macintosh') { + if ($parts[$n - 2] == 'Power') { + $cpu = 'powerpc'; + } + } + $release = ereg_replace('^([[:digit:]]+\.[[:digit:]]+).*', '\1', $parts[2]); + break; default: $release = ereg_replace('-.*', '', $parts[2]); break; @@ -255,7 +278,6 @@ function _matchFragment($fragment, $value) } } - /* * Local Variables: * indent-tabs-mode: nil diff --git a/pear/PEAR.php b/pear/PEAR.php index a42b825f6a5c..b3b8633e1376 100644 --- a/pear/PEAR.php +++ b/pear/PEAR.php @@ -59,7 +59,7 @@ $GLOBALS['_PEAR_shutdown_funcs'] = array(); $GLOBALS['_PEAR_error_handler_stack'] = array(); -ini_set('track_errors', true); +@ini_set('track_errors', true); /** * Base class for other PEAR classes. Provides rudimentary @@ -152,7 +152,7 @@ class PEAR */ function PEAR($error_class = null) { - $classname = get_class($this); + $classname = strtolower(get_class($this)); if ($this->_debug) { print "PEAR constructor called, class=$classname\n"; } @@ -164,6 +164,10 @@ function PEAR($error_class = null) if (method_exists($this, $destructor)) { global $_PEAR_destructor_object_list; $_PEAR_destructor_object_list[] = &$this; + if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) { + register_shutdown_function("_PEAR_call_destructors"); + $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true; + } break; } else { $classname = get_parent_class($classname); @@ -187,7 +191,7 @@ function PEAR($error_class = null) */ function _PEAR() { if ($this->_debug) { - printf("PEAR destructor called, class=%s\n", get_class($this)); + printf("PEAR destructor called, class=%s\n", strtolower(get_class($this))); } } @@ -488,7 +492,7 @@ function delExpect($error_code) * @see PEAR::setErrorHandling * @since PHP 4.0.5 */ - function raiseError($message = null, + function &raiseError($message = null, $code = null, $mode = null, $options = null, @@ -533,9 +537,11 @@ function raiseError($message = null, $ec = 'PEAR_Error'; } if ($skipmsg) { - return new $ec($code, $mode, $options, $userinfo); + $a = &new $ec($code, $mode, $options, $userinfo); + return $a; } else { - return new $ec($message, $code, $mode, $options, $userinfo); + $a = &new $ec($message, $code, $mode, $options, $userinfo); + return $a; } } @@ -554,13 +560,86 @@ function throwError($message = null, $userinfo = null) { if (isset($this) && is_a($this, 'PEAR')) { - return $this->raiseError($message, $code, null, null, $userinfo); + $a = &$this->raiseError($message, $code, null, null, $userinfo); + return $a; } else { - return PEAR::raiseError($message, $code, null, null, $userinfo); + $a = &PEAR::raiseError($message, $code, null, null, $userinfo); + return $a; } } // }}} + function staticPushErrorHandling($mode, $options = null) + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + $def_mode = &$GLOBALS['_PEAR_default_error_mode']; + $def_options = &$GLOBALS['_PEAR_default_error_options']; + $stack[] = array($def_mode, $def_options); + switch ($mode) { + case PEAR_ERROR_EXCEPTION: + case PEAR_ERROR_RETURN: + case PEAR_ERROR_PRINT: + case PEAR_ERROR_TRIGGER: + case PEAR_ERROR_DIE: + case null: + $def_mode = $mode; + $def_options = $options; + break; + + case PEAR_ERROR_CALLBACK: + $def_mode = $mode; + // class/object method callback + if (is_callable($options)) { + $def_options = $options; + } else { + trigger_error("invalid error callback", E_USER_WARNING); + } + break; + + default: + trigger_error("invalid error mode", E_USER_WARNING); + break; + } + $stack[] = array($mode, $options); + return true; + } + + function staticPopErrorHandling() + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + $setmode = &$GLOBALS['_PEAR_default_error_mode']; + $setoptions = &$GLOBALS['_PEAR_default_error_options']; + array_pop($stack); + list($mode, $options) = $stack[sizeof($stack) - 1]; + array_pop($stack); + switch ($mode) { + case PEAR_ERROR_EXCEPTION: + case PEAR_ERROR_RETURN: + case PEAR_ERROR_PRINT: + case PEAR_ERROR_TRIGGER: + case PEAR_ERROR_DIE: + case null: + $setmode = $mode; + $setoptions = $options; + break; + + case PEAR_ERROR_CALLBACK: + $setmode = $mode; + // class/object method callback + if (is_callable($options)) { + $setoptions = $options; + } else { + trigger_error("invalid error callback", E_USER_WARNING); + } + break; + + default: + trigger_error("invalid error mode", E_USER_WARNING); + break; + } + return true; + } + // {{{ pushErrorHandling() /** @@ -665,6 +744,9 @@ function _PEAR_call_destructors() sizeof($_PEAR_destructor_object_list)) { reset($_PEAR_destructor_object_list); + if (@PEAR::getStaticProperty('PEAR', 'destructlifo')) { + $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list); + } while (list($k, $objref) = each($_PEAR_destructor_object_list)) { $classname = get_class($objref); while ($classname) { @@ -738,7 +820,9 @@ function PEAR_Error($message = 'unknown error', $code = null, $this->mode = $mode; $this->userinfo = $userinfo; if (function_exists("debug_backtrace")) { - $this->backtrace = debug_backtrace(); + if (@!PEAR::getStaticProperty('PEAR_Error', 'skiptrace')) { + $this->backtrace = debug_backtrace(); + } } if ($mode & PEAR_ERROR_CALLBACK) { $this->level = E_USER_NOTICE; @@ -929,14 +1013,16 @@ function toString() { E_USER_ERROR => 'error'); if ($this->mode & PEAR_ERROR_CALLBACK) { if (is_array($this->callback)) { - $callback = get_class($this->callback[0]) . '::' . + $callback = (is_object($this->callback[0]) ? + strtolower(get_class($this->callback[0])) : + $this->callback[0]) . '::' . $this->callback[1]; } else { $callback = $this->callback; } return sprintf('[%s: message="%s" code=%d mode=callback '. 'callback=%s prefix="%s" info="%s"]', - get_class($this), $this->message, $this->code, + strtolower(get_class($this)), $this->message, $this->code, $callback, $this->error_message_prefix, $this->userinfo); } @@ -954,7 +1040,7 @@ function toString() { } return sprintf('[%s: message="%s" code=%d mode=%s level=%s '. 'prefix="%s" info="%s"]', - get_class($this), $this->message, $this->code, + strtolower(get_class($this)), $this->message, $this->code, implode("|", $modes), $levels[$this->level], $this->error_message_prefix, $this->userinfo); @@ -963,8 +1049,6 @@ function toString() { // }}} } -register_shutdown_function("_PEAR_call_destructors"); - /* * Local Variables: * mode: php diff --git a/pear/PEAR/Builder.php b/pear/PEAR/Builder.php index 4806155ef594..0f37d24acb02 100644 --- a/pear/PEAR/Builder.php +++ b/pear/PEAR/Builder.php @@ -150,6 +150,49 @@ function msdevCallback($what, $data) } // }}} + // {{{ _harventInstDir + /** + * @param string + * @param string + * @param array + * @access private + */ + function _harvestInstDir($dest_prefix, $dirname, &$built_files) + { + $d = opendir($dirname); + if (!$d) + return false; + + $ret = true; + while (($ent = readdir($d)) !== false) { + if ($ent{0} == '.') + continue; + + $full = $dirname . DIRECTORY_SEPARATOR . $ent; + if (is_dir($full)) { + if (!$this->_harvestInstDir( + $dest_prefix . DIRECTORY_SEPARATOR . $ent, + $full, $built_files)) { + $ret = false; + break; + } + } else { + $dest = $dest_prefix . DIRECTORY_SEPARATOR . $ent; + $built_files[] = array( + 'file' => $full, + 'dest' => $dest, + 'php_api' => $this->php_api_version, + 'zend_mod_api' => $this->zend_module_api_no, + 'zend_ext_api' => $this->zend_extension_api_no, + ); + } + } + closedir($d); + return $ret; + } + + // }}} + // {{{ build() /** @@ -198,7 +241,7 @@ function build($descfile, $callback = null) $dir = getcwd(); $this->log(2, "building in $dir"); $this->current_callback = $callback; - putenv('PATH=' . getenv('PATH') . ':' . $this->config->get('bin_dir')); + putenv('PATH=' . $this->config->get('bin_dir') . ':' . getenv('PATH')); $err = $this->_runCommand("phpize", array(&$this, 'phpizeCallback')); if (PEAR::isError($err)) { return $err; @@ -231,14 +274,20 @@ function build($descfile, $callback = null) } $build_basedir = "/var/tmp/pear-build-$user"; $build_dir = "$build_basedir/$info[package]-$info[version]"; + $inst_dir = "$build_basedir/install-$info[package]-$info[version]"; $this->log(1, "building in $build_dir"); if (is_dir($build_dir)) { - System::rm("-rf $build_dir"); + System::rm(array('-rf', $build_dir)); } - if (!System::mkDir("-p $build_dir")) { + if (!System::mkDir(array('-p', $build_dir))) { return $this->raiseError("could not create build dir: $build_dir"); } $this->addTempFile($build_dir); + if (!System::mkDir(array('-p', $inst_dir))) { + return $this->raiseError("could not create temporary install dir: $inst_dir"); + } + $this->addTempFile($inst_dir); + if (getenv('MAKE')) { $make_command = getenv('MAKE'); } else { @@ -247,10 +296,13 @@ function build($descfile, $callback = null) $to_run = array( $configure_command, $make_command, + "$make_command INSTALL_ROOT=\"$inst_dir\" install", + "find \"$inst_dir\" -ls" ); if (!@chdir($build_dir)) { return $this->raiseError("could not chdir to $build_dir"); } + putenv('PHP_PEAR_VERSION=@PEAR-VER@'); foreach ($to_run as $cmd) { $err = $this->_runCommand($cmd, $callback); if (PEAR::isError($err)) { @@ -267,26 +319,8 @@ function build($descfile, $callback = null) return $this->raiseError("no `modules' directory found"); } $built_files = array(); - while ($ent = readdir($dp)) { - if ($ent{0} == '.' || substr($ent, -3) == '.la') { - continue; - } - // harvest! - if (@copy("modules/$ent", "$dir/$ent")) { - $built_files[] = array( - 'file' => "$dir/$ent", - 'php_api' => $this->php_api_version, - 'zend_mod_api' => $this->zend_module_api_no, - 'zend_ext_api' => $this->zend_extension_api_no, - ); - - $this->log(1, "$ent copied to $dir/$ent"); - } else { - chdir($old_cwd); - return $this->raiseError("failed copying $ent to $dir"); - } - } - closedir($dp); + $prefix = exec("php-config --prefix"); + $this->_harvestInstDir($prefix, $inst_dir . DIRECTORY_SEPARATOR . $prefix, $built_files); chdir($old_cwd); return $built_files; } diff --git a/pear/PEAR/Command/Install.php b/pear/PEAR/Command/Install.php index f804a838e3aa..7a89c7cddd62 100644 --- a/pear/PEAR/Command/Install.php +++ b/pear/PEAR/Command/Install.php @@ -303,7 +303,13 @@ function doInstall($command, $options, $params) $downloaded = $this->downloader->getDownloadedPackages(); $this->installer->sortPkgDeps($downloaded); foreach ($downloaded as $pkg) { + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $info = $this->installer->install($pkg['file'], $options, $this->config); + PEAR::popErrorHandling(); + if (PEAR::isError($info)) { + $this->ui->outputData('ERROR: ' .$info->getMessage()); + continue; + } if (is_array($info)) { if ($this->config->get('verbose') > 0) { $label = "$info[package] $info[version]"; diff --git a/pear/PEAR/Command/Package.php b/pear/PEAR/Command/Package.php index dcdc86bd1a4e..0923a5177555 100644 --- a/pear/PEAR/Command/Package.php +++ b/pear/PEAR/Command/Package.php @@ -15,6 +15,7 @@ // +----------------------------------------------------------------------+ // | Authors: Stig Bakken | // | Martin Jansen | +// | Greg Beaver | // +----------------------------------------------------------------------+ // // $Id$ @@ -155,7 +156,21 @@ class PEAR_Command_Package extends PEAR_Command_Common 'summary' => 'Run Regression Tests', 'function' => 'doRunTests', 'shortcut' => 'rt', - 'options' => array(), + 'options' => array( + 'recur' => array( + 'shortopt' => 'r', + 'doc' => 'Run tests in child directories, recursively. 4 dirs deep maximum', + ), + 'ini' => array( + 'shortopt' => 'i', + 'doc' => 'actual string of settings to pass to php in format " -d setting=blah"', + 'arg' => 'SETTINGS' + ), + 'realtimelog' => array( + 'shortopt' => 'l', + 'doc' => 'Log test runs/results as they are run', + ), + ), 'doc' => '[testfile|dir ...] Run regression tests with PHP\'s regression testing script (run-tests.php).', ), @@ -250,6 +265,9 @@ function doPackage($command, $options, $params) { $this->output = ''; include_once 'PEAR/Packager.php'; + if (sizeof($params) < 1) { + $params[0] = "package.xml"; + } $pkginfofile = isset($params[0]) ? $params[0] : 'package.xml'; $packager =& new PEAR_Packager(); $err = $warn = array(); @@ -264,12 +282,6 @@ function doPackage($command, $options, $params) if (isset($options['showname'])) { $this->output = $result; } - /* (cox) What is supposed to do that code? - $lines = explode("\n", $this->output); - foreach ($lines as $line) { - $this->output .= $line."n"; - } - */ if (PEAR::isError($result)) { $this->output .= "Package failed: ".$result->getMessage(); } @@ -434,34 +446,118 @@ function doCvsDiff($command, $options, $params) function doRunTests($command, $options, $params) { - $cwd = getcwd(); - $php = $this->config->get('php_bin'); - putenv("TEST_PHP_EXECUTABLE=$php"); - // all core PEAR tests use this constant to determine whether they should be run or not - putenv("PHP_PEAR_RUNTESTS=1"); - $ip = ini_get("include_path"); - $ps = OS_WINDOWS ? ';' : ':'; - $run_tests = $rtsts = $this->config->get('php_dir') . DIRECTORY_SEPARATOR . 'run-tests.php'; - if (!file_exists($run_tests)) { - $run_tests = PEAR_INSTALL_DIR . DIRECTORY_SEPARATOR . 'run-tests.php'; - if (!file_exists($run_tests)) { - return $this->raiseError("No run-tests.php file found. Please copy this ". - "file from the sources of your PHP distribution to $rtsts"); + include_once 'PEAR/RunTest.php'; + $log = new PEAR_Common; + $log->ui = &$this->ui; // slightly hacky, but it will work + $run = new PEAR_RunTest($log); + $tests = array(); + if (isset($options['recur'])) { + $depth = 4; + } else { + $depth = 1; + } + if (!count($params)) { + $params[] = '.'; + } + foreach ($params as $p) { + if (is_dir($p)) { + $dir = System::find(array($p, '-type', 'f', + '-maxdepth', $depth, + '-name', '*.phpt')); + $tests = array_merge($tests, $dir); + } else { + if (!@file_exists($p)) { + if (!preg_match('/\.phpt$/', $p)) { + $p .= '.phpt'; + } + $dir = System::find(array(dirname($p), '-type', 'f', + '-maxdepth', $depth, + '-name', $p)); + $tests = array_merge($tests, $dir); + } else { + $tests[] = $p; + } } } - if (OS_WINDOWS) { - // note, this requires a slightly modified version of run-tests.php - // for some setups - // unofficial download location is in the pear-dev archives - $argv = $params; - array_unshift($argv, $run_tests); - $argc = count($argv); - include $run_tests; - } else { - $plist = implode(' ', $params); - $cmd = "$php -d include_path=$cwd$ps$ip -f $run_tests -- $plist"; - system($cmd); + $ini_settings = ''; + if (isset($options['ini'])) { + $ini_settings .= $options['ini']; } + if (isset($_ENV['TEST_PHP_INCLUDE_PATH'])) { + $ini_settings .= " -d include_path={$_ENV['TEST_PHP_INCLUDE_PATH']}"; + } + if ($ini_settings) { + $this->ui->outputData('Using INI settings: "' . $ini_settings . '"'); + } + $skipped = $passed = $failed = array(); + $this->ui->outputData('Running ' . count($tests) . ' tests', $command); + $start = time(); + if (isset($options['realtimelog'])) { + @unlink('run-tests.log'); + } + foreach ($tests as $t) { + if (isset($options['realtimelog'])) { + $fp = @fopen('run-tests.log', 'a'); + if ($fp) { + fwrite($fp, "Running test $t..."); + fclose($fp); + } + } + $result = $run->run($t, $ini_settings); + if (OS_WINDOWS) { + for($i=0;$i<2000;$i++) { + $i = $i; // delay - race conditions on windows + } + } + if (isset($options['realtimelog'])) { + $fp = @fopen('run-tests.log', 'a'); + if ($fp) { + fwrite($fp, "$result\n"); + fclose($fp); + } + } + if ($result == 'FAILED') { + $failed[] = $t; + } + if ($result == 'PASSED') { + $passed[] = $t; + } + if ($result == 'SKIPPED') { + $skipped[] = $t; + } + } + $total = date('i:s', time() - $start); + if (count($failed)) { + $output = "TOTAL TIME: $total\n"; + $output .= count($passed) . " PASSED TESTS\n"; + $output .= count($skipped) . " SKIPPED TESTS\n"; + $output .= count($failed) . " FAILED TESTS:\n"; + foreach ($failed as $failure) { + $output .= $failure . "\n"; + } + if (isset($options['realtimelog'])) { + $fp = @fopen('run-tests.log', 'a'); + } else { + $fp = @fopen('run-tests.log', 'w'); + } + if ($fp) { + fwrite($fp, $output, strlen($output)); + fclose($fp); + $this->ui->outputData('wrote log to "' . realpath('run-tests.log') . '"', $command); + } + } elseif (@file_exists('run-tests.log') && !@is_dir('run-tests.log')) { + @unlink('run-tests.log'); + } + $this->ui->outputData('TOTAL TIME: ' . $total); + $this->ui->outputData(count($passed) . ' PASSED TESTS', $command); + $this->ui->outputData(count($skipped) . ' SKIPPED TESTS', $command); + if (count($failed)) { + $this->ui->outputData(count($failed) . ' FAILED TESTS:', $command); + foreach ($failed as $failure) { + $this->ui->outputData($failure, $command); + } + } + return true; } @@ -642,6 +738,7 @@ function doMakeRPM($command, $options, $params) if (!isset($attr['role'])) { continue; } + $name = preg_replace('![/:\\\\]!', '/', $name); if ($attr['role'] == 'doc') { $info['doc_files'] .= " $name"; diff --git a/pear/PEAR/Common.php b/pear/PEAR/Common.php index 2f9c6118234c..cfb73c603186 100644 --- a/pear/PEAR/Common.php +++ b/pear/PEAR/Common.php @@ -34,7 +34,7 @@ define('PEAR_COMMON_PACKAGE_NAME_PREG', '/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '$/'); // this should allow: 1, 1.0, 1.0RC1, 1.0dev, 1.0dev123234234234, 1.0a1, 1.0b1, 1.0pl1 -define('_PEAR_COMMON_PACKAGE_VERSION_PREG', '\d+(?:\.\d+)*(?:[a-z]+\d*)?'); +define('_PEAR_COMMON_PACKAGE_VERSION_PREG', '\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?'); define('PEAR_COMMON_PACKAGE_VERSION_PREG', '/^' . _PEAR_COMMON_PACKAGE_VERSION_PREG . '$/i'); // XXX far from perfect :-) @@ -69,7 +69,7 @@ * Valid dependency relations * @var array */ -$GLOBALS['_PEAR_Common_dependency_relations'] = array('has','eq','lt','le','gt','ge','not'); +$GLOBALS['_PEAR_Common_dependency_relations'] = array('has','eq','lt','le','gt','ge','not', 'ne'); /** * Valid file roles @@ -98,7 +98,9 @@ // }}} /** - * Class providing common functionality for PEAR adminsitration classes. + * Class providing common functionality for PEAR administration classes. + * @deprecated This class will disappear, and its components will be spread + * into smaller classes, like the AT&T breakup */ class PEAR_Common extends PEAR { @@ -142,12 +144,6 @@ class PEAR_Common extends PEAR * @access private */ var $_validPackageFile; - /** - * Temporary variable used in sorting packages by dependency in {@link sortPkgDeps()} - * @var array - * @access private - */ - var $_packageSortTree; // }}} @@ -1133,18 +1129,31 @@ function validatePackageInfo($info, &$errors, &$warnings, $dir_prefix = '') if (!empty($d['optional'])) { if (!in_array($d['optional'], array('yes', 'no'))) { $errors[] = "dependency $i: invalid relation optional attribute '$d[optional]', should be one of: yes no"; + } else { + if (($d['rel'] == 'not' || $d['rel'] == 'ne') && $d['optional'] == 'yes') { + $errors[] = "dependency $i: 'not' and 'ne' dependencies cannot be " . + "optional"; + } } } - if ($d['rel'] != 'has' && empty($d['version'])) { + if ($d['rel'] != 'not' && $d['rel'] != 'has' && empty($d['version'])) { $warnings[] = "dependency $i: missing version"; - } elseif ($d['rel'] == 'has' && !empty($d['version'])) { - $warnings[] = "dependency $i: version ignored for `has' dependencies"; + } elseif (($d['rel'] == 'not' || $d['rel'] == 'has') && !empty($d['version'])) { + $warnings[] = "dependency $i: version ignored for `$d[rel]' dependencies"; + } + if ($d['rel'] == 'not' && !empty($d['version'])) { + $warnings[] = "dependency $i: 'not' defines a total conflict, to exclude " . + "specific versions, use 'ne'"; } if ($d['type'] == 'php' && !empty($d['name'])) { $warnings[] = "dependency $i: name ignored for php type dependencies"; } elseif ($d['type'] != 'php' && empty($d['name'])) { $errors[] = "dependency $i: missing name"; } + if ($d['type'] == 'php' && $d['rel'] == 'not') { + $errors[] = "dependency $i: PHP dependencies cannot use 'not' " . + "rel, use 'ne' to exclude versions"; + } $i++; } } @@ -1293,6 +1302,15 @@ function analyzeSourceCode($file) if (!function_exists("token_get_all")) { return false; } + if (!defined('T_DOC_COMMENT')) { + define('T_DOC_COMMENT', T_COMMENT); + } + if (!defined('T_INTERFACE')) { + define('T_INTERFACE', -1); + } + if (!defined('T_IMPLEMENTS')) { + define('T_IMPLEMENTS', -1); + } if (!$fp = @fopen($file, "r")) { return false; } @@ -1315,17 +1333,21 @@ function analyzeSourceCode($file) $brace_level = 0; $lastphpdoc = ''; $current_class = ''; + $current_interface = ''; $current_class_level = -1; $current_function = ''; $current_function_level = -1; $declared_classes = array(); + $declared_interfaces = array(); $declared_functions = array(); $declared_methods = array(); $used_classes = array(); $used_functions = array(); $extends = array(); + $implements = array(); $nodeps = array(); $inquote = false; + $interface = false; for ($i = 0; $i < sizeof($tokens); $i++) { if (is_array($tokens[$i])) { list($token, $data) = $tokens[$i]; @@ -1341,6 +1363,14 @@ function analyzeSourceCode($file) } } switch ($token) { + case T_WHITESPACE: + continue; + case ';': + if ($interface) { + $current_function = ''; + $current_function_level = -1; + } + break; case '"': $inquote = true; break; @@ -1362,6 +1392,8 @@ function analyzeSourceCode($file) case ']': $bracket_level--; continue 2; case '(': $paren_level++; continue 2; case ')': $paren_level--; continue 2; + case T_INTERFACE: + $interface = true; case T_CLASS: if (($current_class_level != -1) || ($current_function_level != -1)) { PEAR::raiseError("Parser error: Invalid PHP file $file", @@ -1371,19 +1403,38 @@ function analyzeSourceCode($file) case T_FUNCTION: case T_NEW: case T_EXTENDS: + case T_IMPLEMENTS: $look_for = $token; continue 2; case T_STRING: + if (version_compare(zend_version(), '2.0', '<')) { + if (in_array(strtolower($data), + array('public', 'private', 'protected', 'abstract', + 'interface', 'implements', 'clone', 'throw') + )) { + PEAR::raiseError('Error: PHP5 packages must be packaged by php 5 PEAR'); + return false; + } + } if ($look_for == T_CLASS) { $current_class = $data; $current_class_level = $brace_level; $declared_classes[] = $current_class; + } elseif ($look_for == T_INTERFACE) { + $current_interface = $data; + $current_class_level = $brace_level; + $declared_interfaces[] = $current_interface; + } elseif ($look_for == T_IMPLEMENTS) { + $implements[$current_class] = $data; } elseif ($look_for == T_EXTENDS) { $extends[$current_class] = $data; } elseif ($look_for == T_FUNCTION) { if ($current_class) { $current_function = "$current_class::$data"; $declared_methods[$current_class][] = $data; + } elseif ($current_interface) { + $current_function = "$current_interface::$data"; + $declared_methods[$current_interface][] = $data; } else { $current_function = $data; $declared_functions[] = $current_function; @@ -1398,6 +1449,7 @@ function analyzeSourceCode($file) case T_VARIABLE: $look_for = 0; continue 2; + case T_DOC_COMMENT: case T_COMMENT: if (preg_match('!^/\*\*\s!', $data)) { $lastphpdoc = $data; @@ -1422,10 +1474,12 @@ function analyzeSourceCode($file) return array( "source_file" => $file, "declared_classes" => $declared_classes, + "declared_interfaces" => $declared_interfaces, "declared_methods" => $declared_methods, "declared_functions" => $declared_functions, "used_classes" => array_diff(array_keys($used_classes), $nodeps), "inheritance" => $extends, + "implements" => $implements, ); } diff --git a/pear/PEAR/Dependency.php b/pear/PEAR/Dependency.php index 3239fc98ee34..ec2bd7e86d83 100644 --- a/pear/PEAR/Dependency.php +++ b/pear/PEAR/Dependency.php @@ -204,7 +204,7 @@ function checkPackageUninstall(&$error, &$warning, $package) } foreach ($deps as $dep) { if ($dep['type'] == 'pkg' && strcasecmp($dep['name'], $package) == 0) { - if ($dep['rel'] == 'ne') { + if ($dep['rel'] == 'ne' || $dep['rel'] == 'not') { continue; } if (isset($dep['optional']) && $dep['optional'] == 'yes') { @@ -244,7 +244,7 @@ function checkExtension(&$errmsg, $name, $req = null, $relation = 'has', } if (!extension_loaded($name)) { - if ($relation == 'ne') { + if ($relation == 'not') { return false; } if ($opt) { @@ -322,7 +322,8 @@ function checkPHP(&$errmsg, $req, $relation = 'ge') return false; } if ($relation == 'not') { - $errmsg = "Invalid dependency - 'not' is allowed when specifying PHP, you must run PHP in PHP"; + $errmsg = 'Invalid dependency - "not" is not allowed for php dependencies, ' . + 'php cannot conflict with itself'; return PEAR_DEPENDENCY_BAD_DEPENDENCY; } if (substr($req, 0, 2) == 'v.') { diff --git a/pear/PEAR/Downloader.php b/pear/PEAR/Downloader.php index 17ad4566a10c..793cc0410e7f 100644 --- a/pear/PEAR/Downloader.php +++ b/pear/PEAR/Downloader.php @@ -381,7 +381,8 @@ function doDownload($packages) // there are no dependencies continue; } - foreach($alldeps as $info) { + $fail = false; + foreach ($alldeps as $info) { if ($info['type'] != 'pkg') { continue; } @@ -389,11 +390,18 @@ function doDownload($packages) if ($ret === false) { continue; } + if ($ret === 0) { + $fail = true; + continue; + } if (PEAR::isError($ret)) { return $ret; } $deppackages[] = $ret; } // foreach($alldeps + if ($fail) { + $deppackages = array(); + } } if (count($deppackages)) { @@ -561,7 +569,7 @@ function _processDependency($package, $info, $mywillinstall) $savestate = array_shift($get); $this->pushError( "Release for '$package' dependency '$info[name]' " . "has state '$savestate', requires '$state'"); - return false; + return 0; } if (in_array(strtolower($info['name']), $this->_toDownload) || isset($mywillinstall[strtolower($info['name'])])) { diff --git a/pear/PEAR/ErrorStack.php b/pear/PEAR/ErrorStack.php index 6f44f4d686e7..9ad94d738cb4 100644 --- a/pear/PEAR/ErrorStack.php +++ b/pear/PEAR/ErrorStack.php @@ -35,8 +35,11 @@ * * Since version 0.3alpha, it is possible to specify the exception class * returned from {@link push()} + * + * Since version PEAR1.3.2, ErrorStack no longer instantiates an exception class. This can + * still be done quite handily in an error callback or by manipulating the returned array * @author Greg Beaver - * @version 0.6alpha + * @version PEAR1.3.2 (beta) * @package PEAR_ErrorStack * @category Debugging * @license http://www.php.net/license/3_0.txt PHP License v3.0 @@ -119,6 +122,10 @@ * If this is returned, then the error is completely ignored. */ define('PEAR_ERRORSTACK_IGNORE', 4); +/** + * If this is returned, then the error is logged and die() is called. + */ +define('PEAR_ERRORSTACK_DIE', 5); /**#@-*/ /** @@ -220,13 +227,6 @@ class PEAR_ErrorStack { */ var $_logger = false; - /** - * Class name to use for a PHP 5 exception that will be returned - * @var string - * @access protected - */ - var $_exceptionClass = 'Exception'; - /** * Error messages - designed to be overridden * @var array @@ -242,20 +242,14 @@ class PEAR_ErrorStack { * @param callback $contextCallback callback used for context generation, * defaults to {@link getFileLine()} * @param boolean $throwPEAR_Error - * @param string $exceptionClass exception class to instantiate if - * in PHP 5 */ function PEAR_ErrorStack($package, $msgCallback = false, $contextCallback = false, - $throwPEAR_Error = false, $exceptionClass = null) + $throwPEAR_Error = false) { $this->_package = $package; $this->setMessageCallback($msgCallback); $this->setContextCallback($contextCallback); $this->_compat = $throwPEAR_Error; - // this allows child classes to simply redefine $this->_exceptionClass - if (!is_null($exceptionClass)) { - $this->_exceptionClass = $exceptionClass; - } } /** @@ -268,29 +262,27 @@ function PEAR_ErrorStack($package, $msgCallback = false, $contextCallback = fals * @param callback $contextCallback callback used for context generation, * defaults to {@link getFileLine()} * @param boolean $throwPEAR_Error - * @param string $exceptionClass exception class to instantiate if - * in PHP 5 * @param string $stackClass class to instantiate * @static * @return PEAR_ErrorStack */ function &singleton($package, $msgCallback = false, $contextCallback = false, - $throwPEAR_Error = false, $exceptionClass = null, - $stackClass = 'PEAR_ErrorStack') + $throwPEAR_Error = false, $stackClass = 'PEAR_ErrorStack') { if (isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) { return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]; } if (!class_exists($stackClass)) { - $trace = debug_backtrace(); + if (function_exists('debug_backtrace')) { + $trace = debug_backtrace(); + } PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_NONCLASS, 'exception', array('stackclass' => $stackClass), 'stack class "%stackclass%" is not a valid class name (should be like PEAR_ErrorStack)', false, $trace); } return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package] = - &new $stackClass($package, $msgCallback, $contextCallback, $throwPEAR_Error, - $exceptionClass); + &new $stackClass($package, $msgCallback, $contextCallback, $throwPEAR_Error); } /** @@ -320,7 +312,11 @@ function _handleError($err) */ function setDefaultLogger(&$log) { - $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log; + if (is_object($log) && method_exists($log, 'log') ) { + $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log; + } elseif (is_callable($log)) { + $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log; + } } /** @@ -329,7 +325,11 @@ function setDefaultLogger(&$log) */ function setLogger(&$log) { - $this->_logger = &$log; + if (is_object($log) && method_exists($log, 'log') ) { + $this->_logger = &$log; + } elseif (is_callable($log)) { + $this->_logger = &$log; + } } /** @@ -381,14 +381,18 @@ function setDefaultCallback($callback = false, $package = false) } /** - * Set an error code => error message mapping callback + * Set a callback that generates context information (location of error) for an error stack * - * This method sets the callback that can be used to generate error - * messages for any PEAR_ErrorStack instance - * @param array|string Callback function/method + * This method sets the callback that can be used to generate context + * information for an error. Passing in NULL will disable context generation + * and remove the expensive call to debug_backtrace() + * @param array|string|null Callback function/method */ function setContextCallback($contextCallback) { + if ($contextCallback === null) { + return $this->_contextCallback = false; + } if (!$contextCallback) { $this->_contextCallback = array(&$this, 'getFileLine'); } else { @@ -454,10 +458,11 @@ function staticPushCallback($cb) */ function staticPopCallback() { - array_pop($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK']); + $ret = array_pop($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK']); if (!is_array($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'])) { $GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array(); } + return $ret; } /** @@ -504,7 +509,7 @@ function staticPopCallback() * 'time' => time(), * 'context' => $context, * 'message' => $msg, - * //['repackage' => $err] repackaged error array + * //['repackage' => $err] repackaged error array/Exception class * ); * */ @@ -533,18 +538,19 @@ function push($code, $level = 'error', $params = array(), $msg = false, 'message' => $msg, ); + if ($repackage) { + $err['repackage'] = $repackage; + } + // set up the error message, if necessary if ($this->_msgCallback) { $msg = call_user_func_array($this->_msgCallback, array(&$this, $err)); $err['message'] = $msg; - } + } - - if ($repackage) { - $err['repackage'] = $repackage; - } $push = $log = true; + $die = false; // try the overriding callback first $callback = $this->staticPopCallback(); if ($callback) { @@ -573,6 +579,9 @@ function push($code, $level = 'error', $params = array(), $msg = false, case PEAR_ERRORSTACK_LOG: $push = false; break; + case PEAR_ERRORSTACK_DIE: + $die = true; + break; // anything else returned has the same effect as pushandlog } } @@ -585,18 +594,12 @@ function push($code, $level = 'error', $params = array(), $msg = false, $this->_log($err); } } + if ($die) { + die(); + } if ($this->_compat && $push) { return $this->raiseError($msg, $code, null, null, $err); } - if (class_exists($this->_exceptionClass)) { - $exception = $this->_exceptionClass; - if (is_string($msg) && is_numeric($code)) { - $code = $code + 0; - } - $ret = new $exception($msg, $code); - $ret->errorData = $err; - return $ret; - } return $err; } @@ -630,7 +633,9 @@ function staticPush($package, $code, $level = 'error', $params = array(), $s = &PEAR_ErrorStack::singleton($package); if ($s->_contextCallback) { if (!$backtrace) { - $backtrace = debug_backtrace(); + if (function_exists('debug_backtrace')) { + $backtrace = debug_backtrace(); + } } } return $s->push($code, $level, $params, $msg, $repackage, $backtrace); @@ -642,7 +647,15 @@ function staticPush($package, $code, $level = 'error', $params = array(), * @param array $levels Error level => Log constant map * @access protected */ - function _log($err, $levels = array( + function _log($err) + { + if ($this->_logger) { + $logger = &$this->_logger; + } else { + $logger = &$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']; + } + if (is_a($logger, 'Log')) { + $levels = array( 'exception' => PEAR_LOG_CRIT, 'alert' => PEAR_LOG_ALERT, 'critical' => PEAR_LOG_CRIT, @@ -650,17 +663,15 @@ function _log($err, $levels = array( 'warning' => PEAR_LOG_WARNING, 'notice' => PEAR_LOG_NOTICE, 'info' => PEAR_LOG_INFO, - 'debug' => PEAR_LOG_DEBUG)) - { - if (isset($levels[$err['level']])) { - $level = $levels[$err['level']]; - } else { - $level = PEAR_LOG_INFO; - } - if ($this->_logger) { - $this->_logger->log($err['message'], $level, $err); - } else { - $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']->log($err['message'], $level, $err); + 'debug' => PEAR_LOG_DEBUG); + if (isset($levels[$err['level']])) { + $level = $levels[$err['level']]; + } else { + $level = PEAR_LOG_INFO; + } + $logger->log($err['message'], $level, $err); + } else { // support non-standard logs + call_user_func($logger, $err); } } @@ -757,7 +768,7 @@ function staticHasErrors($package = false, $level = false) /** * Get a list of all errors since last purge, organized by package * @since PEAR 1.4.0dev BC break! $level is now in the place $merge used to be - * @param boolean $clearStack Set to purge the error stack of existing errors + * @param boolean $purge Set to purge the error stack of existing errors * @param string $level Set to a level name in order to retrieve only errors of a particular level * @param boolean $merge Set to return a flat array, not organized by package * @param array $sortfunc Function used to sort a merged array - default @@ -765,7 +776,8 @@ function staticHasErrors($package = false, $level = false) * @static * @return array */ - function staticGetErrors($purge = false, $level = false, $merge = false, $sortfunc = array('PEAR_ErrorStack', '_sortErrors')) + function staticGetErrors($purge = false, $level = false, $merge = false, + $sortfunc = array('PEAR_ErrorStack', '_sortErrors')) { $ret = array(); if (!is_callable($sortfunc)) { @@ -898,8 +910,10 @@ function getErrorMessage(&$stack, $err, $template = false) } else { $mainmsg = $stack->getErrorMessageTemplate($err['code']); } + $mainmsg = str_replace('%__msg%', $err['message'], $mainmsg); - if (count($err['params'])) { + + if (count($err['params']) && count($err['params'])) { foreach ($err['params'] as $name => $val) { if (is_array($val)) { // @ is needed in case $val is a multi-dimensional array @@ -967,4 +981,4 @@ function raiseError() } $stack = &PEAR_ErrorStack::singleton('PEAR_ErrorStack'); $stack->pushCallback(array('PEAR_ErrorStack', '_handleError')); -?> \ No newline at end of file +?> diff --git a/pear/PEAR/Exception.php b/pear/PEAR/Exception.php index 8322fd034a2c..1e191f84ea5d 100644 --- a/pear/PEAR/Exception.php +++ b/pear/PEAR/Exception.php @@ -15,24 +15,29 @@ // +----------------------------------------------------------------------+ // | Authors: Tomas V.V.Cox | // | Hans Lellelid | -// | | +// | Bertrand Mansion | +// | Greg Beaver | // +----------------------------------------------------------------------+ // // $Id$ -define('PEAR_OBSERVER_PRINT', -2); -define('PEAR_OBSERVER_TRIGGER', -4); -define('PEAR_OBSERVER_DIE', -8); /** * Base PEAR_Exception Class * + * WARNING: This code should be considered stable, but the API is + * subject to immediate and drastic change, so API stability is + * at best alpha + * * 1) Features: * * - Nestable exceptions (throw new PEAR_Exception($msg, $prev_exception)) * - Definable triggers, shot when exceptions occur * - Pretty and informative error messages - * - Added more context info avaible (like class, method or cause) + * - Added more context info available (like class, method or cause) + * - cause can be a PEAR_Exception or an array of mixed + * PEAR_Exceptions/PEAR_ErrorStack warnings + * - callbacks for specific exception classes and their children * * 2) Ideas: * @@ -54,8 +59,8 @@ * getCode * getFile * getLine - * getTrace - * getTraceAsString + * getTraceSafe + * getTraceSafeAsString * __toString * * 5) Usage example @@ -88,16 +93,18 @@ * @version $Revision$ * @author Tomas V.V.Cox * @author Hans Lellelid + * @author Bertrand Mansion * */ class PEAR_Exception extends Exception { + const OBSERVER_PRINT = -2; + const OBSERVER_TRIGGER = -4; + const OBSERVER_DIE = -8; protected $cause; - protected $error_class; - protected $error_method; - - private $_method; private static $_observers = array(); + private static $_uniqueid = 0; + private $_trace; /** * Supported signatures: @@ -105,49 +112,56 @@ class PEAR_Exception extends Exception * PEAR_Exception(string $message, int $code); * PEAR_Exception(string $message, Exception $cause); * PEAR_Exception(string $message, Exception $cause, int $code); + * PEAR_Exception(string $message, array $causes); + * PEAR_Exception(string $message, array $causes, int $code); */ public function __construct($message, $p2 = null, $p3 = null) { - $code = null; - $cause = null; - if (is_int($p3) && $p2 instanceof Exception) { - $code = $p3; - $cause = $p2; - } elseif (is_int($p2)) { + if (is_int($p2)) { $code = $p2; - } elseif ($p2 instanceof Exception) { - $cause = $p2; + $this->cause = null; + } elseif ($p2 instanceof Exception || is_array($p2)) { + $code = $p3; + if (is_array($p2) && isset($p2['message'])) { + // fix potential problem of passing in a single warning + $p2 = array($p2); + } + $this->cause = $p2; + } else { + $code = null; + $this->cause = null; } - $this->cause = $cause; - $trace = parent::getTrace(); - $this->error_class = $trace[0]['class']; - $this->error_method = $trace[0]['function']; - $this->_method = $this->error_class . '::' . $this->error_method . '()'; parent::__construct($message, $code); - - $this->_signal(); + $this->signal(); } /** * @param mixed $callback - A valid php callback, see php func is_callable() - * - A PEAR_OBSERVER_* constant - * - An array(const PEAR_OBSERVER_*, mixed $options) - * - * @param string $label - The name of the observer. Use this if you want - * to remove it later with delObserver() + * - A PEAR_Exception::OBSERVER_* constant + * - An array(const PEAR_Exception::OBSERVER_*, + * mixed $options) + * @param string $label The name of the observer. Use this if you want + * to remove it later with removeObserver() */ - public static function addObserver($callback, $label = 'default') { self::$_observers[$label] = $callback; } - public static function delObserver($label = 'default') + public static function removeObserver($label = 'default') { unset(self::$_observers[$label]); } - private function _signal() + /** + * @return int unique identifier for an observer + */ + public static function getUniqueId() + { + return self::$_uniqueid++; + } + + private function signal() { foreach (self::$_observers as $func) { if (is_callable($func)) { @@ -156,15 +170,15 @@ private function _signal() } settype($func, 'array'); switch ($func[0]) { - case PEAR_OBSERVER_PRINT: + case self::OBSERVER_PRINT : $f = (isset($func[1])) ? $func[1] : '%s'; printf($f, $this->getMessage()); break; - case PEAR_OBSERVER_TRIGGER: + case self::OBSERVER_TRIGGER : $f = (isset($func[1])) ? $func[1] : E_USER_NOTICE; trigger_error($this->getMessage(), $f); break; - case PEAR_OBSERVER_DIE: + case self::OBSERVER_DIE : $f = (isset($func[1])) ? $func[1] : '%s'; die(printf($f, $this->getMessage())); break; @@ -174,48 +188,171 @@ private function _signal() } } - private function _getCauseMessage() + /** + * Return specific error information that can be used for more detailed + * error messages or translation. + * + * This method may be overridden in child exception classes in order + * to add functionality not present in PEAR_Exception and is a placeholder + * to define API + * + * The returned array must be an associative array of parameter => value like so: + *
+     * array('name' => $name, 'context' => array(...))
+     * 
+ * @return array + */ + public function getErrorData() { - $msg = " #{$this->_method} at {$this->file} ({$this->line})\n" . - " {$this->message}\n"; - if ($this->cause instanceof Exception) { - return $this->cause->_getCauseMessage() . $msg; - } - return $msg; + return array(); } /** - * @return Exception_object The context of the exception + * Returns the exception that caused this exception to be thrown + * @access public + * @return Exception|array The context of the exception */ public function getCause() { return $this->cause; } + /** + * Function must be public to call on caused exceptions + * @param array + */ + public function getCauseMessage(&$causes) + { + $trace = $this->getTraceSafe(); + $cause = array('class' => get_class($this), + 'message' => $this->message, + 'file' => 'unknown', + 'line' => 'unknown'); + if (isset($trace[0])) { + if (isset($trace[0]['file'])) { + $cause['file'] = $trace[0]['file']; + $cause['line'] = $trace[0]['line']; + } + } + if ($this->cause instanceof PEAR_Exception) { + $this->cause->getCauseMessage($causes); + } + if (is_array($this->cause)) { + foreach ($this->cause as $cause) { + if ($cause instanceof PEAR_Exception) { + $cause->getCauseMessage($causes); + } elseif (is_array($cause) && isset($cause['message'])) { + // PEAR_ErrorStack warning + $causes[] = array( + 'class' => $cause['package'], + 'message' => $cause['message'], + 'file' => isset($cause['context']['file']) ? + $cause['context']['file'] : + 'unknown', + 'line' => isset($cause['context']['line']) ? + $cause['context']['line'] : + 'unknown', + ); + } + } + } + } + + public function getTraceSafe() + { + if (!isset($this->_trace)) { + $this->_trace = $this->getTrace(); + if (empty($this->_trace)) { + $backtrace = debug_backtrace(); + $this->_trace = array($backtrace[count($backtrace)-1]); + } + } + return $this->_trace; + } + public function getErrorClass() { - return $this->error_class; + $trace = $this->getTraceSafe(); + return $trace[0]['class']; } public function getErrorMethod() { - return $this->error_method; + $trace = $this->getTraceSafe(); + return $trace[0]['function']; } public function __toString() { - $str = get_class($this) . " occurred: \n" . - " Error message: {$this->message}\n" . - " Error code : {$this->code}\n" . - " File (Line) : {$this->file} ({$this->line})\n" . - " Method : {$this->_method}\n"; - if ($this->cause instanceof Exception) { - $str .= " Nested Error :\n" . $this->_getCauseMessage(); - } if (isset($_SERVER['REQUEST_URI'])) { - return nl2br('
'.htmlentities($str).'
'); + return $this->toHtml(); + } + return $this->toText(); + } + + public function toHtml() + { + $trace = $this->getTraceSafe(); + $causes = array(); + $this->getCauseMessage($causes); + $html = '' . "\n"; + foreach ($causes as $i => $cause) { + $html .= '\n"; + } + $html .= '' . "\n" + . '' + . '' + . '' . "\n"; + + foreach ($trace as $k => $v) { + $html .= '' + . '' + . '' . "\n"; + } + $html .= '' + . '' + . '' . "\n" + . '
' + . str_repeat('-', $i) . ' ' . $cause['class'] . ': ' + . htmlspecialchars($cause['message']) . ' in ' . $cause['file'] . ' ' + . 'on line ' . $cause['line'] . '' + . "
Exception trace
#FunctionLocation
' . $k . ''; + if (!empty($v['class'])) { + $html .= $v['class'] . $v['type']; + } + $html .= $v['function']; + $args = array(); + if (!empty($v['args'])) { + foreach ($v['args'] as $arg) { + if (is_null($arg)) $args[] = 'null'; + elseif (is_array($arg)) $args[] = 'Array'; + elseif (is_object($arg)) $args[] = 'Object('.get_class($arg).')'; + elseif (is_bool($arg)) $args[] = $arg ? 'true' : 'false'; + elseif (is_int($arg) || is_double($arg)) $args[] = $arg; + else { + $arg = (string)$arg; + $str = htmlspecialchars(substr($arg, 0, 16)); + if (strlen($arg) > 16) $str .= '…'; + $args[] = "'" . $str . "'"; + } + } + } + $html .= '(' . implode(', ',$args) . ')' + . '' . $v['file'] . ':' . $v['line'] . '
' . ($k+1) . '{main} 
'; + return $html; + } + + public function toText() + { + $causes = array(); + $this->getCauseMessage($causes); + $causeMsg = ''; + foreach ($causes as $i => $cause) { + $causeMsg .= str_repeat(' ', $i) . $cause['class'] . ': ' + . $cause['message'] . ' in ' . $cause['file'] + . ' on line ' . $cause['line'] . "\n"; } - return $str; + return $causeMsg . $this->getTraceAsString(); } } diff --git a/pear/PEAR/Installer.php b/pear/PEAR/Installer.php index 5b178267813c..af4ae5b62e68 100644 --- a/pear/PEAR/Installer.php +++ b/pear/PEAR/Installer.php @@ -165,7 +165,14 @@ function _installFile($file, $atts, $tmp_path, $options) include_once "OS/Guess.php"; $os = new OS_Guess(); } - if (!$os->matchSignature($atts['platform'])) { + if (strlen($atts['platform']) && $atts['platform']{0} == '!') { + $negate = true; + $platform = substr($atts['platform'], 1); + } else { + $negate = false; + $platform = $atts['platform']; + } + if ((bool) $os->matchSignature($platform) === $negate) { $this->log(3, "skipped $file (meant for $atts[platform], we are ".$os->getSignature().")"); return PEAR_INSTALLER_SKIPPED; } @@ -790,28 +797,43 @@ function install($pkgfile, $options = array()) $this->log(1, "\nBuild process completed successfully"); foreach ($built as $ext) { $bn = basename($ext['file']); - list($_ext_name, ) = explode('.', $bn); - if (extension_loaded($_ext_name)) { - $this->raiseError("Extension '$_ext_name' already loaded. Please unload it ". - "in your php.ini file prior to install or upgrade it."); - } - // extension dir must be created if it doesn't exist - // patch by Tomas Cox (modified by Greg Beaver) - $ext_dir = $this->config->get('ext_dir'); - if (!@is_dir($ext_dir) && !System::mkdir(array('-p', $ext_dir))) { - $this->log(3, "+ mkdir -p $ext_dir"); - return $this->raiseError("failed to create extension dir '$ext_dir'"); + list($_ext_name, $_ext_suff) = explode('.', $bn); + if ($_ext_suff == '.so' || $_ext_suff == '.dll') { + if (extension_loaded($_ext_name)) { + $this->raiseError("Extension '$_ext_name' already loaded. " . + 'Please unload it in your php.ini file ' . + 'prior to install or upgrade'); + } + $role = 'ext'; + } else { + $role = 'src'; } - $dest = $ext_dir . DIRECTORY_SEPARATOR . $bn; - $this->log(1, "Installing '$bn' at ext_dir ($dest)"); - $this->log(3, "+ cp $ext[file] ext_dir ($dest)"); + $dest = $ext['dest']; + $this->log(1, "Installing '$ext[file]'"); $copyto = $this->_prependPath($dest, $this->installroot); + $copydir = dirname($copyto); + if (!@is_dir($copydir)) { + if (!$this->mkDirHier($copydir)) { + return $this->raiseError("failed to mkdir $copydir", + PEAR_INSTALLER_FAILED); + } + $this->log(3, "+ mkdir $copydir"); + } if (!@copy($ext['file'], $copyto)) { - $this->rollbackFileTransaction(); - return $this->raiseError("failed to copy $bn to $copyto"); + return $this->raiseError("failed to write $copyto", PEAR_INSTALLER_FAILED); } + $this->log(3, "+ cp $ext[file] $copyto"); + if (!OS_WINDOWS) { + $mode = 0666 & ~(int)octdec($this->config->get('umask')); + $this->addFileOperation('chmod', array($mode, $copyto)); + if (!@chmod($copyto, $mode)) { + $this->log(0, "failed to change mode of $copyto"); + } + } + $this->addFileOperation('rename', array($ext['file'], $copyto)); + $pkginfo['filelist'][$bn] = array( - 'role' => 'ext', + 'role' => $role, 'installed_as' => $dest, 'php_api' => $ext['php_api'], 'zend_mod_api' => $ext['zend_mod_api'], diff --git a/pear/PEAR/Registry.php b/pear/PEAR/Registry.php index f85bbfdd5644..631328bea9de 100644 --- a/pear/PEAR/Registry.php +++ b/pear/PEAR/Registry.php @@ -286,7 +286,9 @@ function _lock($mode = LOCK_EX) $open_mode = 'r'; } - $this->lock_fp = @fopen($this->lockfile, $open_mode); + if (!is_resource($this->lock_fp)) { + $this->lock_fp = @fopen($this->lockfile, $open_mode); + } if (!is_resource($this->lock_fp)) { return $this->raiseError("could not create lock file" . @@ -312,6 +314,9 @@ function _lock($mode = LOCK_EX) function _unlock() { $ret = $this->_lock(LOCK_UN); + if (is_resource($this->lock_fp)) { + fclose($this->lock_fp); + } $this->lock_fp = null; return $ret; } diff --git a/pear/PEAR/Remote.php b/pear/PEAR/Remote.php index c75b11b5c190..555ec63b6c92 100644 --- a/pear/PEAR/Remote.php +++ b/pear/PEAR/Remote.php @@ -115,10 +115,10 @@ function call($method) $this->saveCache($_args, $result); }; return $result; - } - if (!@include_once("XML/RPC.php")) { + } elseif (!@include_once("XML/RPC.php")) { return $this->raiseError("For this remote PEAR operation you need to install the XML_RPC package"); } + array_shift($args); $server_host = $this->config->get('master_server'); $username = $this->config->get('username'); diff --git a/pear/PEAR/RunTest.php b/pear/PEAR/RunTest.php new file mode 100644 index 000000000000..707bcdfe303b --- /dev/null +++ b/pear/PEAR/RunTest.php @@ -0,0 +1,363 @@ + | +// | Greg Beaver | +// | | +// +----------------------------------------------------------------------+ +// +// $Id$ +// + +/** + * Simplified version of PHP's test suite + * -- EXPERIMENTAL -- + + Try it with: + + $ php -r 'include "../PEAR/RunTest.php"; $t=new PEAR_RunTest; $o=$t->run("./pear_system.phpt");print_r($o);' + + +TODO: + +Actually finish the development and testing + + */ + +require_once 'PEAR.php'; +require_once 'PEAR/Config.php'; + +define('DETAILED', 1); +putenv("PHP_PEAR_RUNTESTS=1"); + +class PEAR_RunTest +{ + var $_logger; + + /** + * An object that supports the PEAR_Common->log() signature, or null + * @param PEAR_Common|null + */ + function PEAR_RunTest($logger = null) + { + $this->_logger = $logger; + } + + // + // Run an individual test case. + // + + function run($file, $ini_settings = '') + { + $cwd = getcwd(); + $conf = &PEAR_Config::singleton(); + $php = $conf->get('php_bin'); + //var_dump($php);exit; + global $log_format, $info_params, $ini_overwrites; + + $info_params = ''; + $log_format = 'LEOD'; + + // Load the sections of the test file. + $section_text = array( + 'TEST' => '(unnamed test)', + 'SKIPIF' => '', + 'GET' => '', + 'ARGS' => '', + ); + + if (!is_file($file) || !$fp = fopen($file, "r")) { + return PEAR::raiseError("Cannot open test file: $file"); + } + + $section = ''; + while (!feof($fp)) { + $line = fgets($fp); + + // Match the beginning of a section. + if (ereg('^--([A-Z]+)--',$line,$r)) { + $section = $r[1]; + $section_text[$section] = ''; + continue; + } + + // Add to the section text. + $section_text[$section] .= $line; + } + fclose($fp); + + $shortname = str_replace($cwd.'/', '', $file); + $tested = trim($section_text['TEST'])." [$shortname]"; + + $tmp = realpath(dirname($file)); + $tmp_skipif = $tmp . uniqid('/phpt.'); + $tmp_file = ereg_replace('\.phpt$','.php',$file); + $tmp_post = $tmp . uniqid('/phpt.'); + + @unlink($tmp_skipif); + @unlink($tmp_file); + @unlink($tmp_post); + + // unlink old test results + @unlink(ereg_replace('\.phpt$','.diff',$file)); + @unlink(ereg_replace('\.phpt$','.log',$file)); + @unlink(ereg_replace('\.phpt$','.exp',$file)); + @unlink(ereg_replace('\.phpt$','.out',$file)); + + // Check if test should be skipped. + $info = ''; + $warn = false; + if (array_key_exists('SKIPIF', $section_text)) { + if (trim($section_text['SKIPIF'])) { + $this->save_text($tmp_skipif, $section_text['SKIPIF']); + //$extra = substr(PHP_OS, 0, 3) !== "WIN" ? + // "unset REQUEST_METHOD;": ""; + + //$output = `$extra $php $info_params -f $tmp_skipif`; + $output = `$php $info_params -f $tmp_skipif`; + unlink($tmp_skipif); + if (eregi("^skip", trim($output))) { + $skipreason = "SKIP $tested"; + $reason = (eregi("^skip[[:space:]]*(.+)\$", trim($output))) ? eregi_replace("^skip[[:space:]]*(.+)\$", "\\1", trim($output)) : FALSE; + if ($reason) { + $skipreason .= " (reason: $reason)"; + } + $this->_logger->log(0, $skipreason); + if (isset($old_php)) { + $php = $old_php; + } + return 'SKIPPED'; + } + if (eregi("^info", trim($output))) { + $reason = (ereg("^info[[:space:]]*(.+)\$", trim($output))) ? ereg_replace("^info[[:space:]]*(.+)\$", "\\1", trim($output)) : FALSE; + if ($reason) { + $info = " (info: $reason)"; + } + } + if (eregi("^warn", trim($output))) { + $reason = (ereg("^warn[[:space:]]*(.+)\$", trim($output))) ? ereg_replace("^warn[[:space:]]*(.+)\$", "\\1", trim($output)) : FALSE; + if ($reason) { + $warn = true; /* only if there is a reason */ + $info = " (warn: $reason)"; + } + } + } + } + + // We've satisfied the preconditions - run the test! + $this->save_text($tmp_file,$section_text['FILE']); + + $args = $section_text['ARGS'] ? ' -- '.$section_text['ARGS'] : ''; + + $cmd = "$php$ini_settings -f $tmp_file$args 2>&1"; + if (isset($this->_logger)) { + $this->_logger->log(2, 'Running command "' . $cmd . '"'); + } + + $savedir = getcwd(); // in case the test moves us around + if (isset($section_text['RETURNS'])) { + ob_start(); + system($cmd, $return_value); + $out = ob_get_contents(); + ob_end_clean(); + @unlink($tmp_post); + $section_text['RETURNS'] = (int) trim($section_text['RETURNS']); + $returnfail = ($return_value != $section_text['RETURNS']); + } else { + $out = `$cmd`; + $returnfail = false; + } + chdir($savedir); + // Does the output match what is expected? + $output = trim($out); + $output = preg_replace('/\r\n/', "\n", $output); + + if (isset($section_text['EXPECTF']) || isset($section_text['EXPECTREGEX'])) { + if (isset($section_text['EXPECTF'])) { + $wanted = trim($section_text['EXPECTF']); + } else { + $wanted = trim($section_text['EXPECTREGEX']); + } + $wanted_re = preg_replace('/\r\n/',"\n",$wanted); + if (isset($section_text['EXPECTF'])) { + $wanted_re = preg_quote($wanted_re, '/'); + // Stick to basics + $wanted_re = str_replace("%s", ".+?", $wanted_re); //not greedy + $wanted_re = str_replace("%i", "[+\-]?[0-9]+", $wanted_re); + $wanted_re = str_replace("%d", "[0-9]+", $wanted_re); + $wanted_re = str_replace("%x", "[0-9a-fA-F]+", $wanted_re); + $wanted_re = str_replace("%f", "[+\-]?\.?[0-9]+\.?[0-9]*(E-?[0-9]+)?", $wanted_re); + $wanted_re = str_replace("%c", ".", $wanted_re); + // %f allows two points "-.0.0" but that is the best *simple* expression + } + /* DEBUG YOUR REGEX HERE + var_dump($wanted_re); + print(str_repeat('=', 80) . "\n"); + var_dump($output); + */ + if (!$returnfail && preg_match("/^$wanted_re\$/s", $output)) { + @unlink($tmp_file); + $this->_logger->log(0, "PASS $tested$info"); + if (isset($old_php)) { + $php = $old_php; + } + return 'PASSED'; + } + + } else { + $wanted = trim($section_text['EXPECT']); + $wanted = preg_replace('/\r\n/',"\n",$wanted); + // compare and leave on success + $ok = (0 == strcmp($output,$wanted)); + if (!$returnfail && $ok) { + @unlink($tmp_file); + $this->_logger->log(0, "PASS $tested$info"); + if (isset($old_php)) { + $php = $old_php; + } + return 'PASSED'; + } + } + + // Test failed so we need to report details. + if ($warn) { + $this->_logger->log(0, "WARN $tested$info"); + } else { + $this->_logger->log(0, "FAIL $tested$info"); + } + + if (isset($section_text['RETURNS'])) { + $GLOBALS['__PHP_FAILED_TESTS__'][] = array( + 'name' => $file, + 'test_name' => $tested, + 'output' => ereg_replace('\.phpt$','.log', $file), + 'diff' => ereg_replace('\.phpt$','.diff', $file), + 'info' => $info, + 'return' => $return_value + ); + } else { + $GLOBALS['__PHP_FAILED_TESTS__'][] = array( + 'name' => $file, + 'test_name' => $tested, + 'output' => ereg_replace('\.phpt$','.log', $file), + 'diff' => ereg_replace('\.phpt$','.diff', $file), + 'info' => $info, + ); + } + + // write .exp + if (strpos($log_format,'E') !== FALSE) { + $logname = ereg_replace('\.phpt$','.exp',$file); + if (!$log = fopen($logname,'w')) { + return PEAR::raiseError("Cannot create test log - $logname"); + } + fwrite($log,$wanted); + fclose($log); + } + + // write .out + if (strpos($log_format,'O') !== FALSE) { + $logname = ereg_replace('\.phpt$','.out',$file); + if (!$log = fopen($logname,'w')) { + return PEAR::raiseError("Cannot create test log - $logname"); + } + fwrite($log,$output); + fclose($log); + } + + // write .diff + if (strpos($log_format,'D') !== FALSE) { + $logname = ereg_replace('\.phpt$','.diff',$file); + if (!$log = fopen($logname,'w')) { + return PEAR::raiseError("Cannot create test log - $logname"); + } + fwrite($log, $this->generate_diff($wanted, $output, + isset($section_text['RETURNS']) ? array(trim($section_text['RETURNS']), + $return_value) : null)); + fclose($log); + } + + // write .log + if (strpos($log_format,'L') !== FALSE) { + $logname = ereg_replace('\.phpt$','.log',$file); + if (!$log = fopen($logname,'w')) { + return PEAR::raiseError("Cannot create test log - $logname"); + } + fwrite($log," +---- EXPECTED OUTPUT +$wanted +---- ACTUAL OUTPUT +$output +---- FAILED +"); + if ($returnfail) { + fwrite($log," +---- EXPECTED RETURN +$section_text[RETURNS] +---- ACTUAL RETURN +$return_value +"); + } + fclose($log); + //error_report($file,$logname,$tested); + } + + if (isset($old_php)) { + $php = $old_php; + } + + return $warn ? 'WARNED' : 'FAILED'; + } + + function generate_diff($wanted, $output, $return_value) + { + $w = explode("\n", $wanted); + $o = explode("\n", $output); + $w1 = array_diff_assoc($w,$o); + $o1 = array_diff_assoc($o,$w); + $w2 = array(); + $o2 = array(); + foreach($w1 as $idx => $val) $w2[sprintf("%03d<",$idx)] = sprintf("%03d- ", $idx+1).$val; + foreach($o1 as $idx => $val) $o2[sprintf("%03d>",$idx)] = sprintf("%03d+ ", $idx+1).$val; + $diff = array_merge($w2, $o2); + ksort($diff); + if ($return_value) { + $extra = "##EXPECTED: $return_value[0]\r\n##RETURNED: $return_value[1]"; + } else { + $extra = ''; + } + return implode("\r\n", $diff) . $extra; + } + + // + // Write the given text to a temporary file, and return the filename. + // + + function save_text($filename, $text) + { + if (!$fp = fopen($filename, 'w')) { + return PEAR::raiseError("Cannot open file '" . $filename . "' (save_text)"); + } + fwrite($fp,$text); + fclose($fp); + if (1 < DETAILED) echo " +FILE $filename {{{ +$text +}}} +"; + } + +} +?> \ No newline at end of file diff --git a/pear/go-pear-list.php b/pear/go-pear-list.php index e2a37881746c..3085306cceae 100755 --- a/pear/go-pear-list.php +++ b/pear/go-pear-list.php @@ -7,15 +7,15 @@ */ $packages = array( // required packages for the installer -"PEAR" => "1.3.1", -"XML_RPC" => "1.1.0", +"PEAR" => "1.3.6", +"XML_RPC" => "1.4.0", "Console_Getopt" => "1.2", -"Archive_Tar" => "1.2", +"Archive_Tar" => "1.3.1", // required packages for the web frontend -"PEAR_Frontend_Web" => "0.4" +"PEAR_Frontend_Web" => "0.4", "HTML_Template_IT" => "1.1", -"Net_UserAgent_Detect" => "1.0", +"Net_UserAgent_Detect" => "2.0.1", ); ?> diff --git a/pear/go-pear.bat b/pear/go-pear.bat new file mode 100644 index 000000000000..b61dc602b5ee --- /dev/null +++ b/pear/go-pear.bat @@ -0,0 +1,4 @@ +@ECHO OFF +set PHP_BIN=php.exe +%PHP_BIN% -d output_buffering=0 PEAR\go-pear.php %1 +pause diff --git a/pear/package-Archive_Tar.xml b/pear/package-Archive_Tar.xml index 7d54a01739fe..14787a08ab06 100644 --- a/pear/package-Archive_Tar.xml +++ b/pear/package-Archive_Tar.xml @@ -19,7 +19,7 @@ loaded. Bz2 compression is also supported with the bz2 extension loaded. ssb helper - Stig Sæther Bakken + Stig Bakken stig@php.net diff --git a/pear/package-PEAR.xml b/pear/package-PEAR.xml index 4811c9dfbc87..9a134fdd4c52 100644 --- a/pear/package-PEAR.xml +++ b/pear/package-PEAR.xml @@ -4,22 +4,22 @@ PEAR PEAR Base System The PEAR package contains: - * the PEAR base class - * the PEAR_Error error handling mechanism - * the alpha-quality PEAR_ErrorStack advanced error handling mechanism * the PEAR installer, for creating, distributing and installing packages + * the alpha-quality PEAR_Exception php5-only exception class + * the beta-quality PEAR_ErrorStack advanced error handling mechanism + * the PEAR_Error error handling mechanism * the OS_Guess class for retrieving info about the OS where PHP is running on * the System class for quick handling common operations with files and directories + * the PEAR base class - PHP License ssb lead - Stig Sæther Bakken + Stig Bakken stig@php.net @@ -29,10 +29,10 @@ cox@idecnet.com - mj - developer - Martin Jansen - mj@php.net + cellog + lead + Greg Beaver + cellog@php.net pajoye @@ -41,32 +41,29 @@ pajoye@pearfr.org - cellog - lead - Greg Beaver - cellog@php.net + mj + developer + Martin Jansen + mj@php.net - 1.3.2 - 2004-04-06 + 1.3.6 + 2005-08-18 stable + PHP License -Installer: - * fix Bug #1186 raise a notice error on PEAR::Common $_packageName - * fix Bug #1249 display the right state when using --force option + * Bump XML_RPC dependency to 1.4.0 + * return by reference from PEAR::raiseError() - - - - + + + - - @@ -78,22 +75,25 @@ Installer: + + + + + + - - - - + + + - - - + @@ -114,17 +114,33 @@ Installer: + + + + Archive_Tar Console_Getopt - XML_RPC + XML_RPC xml pcre + xmlrpc + + 1.3.5 + 2005-02-18 + stable + PHP License + + * fix Bug #3505: pecl can't install PDO + * enhance pear run-tests dramatically + * fix Bug #3506: pear install should export the pear version into the environment + + 1.3.1 2004-04-06 @@ -147,22 +163,49 @@ PEAR_ErrorStack: - 1.3 - 2004-02-20 + 1.3.3 + 2004-10-28 stable -PEAR Installer: - -* Bug #171 --alldeps with a rel="eq" should install the required version, if possible -* Bug #249 installing from an url doesnt work -* Bug #248 --force command does not work as expected -* Bug #293 [Patch] PEAR_Error not calling static method callbacks for error-handler -* Bug #324 pear -G gives Fatal Error (PHP-GTK not installed, but error is at engine level) -* Bug #594 PEAR_Common::analyzeSourceCode fails on string with $var and { -* Bug #521 Incorrect filename in naming warnings -* Moved download code into its own class -* Fully unit tested the installer, packager, downloader, and PEAR_Common +Installer: + * fix Bug #1186 raise a notice error on PEAR::Common $_packageName + * fix Bug #1249 display the right state when using --force option + * fix Bug #2189 upgrade-all stops if dependancy fails + * fix Bug #1637 The use of interface causes warnings when packaging with PEAR + * fix Bug #1420 Parser bug for T_DOUBLE_COLON + * fix Request #2220 pear5 build fails on dual php4/php5 system + * fix Bug #1163 pear makerpm fails with packages that supply role="doc" +Other: + * add PEAR_Exception class for PHP5 users + * fix critical problem in package.xml for linux in 1.3.2 + * fix staticPopCallback() in PEAR_ErrorStack + * fix warning in PEAR_Registry for windows 98 users + + + + 1.3.3.1 + 2004-11-08 + stable + + add RunTest.php to package.xml, make run-tests display failed tests, and use ui + + + + 1.3.4 + 2005-01-01 + stable + + * fix a serious problem caused by a bug in all versions of PHP that caused multiple registration + of the shutdown function of PEAR.php + * fix Bug #2861: package.dtd does not define NUMBER + * fix Bug #2946: ini_set warning errors + * fix Bug #3026: Dependency type "ne" is needed, "not" is not handled + properly + * fix Bug #3061: potential warnings in PEAR_Exception + * implement Request #2848: PEAR_ErrorStack logger extends, PEAR_ERRORSTACK_DIE + * implement Request #2914: Dynamic Include Path for run-tests command + * make pear help listing more useful (put how-to-use info at the bottom of the listing) diff --git a/pear/package.dtd b/pear/package.dtd index 45beb7ba849f..5ed7a7e9a1a8 100644 --- a/pear/package.dtd +++ b/pear/package.dtd @@ -1,5 +1,5 @@ - + @@ -65,8 +65,8 @@ outputData('WARNING: running in safe mode requires that all files created ' . + 'be the same uid as the current script. PHP reports this script is uid: ' . + @getmyuid() . ', and current user is: ' . @get_current_user()); +} $pear_user_config = ''; $pear_system_config = ''; @@ -212,9 +217,6 @@ function usage($error = null, $helpsubject = null) $put = cmdHelp($helpsubject); } else { $put = - "Usage: $progname [options] command [command-options] \n". - "Type \"$progname help options\" to list all options.\n". - "Type \"$progname help \" to get the help for the specified command.\n". "Commands:\n"; $maxlen = max(array_map("strlen", $all_commands)); $formatstr = "%-{$maxlen}s %s\n"; @@ -222,6 +224,11 @@ function usage($error = null, $helpsubject = null) foreach ($all_commands as $cmd => $class) { $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd)); } + $put .= + "Usage: $progname [options] command [command-options] \n". + "Type \"$progname help options\" to list all options.\n". + "Type \"$progname help shortcuts\" to list all command shortcuts.\n". + "Type \"$progname help \" to get the help for the specified command."; } fputs($stderr, "$put\n"); fclose($stderr); diff --git a/pear/template.spec b/pear/template.spec index 9bf356c7f5a6..f6f91a524ec7 100644 --- a/pear/template.spec +++ b/pear/template.spec @@ -30,25 +30,29 @@ pear -v -c %{buildroot}/pearrc \ %build echo BuildRoot=%{buildroot} +%clean +[ -n "%{buildroot}" -a "%{buildroot}" != / ] && rm -rf %{buildroot} + %postun pear uninstall --nodeps -r @package@ -rm @rpm_xml_dir@/@package@.xml %post pear install --nodeps -r @rpm_xml_dir@/@package@.xml %install -pear -c %{buildroot}/pearrc install --nodeps -R %{buildroot} \ - $RPM_SOURCE_DIR/@package@-%{version}.tgz +pear -c "%{buildroot}/pearrc" install --nodeps -R "%{buildroot}" \ + "$RPM_SOURCE_DIR/@package@-%{version}.tgz" rm %{buildroot}/pearrc rm %{buildroot}/%{_libdir}/php/pear/.filemap rm %{buildroot}/%{_libdir}/php/pear/.lock rm -rf %{buildroot}/%{_libdir}/php/pear/.registry -if [ -d "%{buildroot}/docs/@package@/doc" ]; then - rm -rf $RPM_BUILD_DIR/doc - mv %{buildroot}/docs/@package@/doc $RPM_BUILD_DIR - rm -rf %{buildroot}/docs -fi +for DOCDIR in docs doc examples; do + if [ -d "%{buildroot}/docs/@package@/$DOCDIR" ]; then + rm -rf $RPM_BUILD_DIR/$DOCDIR + mv %{buildroot}/docs/@package@/$DOCDIR $RPM_BUILD_DIR + rm -rf %{buildroot}/docs + fi +done mkdir -p %{buildroot}@rpm_xml_dir@ tar -xzf $RPM_SOURCE_DIR/@package@-%{version}.tgz package.xml cp -p package.xml %{buildroot}@rpm_xml_dir@/@package@.xml diff --git a/php.ini-dist b/php.ini-dist index 51387cb4ac12..5f2209bf01f1 100644 --- a/php.ini-dist +++ b/php.ini-dist @@ -137,7 +137,7 @@ zlib.output_compression = Off ; implications and is generally recommended for debugging purposes only. implicit_flush = Off -; The unserialize callback function will called (with the undefind class' +; The unserialize callback function will be called (with the undefined class' ; name as parameter), if the unserializer finds an undefined class ; which should be instanciated. ; A warning appears if the specified function is not defined, or if the @@ -214,7 +214,7 @@ disable_functions = disable_classes = ; Colors for Syntax Highlighting mode. Anything that's acceptable in -; would work. +; would work. ;highlight.string = #DD0000 ;highlight.comment = #FF9900 ;highlight.keyword = #007700 @@ -248,7 +248,7 @@ memory_limit = 8M ; Maximum amount of memory a script may consume (8MB) ; error_reporting is a bit-field. Or each number up to get desired error ; reporting level -; E_ALL - All errors and warnings +; E_ALL - All errors and warnings (doesn't include E_STRICT) ; E_ERROR - fatal run-time errors ; E_WARNING - run-time warnings (non-fatal errors) ; E_PARSE - compile-time parse errors @@ -259,7 +259,7 @@ memory_limit = 8M ; Maximum amount of memory a script may consume (8MB) ; empty string) ; E_STRICT - run-time notices, enable to have PHP suggest changes ; to your code which will ensure the best interoperability -; and forward compatability of your code +; and forward compatibility of your code ; E_CORE_ERROR - fatal errors that occur during PHP's initial startup ; E_CORE_WARNING - warnings (non-fatal errors) that occur during PHP's ; initial startup @@ -394,6 +394,13 @@ register_long_arrays = On ; should turn it off for increased performance. register_argc_argv = On +; When enabled, the SERVER and ENV variables are created when they're first +; used (Just In Time) instead of when the script starts. If these variables +; are not used within a script, having this directive on will result in a +; performance gain. The PHP directives register_globals, register_long_arrays, +; and register_argc_argv must be disabled for this directive to have any affect. +auto_globals_jit = On + ; Maximum size of POST data that PHP will accept. post_max_size = 8M @@ -477,6 +484,9 @@ enable_dl = On ; Set to 1 if running under IIS. Default is zero. ; fastcgi.impersonate = 1; +; Disable logging through FastCGI connection +; fastcgi.log = 0 + ; cgi.rfc2616_headers configuration option tells PHP what type of headers to ; use when sending HTTP response code. If it's set 0 PHP sends Status: header that ; is supported by Apache. When this option is set to 1 PHP will send @@ -550,6 +560,7 @@ default_socket_timeout = 60 ;Note that ODBC support is built in, so no dll is needed for it. ; +;extension=php_mbstring.dll ;extension=php_bz2.dll ;extension=php_cpdf.dll ;extension=php_curl.dll @@ -561,14 +572,12 @@ default_socket_timeout = 60 ;extension=php_filepro.dll ;extension=php_gd2.dll ;extension=php_gettext.dll -;extension=php_iconv.dll ;extension=php_ifx.dll ;extension=php_iisfunc.dll ;extension=php_imap.dll ;extension=php_interbase.dll ;extension=php_java.dll ;extension=php_ldap.dll -;extension=php_mbstring.dll ;extension=php_mcrypt.dll ;extension=php_mhash.dll ;extension=php_mime_magic.dll @@ -617,7 +626,7 @@ smtp_port = 25 ; Force the addition of the specified parameters to be passed as extra parameters ; to the sendmail binary. These parameters will always replace the value of ; the 5th parameter to mail(), even in safe mode. -;mail.force_extra_paramaters = +;mail.force_extra_parameters = [SQL] sql.safe_mode = Off @@ -681,11 +690,11 @@ mysql.default_user = ; file will be able to reveal the password as well. mysql.default_password = -; Maximum time (in secondes) for connect timeout. -1 means no limimt +; Maximum time (in secondes) for connect timeout. -1 means no limit mysql.connect_timeout = 60 ; Trace mode. When trace_mode is active (=On), warnings for table/index scans and -; SQL-Erros will be displayed. +; SQL-Errors will be displayed. mysql.trace_mode = Off [MySQLI] @@ -711,10 +720,10 @@ mysqli.default_user = ; Default password for mysqli_connect() (doesn't apply in safe mode). ; Note that this is generally a *bad* idea to store passwords in this file. -; *Any* user with PHP access can run 'echo get_cfg_var("mysqli.default_password") +; *Any* user with PHP access can run 'echo get_cfg_var("mysqli.default_pw") ; and reveal this password! And of course, any users with read access to this ; file will be able to reveal the password as well. -mysqli.default_password = +mysqli.default_pw = ; Allow or prevent reconnect mysqli.reconnect = Off @@ -927,7 +936,7 @@ session.gc_maxlifetime = 1440 ; PHP 4.2 and less have an undocumented feature/bug that allows you to ; to initialize a session variable in the global scope, albeit register_globals ; is disabled. PHP 4.3 and later will warn you, if this feature is used. -; You can disable the feature and the warning seperately. At this time, +; You can disable the feature and the warning separately. At this time, ; the warning is only displayed, if bug_compat_42 is enabled. session.bug_compat_42 = 1 @@ -1089,10 +1098,6 @@ pfpro.defaulttimeout = 30 ; Default proxy password. ;pfpro.proxypassword = -[Sockets] -; Use the system read() function instead of the php_read() wrapper. -sockets.use_system_read = On - [com] ; path to a file containing GUIDs, IIDs or filenames of files with TypeLibs ;com.typelib_file = diff --git a/php.ini-recommended b/php.ini-recommended index e7afd66fc103..e9b642c33f8c 100644 --- a/php.ini-recommended +++ b/php.ini-recommended @@ -195,7 +195,7 @@ zlib.output_compression = Off ; implications and is generally recommended for debugging purposes only. implicit_flush = Off -; The unserialize callback function will called (with the undefind class' +; The unserialize callback function will be called (with the undefined class' ; name as parameter), if the unserializer finds an undefined class ; which should be instanciated. ; A warning appears if the specified function is not defined, or if the @@ -272,7 +272,7 @@ disable_functions = disable_classes = ; Colors for Syntax Highlighting mode. Anything that's acceptable in -; would work. +; would work. ;highlight.string = #DD0000 ;highlight.comment = #FF9900 ;highlight.keyword = #007700 @@ -306,7 +306,7 @@ memory_limit = 8M ; Maximum amount of memory a script may consume (8MB) ; error_reporting is a bit-field. Or each number up to get desired error ; reporting level -; E_ALL - All errors and warnings +; E_ALL - All errors and warnings (doesn't include E_STRICT) ; E_ERROR - fatal run-time errors ; E_WARNING - run-time warnings (non-fatal errors) ; E_PARSE - compile-time parse errors @@ -317,7 +317,7 @@ memory_limit = 8M ; Maximum amount of memory a script may consume (8MB) ; empty string) ; E_STRICT - run-time notices, enable to have PHP suggest changes ; to your code which will ensure the best interoperability -; and forward compatability of your code +; and forward compatibility of your code ; E_CORE_ERROR - fatal errors that occur during PHP's initial startup ; E_CORE_WARNING - warnings (non-fatal errors) that occur during PHP's ; initial startup @@ -452,6 +452,13 @@ register_long_arrays = Off ; should turn it off for increased performance. register_argc_argv = Off +; When enabled, the SERVER and ENV variables are created when they're first +; used (Just In Time) instead of when the script starts. If these variables +; are not used within a script, having this directive on will result in a +; performance gain. The PHP directives register_globals, register_long_arrays, +; and register_argc_argv must be disabled for this directive to have any affect. +auto_globals_jit = On + ; Maximum size of POST data that PHP will accept. post_max_size = 8M @@ -535,6 +542,9 @@ enable_dl = On ; Set to 1 if running under IIS. Default is zero. ; fastcgi.impersonate = 1; +; Disable logging through FastCGI connection +; fastcgi.log = 0 + ; cgi.rfc2616_headers configuration option tells PHP what type of headers to ; use when sending HTTP response code. If it's set 0 PHP sends Status: header that ; is supported by Apache. When this option is set to 1 PHP will send @@ -608,6 +618,7 @@ default_socket_timeout = 60 ;Note that ODBC support is built in, so no dll is needed for it. ; +;extension=php_mbstring.dll ;extension=php_bz2.dll ;extension=php_cpdf.dll ;extension=php_curl.dll @@ -619,14 +630,12 @@ default_socket_timeout = 60 ;extension=php_filepro.dll ;extension=php_gd2.dll ;extension=php_gettext.dll -;extension=php_iconv.dll ;extension=php_ifx.dll ;extension=php_iisfunc.dll ;extension=php_imap.dll ;extension=php_interbase.dll ;extension=php_java.dll ;extension=php_ldap.dll -;extension=php_mbstring.dll ;extension=php_mcrypt.dll ;extension=php_mhash.dll ;extension=php_mime_magic.dll @@ -675,7 +684,7 @@ smtp_port = 25 ; Force the addition of the specified parameters to be passed as extra parameters ; to the sendmail binary. These parameters will always replace the value of ; the 5th parameter to mail(), even in safe mode. -;mail.force_extra_paramaters = +;mail.force_extra_parameters = [SQL] sql.safe_mode = Off @@ -739,11 +748,11 @@ mysql.default_user = ; file will be able to reveal the password as well. mysql.default_password = -; Maximum time (in secondes) for connect timeout. -1 means no limimt +; Maximum time (in secondes) for connect timeout. -1 means no limit mysql.connect_timeout = 60 ; Trace mode. When trace_mode is active (=On), warnings for table/index scans and -; SQL-Erros will be displayed. +; SQL-Errors will be displayed. mysql.trace_mode = Off [MySQLI] @@ -769,10 +778,10 @@ mysqli.default_user = ; Default password for mysqli_connect() (doesn't apply in safe mode). ; Note that this is generally a *bad* idea to store passwords in this file. -; *Any* user with PHP access can run 'echo get_cfg_var("mysqli.default_password") +; *Any* user with PHP access can run 'echo get_cfg_var("mysqli.default_pw") ; and reveal this password! And of course, any users with read access to this ; file will be able to reveal the password as well. -mysqli.default_password = +mysqli.default_pw = ; Allow or prevent reconnect mysqli.reconnect = Off @@ -985,7 +994,7 @@ session.gc_maxlifetime = 1440 ; PHP 4.2 and less have an undocumented feature/bug that allows you to ; to initialize a session variable in the global scope, albeit register_globals ; is disabled. PHP 4.3 and later will warn you, if this feature is used. -; You can disable the feature and the warning seperately. At this time, +; You can disable the feature and the warning separately. At this time, ; the warning is only displayed, if bug_compat_42 is enabled. session.bug_compat_42 = 0 @@ -1147,10 +1156,6 @@ pfpro.defaulttimeout = 30 ; Default proxy password. ;pfpro.proxypassword = -[Sockets] -; Use the system read() function instead of the php_read() wrapper. -sockets.use_system_read = On - [com] ; path to a file containing GUIDs, IIDs or filenames of files with TypeLibs ;com.typelib_file = diff --git a/regex/engine.c b/regex/engine.c index c4bdc8079f07..0682267f6180 100644 --- a/regex/engine.c +++ b/regex/engine.c @@ -270,7 +270,7 @@ sopno stopst; /* figure out what it matched */ switch (OP(m->g->strip[ss])) { case OEND: - assert(nope); + assert(PHP_REGEX_NOPE); break; case OCHAR: sp++; @@ -286,7 +286,7 @@ sopno stopst; break; case OBACK_: case O_BACK: - assert(nope); + assert(PHP_REGEX_NOPE); break; /* cases where length of match is hard to find */ case OQUEST_: @@ -389,7 +389,7 @@ sopno stopst; case OOR1: case OOR2: case O_CH: - assert(nope); + assert(PHP_REGEX_NOPE); break; case OLPAREN: i = OPND(m->g->strip[ss]); @@ -402,7 +402,7 @@ sopno stopst; m->pmatch[i].rm_eo = sp - m->offp; break; default: /* uh oh */ - assert(nope); + assert(PHP_REGEX_NOPE); break; } } @@ -606,12 +606,12 @@ sopno lev; /* PLUS nesting level */ return(NULL); break; default: /* uh oh */ - assert(nope); + assert(PHP_REGEX_NOPE); break; } /* "can't happen" */ - assert(nope); + assert(PHP_REGEX_NOPE); /* NOTREACHED */ return((unsigned char *)NULL); /* dummy */ } @@ -914,7 +914,7 @@ register states aft; /* states already known reachable after */ FWD(aft, aft, 1); break; default: /* ooooops... */ - assert(nope); + assert(PHP_REGEX_NOPE); break; } } diff --git a/regex/regexec.c b/regex/regexec.c index c8cb8fdf5644..bbfe094c96ca 100644 --- a/regex/regexec.c +++ b/regex/regexec.c @@ -16,7 +16,7 @@ #include "utils.h" #include "regex2.h" -static int nope = 0; /* for use in asserts; shuts lint up */ +#define PHP_REGEX_NOPE 0; /* for use in asserts; shuts lint up */ /* macros for manipulating states, small version */ #define states unsigned diff --git a/run-tests.php b/run-tests.php index 817113f600ad..cabc6cb9b972 100755 --- a/run-tests.php +++ b/run-tests.php @@ -37,7 +37,7 @@ */ -/* Sanity check to ensure that pcre extension needed by this script is avaliable. +/* Sanity check to ensure that pcre extension needed by this script is available. * In the event it is not, print a nice error message indicating that this script will * not run without it. */ @@ -423,12 +423,13 @@ function test_sort($a, $b) define('PHP_QA_EMAIL', 'qa-reports@lists.php.net'); define('QA_SUBMISSION_PAGE', 'http://qa.php.net/buildtest-process.php'); -/* We got failed Tests, offer the user to send and e-mail to QA team, unless NO_INTERACTION is set */ +/* We got failed Tests, offer the user to send an e-mail to QA team, unless NO_INTERACTION is set */ if (!getenv('NO_INTERACTION')) { $fp = fopen("php://stdin", "r+"); - echo "\nPlease allow this report to be send to the PHP QA\nteam. This will give us a better understanding in how\n"; - echo "PHP's test cases are doing.\n"; - echo "(choose \"s\" to just save the results to a file)? [Yns]: "; + echo "\nYou may have found a problem in PHP.\nWe would like to send this report automatically to the\n"; + echo "PHP QA team, to give us a better understanding of how\nthe test cases are doing. If you don't want to send it\n"; + echo "immediately, you can choose \"s\" to save the report to\na file that you can send us later.\n"; + echo "Do you want to send this report now? [Yns]: "; flush(); $user_input = fgets($fp, 10); $just_save_results = (strtolower($user_input[0]) == 's'); @@ -445,7 +446,6 @@ function test_sort($a, $b) if (!strncasecmp($user_input, 'y', 1) || strlen(trim($user_input)) == 0) { echo "\nPlease enter your email address.\n(Your address will be mangled so that it will not go out on any\nmailinglist in plain text): "; flush(); - $fp = fopen("php://stdin", "r+"); $user_email = trim(fgets($fp, 1024)); $user_email = str_replace("@", " at ", str_replace(".", " dot ", $user_email)); } @@ -477,7 +477,11 @@ function test_sort($a, $b) $autoconf = shell_exec('autoconf --version'); /* Always use the generated libtool - Mac OSX uses 'glibtool' */ $libtool = shell_exec($_SERVER['PWD'] . '/libtool --version'); - $sys_libtool = shell_exec('libtool --version'); + + /* Use shtool to find out if there is glibtool present (MacOSX) */ + $sys_libtool_path = shell_exec(dirname(__FILE__) . "/build/shtool path glibtool libtool"); + $sys_libtool = shell_exec(str_replace("\n", "", $sys_libtool_path) . ' --version'); + /* Try the most common flags for 'version' */ $flags = array('-v', '-V', '--version'); $cc_status=0; @@ -488,7 +492,7 @@ function test_sort($a, $b) break; } } - $ldd = shell_exec("ldd $php"); + $ldd = shell_exec("ldd $php 2>/dev/null"); } $failed_tests_data .= "Automake:\n$automake\n"; $failed_tests_data .= "Autoconf:\n$autoconf\n"; @@ -621,7 +625,7 @@ function system_with_timeout($commandline) $e = null; $n = @stream_select($r, $w, $e, 60); - if ($n == 0) { + if ($n === 0) { /* timed out */ $data .= "\n ** ERROR: process timed out **\n"; proc_terminate($proc); @@ -700,7 +704,7 @@ function run_test($php, $file, $test_cnt, $test_idx) } fclose($fp); - /* For GET/POST tests, check if cgi sapi is avaliable and if it is, use it. */ + /* For GET/POST tests, check if cgi sapi is available and if it is, use it. */ if ((!empty($section_text['GET']) || !empty($section_text['POST']))) { if (file_exists("./sapi/cgi/php")) { $old_php = $php; @@ -1147,13 +1151,13 @@ function get_summary($show_ext_summary) Number of tests : " . sprintf("%4d",$n_total). " " . sprintf("%8d",$x_total); if ($sum_results['BORKED']) { $summary .= " -Tests borked : " . sprintf("%4d (%3.1f%%)",$sum_results['BORKED'],$percent_results['BORKED']) . " --------"; +Tests borked : " . sprintf("%4d (%5.1f%%)",$sum_results['BORKED'],$percent_results['BORKED']) . " --------"; } $summary .= " -Tests skipped : " . sprintf("%4d (%3.1f%%)",$sum_results['SKIPPED'],$percent_results['SKIPPED']) . " -------- -Tests warned : " . sprintf("%4d (%3.1f%%)",$sum_results['WARNED'],$percent_results['WARNED']) . " " . sprintf("(%3.1f%%)",$x_warned) . " -Tests failed : " . sprintf("%4d (%3.1f%%)",$sum_results['FAILED'],$percent_results['FAILED']) . " " . sprintf("(%3.1f%%)",$x_failed) . " -Tests passed : " . sprintf("%4d (%3.1f%%)",$sum_results['PASSED'],$percent_results['PASSED']) . " " . sprintf("(%3.1f%%)",$x_passed) . " +Tests skipped : " . sprintf("%4d (%5.1f%%)",$sum_results['SKIPPED'],$percent_results['SKIPPED']) . " -------- +Tests warned : " . sprintf("%4d (%5.1f%%)",$sum_results['WARNED'],$percent_results['WARNED']) . " " . sprintf("(%5.1f%%)",$x_warned) . " +Tests failed : " . sprintf("%4d (%5.1f%%)",$sum_results['FAILED'],$percent_results['FAILED']) . " " . sprintf("(%5.1f%%)",$x_failed) . " +Tests passed : " . sprintf("%4d (%5.1f%%)",$sum_results['PASSED'],$percent_results['PASSED']) . " " . sprintf("(%5.1f%%)",$x_passed) . " --------------------------------------------------------------------- Time taken : " . sprintf("%4d seconds", $end_time - $start_time) . " ===================================================================== diff --git a/sapi/activescript/CREDITS b/sapi/activescript/CREDITS deleted file mode 100644 index ef347bac0d88..000000000000 --- a/sapi/activescript/CREDITS +++ /dev/null @@ -1,2 +0,0 @@ -ActiveScript -Wez Furlong diff --git a/sapi/activescript/EXPERIMENTAL b/sapi/activescript/EXPERIMENTAL deleted file mode 100644 index 293159a693de..000000000000 --- a/sapi/activescript/EXPERIMENTAL +++ /dev/null @@ -1,5 +0,0 @@ -this module is experimental, -its functions may change their names -or move to extension all together -so do not rely to much on them -you have been warned! diff --git a/sapi/activescript/README b/sapi/activescript/README deleted file mode 100644 index 39066f578362..000000000000 --- a/sapi/activescript/README +++ /dev/null @@ -1,56 +0,0 @@ -This is the ActiveScript SAPI for PHP. -====================================== - -Once registered on your system (using regsvr32), you will be able to use -PHP script in any ActiveScript compliant host. The list includes: - -o. Client-side script in Internet Explorer -o. Windows Script Host -o. ASP and ASP.NET -o. Windows Script Components / Behaviours -o. MS Scriptlet control - -Probably the most useful of these will be using it with the scriptlet -control, or in your own activescript host, so that you can very easily -embed PHP into your win32 application. - -Installation. -============= - -Build and install it somewhere; then register the engine like this: - - regsvr32 php5activescript.dll - -Usage. -====== - -o. Client-side script in Internet Explorer - - - -o. Windows Script Host - - Create a .wsf file like this: - - - - - -o. ASP and ASP.NET - - <%@language=ActivePHP5 %> - <% $Response->Write("Hello"); %> - -o. Windows Script Components / Behaviours - - Use language="ActivePHP5" on your ) +--FILE-- +bar +bar +--EXPECT-- +Foobar +Foobar diff --git a/tests/classes/__call_002.phpt b/tests/classes/__call_002.phpt new file mode 100755 index 000000000000..53a179f78778 --- /dev/null +++ b/tests/classes/__call_002.phpt @@ -0,0 +1,15 @@ +--TEST-- +ZE2 __call() signature check +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Fatal error: Method Test::__call() must take exactly 2 arguments in %s__call_002.php on line %d diff --git a/tests/classes/__set__get_002.phpt b/tests/classes/__set__get_002.phpt new file mode 100755 index 000000000000..71111ccdf810 --- /dev/null +++ b/tests/classes/__set__get_002.phpt @@ -0,0 +1,14 @@ +--TEST-- +ZE2 __get() signature check +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Fatal error: Method Test::__get() must take exactly 1 argument in %s__set__get_002.php on line %d diff --git a/tests/classes/__set__get_003.phpt b/tests/classes/__set__get_003.phpt new file mode 100755 index 000000000000..390d3033627c --- /dev/null +++ b/tests/classes/__set__get_003.phpt @@ -0,0 +1,14 @@ +--TEST-- +ZE2 __set() signature check +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Fatal error: Method Test::__set() must take exactly 2 arguments in %s__set__get_003.php on line %d diff --git a/tests/classes/abstract_derived.phpt b/tests/classes/abstract_derived.phpt index 81cb3341ec4f..0feceac6bb28 100644 --- a/tests/classes/abstract_derived.phpt +++ b/tests/classes/abstract_derived.phpt @@ -17,4 +17,4 @@ class derived extends base { --EXPECTF-- -Fatal error: Class derived contains 1 abstract methods and must therefore be declared abstract (derived::show) in %sabstract_derived.php on line %d +Fatal error: Class derived contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (derived::show) in %sabstract_derived.php on line %d diff --git a/tests/classes/abstract_not_declared.phpt b/tests/classes/abstract_not_declared.phpt index 96c98857e314..3b81cd4980a3 100644 --- a/tests/classes/abstract_not_declared.phpt +++ b/tests/classes/abstract_not_declared.phpt @@ -12,4 +12,4 @@ class fail { echo "Done\n"; // shouldn't be displayed ?> --EXPECTF-- -Fatal error: Class fail contains 1 abstract methods and must therefore be declared abstract (fail::show) in %s on line %d +Fatal error: Class fail contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (fail::show) in %s on line %d diff --git a/tests/classes/abstract_redeclare.phpt b/tests/classes/abstract_redeclare.phpt index 716dd17fd112..9a0a1edc3c23 100644 --- a/tests/classes/abstract_redeclare.phpt +++ b/tests/classes/abstract_redeclare.phpt @@ -19,4 +19,4 @@ echo "Done\n"; // Shouldn't be displayed ?> --EXPECTF-- -Fatal error: Class fail contains 1 abstract methods and must therefore be declared abstract (fail::show) in %sabstract_redeclare.php on line %d +Fatal error: Class fail contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (fail::show) in %sabstract_redeclare.php on line %d diff --git a/tests/classes/array_access_001.phpt b/tests/classes/array_access_001.phpt index 8a670c1c24e0..9b3d8891ebec 100644 --- a/tests/classes/array_access_001.phpt +++ b/tests/classes/array_access_001.phpt @@ -1,9 +1,5 @@ --TEST-- ZE2 ArrayAccess ---SKIPIF-- - --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- +--FILE-- + +===DONE=== +--EXPECTF-- +bool(false) +bool(false) +Test::__destruct +bool(false) +bool(false) +__autoload(autoload_root) +__autoload(autoload_derived) +object(autoload_derived)#%d (0) { +} +===DONE=== diff --git a/tests/classes/autoload_006.phpt b/tests/classes/autoload_006.phpt new file mode 100755 index 000000000000..9af6fc98299d --- /dev/null +++ b/tests/classes/autoload_006.phpt @@ -0,0 +1,40 @@ +--TEST-- +ZE2 Autoload from destructor +--SKIPIF-- + +--FILE-- + +===DONE=== +--EXPECTF-- +bool(false) +bool(false) +__autoload(autoload_interface) +__autoload(Autoload_Implements) +object(autoload_implements)#%d (0) { +} +bool(true) +bool(true) +bool(true) +===DONE=== diff --git a/tests/classes/autoload_implements.p5c b/tests/classes/autoload_implements.p5c new file mode 100755 index 000000000000..2c3479c86078 --- /dev/null +++ b/tests/classes/autoload_implements.p5c @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/tests/classes/autoload_interface.p5c b/tests/classes/autoload_interface.p5c new file mode 100755 index 000000000000..6908155e610e --- /dev/null +++ b/tests/classes/autoload_interface.p5c @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/tests/classes/bug26737.phpt b/tests/classes/bug26737.phpt index de37eaffbc28..39ac9b1edc50 100644 --- a/tests/classes/bug26737.phpt +++ b/tests/classes/bug26737.phpt @@ -2,6 +2,7 @@ Bug #26737 (Protected and private variables are not saved on serialization when a user defined __sleep is used) --FILE-- ---EXPECT-- -string(114) "O:3:"foo":3:{s:12:"\0foo\0private";s:7:"private";s:12:"\0*\0protected";s:9:"protected";s:6:"public";s:6:"public";}" +--EXPECTF-- +Notice: serialize(): "no_such" returned as member variable from __sleep() but does not exist in %s on line %d +string(130) "O:3:"foo":4:{s:12:"\0foo\0private";s:7:"private";s:12:"\0*\0protected";s:9:"protected";s:6:"public";s:6:"public";s:7:"no_such";N;}" diff --git a/tests/classes/clone_006.phpt b/tests/classes/clone_006.phpt index 346911ad0d4a..de22fec15193 100755 --- a/tests/classes/clone_006.phpt +++ b/tests/classes/clone_006.phpt @@ -2,6 +2,8 @@ ZE2 object cloning, 6 --SKIPIF-- +--INI-- +error_reporting=2047 --FILE-- getMessage() . ")\n"; +} + +?> +===DONE=== +--EXPECT-- +Test::__construct(Hello) +Caught Exception(Hello) +===DONE=== diff --git a/tests/classes/destructor_and_echo.phpt b/tests/classes/destructor_and_echo.phpt new file mode 100755 index 000000000000..c6c6f23a7185 --- /dev/null +++ b/tests/classes/destructor_and_echo.phpt @@ -0,0 +1,24 @@ +--TEST-- +Destructors and echo +--FILE-- + +===DONE=== +--EXPECT-- +Test::__construct +===DONE=== +Test::__destruct diff --git a/tests/classes/destructor_visibility_001.phpt b/tests/classes/destructor_visibility_001.phpt new file mode 100755 index 000000000000..7674c512f62a --- /dev/null +++ b/tests/classes/destructor_visibility_001.phpt @@ -0,0 +1,24 @@ +--TEST-- +ZE2 Ensuring destructor visibility +--SKIPIF-- + +--FILE-- + +===DONE=== +--EXPECTF-- +Fatal error: Call to private Derived::__destruct() from context '' in %sdestructor_visibility_001.php on line %d diff --git a/tests/classes/destructor_visibility_002.phpt b/tests/classes/destructor_visibility_002.phpt new file mode 100755 index 000000000000..2cc83334a987 --- /dev/null +++ b/tests/classes/destructor_visibility_002.phpt @@ -0,0 +1,24 @@ +--TEST-- +ZE2 Ensuring destructor visibility +--SKIPIF-- + +--FILE-- + +===DONE=== +--EXPECTF-- +===DONE=== + +Warning: Call to private Derived::__destruct() from context '' during shutdown ignored in Unknown on line %d diff --git a/tests/classes/destructor_visibility_003.phpt b/tests/classes/destructor_visibility_003.phpt new file mode 100755 index 000000000000..83e3efe22e44 --- /dev/null +++ b/tests/classes/destructor_visibility_003.phpt @@ -0,0 +1,28 @@ +--TEST-- +ZE2 Ensuring destructor visibility +--SKIPIF-- + +--FILE-- + +===DONE=== +--EXPECTF-- +Derived::__destruct +===DONE=== diff --git a/tests/classes/interface_and_extends.phpt b/tests/classes/interface_and_extends.phpt new file mode 100755 index 000000000000..559b6112500c --- /dev/null +++ b/tests/classes/interface_and_extends.phpt @@ -0,0 +1,26 @@ +--TEST-- +ZE2 a class cannot extend an interface +--SKIPIF-- + +--FILE-- +show(); + +?> +===DONE=== +--EXPECTF-- +Fatal error: Class Tester cannot extend from interface Test in %sinterface_and_extends.php on line %d \ No newline at end of file diff --git a/tests/classes/interface_must_be_implemented.phpt b/tests/classes/interface_must_be_implemented.phpt index 82ddf24df885..a4d79704e1ef 100644 --- a/tests/classes/interface_must_be_implemented.phpt +++ b/tests/classes/interface_must_be_implemented.phpt @@ -6,7 +6,7 @@ ZE2 An interface must be implemented --EXPECTF-- -Fatal error: Class derived_a contains 1 abstract methods and must therefore be declared abstract (if_a::f_a) in %s on line %d +Fatal error: Class derived_a contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (if_a::f_a) in %s on line %d diff --git a/tests/classes/interfaces_002.phpt b/tests/classes/interfaces_002.phpt index 66d46f5d3608..d26b5349bf51 100644 --- a/tests/classes/interfaces_002.phpt +++ b/tests/classes/interfaces_002.phpt @@ -20,10 +20,10 @@ class Exception_foo implements Throwable { // this should die -- Exception class must be abstract... $foo = new Exception_foo; -echo $foo->getMessage() . "\n"; +echo "Message: " . $foo->getMessage() . "\n"; ?> +===DONE=== --EXPECTF-- -Fatal error: Class Exception_foo contains 1 abstract methods and must therefore be declared abstract (Throwable::getErrno) in %s on line %d - +Fatal error: Class Exception_foo contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Throwable::getErrno) in %s on line %d diff --git a/tests/classes/static_this.phpt b/tests/classes/static_this.phpt new file mode 100755 index 000000000000..12f4b6389b3d --- /dev/null +++ b/tests/classes/static_this.phpt @@ -0,0 +1,39 @@ +--TEST-- +$this can be an argument to a static function +--FILE-- +Test1(); + } + + static function Test1() + { + var_dump($this); + } + + static function Test2($this) + { + var_dump($this); + } +} + +$obj = new TestClass; +TestClass::Test2(new stdClass); + +?> +===DONE=== +--EXPECTF-- + +Notice: Undefined variable: this in %sstatic_this.php on line %d +NULL + +Notice: Undefined variable: this in %sstatic_this.php on line %d +NULL +object(stdClass)#%d (0) { +} +===DONE=== diff --git a/tests/lang/034.phpt b/tests/lang/034.phpt index 475a0b756881..9c640415d538 100644 --- a/tests/lang/034.phpt +++ b/tests/lang/034.phpt @@ -1,5 +1,5 @@ --TEST-- -Locale settings affecting float parsing +Bug #12647 (Locale settings affecting float parsing) --SKIPIF-- --EXPECT-- 3,14 diff --git a/tests/lang/bug20175.phpt b/tests/lang/bug20175.phpt index 55ff7d82b80b..d2248e6f0eb8 100644 --- a/tests/lang/bug20175.phpt +++ b/tests/lang/bug20175.phpt @@ -2,6 +2,8 @@ Bug #20175 (Static vars can't store ref to new instance) --SKIPIF-- +--INI-- +error_reporting=4095 --FILE-- ---EXPECT-- +--EXPECTF-- +Strict Standards: Only variables should be assigned by reference in %sbug21600.php on line 4 array(1) { ["foo"]=> - &string(4) "test" + string(4) "test" } + +Strict Standards: Only variables should be assigned by reference in %sbug21600.php on line 11 array(1) { ["foo"]=> string(4) "test" diff --git a/tests/lang/bug25922.phpt b/tests/lang/bug25922.phpt index 0588eef949af..bb030c9df834 100755 --- a/tests/lang/bug25922.phpt +++ b/tests/lang/bug25922.phpt @@ -6,6 +6,7 @@ error_reporting=2047 --EXPECT-- +Undefined variable: data Undefined index here: '' diff --git a/tests/lang/bug27354.phpt b/tests/lang/bug27354.phpt index bcf68d426561..e10ad9c92402 100644 --- a/tests/lang/bug27354.phpt +++ b/tests/lang/bug27354.phpt @@ -7,8 +7,8 @@ Bug #27354 (Modulus operator crashes PHP) var_dump(-2147483648 % -1); var_dump(-2147483648 % -2); ?> ---EXPECT-- -int(0) -int(0) -int(0) -int(0) +--EXPECTF-- +int(%i) +int(%i) +int(%i) +int(%i) diff --git a/tests/lang/bug28800.phpt b/tests/lang/bug28800.phpt new file mode 100644 index 000000000000..f81ad7fec982 --- /dev/null +++ b/tests/lang/bug28800.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #28800 (Incorrect string to number conversion for strings starting with 'inf') +--FILE-- + +--EXPECT-- +0 +0 +0 +0 +0 +0 + diff --git a/tests/lang/bug29566.phpt b/tests/lang/bug29566.phpt new file mode 100755 index 000000000000..5f292bd75934 --- /dev/null +++ b/tests/lang/bug29566.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug #29566 (foreach/string handling strangeness) +--FILE-- + +===DONE=== +--EXPECTF-- +Warning: Invalid argument supplied for foreach() in %sbug29566.php on line %d +===DONE=== diff --git a/tests/lang/bug29893.phpt b/tests/lang/bug29893.phpt new file mode 100755 index 000000000000..d320de0ee72d --- /dev/null +++ b/tests/lang/bug29893.phpt @@ -0,0 +1,11 @@ +--TEST-- +Bug #29893 (segfault when using array as index) +--FILE-- + +===DONE=== +--EXPECTF-- +Warning: Cannot use a scalar value as an array in %sbug29893.php on line %d +===DONE=== diff --git a/tests/lang/bug29944.phpt b/tests/lang/bug29944.phpt new file mode 100755 index 000000000000..7882936f08b8 --- /dev/null +++ b/tests/lang/bug29944.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #29944 (function defined in switch crashes PHP) +--FILE-- + + +===DONE=== +--EXPECT-- +1 +===DONE=== diff --git a/tests/lang/bug30085.phpt b/tests/lang/bug30085.phpt new file mode 100644 index 000000000000..ad69c26fc10c --- /dev/null +++ b/tests/lang/bug30085.phpt @@ -0,0 +1,24 @@ +--TEST-- +Bug #30085 (When destructor terminates script) +--FILE-- +test = new test; + } + + public function __destruct() { + exit("Bye"); + } + +} + +$test = new test2; +?> +--EXPECT-- +Bye \ No newline at end of file diff --git a/tests/lang/bug30638.phpt b/tests/lang/bug30638.phpt new file mode 100644 index 000000000000..2574d132d3d1 --- /dev/null +++ b/tests/lang/bug30638.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #30638 (localeconv returns wrong LC_NUMERIC settings) +--SKIPIF-- + +--FILE-- + +--EXPECT-- +decimal_point: , +thousands_sep: . diff --git a/tests/lang/bug30726.phpt b/tests/lang/bug30726.phpt new file mode 100644 index 000000000000..79aeff7d265c --- /dev/null +++ b/tests/lang/bug30726.phpt @@ -0,0 +1,8 @@ +--TEST-- +Bug #30726 (-.1 like numbers are not being handled correctly) +--FILE-- + +--EXPECT-- +1 diff --git a/tests/lang/bug30862.phpt b/tests/lang/bug30862.phpt new file mode 100644 index 000000000000..12c95d57e87b --- /dev/null +++ b/tests/lang/bug30862.phpt @@ -0,0 +1,30 @@ +--TEST-- +Bug #30862 (Static array with boolean indexes) +--FILE-- +"false", true=>"true"); +} +print_r(T::$a); +?> +---------- +"false", Y=>"true"); +} +print_r(T2::$a); +?> +--EXPECT-- +Array +( + [0] => false + [1] => true +) +---------- +Array +( + [0] => false + [1] => true +) diff --git a/tests/lang/bug32828.phpt b/tests/lang/bug32828.phpt new file mode 100644 index 000000000000..ad59646f5007 --- /dev/null +++ b/tests/lang/bug32828.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug #32828 (Throwing exception in output_callback function with ob_start and ob_end_clean leads to segfault) +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught exception 'Exception' in %s:%d +Stack trace: +#0 [internal function]: output_handler('', %d) +#1 %s(%d): ob_end_clean() +#2 {main} + thrown in %s on line %d diff --git a/tests/strings/004.phpt b/tests/strings/004.phpt index ac5e2ce43d86..a283fda6991e 100644 --- a/tests/strings/004.phpt +++ b/tests/strings/004.phpt @@ -15,8 +15,8 @@ echo "\n[$var]\n"; ?> --EXPECT-- -<br /><?php echo "foo"; ?><br /> +<br /><?php echo "foo"; ?><br /> [ -<br /><?php echo "bar"; ?><br /> +<br /><?php echo "bar"; ?><br /> ] diff --git a/tests/strings/bug26703.phpt b/tests/strings/bug26703.phpt index c9a7790c0109..f21bcb900aee 100644 --- a/tests/strings/bug26703.phpt +++ b/tests/strings/bug26703.phpt @@ -13,6 +13,6 @@ highlight.html=#000000 ?> --EXPECT-- -<?php echo "foo[] $a \n"; ?> +<?php echo "foo[] $a \n"; ?> diff --git a/win32/build/Makefile b/win32/build/Makefile index d12d47b4b4f1..d249efa1be5d 100644 --- a/win32/build/Makefile +++ b/win32/build/Makefile @@ -19,14 +19,19 @@ CC="$(CL)" LD="$(LINK)" +MC="$(MC)" -all: $(BUILD_DIR) $(BUILD_DIRS_SUB) generated_files $(EXT_TARGETS) $(PECL_TARGETS) $(SAPI_TARGETS) +MCFILE=$(BUILD_DIR)\wsyslog.rc -generated_files: Zend\zend_ini_parser.c \ +all: generated_files $(EXT_TARGETS) $(PECL_TARGETS) $(SAPI_TARGETS) + +build_dirs: $(BUILD_DIR) $(BUILD_DIRS_SUB) + +generated_files: build_dirs Zend\zend_ini_parser.c \ Zend\zend_language_parser.c Zend\zend_ini_scanner.c \ Zend\zend_language_scanner.c \ ext\standard\parsedate.c \ - $(PHPDEF) + $(PHPDEF) $(MCFILE) $(BUILD_DIR)\$(PHPDLL).def: $(PHP_DLL_DEF_SOURCES) type $(PHP_DLL_DEF_SOURCES) > $(BUILD_DIR)\$(PHPDLL).def @@ -48,13 +53,19 @@ ext\standard\parsedate.c ext\standard\parsedate.h: ext\standard\parsedate.y PHPDLL_RES=$(BUILD_DIR)\$(PHPDLL).res +$(MCFILE): win32\build\wsyslog.mc + $(MC) -h win32\ -r $(BUILD_DIR)\ -x $(BUILD_DIR)\ win32\build\wsyslog.mc + +# $(RC) /fo $(MCFILE) $(BUILD_DIR)\wsyslog.rc + $(PHPDLL_RES): win32\build\template.rc $(RC) /fo $(PHPDLL_RES) /d FILE_DESCRIPTION="\"PHP Script Interpreter\"" \ /d FILE_NAME="\"$(PHPDLL)\"" /d PRODUCT_NAME="\"PHP Script Interpreter\"" \ - win32\build\template.rc + /I$(BUILD_DIR) /d MC_INCLUDE="\"$(MCFILE)\"" \ + win32\build\template.rc -$(BUILD_DIR)\$(PHPDLL): $(PHPDEF) $(PHP_GLOBAL_OBJS) $(STATIC_EXT_OBJS) $(PHPDLL_RES) - $(LD) /out:$(BUILD_DIR)\$(PHPDLL) $(PHP_LDFLAGS) $(LDFLAGS) $(STATIC_EXT_LDFLAGS) $(PHP_GLOBAL_OBJS) $(STATIC_EXT_OBJS) $(STATIC_EXT_LIBS) $(LIBS) $(PHPDLL_RES) +$(BUILD_DIR)\$(PHPDLL): generated_files $(PHPDEF) $(PHP_GLOBAL_OBJS) $(STATIC_EXT_OBJS) $(PHPDLL_RES) $(MCFILE) + @$(LD) /out:$(BUILD_DIR)\$(PHPDLL) $(PHP_LDFLAGS) $(LDFLAGS) $(STATIC_EXT_LDFLAGS) $(PHP_GLOBAL_OBJS) $(STATIC_EXT_OBJS) $(STATIC_EXT_LIBS) $(LIBS) $(PHPDLL_RES) $(BUILD_DIR)\$(PHPLIB): $(BUILD_DIR)\$(PHPDLL) @@ -73,7 +84,7 @@ clean-sapi: clean: clean-sapi @echo Cleaning build dirs @for %D in (_x $(BUILD_DIRS_SUB)) do @if exist %D @del /F /Q %D\*.* > NUL - -@del /F /Q $(BUILD_DIR)\*.res $(BUILD_DIR)\*.lib $(BUILD_DIR)\*.ilk $(BUILD_DIR)\*.pdb $(BUILD_DIR)\*.exp $(PHPDEF) $(BUILD_DIR)\php-$(PHP_VERSION_STRING).zip > NUL + -@del /F /Q $(BUILD_DIR)\*.res $(BUILD_DIR)\*.lib $(BUILD_DIR)\*.ilk $(BUILD_DIR)\*.pdb $(BUILD_DIR)\*.exp $(PHPDEF) $(BUILD_DIR)\php-$(PHP_VERSION_STRING)-Win32.zip $(BUILD_DIR)\pecl-$(PHP_VERSION_STRING)-Win32.zip > NUL -rmdir /s /q $(BUILD_DIR)\php-$(PHP_VERSION_STRING) clean-pecl: @@ -86,7 +97,7 @@ set TEST_PHP_EXECUTABLE=$(BUILD_DIR)\php.exe $(BUILD_DIR)\php.exe -d open_basedir= -d safe_mode=0 -d output_buffering=0 run-tests.php $(TESTS) <nul @copy $(BUILD_DIR)\*.dll $(PHP_PREFIX) /y >nul - + @echo Registering event source with syslog (requires admin rights) + @echo It's okay for this step to fail: + -$(PHP_PREFIX)\php.exe -n -dextension_dir=$(PHP_PREFIX) win32/build/registersyslog.php $(PHP_PREFIX)\$(PHPDLL) + + diff --git a/win32/build/buildconf.js b/win32/build/buildconf.js index a73094258c03..1f12677b518b 100644 --- a/win32/build/buildconf.js +++ b/win32/build/buildconf.js @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: buildconf.js,v 1.11 2004-02-12 12:30:41 wez Exp $ */ +/* $Id: buildconf.js,v 1.11.2.1 2005-07-22 18:09:33 wez Exp $ */ // This generates a configure script for win32 build WScript.StdOut.WriteLine("Rebuilding configure.js"); @@ -209,7 +209,11 @@ re = new RegExp("(ARG_(ENABLE|WITH)\([^;]+\);)", "gm"); calls = modules.match(re); for (i = 0; i < calls.length; i++) { item = calls[i]; + C.WriteLine("try {"); C.WriteLine(item); + C.WriteLine("} catch (e) {"); + C.WriteLine('\tSTDOUT.WriteLine("problem: " + e);'); + C.WriteLine("}"); } C.WriteBlankLines(1); diff --git a/win32/build/config.w32 b/win32/build/config.w32 index 2dfe853c6f9e..a2f64d2bd63b 100644 --- a/win32/build/config.w32 +++ b/win32/build/config.w32 @@ -4,22 +4,45 @@ // equivalent. ARG_WITH('cygwin', 'Path to cygwin utilities on your system', '\\cygwin'); - PATH_PROG('cl'); -PATH_PROG('link'); + +// cygwin now ships with link.exe. Avoid searching the cygwin path +// for this, as we want the MS linker, not the fileutil +PATH_PROG('link', WshShell.Environment("Process").Item("PATH")); + PATH_PROG('nmake'); + // we don't want to define LIB, as that will override the default library path // that is set in that env var PATH_PROG('lib', null, 'MAKE_LIB'); -PATH_PROG('bison'); -PATH_PROG('flex'); +if (!PATH_PROG('bison')) { + ERROR('bison is required') +} +if (!PATH_PROG('flex')) { + ERROR('flex is required') +} PATH_PROG('re2c'); PATH_PROG('zip'); PATH_PROG('lemon'); +// avoid picking up midnight commander from cygwin +PATH_PROG('mc', WshShell.Environment("Process").Item("PATH")); + +// stick objects somewhere outside of the source tree +ARG_ENABLE('object-out-dir', 'Alternate location for binary objects during build', ''); +if (PHP_OBJECT_OUT_DIR.length) { + if (!FSO.FolderExists(PHP_OBJECT_OUT_DIR)) { + ERROR('you chosen output directory ' + PHP_OBJECT_OUT_DIR + ' does not exist'); + } + PHP_OBJECT_OUT_DIR += '\\'; +} + ARG_ENABLE('debug', 'Compile with debugging symbols', "no"); +ARG_ENABLE('debug-pack', 'Release binaries with external debug symbols (--enable-debug must not be specified)', 'no'); +if (PHP_DEBUG == "yes" && PHP_DEBUG_PACK == "yes") { + ERROR("Use of both --enable-debug and --enable-debug-pack not allowed."); +} ARG_ENABLE('zts', 'Thread safety', 'yes'); - // Configures the hard-coded installation dir ARG_ENABLE('prefix', 'where PHP will be installed', ''); if (PHP_PREFIX == '') { @@ -63,6 +86,11 @@ if (PHP_DEBUG == "yes") { // version of the libc ADD_FLAG("PHP_LDFLAGS", "/nodefaultlib:msvcrt"); } else { + // Generate external debug files when --enable-debug-pack is specified + if (PHP_DEBUG_PACK == "yes") { + ADD_FLAG("CFLAGS", "/Zi"); + ADD_FLAG("LDFLAGS", "/incremental:no /debug /opt:ref,icf"); + } // Equivalent to Release_TSInline build -> best optimization ADD_FLAG("CFLAGS", "/LD /MD /W3 /Ox /D NDebug /D NDEBUG \ /D ZEND_WIN32_FORCE_INLINE /GB /GF /D ZEND_DEBUG=0"); @@ -79,19 +107,19 @@ ADD_FLAG("PHP_LDFLAGS", "/nodefaultlib:libcmt"); // set up the build dir and DLL name if (PHP_DEBUG == "yes" && PHP_ZTS == "yes") { - DEFINE("BUILD_DIR", "Debug_TS"); + DEFINE("BUILD_DIR", PHP_OBJECT_OUT_DIR + "Debug_TS"); DEFINE("PHPDLL", "php5ts_debug.dll"); DEFINE("PHPLIB", "php5ts_debug.lib"); } else if (PHP_DEBUG == "yes" && PHP_ZTS == "no") { - DEFINE("BUILD_DIR", "Debug"); + DEFINE("BUILD_DIR", PHP_OBJECT_OUT_DIR + "Debug"); DEFINE("PHPDLL", "php5_debug.dll"); DEFINE("PHPLIB", "php5_debug.lib"); } else if (PHP_DEBUG == "no" && PHP_ZTS == "yes") { - DEFINE("BUILD_DIR", "Release_TS"); + DEFINE("BUILD_DIR", PHP_OBJECT_OUT_DIR + "Release_TS"); DEFINE("PHPDLL", "php5ts.dll"); DEFINE("PHPLIB", "php5ts.lib"); } else if (PHP_DEBUG == "no" && PHP_ZTS == "no") { - DEFINE("BUILD_DIR", "Release"); + DEFINE("BUILD_DIR", PHP_OBJECT_OUT_DIR + "Release"); DEFINE("PHPDLL", "php5.dll"); DEFINE("PHPLIB", "php5.lib"); } @@ -183,18 +211,18 @@ ADD_SOURCES("Zend", "zend_language_parser.c zend_language_scanner.c \ zend_sprintf.c zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c \ zend_stream.c zend_iterators.c zend_interfaces.c zend_objects.c \ zend_object_handlers.c zend_objects_API.c \ - zend_mm.c zend_default_classes.c zend_reflection_api.c zend_execute.c"); + zend_mm.c zend_default_classes.c zend_reflection_api.c zend_execute.c zend_strtod.c"); ADD_SOURCES("main", "main.c snprintf.c spprintf.c safe_mode.c fopen_wrappers.c \ php_scandir.c php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \ strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c network.c \ - php_open_temporary_file.c php_logos.c output.c internal_functions.c"); + php_open_temporary_file.c php_logos.c output.c internal_functions.c php_sprintf.c"); ADD_SOURCES("main/streams", "streams.c cast.c memory.c filter.c plain_wrapper.c \ userspace.c transports.c xp_socket.c mmap.c"); ADD_SOURCES("win32", "crypt_win32.c flock.c glob.c md5crypt.c pwd.c readdir.c \ - registry.c select.c sendmail.c time.c wfile.c winutil.c wsyslog.c"); + registry.c select.c sendmail.c time.c wfile.c winutil.c wsyslog.c globals.c"); ADD_SOURCES("regex", "regcomp.c regerror.c regexec.c regfree.c"); @@ -214,10 +242,26 @@ AC_DEFINE('HAVE_GETADDRINFO', main_network_has_ipv6); AC_DEFINE('HAVE_GAI_STRERROR', main_network_has_ipv6); AC_DEFINE('HAVE_IPV6', main_network_has_ipv6); -ARG_ENABLE("memory-limit", "Enable memory limit checking code", "no"); +/* this allows up to 256 sockets to be select()ed in a single + * call to select(), instead of the usual 64 */ +ARG_ENABLE('fd-setsize', "Set maximum number of sockets for select(2)", "256"); +ADD_FLAG("CFLAGS", "/D FD_SETSIZE=" + parseInt(PHP_FD_SETSIZE)); +ARG_ENABLE("memory-limit", "Enable memory limit checking code", "no"); AC_DEFINE('MEMORY_LIMIT', PHP_MEMORY_LIMIT == "yes" ? 1 : 0); +ARG_ENABLE("memory-manager", "Enable Zend memory manager", "yes"); +AC_DEFINE('USE_ZEND_ALLOC', PHP_MEMORY_MANAGER == "yes" ? 1 : 0); + +ARG_ENABLE("zend-multibyte", "Enable Zend multibyte encoding support", "no"); +if (PHP_ZEND_MULTIBYTE == "yes") { + STDOUT.WriteLine("Enabling Zend multibyte encoding support"); + AC_DEFINE('ZEND_MULTIBYTE', 1); +} + +AC_DEFINE('HAVE_USLEEP', 1); +AC_DEFINE('HAVE_STRCOLL', 1); + /* For snapshot builders, where can we find the additional * files that make up the snapshot template? */ ARG_WITH("snapshot-template", "Path to snapshot builder template dir", "no"); diff --git a/win32/build/confutils.js b/win32/build/confutils.js index 76d91cc038a6..77979231610d 100644 --- a/win32/build/confutils.js +++ b/win32/build/confutils.js @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -// $Id: confutils.js,v 1.42 2004-07-07 12:25:10 edink Exp $ +// $Id: confutils.js,v 1.42.2.4 2005-07-22 18:09:33 wez Exp $ var STDOUT = WScript.StdOut; var STDERR = WScript.StdErr; @@ -349,7 +349,8 @@ can be built that way. \ 'debug', 'crt-debug', 'lzf-better-compression', 'php-build', 'snapshot-template', 'pcre-regex', 'fastcgi', 'force-cgi-redirect', - 'path-info-check', 'zts', 'ipv6', 'memory-limit' + 'path-info-check', 'zts', 'ipv6', 'memory-limit', + 'zend-multibyte', 'fd-setsize', 'memory-manager' ); var force; @@ -708,7 +709,7 @@ function OLD_CHECK_LIB(libnames, target, path_to_check) } -function CHECK_FUNC_IN_HEADER(header_name, func_name, path_to_check) +function CHECK_FUNC_IN_HEADER(header_name, func_name, path_to_check, add_to_flag) { var c = false; var sym; @@ -720,7 +721,11 @@ function CHECK_FUNC_IN_HEADER(header_name, func_name, path_to_check) sym = func_name.toUpperCase(); sym = sym.replace(new RegExp("[\\\\/\.-]", "g"), "_"); - AC_DEFINE("HAVE_" + sym, c ? 1 : 0); + if (typeof(add_to_flag) == "undefined") { + AC_DEFINE("HAVE_" + sym, c ? 1 : 0); + } else { + ADD_FLAG(add_to_flag, "/DHAVE_" + sym + "=" + (c ? "1" : "0")); + } if (c) { STDOUT.WriteLine("OK"); @@ -766,7 +771,7 @@ function GREP_HEADER(header_name, regex, path_to_check) return false; } -function CHECK_HEADER_ADD_INCLUDE(header_name, flag_name, path_to_check, use_env, add_dir_part) +function CHECK_HEADER_ADD_INCLUDE(header_name, flag_name, path_to_check, use_env, add_dir_part, add_to_flag_only) { var dir_part_to_add = ""; @@ -810,7 +815,16 @@ function CHECK_HEADER_ADD_INCLUDE(header_name, flag_name, path_to_check, use_env sym = header_name.toUpperCase(); sym = sym.replace(new RegExp("[\\\\/\.-]", "g"), "_"); - AC_DEFINE("HAVE_" + sym, have); + if (typeof(add_to_flag_only) == "undefined" && + flag_name.match(new RegExp("^CFLAGS_(.*)$"))) { + add_to_flag_only = true; + } + + if (typeof(add_to_flag_only) != "undefined") { + ADD_FLAG(flag_name, "/DHAVE_" + sym + "=" + have); + } else { + AC_DEFINE("HAVE_" + sym, have, "have the " + header_name + " header file"); + } return p; } @@ -862,7 +876,7 @@ function SAPI(sapiname, file_list, makefiletarget, cflags) var SAPI = sapiname.toUpperCase(); var ldflags; var resname; - var ld = "$(LD)"; + var ld = "@$(LD)"; STDOUT.WriteLine("Enabling SAPI " + configure_module_dirname); @@ -908,6 +922,15 @@ function SAPI(sapiname, file_list, makefiletarget, cflags) MFO.WriteBlankLines(1); } +function ADD_DIST_FILE(filename) +{ + if (configure_module_dirname.match("pecl")) { + ADD_FLAG("PECL_EXTRA_DIST_FILES", filename); + } else { + ADD_FLAG("PHP_EXTRA_DIST_FILES", filename); + } +} + function file_get_contents(filename) { var f, c; @@ -959,10 +982,11 @@ function ADD_EXTENSION_DEP(extname, dependson, optional) } } -function EXTENSION(extname, file_list, shared, cflags, dllname) +function EXTENSION(extname, file_list, shared, cflags, dllname, obj_dir) { var objs = null; var EXT = extname.toUpperCase(); + var extname_for_printing; if (shared == null) { eval("shared = PHP_" + EXT + "_SHARED;"); @@ -971,12 +995,18 @@ function EXTENSION(extname, file_list, shared, cflags, dllname) cflags = ""; } + if (typeof(obj_dir) == "undefined") { + extname_for_printing = configure_module_dirname; + } else { + extname_for_printing = configure_module_dirname + " (via " + obj_dir + ")"; + } + if (shared) { - STDOUT.WriteLine("Enabling extension " + configure_module_dirname + " [shared]"); + STDOUT.WriteLine("Enabling extension " + extname_for_printing + " [shared]"); cflags = "/D COMPILE_DL_" + EXT + " /D " + EXT + "_EXPORTS=1 " + cflags; ADD_FLAG("CFLAGS_PHP", "/D COMPILE_DL_" + EXT); } else { - STDOUT.WriteLine("Enabling extension " + configure_module_dirname); + STDOUT.WriteLine("Enabling extension " + extname_for_printing); } MFO.WriteBlankLines(1); @@ -984,7 +1014,7 @@ function EXTENSION(extname, file_list, shared, cflags, dllname) MFO.WriteBlankLines(1); - ADD_SOURCES(configure_module_dirname, file_list, extname); + ADD_SOURCES(configure_module_dirname, file_list, extname, obj_dir); MFO.WriteBlankLines(1); @@ -995,7 +1025,7 @@ function EXTENSION(extname, file_list, shared, cflags, dllname) var libname = dllname.substring(0, dllname.length-4) + ".lib"; var resname = generate_version_info_resource(dllname, configure_module_dirname); - var ld = "$(LD)"; + var ld = "@$(LD)"; MFO.WriteLine("$(BUILD_DIR)\\" + dllname + " $(BUILD_DIR)\\" + libname + ": $(DEPS_" + EXT + ") $(" + EXT + "_GLOBAL_OBJS) $(BUILD_DIR)\\$(PHPLIB) $(BUILD_DIR)\\" + resname); MFO.WriteLine("\t" + ld + " /out:$(BUILD_DIR)\\" + dllname + " $(DLL_LDFLAGS) $(LDFLAGS) $(LDFLAGS_" + EXT + ") $(" + EXT + "_GLOBAL_OBJS) $(BUILD_DIR)\\$(PHPLIB) $(LIBS_" + EXT + ") $(LIBS) $(BUILD_DIR)\\" + resname); @@ -1040,7 +1070,7 @@ function EXTENSION(extname, file_list, shared, cflags, dllname) ADD_FLAG("CFLAGS_" + EXT, cflags); } -function ADD_SOURCES(dir, file_list, target) +function ADD_SOURCES(dir, file_list, target, obj_dir) { var i; var tv; @@ -1077,11 +1107,17 @@ function ADD_SOURCES(dir, file_list, target) * This probably breaks for non-sibling dirs, but that * is not a problem as buildconf only checks for pecl * as either a child or a sibling */ - var build_dir = dir.replace(new RegExp("^..\\\\"), ""); - - var mangle_dir = build_dir.replace(new RegExp("[\\\\/.]", "g"), "_"); - var bd_flags_name = "CFLAGS_BD_" + mangle_dir.toUpperCase(); - + if (obj_dir == null) { + var build_dir = dir.replace(new RegExp("^..\\\\"), ""); + var mangle_dir = build_dir.replace(new RegExp("[\\\\/.]", "g"), "_"); + var bd_flags_name = "CFLAGS_BD_" + mangle_dir.toUpperCase(); + } + else { + var build_dir = obj_dir.replace(new RegExp("^..\\\\"), ""); + var mangle_dir = build_dir.replace(new RegExp("[\\\\/.]", "g"), "_"); + var bd_flags_name = "CFLAGS_BD_" + mangle_dir.toUpperCase(); + } + var dirs = build_dir.split("\\"); var i, d = ""; for (i = 0; i < dirs.length; i++) { @@ -1092,7 +1128,7 @@ function ADD_SOURCES(dir, file_list, target) sub_build += d; - DEFINE(bd_flags_name, "/Fo" + sub_build + " /Fd" + sub_build + " /Fp" + sub_build + " /FR" + sub_build + " "); + DEFINE(bd_flags_name, " /Fd" + sub_build + " /Fp" + sub_build + " /FR" + sub_build + " "); for (i in file_list) { src = file_list[i]; @@ -1109,13 +1145,13 @@ function ADD_SOURCES(dir, file_list, target) } } else { MFO.WriteLine(sub_build + obj + ": " + dir + "\\" + src); - MFO.WriteLine("\t$(CC) $(" + flags + ") $(CFLAGS) $(" + bd_flags_name + ") -c " + dir + "\\" + src + " -o " + sub_build + obj); + MFO.WriteLine("\t@$(CC) $(" + flags + ") $(CFLAGS) $(" + bd_flags_name + ") /c " + dir + "\\" + src + " /Fo" + sub_build + obj); } } if (PHP_ONE_SHOT == "yes") { MFO.WriteLine(objs_line + ": " + srcs_line); - MFO.WriteLine("\t$(CC) $(" + flags + ") $(CFLAGS) $(" + bd_flags_name + ") -c " + srcs_line); + MFO.WriteLine("\t$(CC) $(" + flags + ") $(CFLAGS) /Fo" + sub_build + " $(" + bd_flags_name + ") /c " + srcs_line); } DEFINE(sym, tv); @@ -1210,8 +1246,9 @@ function generate_config_h() outfile.Write(indata); var keys = (new VBArray(configure_hdr.Keys())).toArray(); - var i; + var i, j; var item; + var pieces, stuff_to_crack, chunk; outfile.WriteBlankLines(1); outfile.WriteLine("/* values determined by configure.js */"); @@ -1220,7 +1257,29 @@ function generate_config_h() item = configure_hdr.Item(keys[i]); outfile.WriteBlankLines(1); outfile.WriteLine("/* " + item[1] + " */"); - outfile.WriteLine("#define " + keys[i] + " " + item[0]); + pieces = item[0]; + + if (typeof(pieces) == "string" && pieces.charCodeAt(0) == 34) { + /* quoted string have a maximal length of 2k under vc. + * solution is to crack them and let the compiler concat + * them implicitly */ + stuff_to_crack = pieces; + pieces = ""; + + while (stuff_to_crack.length) { + j = 65; + while (stuff_to_crack.charCodeAt(j) != 32 && j < stuff_to_crack.length) + j++; + + chunk = stuff_to_crack.substr(0, j); + pieces += chunk; + stuff_to_crack = stuff_to_crack.substr(chunk.length); + if (stuff_to_crack.length) + pieces += '" "'; + } + } + + outfile.WriteLine("#define " + keys[i] + " " + pieces); } outfile.Close(); diff --git a/win32/build/mkdist.php b/win32/build/mkdist.php index fd8ad4ae44e8..51c304909d2f 100644 --- a/win32/build/mkdist.php +++ b/win32/build/mkdist.php @@ -222,6 +222,8 @@ function extract_file_from_tarball($pkg, $filename, $dest_dir) /* {{{ */ "php.ini-dist" => "php.ini-dist", "php.ini-recommended" => "php.ini-recommended", "win32/install.txt" => "install.txt", + "win32/pws-php5cgi.reg" => "pws-php5cgi.reg", + "win32/pws-php5isapi.reg" => "pws-php5isapi.reg", ); foreach ($text_files as $src => $dest) { diff --git a/win32/build/template.rc b/win32/build/template.rc index 1a6b04cbfe33..3bb57a71470f 100644 --- a/win32/build/template.rc +++ b/win32/build/template.rc @@ -62,3 +62,8 @@ BEGIN VALUE "Translation", 0x409, 1200 END END + +#ifdef MC_INCLUDE +#include MC_INCLUDE +#endif + diff --git a/win32/build/wsyslog.mc b/win32/build/wsyslog.mc new file mode 100755 index 000000000000..01d4d3a86bfd --- /dev/null +++ b/win32/build/wsyslog.mc @@ -0,0 +1,28 @@ +MessageId=1 +Severity=Success +SymbolicName=PHP_SYSLOG_SUCCESS_TYPE +Language=English +%1 %2 +. + +MessageId=2 +Severity=Informational +SymbolicName=PHP_SYSLOG_INFO_TYPE +Language=English +%1 %2 +. + +MessageId=3 +Severity=Warning +SymbolicName=PHP_SYSLOG_WARNING_TYPE +Language=English +%1 %2 +. + +MessageId=4 +Severity=Error +SymbolicName=PHP_SYSLOG_ERROR_TYPE +Language=English +%1 %2 +. + diff --git a/sapi/activescript/php5activescript.h b/win32/globals.c old mode 100644 new mode 100755 similarity index 63% rename from sapi/activescript/php5activescript.h rename to win32/globals.c index ba8be9b51e02..f77df9d4ba41 --- a/sapi/activescript/php5activescript.h +++ b/win32/globals.c @@ -12,14 +12,40 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Authors: Wez Furlong | + | Author: Wez Furlong | +----------------------------------------------------------------------+ - */ +*/ + /* $Id$ */ -extern zend_module_entry php_activescript_module; -extern sapi_module_struct activescript_sapi_module; -extern HINSTANCE module_handle; -extern void activescript_error_func(int type, const char *error_msg, ...); -extern void activescript_error_handler(int type, const char *error_filename, - const uint error_lineno, const char *format, va_list args); +#include "php.h" +#include "php_win32_globals.h" + +#ifdef ZTS +PHPAPI int php_win32_core_globals_id; +#else +php_win32_core_globals php_win32_core_globals; +#endif + +void php_win32_core_globals_ctor(void *vg TSRMLS_DC) +{ + php_win32_core_globals *wg = (php_win32_core_globals*)vg; + memset(wg, 0, sizeof(*wg)); +} + +PHP_RSHUTDOWN_FUNCTION(win32_core_globals) +{ + php_win32_core_globals *wg = +#ifdef ZTS + ts_resource(php_win32_core_globals_id) +#else + &php_win32_core_globals +#endif + ; + + STR_FREE(wg->login_name); + + memset(wg, 0, sizeof(*wg)); + return SUCCESS; +} + diff --git a/win32/install.txt b/win32/install.txt index 695a00a8c556..470d944e2ad1 100644 --- a/win32/install.txt +++ b/win32/install.txt @@ -1,794 +1,1624 @@ -PHP/Windows Installation Notes -============================== - -Installation on Windows 9x/Me/NT/2000/XP systems -============================================= - -There are two main ways to install PHP for Windows: either -manually or by using the InstallShield installer. - - -Windows InstallShield -===================== - - The Windows PHP installer is available from the downloads page at - www.php.net. This installs the CGI version of PHP and, for IIS, PWS, - and Xitami, configures the web server as well. - Note that this version does *NOT* install any extensions or server - api versions of PHP. - - Install your selected HTTP server on your system and make sure - that it works. - - Run the executable installer and follow the instructions provided by - the installation wizard. Two types of installation are supported - - standard, which provides sensible defaults for all the settings it - can, and advanced, which asks questions as it goes along. - - The installation wizard gathers enough information to set up the - php.ini file and configure the web server to use PHP. - For IIS and also PWS on NT Workstation, a list of all the - nodes on the server with script map settings is displayed, and you - can choose those nodes to which you wish to add the PHP script - mappings. - - Once the installation has completed the installer will inform you - if you need to restart your system, restart the server, or just - start using PHP. - -Windows Manual installation from zip binary distribution -======================================================== - - This install guide will help you manually install and configure - PHP on your Windows 9x/Me/NT/2000/XP webservers. This guide was compiled by - Bob Silva. The original version can be found at - http://www.umesd.k12.or.us/php/win32install.html - - This guide provides manual installation support for: - Personal Web Server 3 and 4 or newer - Internet Information Server 3 and 4 or newer - Apache 1.3.x - Apache 2.0.x (experimental) - OmniHTTPd 2.0b1 and up - Oreilly Website Pro - Xitami - SunONE Webserver, Netscape Enterprise Server, iPlanet - - PHP for Windows comes in two flavours - a CGI executable (php.exe), - and several SAPI modules (for exapmle php5isapi.dll). The latter form - is new to PHP, and provides significantly improved performance and - some new functionality. However, please note that the SAPI modules - are *NOT* yet considered to be production quality. - In particular, with the ISAPI module, you are likely to encounter serious - reliability problems especially on platforms older than W2K - you may - witness a lot of server 500 errors and suffer from other server modules - such as ASP also failing. You have been warned! - - The reason for this is that the PHP SAPI modules are using the - thread-safe version of the PHP code, which is new to PHP, and has - not yet been tested and pounded enough to be considered completely - stable, and there are actually a few known bugs. On the other hand, - some people have reported very good results with the SAPI modules, - and there a few reports of problems with the Apache module version. - In short - your mileage may vary; If you need - absolute stability, trade the performance of the SAPI modules - with the stability of the CGI executable. - - If you choose one of the SAPI modules and use Windows 95, be sure - to download the DCOM update from - http://download.microsoft.com/msdownload/dcom/95/x86/en/dcom95.exe" - For the ISAPI module, an ISAPI 4.0 compliant Web server - is required (tested on IIS 4.0, PWS 4.0 and IIS 5.0). IIS 3.0 is - *NOT* supported; You should download and install the Windows NT 4.0 - Option Pack with IIS 4.0 if you want native PHP support. - - The following steps should be performed on all installations - before the server specific instructions. - - Extract the distribution file to a directory of your choice. - C:\PHP\ is a good start. - - You need to ensure that the dlls which php uses can be found. The precise - dlls involved depend on which web server you use and whether you want to - run php as a cgi or as a server module. php5ts.dll is always used. If you are - using a server module (e.g. isapi or apache) then you will need the relevent - dll from the sapi folder. If you are using any php extension dlls then you - will need those as well. To make sure that the dlls can be found, you can - either copy them to the system directory (e.g. winnt/system32 or - windows/system) or you can make sure that they live in the same directory - as the main php executable or dll your web server will use (e.g. php.exe, - php5apache.dll). - - Copy the file, php.ini-dist to your %WINDOWS% directory on - Windows 95/98 or to your %SYSTEMROOT% directory under Windows NT, - Windows 2000 or Windows XP and rename it to php.ini. Your %WINDOWS% or - %SYSTEMROOT% directory is typically: - c:\windows for Windows 95/98 - c:\winnt or c:\winnt40 for NT/2000/XP servers - We will refer to %SYSTEMROOT% for both %WINDOWS% or - %SYSTEMROOT% throughout the text. - - Edit your php.ini file: - - You will need to change the 'extension_dir' setting to - point to your php-install-dir, or where you have placed - your 'php_*.dll' files. ex: c:\php - - If you are using OmniHTTPd, do not follow the next step. - Set the 'doc_root' to point to your webservers - document_root. ex: c:\apache\htdocs or c:\webroot - - Choose which extensions you would like to load when PHP - starts, noting that several extensions are already built - into the Windows release, see the section about - Windows extensions for details of the built-in extensions. - You can uncomment the: 'extension=php_*.dll' lines - in php.ini to load these extensions. - - Note that on a new installation it is advisable to first get - PHP working and tested without any extensions before enabling - them in php.ini. - - On PWS and IIS, you can set the browscap.ini - to point to: 'c:\windows\system\inetsrv\browscap.ini' on - Windows 9x/Me and 'c:\winnt\system32\inetsrv\browscap.ini' - on NT/2000/XP Server. - - More information on the capabilities of browscap can be found here: - - http://www.php.net/manual/en/function.get-browser.php - - Note that the mibs directory supplied with the Windows distribution - contains support files for SNMP. This directory should be moved to - DRIVE:\usr\mibs (DRIVE being the drive where PHP is installed.) - - -Installation of Windows extensions -================================== - - After installing PHP and a webserver on Windows, you will - probably want to install some extensions for added functionality. - The following table describes some of the extensions available. As - described in the manual installation steps, you can choose which - extensions you would like to load when PHP starts by uncommenting the: - extension=php_*.dll' lines in php.ini. - - - ATTENTION! ATTENTION! ATTENTION! - Some extra DLLs are required for some PHP extensions. Please copy the - bundled dlls from the 'dlls/' directory in distribution package to your - windows/system (Win9.x) or winnt/system32 (WinNT, Win2000, XP) directory. - If you already have these DLLs installed on your system, - overwrite them only if something is not working correctly. - Before overwriting them, it is a good idea to backup them or move them to - another folder - just in case something goes wrong. - - Download the latest version of the Microsoft Data Access Components (MDAC) - for your platform, especially Microsoft Windows 9x/NT4 users. - MDAC is available at http://www.microsoft.com/data/ . - - Also note that some extensions need 3rd party libraries, - e.g. php_oci8.dll needs the Oracle 8 client libraries to be installed - on your system. These are not bundled with PHP distribution. - ATTENTION! ATTENTION! ATTENTION! - - - The DLLs for PHP extensions are prefixed with 'php_'. This - prevents confusion between PHP extensions and their supporting - libraries. - - Note: - Since PHP 4.0.5 MySQL, ODBC, FTP, Calendar, BCMath, COM, PCRE, - Session, WDDX and XML support is built-in. You don't need to - load any additional extensions in order to use these functions. - Examples of PHP Extensions +Installing PHP + _________________________________________________________________ + + Table of Contents + Preface + 1. General Installation Considerations + 2. Installation on Windows systems + + Windows Installer + Manual Installation Steps + ActiveScript + Microsoft IIS / PWS + Apache 1.3.x on Microsoft Windows + Apache 2.0.x on Microsoft Windows + Sun, iPlanet and Netscape servers on Microsoft Windows + OmniHTTPd Server + Sambar Server on Microsoft Windows + Xitami on Microsoft Windows + Installation of extensions on Windows + + 3. Installation of PECL extensions + + Introduction to PECL Installations + Downloading PECL extensions + PECL for Windows users + Compiling shared PECL extensions with PEAR + Compiling shared PECL extensions with phpize + Compiling PECL extensions statically into PHP + + 4. Problems? + + Read the FAQ + Other problems + Bug reports + + 5. Runtime Configuration + + The configuration file + How to change configuration settings + _________________________________________________________________ + +Preface + + These installation instructions were generated from the HTML version + of the PHP Manual so formatting and linking have been altered. See the + online and updated version at: http://php.net/install.windows + _________________________________________________________________ + +Chapter 1. General Installation Considerations + + Before starting the installation, first you need to know what do you + want to use PHP for. There are three main fields you can use PHP, as + described in the What can PHP do? section: + + * Server-side scripting + * Command line scripting + * Client-side GUI applications + + For the first and most common form, you need three things: PHP itself, + a web server and a web browser. You probably already have a web + browser, and depending on your operating system setup, you may also + have a web server (e.g. Apache on Linux and MacOS X; IIS on Windows). + You may also rent webspace at a company. This way, you don't need to + set up anything on your own, only write your PHP scripts, upload it to + the server you rent, and see the results in your browser. + + While setting up the server and PHP on your own, you have two choices + for the method of connecting PHP to the server. For many servers PHP + has a direct module interface (also called SAPI). These servers + include Apache, Microsoft Internet Information Server, Netscape and + iPlanet servers. Many other servers have support for ISAPI, the + Microsoft module interface (OmniHTTPd for example). If PHP has no + module support for your web server, you can always use it as a CGI or + FastCGI processor. This means you set up your server to use the CGI + executable of PHP to process all PHP file requests on the server. + + If you are also interested to use PHP for command line scripting (e.g. + write scripts autogenerating some images for you offline, or + processing text files depending on some arguments you pass to them), + you always need the command line executable. For more information, + read the section about writing command line PHP applications. In this + case, you need no server and no browser. + + With PHP you can also write desktop GUI applications using the PHP-GTK + extension. This is a completely different approach than writing web + pages, as you do not output any HTML, but manage windows and objects + within them. For more information about PHP-GTK, please visit the site + dedicated to this extension. PHP-GTK is not included in the official + PHP distribution. + + From now on, this section deals with setting up PHP for web servers on + Unix and Windows with server module interfaces and CGI executables. + You will also find information on the command line executable in the + following sections. + + PHP source code and binary distributions for Windows can be found at + http://www.php.net/downloads.php. We recommend you to choose a mirror + nearest to you for downloading the distributions. + _________________________________________________________________ + +Chapter 2. Installation on Windows systems + + This section applies to Windows 98/Me and Windows NT/2000/XP/2003. PHP + will not work on 16 bit platforms such as Windows 3.1 and sometimes we + refer to the supported Windows platforms as Win32. Windows 95 is no + longer supported as of PHP 4.3.0. + + There are two main ways to install PHP for Windows: either manually or + by using the installer. + + If you have Microsoft Visual Studio, you can also build PHP from the + original source code. + + Once you have PHP installed on your Windows system, you may also want + to load various extensions for added functionality. + + Warning + + There are several all-in-one installers over the Internet, but none of + those are endorsed by PHP.net, as we believe that the manual + installation is the best choice to have your system secure and + optimised. + _________________________________________________________________ + +Windows Installer + + The Windows PHP installer is available from the downloads page at + http://www.php.net/downloads.php. This installs the CGI version of PHP + and for IIS, PWS, and Xitami, it configures the web server as well. + The installer does not include any extra external PHP extensions + (php_*.dll) as you'll only find those in the Windows Zip Package and + PECL downloads. + + Note: While the Windows installer is an easy way to make PHP work, + it is restricted in many aspects as, for example, the automatic + setup of extensions is not supported. Use of the installer isn't + the preferred method for installing PHP. + + First, install your selected HTTP (web) server on your system, and + make sure that it works. + + Run the executable installer and follow the instructions provided by + the installation wizard. Two types of installation are supported - + standard, which provides sensible defaults for all the settings it + can, and advanced, which asks questions as it goes along. + + The installation wizard gathers enough information to set up the + php.ini file, and configure certain web servers to use PHP. One of the + web servers the PHP installer does not configure for is Apache, so + you'll need to configure it manually. + + Once the installation has completed, the installer will inform you if + you need to restart your system, restart the server, or just start + using PHP. + + Warning + + Be aware, that this setup of PHP is not secure. If you would like to + have a secure PHP setup, you'd better go on the manual way, and set + every option carefully. This automatically working setup gives you an + instantly working PHP installation, but it is not meant to be used on + online servers. + _________________________________________________________________ + +Manual Installation Steps + + This install guide will help you manually install and configure PHP + with a web server on Microsoft Windows. To get started you'll need to + download the zip binary distribution from the downloads page at + http://www.php.net/downloads.php. + + Although there are many all-in-one installation kits, and we also + distribute a PHP installer for Microsoft Windows, we recommend you + take the time to setup PHP yourself as this will provide you with a + better understanding of the system, and enables you to install PHP + extensions easily when needed. + + Upgrading from a previous PHP version: Previous editions of the + manual suggest moving various ini and DLL files into your SYSTEM + (i.e. C:\WINDOWS) folder and while this simplifies the installation + procedure it makes upgrading difficult. We advise you remove all of + these files (like php.ini and PHP related DLLs from the Windows + SYSTEM folder) before moving on with a new PHP installation. Be + sure to backup these files as you might break the entire system. + The old php.ini might be useful in setting up the new PHP as well. + And as you'll soon learn, the preferred method for installing PHP + is to keep all PHP related files in one directory and have this + directory available to your systems PATH. + + MDAC requirements: If you use Microsoft Windows 98/NT4 download the + latest version of the Microsoft Data Access Components (MDAC) for + your platform. MDAC is available at + http://msdn.microsoft.com/data/. This requirement exists because + ODBC is built into the distributed Windows binaries. + + The following steps should be completed on all installations before + any server specific instructions are performed: + + Extract the distribution file into a directory of your choice. If you + are installing PHP 4, extract to C:\, as the zip file expands to a + foldername like php-4.3.7-Win32. If you are installing PHP 5, extract + to C:\php as the zip file doesn't expand as in PHP 4. You may choose a + different location but do not have spaces in the path (like C:\Program + Files\PHP) as some web servers will crash if you do. + + The directory structure extracted from the zip is different for PHP + versions 4 and 5 and look like as follows: + + Example 2-1. PHP 4 package structure +c:\php + | + +--cli + | | + | |-php.exe -- CLI executable - ONLY for commandline scripting + | + +--dlls -- support DLLs required by some extensions + | | + | |-expat.dll + | | + | |-fdftk.dll + | | + | |-... + | + +--extensions -- extension DLLs for PHP + | | + | |-php_bz2.dll + | | + | |-php_cpdf.dll + | | + | |-.. + | + +--mibs -- support files for SNMP + | + +--openssl -- support files for Openssl + | + +--pdf-related -- support files for PDF + | + +--sapi -- SAPI (server module support) DLLs + | | + | |-php4activescript.dll + | | + | |-php4apache.dll + | | + | |-php4apache2.dll + | | + | |-.. + | + +--PEAR -- initial copy of PEAR + | + | + |-go-pear.bat -- PEAR setup script + | + |-.. + | + |-php.exe -- CGI executable + | + |-.. + | + |-php.ini-dist -- default php.ini settings + | + |-php.ini-recommended -- recommended php.ini settings + | + |-php4ts.dll -- core PHP DLL + | + |-... + + Or: + + Example 2-2. PHP 5 package structure +c:\php + | + +--dev + | | + | |-php5ts.lib + | + +--ext -- extension DLLs for PHP + | | + | |-php_bz2.dll + | | + | |-php_cpdf.dll + | | + | |-.. + | + +--extras + | | + | +--mibs -- support files for SNMP + | | + | +--openssl -- support files for Openssl + | | + | +--pdf-related -- support files for PDF + | | + | |-mime.magic + | + +--pear -- initial copy of PEAR + | + | + |-go-pear.bat -- PEAR setup script + | + |-fdftk.dll + | + |-.. + | + |-php-cgi.exe -- CGI executable + | + |-php-win.exe -- executes scripts without an opened command prompt + | + |-php.exe -- CLI executable - ONLY for command line scripting + | + |-.. + | + |-php.ini-dist -- default php.ini settings + | + |-php.ini-recommended -- recommended php.ini settings + | + |-php5activescript.dll + | + |-php5apache.dll + | + |-php5apache2.dll + | + |-.. + | + |-php5ts.dll -- core PHP DLL + | + |-... + + Notice the differences and similarities. Both PHP 4 and PHP 5 have a + CGI executable, a CLI executable, and server modules, but they are + located in different folders and/or have different names. While PHP 4 + packages have the server modules in the sapi folder, PHP 5 + distributions have no such directory and instead they're in the PHP + folder root. The supporting DLLs for the PHP 5 extensions are also not + in a seperate directory. + + Note: In PHP 4, you should move all files located in the dll and + sapi folders to the main folder (e.g. C:\php). + + Here is a list of server modules shipped with PHP 4 and PHP 5: + + * sapi/php4activescript.dll (php5activescript.dll) - ActiveScript + engine, allowing you to embed PHP in your Windows applications. + * sapi/php4apache.dll (php5apache.dll) - Apache 1.3.x module. + * sapi/php4apache2.dll (php5apache2.dll) - Apache 2.0.x module. + * sapi/php4isapi.dll (php5isapi.dll) - ISAPI Module for ISAPI + compliant web servers like IIS 4.0/PWS 4.0 or newer. + * sapi/php4nsapi.dll (php5nsapi.dll) - Sun/iPlanet/Netscape server + module. + * sapi/php4pi3web.dll (no equivalent in PHP 5) - Pi3Web server + module. + + Server modules provide significantly better performance and additional + functionality compared to the CGI binary. The CLI version is designed + to let you use PHP for command line scripting. More information about + CLI is available in the chapter about using PHP from the command line. + + Warning + + The SAPI modules have been significantly improved as of the 4.1 + release, however, in older systems you may encounter server errors or + other server modules failing, such as ASP. + + The CGI and CLI binaries, and the web server modules all require the + php4ts.dll (php5ts.dll) file to be available to them. You have to make + sure that this file can be found by your PHP installation. The search + order for this DLL is as follows: + + * The same directory from where php.exe is called, or in case you + use a SAPI module, the web server's directory (e.g. C:\Program + Files\Apache Group\Apache2\bin). + * Any directory in your Windows PATH environment variable. + + To make php4ts.dll / php5ts.dll available you have three options: copy + the file to the Windows system directory, copy the file to the web + server's directory, or add your PHP directory, C:\php to the PATH. For + better maintenance, we advise you to follow the last option, add + C:\php to the PATH, because it will be simpler to upgrade PHP in the + future. Read more about how to add your PHP directory to PATH in the + corresponding FAQ entry. + + The next step is to set up a valid configuration file for PHP, + php.ini. There are two ini files distributed in the zip file, + php.ini-dist and php.ini-recommended. We advise you to use + php.ini-recommended, because we optimized the default settings in this + file for performance, and security. Read this well documented file + carefully because it has changes from php.ini-dist that will + drastically affect your setup. Some examples are display_errors being + off and magic_quotes_gpc being off. In addition to reading these, + study the ini settings and set every element manually yourself. If you + would like to achieve the best security, then this is the way for you, + although PHP works fine with these default ini files. Copy your chosen + ini-file to a directory that PHP is able to find and rename it to + php.ini. PHP searches for php.ini in the following locations (in + order): + + * PHPIniDir directive (Apache 2 module only) + * HKEY_LOCAL_MACHINE\SOFTWARE\PHP\IniFilePath + * The PHPRC environment variable + * Directory of PHP (for CLI), or the web server's directory (for + SAPI modules) + * Windows directory (C:\windows or C:\winnt) + + If you are running Apache 2, the simpler option is to use the + PHPIniDir directive (read the installation on Apache 2 page), + otherwise your best option is to set the PHPRC environment variable. + This process is explained in the following FAQ entry. + + Note: If you're using NTFS on Windows NT, 2000, XP or 2003, make + sure that the user running the web server has read permissions to + your php.ini (e.g. make it readable by Everyone). + + The following steps are optional: + + * Edit your new php.ini file. If you plan to use OmniHTTPd, do not + follow the next step. Set the doc_root to point to your web + servers document_root. For example: + +doc_root = c:\inetpub\wwwroot // for IIS/PWS + +doc_root = c:\apache\htdocs // for Apache + + * Choose the extensions you would like to load when PHP starts. See + the section about Windows extensions, about how to set up one, and + what is already built in. Note that on a new installation it is + advisable to first get PHP working and tested without any + extensions before enabling them in php.ini. + * On PWS and IIS, you can set the browscap configuration setting to + point to: c:\windows\system\inetsrv\browscap.ini on Windows 9x/Me, + c:\winnt\system32\inetsrv\browscap.ini on NT/2000, and + c:\windows\system32\inetsrv\browscap.ini on XP. For an up-to-date + browscap.ini, read the following FAQ. + + PHP is now setup on your system. The next step is to choose a web + server, and enable it to run PHP. Choose a webserver from the table of + contents. + _________________________________________________________________ + +ActiveScript + + This section contains notes specific to the ActiveScript installation. + + ActiveScript is a windows only SAPI that enables you to use PHP script + in any ActiveScript compliant host, like Windows Script Host, + ASP/ASP.NET, Windows Script Components or Microsoft Scriptlet control. + + As of PHP 5.0.1, ActiveScript has been moved to the PECL repository. + You may download this PECL extension DLL from the PHP Downloads page + or at http://snaps.php.net/. + + Note: You should read the manual installation steps first! + + After installing PHP, you should download the ActiveScript DLL + (php5activescript.dll) and place it in the main PHP folder (e.g. + C:\php). + + After having all the files needed, you must register the DLL on your + system. To achieve this, open a Command Prompt window (located in the + Start Menu). Then go to your PHP directory by typing something like cd + C:\php. To register the DLL just type regsvr32 php5activescript.dll. + + To test if ActiveScript is working, create a new file, named test.wsf + (the extension is very important) and type: + + + + + + + Save and double-click on the file. If you receive a little window + saying "Hello World!" you're done. + + Note: ActiveScript doesn't use the default php.ini file. Instead, + it will look only in the same directory as the .exe that caused it + to load. You should create php-activescript.ini and place it in + that folder, if you wish to load extensions, etc. + _________________________________________________________________ + +Microsoft IIS / PWS + + This section contains notes and hints specific to IIS (Microsoft + Internet Information Server). + + Warning + + By using the CGI setup, your server is open to several possible + attacks. Please read our CGI security section to learn how to defend + yourself from those attacks. + _________________________________________________________________ + +General considerations for all installations of PHP with IIS + + * First, read the Manual Installation Instructions. Do not skip this + step as it provides crucial information for installing PHP on + Windows. + * CGI users must set the cgi.force_redirect PHP directive to 0 + inside php.ini. Read the faq on cgi.force_redirect for important + details. Also, CGI users should set the cgi.redirect_status_env + directive to ENV_VAR_NAME. Be sure these directives aren't + commented out inside php.ini. + * The PHP 4 CGI is named php.exe while in PHP 5 it's php-cgi.exe. In + PHP 5, php.exe is the CLI, and not the CGI. + * Modify the Windows PATH environment variable to include the PHP + directory. This way the PHP DLL files, PHP executables, and + php.ini can all remain in the PHP directory without cluttering up + the Windows system directory. For more details, see the FAQ on + Setting the PATH. + * Be sure the extension_dir and doc_root PHP directives are + appropriately set in php.ini. These directives depend on the + system that PHP is being installed on. In PHP 4, the extension_dir + is extensions while with PHP 5 it's ext. So, an example PHP 5 + extensions_dir value is "c:\php\ext" and an example IIS doc_root + value is "c:\Inetpub\wwwroot". + * PHP extension DLL files, such as php_mysql.dll and php_curl.dll, + are found in the zip package of the PHP download (not the PHP + installer). In PHP 5, many extensions are part of PECL and can be + downloaded in the "Collection of PECL modules" package. Files such + as php_zip.dll and php_ssh2.dll. Download PHP files here. + * When defining the executable, the 'check that file exists' box may + also be checked. For a small performance penalty, the IIS (or PWS) + will check that the script file exists and sort out authentication + before firing up PHP. This means that the web server will provide + sensible 404 style error messages instead of CGI errors + complaining that PHP did not output any data. + _________________________________________________________________ + +Windows NT/200x/XP and IIS 4 or newer + + PHP may be installed as a CGI binary, or with the ISAPI module. In + either case, you need to start the Microsoft Management Console (may + appear as 'Internet Services Manager', either in your Windows NT 4.0 + Option Pack branch or the Control Panel=>Administrative Tools under + Windows 2000/XP). Then right click on your Web server node (this will + most probably appear as 'Default Web Server'), and select + 'Properties'. - php_dbase.dll dBase functions - php_filepro.dll Read-only access to Filepro databases - php_gd2.dll GD library functions for image manipulation - php_hyperwave.dll HyperWave functions - php_imap.dll IMAP functions - php_ldap.dll LDAP functions - php_mssql.dll MSSQL client (requires MSSQL DB-Libraries) - php_snmp.dll SNMP get and walk functions (NT only!) - php_zlib.dll ZLib compression functions + If you want to use the CGI binary, do the following: - For more information see the section about Windows extensions at - http://www.php.net/manual/en/install.windows.php#install.windows.extensions + * Under 'Home Directory', 'Virtual Directory', or 'Directory', do + the following: + * Change the Execute Permissions to 'Scripts only' + * Click on the 'Configuration' button, and choose the Application + Mappings tab. Click Add and set the Executable path to the + appropriate CGI file. An example PHP 5 value is: + C:\php\php-cgi.exe Supply .php as the extension. Leave 'Method + exclusions' blank, and check the 'Script engine' checkbox. Now, + click OK a few times. + * Set up the appropriate security. (This is done in Internet Service + Manager), and if your NT Server uses NTFS file system, add execute + rights for I_USR_ to the directory that contains php.exe / + php-cgi.exe. + To use the ISAPI module, do the following: -Web server configuration -======================== + * If you don't want to perform HTTP Authentication using PHP, you + can (and should) skip this step. Under ISAPI Filters, add a new + ISAPI filter. Use PHP as the filter name, and supply a path to the + php4isapi.dll / php5isapi.dll. + * Under 'Home Directory', 'Virtual Directory', or 'Directory', do + the following: + * Change the Execute Permissions to 'Scripts only' + * Click on the 'Configuration' button, and choose the Application + Mappings tab. Click Add and set the Executable path to the + appropriate ISAPI DLL. An example PHP 5 value is: + C:\php\php5isapi.dll Supply .php as the extension. Leave 'Method + exclusions' blank, and check the 'Script engine' checkbox. Now, + click OK a few times. + * Stop IIS completely (NET STOP iisadmin) + * Start IIS again (NET START w3svc) + + With IIS 6 (2003 Server), open up the IIS Manager, go to Web Service + Extensions, choose "Add a new Web service extension", enter in a name + such as PHP, choose the Add button and for the value browse to either + the ISAPI file (php4isapi.dll or php5isapi.dll) or CGI (php.exe or + php-cgi.exe) then check "Set extension status to Allowed" and click + OK. + + In order to use index.php as a default content page, do the following: + From within the Documents tab, choose Add. Type in index.php and click + OK. Adjust the order by choosing Move Up or Move Down. This is similar + to setting DirectoryIndex with Apache. + + The steps above must be repeated for each extension that is to be + associated with PHP scripts. .php is the most common although .php3 + may be required for legacy applications. + + If you experience 100% CPU usage after some time, turn off the IIS + setting Cache ISAPI Application. + _________________________________________________________________ + +Windows and PWS 4 + + PWS 4 does not support ISAPI, only PHP CGI should be used. + + * Edit the enclosed pws-php4cgi.reg / pws-php5cgi.reg file (look + into the SAPI folder for PHP 4, or in the main folder for PHP 5) + to reflect the location of your php.exe / php-cgi.exe. Backslashes + should be escaped, for example: + [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\w3svc\parame + ters\Script Map] ".php"="C:\\php\\php.exe" (change to + C:\\php\\php-cgi.exe if you are using PHP 5) Now merge this + registery file into your system; you may do this by + double-clicking it. + * In the PWS Manager, right click on a given directory you want to + add PHP support to, and select Properties. Check the 'Execute' + checkbox, and confirm. + _________________________________________________________________ + +Windows and PWS/IIS 3 + + The recommended method for configuring these servers is to use the REG + file included with the distribution (pws-php4cgi.reg in the SAPI + folder for PHP 4, or pws-php5cgi.reg in the main folder for PHP 5). + You may want to edit this file and make sure the extensions and PHP + install directories match your configuration. Or you can follow the + steps below to do it manually. + + Warning + + These steps involve working directly with the Windows registry. One + error here can leave your system in an unstable state. We highly + recommend that you back up your registry first. The PHP Development + team will not be held responsible if you damage your registry. + + * Run Regedit. + * Navigate to: HKEY_LOCAL_MACHINE /System /CurrentControlSet + /Services /W3Svc /Parameters /ScriptMap. + * On the edit menu select: New->String Value. + * Type in the extension you wish to use for your php scripts. For + example .php + * Double click on the new string value and enter the path to php.exe + in the value data field. ex: C:\php\php.exe for PHP 4, or + C:\php\php-cgi.exe for PHP 5. + * Repeat these steps for each extension you wish to associate with + PHP scripts. - Installing PHP on Windows with Apache 1.3.x + The following steps do not affect the web server installation and only + apply if you want your PHP scripts to be executed when they are run + from the command line (ex. run C:\myscripts\test.php) or by double + clicking on them in a directory viewer window. You may wish to skip + these steps as you might prefer the PHP files to load into a text + editor when you double click on them. - ------------------------------------------------------------ - ATTENTION: Apache 2 Users + * Navigate to: HKEY_CLASSES_ROOT + * On the edit menu select: New->Key. + * Name the key to the extension you setup in the previous section. + ex: .php + * Highlight the new key and in the right side pane, double click the + "default value" and enter phpfile. + * Repeat the last step for each extension you set up in the previous + section. + * Now create another New->Key under HKEY_CLASSES_ROOT and name it + phpfile. + * Highlight the new key phpfile and in the right side pane, double + click the "default value" and enter PHP Script. + * Right click on the phpfile key and select New->Key, name it Shell. + * Right click on the Shell key and select New->Key, name it open. + * Right click on the open key and select New->Key, name it command. + * Highlight the new key command and in the right side pane, double + click the "default value" and enter the path to php.exe. ex: + c:\php\php.exe -q %1. (don't forget the %1). + * Exit Regedit. + * If using PWS on Windows, reboot to reload the registry. - At this time, support for Apache 2 is experimental. It's - highly recommended you use PHP with Apache 1.3.x and not - Apache 2. Documentation for installing Apache 2 on windows - can be seen here: + PWS and IIS 3 users now have a fully operational system. IIS 3 users + can use a nifty tool from Steven Genusa to configure their script + maps. + _________________________________________________________________ - http://www.php.net/manual/en/install.apache2.php +Apache 1.3.x on Microsoft Windows - With the basic difference being that when installing as a - module you'll use php5apache2.dll instead of php5apache.dll - Both files are included within this release. - ------------------------------------------------------------ + This section contains notes and hints specific to Apache 1.3.x + installs of PHP on Microsoft Windows systems. There are also + instructions and notes for Apache 2 on a separate page. + Note: Please read the manual installation steps first! - There are two ways to set up PHP to work with Apache 1.3.x - on Windows. One is to use the CGI binary (php.exe), - the other is to use the Apache module dll. In either case - you need to stop the Apache server, and edit your - httpd.conf or srm.conf to configure Apache to work with PHP. - We'll refer to either of these files with httpd.conf in the - text. + There are two ways to set up PHP to work with Apache 1.3.x on Windows. + One is to use the CGI binary (php.exe for PHP 4 and php-cgi.exe for + PHP 5), the other is to use the Apache Module DLL. In either case you + need to edit your httpd.conf to configure Apache to work with PHP, and + then restart the server. - Although there can be a few variations of configuring PHP - under Apache, these are simple enough to be used by the - newcomer. Please consult the Apache Docs for further - configuration directives. + It is worth noting here that now the SAPI module has been made more + stable under Windows, we recommend it's use above the CGI binary, + since it is more transparent and secure. + Although there can be a few variations of configuring PHP under + Apache, these are simple enough to be used by the newcomer. Please + consult the Apache Documentation for further configuration directives. - Installing PHP for Apache as module - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + After changing the configuration file, remember to restart the server, + for example, NET STOP APACHE followed by NET START APACHE, if you run + Apache as a Windows Service, or use your regular shortcuts. - Now that version 4.1 introduces a safer sapi module, we recommend - that you configure PHP as a module in Apache. + Note: Remember that when adding path values in the Apache + configuration files on Windows, all backslashes such as + c:\directory\file.ext must be converted to forward slashes, as + c:/directory/file.ext. + _________________________________________________________________ - To accomplish this, you have to load the php5apache.dll in your - Apache httpd.conf. +Installing as an Apache module - !! NOTE !! - Whereever you load php5apache.dll from, php5apache.dll also - needs the php5ts.dll also included in the PHP distribution. - php5apache.dll depends on php5ts.dll which is loaded as soon as - Apache loads php5apache.dll. If php5ts.dll can't be found, you - usually get an error like (also see the "Problems?" section at - the end of the file): + You should add the following lines to your Apache httpd.conf file: - Cannot load c:/php/php5apache.dll into server + Example 2-3. PHP as an Apache 1.3.x module - So where does php5ts.dll has to be to be properly loaded ? - php5ts.dll is searched in the following order: + This assumes PHP is installed to c:\php. Adjust the path if this is + not the case. - 1) in the directory where apache.exe is start from - 2) in the directory where php5apache.dll is loaded from - 3) in your %SYSTEMROOT%\System32, %SYSTEMROOT%\system and - %SYSTEMROOT% directory. - Note: %SYSTEMROOT%\System32 only applies to Windows NT/2000/XP) - 4) in your whole %PATH% + For PHP 4: +# Add to the end of the LoadModule section +LoadModule php4_module "c:/php/php4apache.dll" - Note: What is %SYSTEMROOT% ? Depending on your Windows - installation this may be for example c:\winnt or C:\windows +# Add to the end of the AddModule section +AddModule mod_php4.c - Usually you would just copy it over to %SYSTEMROOT%\System32. - But if you want to have multiple PHP installations (for - whatever reason) this is a bad idea. For this circumstance the - safest thing is to let php5ts.dll reside in the same directory - where php5apache.dll is loaded from (see point 2 above). + For PHP 5: +# Add to the end of the LoadModule section +LoadModule php5_module "c:/php/php5apache.dll" +# Add to the end of the AddModule section +AddModule mod_php5.c - After you've set up the file layout properly, you're ready to - finally configure Apache to load the PHP module. Just add the - following lines to your httpd.conf: + For both: +# Add this line inside the conditional brace +AddType application/x-httpd-php .php - LoadModule php5_module c:/php/php5apache.dll - AddModule mod_php5.c - AddType application/x-httpd-php .php +# For syntax highlighted .phps files, also add +AddType application/x-httpd-php-source .phps + _________________________________________________________________ - Note: Especially newer versions of Apache do not need the - AddModule directive anymore, your milage may vary. +Installing as a CGI binary + If you unzipped the PHP package to C:\php\ as described in the Manual + Installation Steps section, you need to insert these lines to your + Apache configuration file to set up the CGI binary: - Where do I have to put the php.ini ? - The php.ini files is only searched in two places: - 1) in your Apache installation directory (e.g. c:\apache\apache) - 2) in your %SYSTEMROOT% directory. - + Example 2-4. PHP and Apache 1.3.x as CGI +ScriptAlias /php/ "c:/php/" +AddType application/x-httpd-php .php - Installing PHP for Apache as CGI binary - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# For PHP 4 +Action application/x-httpd-php "/php/php.exe" - If you wish to install PHP as a CGI binary, read this first: +# For PHP 5 +Action application/x-httpd-php "/php/php-cgi.exe" - http://www.cert.org/advisories/CA-1996-11.html +# specify the directory where php.ini is +SetEnv PHPRC C:/php - and then if you are really sure, insert these lines to your conf file: + Note that the second line in the list above can be found in the actual + versions of httpd.conf, but it is commented out. Remember also to + substitute the c:/php/ for your actual path to PHP. - ScriptAlias /php/ "c:/php/" - AddType application/x-httpd-php .php - Action application/x-httpd-php "/php/php.exe" + Warning - Note, we consider installing PHP like this suicidal. + By using the CGI setup, your server is open to several possible + attacks. Please read our CGI security section to learn how to defend + yourself from those attacks. - As a further precaution, we recommend you change the "/php/" - ScriptAlias to something more random, to prevent the binary being - called directly, which is a security risk. + If you would like to present PHP source files syntax highlighted, + there is no such convenient option as with the module version of PHP. + If you chose to configure Apache to use PHP as a CGI binary, you will + need to use the highlight_file() function. To do this simply create a + PHP script file and add this code: . + _________________________________________________________________ - Remember when you have finished to restart the server, for example, - NET STOP APACHE - followed by - NET START APACHE +Apache 2.0.x on Microsoft Windows - To use the source code highlighting feature, add the following - line to your apache httpd.conf file: + This section contains notes and hints specific to Apache 2.0.x + installs of PHP on Microsoft Windows systems. We also have + instructions and notes for Apache 1.3.x users on a separate page. - AddType application/x-httpd-php-source .phps + Note: You should read the manual installation steps first! - Note, this will only work when you install php as a sapi module. - If you wish to use this feature with the cgi binary, create a new - file, and use the show_source("path/to/original_file.php"); function. + Warning + We do not recommend using a threaded MPM in production with Apache2. + Use the prefork MPM instead, or use Apache1. For information on why, + read the following FAQ entry - Forward or backslash in pathnames ? - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - On Win-Apache, path names can contain either forward- or backslashes. - Example: + You are highly encouraged to take a look at the Apache Documentation + to get a basic understanding of the Apache 2.0.x Server. Also consider + to read the Windows specific notes for Apache 2.0.x before reading on + here. - LoadModule php5_module C:\php\php5apache.dll + PHP and Apache 2.0.x compatibility notes: The following versions of + PHP are known to work with the most recent version of Apache 2.0.x: - works as good as + * PHP 4.3.0 or later available at http://www.php.net/downloads.php. + * the latest stable development version. Get the source code + http://snaps.php.net/php4-latest.tar.gz or download binaries for + Windows http://snaps.php.net/win32/php4-win32-latest.zip. + * a prerelease version downloadable from http://qa.php.net/. + * you have always the option to obtain PHP through anonymous CVS. - LoadModule php5_module C:/php/php5apache.dll + These versions of PHP are compatible to Apache 2.0.40 and later. - You even can mix the slash-style: + Apache 2.0 SAPI-support started with PHP 4.2.0. PHP 4.2.3 works + with Apache 2.0.39, don't use any other version of Apache with PHP + 4.2.3. However, the recommended setup is to use PHP 4.3.0 or later + with the most recent version of Apache2. - LoadModule php5_module C:\php/php5apache.dll + All mentioned versions of PHP will work still with Apache 1.3.x. ----------------------------------------------------------- + Warning - Installing PHP on Windows with IIS/PWS + Apache 2.0.x is designed to run on Windows NT 4.0, Windows 2000 or + Windows XP. At this time, support for Windows 9x is incomplete. Apache + 2.0.x is not expected to work on those platforms at this time. - This section contains notes and hints specific to IIS (Microsoft - Internet Information Server). Installing PHP for PWS/IIS 3 and - PWS/IIS 4 or newer versions. + Download the most recent version of Apache 2.0.x and a fitting PHP + version. Follow the Manual Installation Steps and come back to go on + with the integration of PHP and Apache. - Windows and PWS/IIS 3 - including PWS on Win 9x/ME + There are two ways to set up PHP to work with Apache 2.0.x on Windows. + One is to use the CGI binary the other is to use the Apache module + DLL. In either case you need to edit your httpd.conf to configure + Apache to work with PHP and then restart the server. - The recommended method for configuring these servers is to use - the REG file incuded with the distribution (pws-php5cgi.reg). - You may want to edit this file and make sure the extensions and PHP - install directories match your configuration - once you have done - this, just double click on the file and it will update your registry. - Alternatively, you can follow the steps below to do it manually. - - WARNING: - These steps involve working directly with the Windows - registry. One error here can leave your system in an unstable - state. We highly recommend that you back up your registry - first. The PHP Development team will not be held responsible if - you damage your registry. - - Run Regedit. - Navigate to: - HKEY_LOCAL_MACHINE/System/CurrentControlSet/Services/W3Svc/Parameters/ScriptMap - On the edit menu select: New->String Value. - Type in the extension you wish to use for your php scripts. ex: .php - Double click on the new string value and enter the path to - php.exe in the value data field. - ex: c:\php\php.exe - Repeat these steps for each extension you wish to associate - with PHP scripts. + Note: Remember that when adding path values in the Apache + configuration files on Windows, all backslashes such as + c:\directory\file.ext must be converted to forward slashes, as + c:/directory/file.ext. + _________________________________________________________________ - The following steps do not affect the web server installation and only - apply if you want your php scripts to be executed when they are run - from the command line (ex. run c:\myscripts\test.php) or by double - clicking on them in a directory viewer window. You may wish to skip - this step as you might prefer the php files to load into a text - editor when you double click on them. +Installing as a CGI binary - Now navigate to: HKEY_CLASSES_ROOT - On the edit menu select: New->Key - Name the key to the extension you setup in the previous - section. ex: .php - Highlight the new key and in the right side pane, double click - the "default value" and enter phpfile. - Repeat the last step for each extension you set up in the - previous section. - Now create another New->Key under - HKEY_CLASSES_ROOT and name it phpfile - Highlight the new key 'phpfile' and in the - right side pane, double click the "default value" and enter - PHP Script. - Right click on the 'phpfile' key and select - New->Key, name it Shell. - Right click on the 'Shell' key and select - New->Key, name it open. - Right click on the 'open' key and select - New->Key, name it command. - Highlight the new key 'command' and in the - right side pane, double click the "default value" and enter - the path to php.exe ex: c:\php\php.exe -q %1 - (don't forget the '%1'). - Exit Regedit. - If using PWS on Windows, reboot to reload the registry. - PWS and IIS 3 users now have a fully operational system. IIS 3 - users can use a nifty tool available at - http://www.genusa.com/iis/iiscfg.html - from Steven Genusa to configure their script maps. - - Windows NT/2000/XP and IIS 4 or newer and PWS 4 on NT Workstation or W2K non server editions - - To install PHP on an NT/2000/XP Server running IIS 4 or newer, - follow these instructions. You have two options to set up - PHP, using the CGI binary (php.exe) or with the ISAPI module. - - In either case, you need to start the Microsoft Management - Console (may appear as 'Internet Services Manager', either - in your Windows NT 4.0 Option Pack branch or the Control - Panel=>Administrative Tools under Windows 2000). Then - right click on your Web server node (this will most probably - appear as 'Default Web Server'), and select 'Properties'. + You need to insert these three lines to your Apache httpd.conf + configuration file to set up the CGI binary: - If you want to use the CGI binary, do the following: - Under 'Home Directory', 'Virtual Directory', or - 'Directory', click on the 'Configuration' button, - and then enter the App Mappings tab. + Example 2-5. PHP and Apache 2.0 as CGI +ScriptAlias /php/ "c:/php/" +AddType application/x-httpd-php .php - Click Add, and in the Executable box, type: - c:\php\php.exe (assuming that you have unzipped PHP in c:\php\). +# For PHP 4 +Action application/x-httpd-php "/php/php.exe" - In the Extension box, type the file name extension you want - associated with PHP scripts. Leave 'Method exclusions' - blank, and check the Script engine checkbox. You may also - like to check the 'check that file exists' box - for a small - performance penalty, IIS (or PWS) will check that the script - file exists and sort out authentication before firing up php. - This means that you will get sensible 404 style error messages - instead of cgi errors complaing that php did not output any data. +# For PHP 5 +Action application/x-httpd-php "/php/php-cgi.exe" - You must repeat from 'Click Add...' for each extension you - want associated with PHP scripts. - (.php is recommended. although .phtml and .php3 may be - required for legacy applications.) + Warning - Set up the appropriate security. (This is done in Internet - Service Manager), and if your NT Server uses NTFS file system, - add execute rights for I_USR_ to the directory that contains - php.exe + By using the CGI setup, your server is open to several possible + attacks. Please read our CGI security section to learn how to defend + yourself from those attacks. + _________________________________________________________________ - !NOTE!: Since 4.1.2, the php.ini setting cgi.force_redirect defaults to '1' - which effectively prevents the cgi from working within IIS. You need to set - up at least a minimal php.ini file with the following directive: +Installing as an Apache module - cgi.force_redirect = 0 + You need to insert these two lines to your Apache httpd.conf + configuration file to set up the PHP module for Apache 2.0: - If it doesn't work immidiately, make sure you have the php.ini file in the - right place (%SYSTEMROOT%\php.ini). + Example 2-6. PHP and Apache 2.0 as Module +# For PHP 4 do something like this: +LoadModule php4_module "c:/php/php4apache2.dll" +AddType application/x-httpd-php .php +# For PHP 5 do something like this: +LoadModule php5_module "c:/php/php5apache2.dll" +AddType application/x-httpd-php .php - To use the ISAPI module, do the following: +# configure the path to php.ini +PHPIniDir "C:/php" - If you don't want to perform HTTP Authentication using PHP, - you can (and should) skip this step. Under ISAPI Filters, - add a new ISAPI filter. Use PHP as the filter name, and - supply a path to the php5isapi.dll. + Note: Remember to substitute the c:/php/ for your actual path to + PHP in the above examples. Take care to use either php4apache2.dll + or php5apache2.dll in your LoadModule directive and not + php4apache.dll or php5apache.dll as the latter ones are designed to + run with Apache 1.3.x. - Under 'Home Directory', click on the 'Configuration' button. - Add a new entry to the Application Mappings. Use the path - to the php5isapi.dll as the Executable, supply .php as the - extension, leave Method exclusions blank, and check the - Script engine checkbox. + Note: If you want to use content negotiation, read related FAQ. - Stop IIS completely (net stop iisadmin) - Start IIS again (net start w3svc) + Warning ----------------------------------------------------------- - - Installing PHP on Windows with OmniHTTPd Server - - This section contains notes and hints specific to - OmniHTTPd 2.0b1 and up for Windows - - This has got to be the easiest config there is: - - Step 1: Install OmniHTTPd server. - Step 2: Right click on the blue OmniHTTPd icon in the system - tray and select 'Properties' - Step 3: Click on 'Web Server Global Settings' - Step 4: On the 'External' tab, enter: - virtual = .php | actual = c:\path-to-php-dir\php.exe - and use the Add button. - Step 5: On the Mime tab, enter: - virtual = wwwserver/stdcgi | actual = .php - and use the Add button. - Step 6: Click 'OK' - - Repeat steps 2 - 6 for each extension you want to associate with PHP. - NOTE: - Some OmniHTTPd packages come with built in PHP support. - You can choose at setup time to do a custom setup, and - uncheck the PHP component. We recommend you to use the latest - PHP binaries. Some OmniHTTPd servers come with PHP 4 beta - distributions, so you should choose not to set up - the built in support, but install your own. If the server - is already on your machine, use the Replace button in Step - 4 and 5 to set the new, correct information. - ----------------------------------------------------------- - - Installing PHP on Windows with Oreilly Website Pro - - This section contains notes and hints specific to Oreilly - Website Pro 2.5 and up for Windows - - This list describes how to set up the PHP CGI binary - or the ISAPI module to work with Oreilly Website Pro - on Windows. - - Edit the Server Properties and select the tab "Mapping". - - From the List select "Associations" and enter the desired - extension (".php") and the path to the CGI exe (ex. c:\php\php.exe) - or the ISAPI dll file (ex. c:\php\php5isapi.dll). - - Select "Content Types" add the same extension ".php" - and enter the content type. If you choose the CGI exe - file, enter 'wwwserver/shellcgi', if you chose the - ISAPI module, enter 'wwwserver/isapi' (both without quotes). - ----------------------------------------------------------- - - Installing PHP on Windows with Xitami - - This section contains notes and hints specific to Xitami. - - This list describes how to set up the PHP CGI binary - to work with Xitami on Windows. - - Make sure the webserver is running, and point - your browser to xitamis admin console - (usually http://127.0.0.1/admin), and click on - Configuration. - - Navigate to the Filters, and put the - extension which php should parse (i.e. .php) - into the field File extensions (.xxx). - - In Filter command or script put the path and name - of your php executable i.e. c:\php\php.exe. - - Press the 'Save' icon. - ----------------------------------------------------------- - - Installing PHP on Windows with Netscape/iPlanet/SunONE servers. - - - These instructions are targetted at Netscape Enterprise Web Server and - SUN/Netscape Alliance iPlanet Web Server/SunONE Webserver. - On other web servers your milage may vary. - - Netscape/iPlanet/SunONE config files are located in: - - \https-servername\config - - - Add the following line to mime.types (you can do that by the administration server): - - type=magnus-internal/x-httpd-php exts=php - - - Place the following two lines after mime.types init in - \https-servername\config\obj.conf (for servers < 6) or - for iPlanet/SunONE Web Server 6.0 and above however at the end of the - \https-servername\config\magnus.conf file: - - Init fn="load-modules" funcs="php5_init,php5_execute,php5_auth_trans" shlib="c:/path/to/PHP/php5nsapi.dll" - Init fn=php5_init errorString="Failed to initialize PHP!" [php_ini="c:/path/to/php.ini"] - - In obj.conf (for virtual server classes [SunONE 6.0+] in their vserver.obj.conf): - - - . - . - . - # NOTE this next line should happen after all 'ObjectType' and before - # all 'AddLog' lines - # You can modify some entries in php.ini request specific by adding it to the Service - # directive, e.g. doc_root="/path" - # For boolean ini-keys please use 0/1 as value, NOT "On","Off",... (this will not work - # correctly), e.g. zlib.output_compression=1 instead of zlib.output_compression="On" - - Service fn="php5_execute" type="magnus-internal/x-httpd-php" [inikey=value ...] - . - . - . - - - This is only needed if you want to configure a directory that only consists of - PHP scripts (same like a cgi-bin directory): - - - ObjectType fn="force-type" type="magnus-internal/x-httpd-php" - Service fn="php5_execute" [inikey=value ...] - - - After that you can configure a directory in the Administration server and assign it - the style "x-httpd-php". All files in it will get executed as PHP. This is nice to - hide PHP usage by renaming files to .html - ----------------------------------------------------------- - - Installing PHP on The Sambar Server - - This section contains notes and hints specific to Sambar - - Find the file called mappings.ini (config directory) in your Sambar - install directory - - Open mappings.ini and add the following line under [isapi] - - *.php = c:\php\php5isapi.dll - Note: The above assumes that PHP was installed in c:\php - - Restart the server - ----------------------------------------------------------- - -Problems? -========= - - Read the FAQ - - Some problems are more common than others. The most common ones - are listed in the PHP FAQ, found at www.php.net/FAQ.php - - Common problems with Windows - - The following problems often occur with IIS/PWS, but some points may - also apply to other servers. - - For test purposes it is best to use just a simple test script. One - containing just the following line will suffice: - - - You have installed PHP, but when try to access a php script file via your - browser, you get a blank screen: - - Do a 'view source' in the web browser and you will probably find that you - can see the source code of your php script. This means that the web server - did not send the script to php for interpretation. Something is wrong with - the server configuration - double check the server configuration against - the php installation instructions. - - You have installed PHP, but when try to access a php script file via your - browser, you get a server 500 error: - - Something went wrong when the server tried to run PHP. To get to see a - sensible error message, from the command line, change to the directory - containing php.exe and run "php.exe -i" (without quotes). - If php has any problems running, then a suitable error message will be displayed - which will give you a clue as to what needs to be done next. - If you get a screen full of html codes (the output of the phpinfo() function) then - php is working ok, and your problem may be related to your server configuration - which you should double check. - - You have installed PHP, but when try to access a php script file via your - browser, you get the error: - cgi error: - The specified CGI application misbehaved by not returning a complete set of - HTTP headers. The headers it did return are: - - This error message means that php failed to output anything at all. - From the command line hange to the directory containing php.exe. Run - php.exe -i - If php has any problems running, then a suitable - error message will be displayed which will give you a clue as to what needs to - be done next. If you get a screen full of html codes (the output of the - phpinfo() function) then php is working ok. - - Once php is working at the command line, try accessing the php script via the browser again. - If it still fails then it could be one of the following: - - file permissions on your php script, php.exe, php5ts.dll, php.ini or any php - extensions you are trying to load are such that the web server cannot access - them. For IIS, IUSR_ needs at least read access. - - The script file does not exist (or possibly isn't where you think it is - relative to your web root directory). Note that for IIS you can trap this error by ticking - the 'check file exists' box when setting up the script mappings in the Internet Services - Manager. If a script file does not exist then the server will return a 404 error instead. - There is also the additional benefit that IIS will do any authentication required for you - based on the NTLanMan permissions on your script file. + Don't mix up your installation with DLL files from different PHP + versions. You have the only choice to use the DLL's and extensions + that ship with your downloaded PHP version. + _________________________________________________________________ + +Sun, iPlanet and Netscape servers on Microsoft Windows + + This section contains notes and hints specific to Sun Java System Web + Server, Sun ONE Web Server, iPlanet and Netscape server installs of + PHP on Windows. + From PHP 4.3.3 on you can use PHP scripts with the NSAPI module to + generate custom directory listings and error pages. Additional + functions for Apache compatibility are also available. For support in + current webservers read the note about subrequests. + _________________________________________________________________ + +CGI setup on Sun, iPlanet and Netscape servers + + To install PHP as a CGI handler, do the following: - You have inherent problems loading the right DLL? - Sometimes, loading the right DLL can be a pain on Windows. - Advanced Windows users may use a tool called strace (named - after the famous Unix application) to trace file access on the - system (however, it only works on NT-alike Windows, read: - NT/2000/XP). It can be found at - http://razor.bindview.com/tools/desc/strace_readme.html . Read - the instruction there carefully! + * Copy php4ts.dll to your systemroot (the directory where you + installed Windows) + * Make a file association from the command line. Type the following + two lines: + +assoc .php=PHPScript +ftype PHPScript=c:\php\php.exe %1 %* + + * In the Netscape Enterprise Administration Server create a dummy + shellcgi directory and remove it just after (this step creates 5 + important lines in obj.conf and allow the web server to handle + shellcgi scripts). + * In the Netscape Enterprise Administration Server create a new mime + type (Category: type, Content-Type: magnus-internal/shellcgi, File + Suffix:php). + * Do it for each web server instance you want PHP to run + + More details about setting up PHP as a CGI executable can be found + here: http://benoit.noss.free.fr/php/install-php.html + _________________________________________________________________ + +NSAPI setup on Sun, iPlanet and Netscape servers + + To install PHP with NSAPI, do the following: + + * Copy php4ts.dll to your systemroot (the directory where you + installed Windows) + * Make a file association from the command line. Type the following + two lines: + +assoc .php=PHPScript +ftype PHPScript=c:\php\php.exe %1 %* + + * In the Netscape Enterprise Administration Server create a new mime + type (Category: type, Content-Type: magnus-internal/x-httpd-php, + File Suffix: php). + * Edit magnus.conf (for servers >= 6) or obj.conf (for servers < 6) + and add the following: You should place the lines after mime types + init. + +Init fn="load-modules" funcs="php4_init,php4_execute,php4_auth_trans" shlib="c: +/php/sapi/php4nsapi.dll" +Init fn="php4_init" LateInit="yes" errorString="Failed to initialise PHP!" [php +_ini="c:/path/to/php.ini"] + + (PHP >= 4.3.3) The php_ini parameter is optional but with it you + can place your php.ini in your webserver config directory. + * Configure the default object in obj.conf (for virtual server + classes [Sun Web Server 6.0+] in their vserver.obj.conf): In the + section, place this line necessarily after + all 'ObjectType' and before all 'AddLog' lines: + +Service fn="php4_execute" type="magnus-internal/x-httpd-php" [inikey=value inik +ey=value ...] + + (PHP >= 4.3.3) As additional parameters you can add some special + php.ini-values, for example you can set a + docroot="/path/to/docroot" specific to the context php4_execute is + called. For boolean ini-keys please use 0/1 as value, not + "On","Off",... (this will not work correctly), e.g. + zlib.output_compression=1 instead of zlib.output_compression="On" + * This is only needed if you want to configure a directory that only + consists of PHP scripts (same like a cgi-bin directory): + + +ObjectType fn="force-type" type="magnus-internal/x-httpd-php" +Service fn=php4_execute [inikey=value inikey=value ...] + + + After that you can configure a directory in the Administration + server and assign it the style x-httpd-php. All files in it will + get executed as PHP. This is nice to hide PHP usage by renaming + files to .html. + * Restart your web service and apply changes + * Do it for each web server instance you want PHP to run + + Note: More details about setting up PHP as an NSAPI filter can be + found here: http://benoit.noss.free.fr/php/install-php4.html + + Note: The stacksize that PHP uses depends on the configuration of + the webserver. If you get crashes with very large PHP scripts, it + is recommended to raise it with the Admin Server (in the section + "MAGNUS EDITOR"). + _________________________________________________________________ + +CGI environment and recommended modifications in php.ini + + Important when writing PHP scripts is the fact that Sun JSWS/Sun ONE + WS/iPlanet/Netscape is a multithreaded web server. Because of that all + requests are running in the same process space (the space of the + webserver itself) and this space has only one environment. If you want + to get CGI variables like PATH_INFO, HTTP_HOST etc. it is not the + correct way to try this in the old PHP 3.x way with getenv() or a + similar way (register globals to environment, $_ENV). You would only + get the environment of the running webserver without any valid CGI + variables! + + Note: Why are there (invalid) CGI variables in the environment? + + Answer: This is because you started the webserver process from the + admin server which runs the startup script of the webserver, you + wanted to start, as a CGI script (a CGI script inside of the admin + server!). This is why the environment of the started webserver has + some CGI environment variables in it. You can test this by starting + the webserver not from the administration server. Use the command + line as root user and start it manually - you will see there are no + CGI-like environment variables. + + Simply change your scripts to get CGI variables in the correct way for + PHP 4.x by using the superglobal $_SERVER. If you have older scripts + which use $HTTP_HOST, etc., you should turn on register_globals in + php.ini and change the variable order too (important: remove "E" from + it, because you do not need the environment here): +variables_order = "GPCS" +register_globals = On + _________________________________________________________________ + +Special use for error pages or self-made directory listings (PHP >= 4.3.3) + + You can use PHP to generate the error pages for "404 Not Found" or + similar. Add the following line to the object in obj.conf for every + error page you want to overwrite: +Error fn="php4_execute" code=XXX script="/path/to/script.php" [inikey=value ini +key=value...] + + where XXX is the HTTP error code. Please delete any other Error + directives which could interfere with yours. If you want to place a + page for all errors that could exist, leave the code parameter out. + Your script can get the HTTP status code with $_SERVER['ERROR_TYPE']. + + Another possibility is to generate self-made directory listings. Just + create a PHP script which displays a directory listing and replace the + corresponding default Service line for + type="magnus-internal/directory" in obj.conf with the following: +Service fn="php4_execute" type="magnus-internal/directory" script="/path/to/scr +ipt.php" [inikey=value inikey=value...] + + For both error and directory listing pages the original URI and + translated URI are in the variables $_SERVER['PATH_INFO'] and + $_SERVER['PATH_TRANSLATED']. + _________________________________________________________________ + +Note about nsapi_virtual() and subrequests (PHP >= 4.3.3) + + The NSAPI module now supports the nsapi_virtual() function (alias: + virtual()) to make subrequests on the webserver and insert the result + in the webpage. The problem is, that this function uses some + undocumented features from the NSAPI library. + + Under Unix this is not a problem, because the module automatically + looks for the needed functions and uses them if available. If not, + nsapi_virtual() is disabled. + + Under Windows limitations in the DLL handling need the use of a + automatic detection of the most recent ns-httpdXX.dll file. This is + tested for servers till version 6.1. If a newer version of the Sun + server is used, the detection fails and nsapi_virtual() is disabled. + + If this is the case, try the following: Add the following parameter to + php4_init in magnus.conf/obj.conf: + Init fn=php4_init ... server_lib="ns-httpdXX.dll" + + where XX is the correct DLL version number. To get it, look in the + server-root for the correct DLL name. The DLL with the biggest + filesize is the right one. + + You can check the status by using the phpinfo() function. + + Note: But be warned: Support for nsapi_virtual() is EXPERIMENTAL!!! + _________________________________________________________________ + +OmniHTTPd Server + + This section contains notes and hints specific to OmniHTTPd on + Windows. + + Note: You should read the manual installation steps first! + + Warning + + By using the CGI setup, your server is open to several possible + attacks. Please read our CGI security section to learn how to defend + yourself from those attacks. + + You need to complete the following steps to make PHP work with + OmniHTTPd. This is a CGI executable setup. SAPI is supported by + OmniHTTPd, but some tests have shown that it is not so stable to use + PHP as an ISAPI module. + + Important for CGI users: Read the faq on cgi.force_redirect for + important details. This directive needs to be set to 0. + + 1. Install OmniHTTPd server. + 2. Right click on the blue OmniHTTPd icon in the system tray and + select Properties + 3. Click on Web Server Global Settings + 4. On the 'External' tab, enter: virtual = .php | actual = + c:\php\php.exe (use php-cgi.exe if installing PHP 5), and use the + Add button. + 5. On the Mime tab, enter: virtual = wwwserver/stdcgi | actual = + .php, and use the Add button. + 6. Click OK + + Repeat steps 2 - 6 for each extension you want to associate with PHP. + + Note: Some OmniHTTPd packages come with built in PHP support. You + can choose at setup time to do a custom setup, and uncheck the PHP + component. We recommend you to use the latest PHP binaries. Some + OmniHTTPd servers come with PHP 4 beta distributions, so you should + choose not to set up the built in support, but install your own. If + the server is already on your machine, use the Replace button in + Step 4 and 5 to set the new, correct information. + _________________________________________________________________ - Example scenery: +Sambar Server on Microsoft Windows - Apache/PHP as module. Though I've properly configured - php5apache.dll in httpd.conf, I always get: + This section contains notes and hints specific to the Sambar Server + for Windows. + + Note: You should read the manual installation steps first! + + This list describes how to set up the ISAPI module to work with the + Sambar server on Windows. + + * Find the file called mappings.ini (in the config directory) in the + Sambar install directory. + * Open mappings.ini and add the following line under [ISAPI]: + + Example 2-7. ISAPI configuration of Sambar +#for PHP 4 +*.php = c:\php\php4isapi.dll + +#for PHP 5 +*.php = c:\php\php5isapi.dll + + (This line assumes that PHP was installed in c:\php.) + * Now restart the Sambar server for the changes to take effect. + _________________________________________________________________ + +Xitami on Microsoft Windows + + This section contains notes and hints specific to Xitami on Windows. + + Note: You should read the manual installation steps first! + + This list describes how to set up the PHP CGI binary to work with + Xitami on Windows. + + Important for CGI users: Read the faq on cgi.force_redirect for + important details. This directive needs to be set to 0. If you want + to use $_SERVER['PHP_SELF'] you have to enable the cgi.fix_pathinfo + directive. + + Warning + + By using the CGI setup, your server is open to several possible + attacks. Please read our CGI security section to learn how to defend + yourself from those attacks. + + * Make sure the webserver is running, and point your browser to + xitamis admin console (usually http://127.0.0.1/admin), and click + on Configuration. + * Navigate to the Filters, and put the extension which PHP should + parse (i.e. .php) into the field File extensions (.xxx). + * In Filter command or script put the path and name of your PHP CGI + executable i.e. C:\php\php.exe for PHP 4, or C:\php\php-cgi.exe + for PHP 5. + * Press the 'Save' icon. + * Restart the server to reflect changes. + _________________________________________________________________ + +Installation of extensions on Windows + + After installing PHP and a webserver on Windows, you will probably + want to install some extensions for added functionality. You can + choose which extensions you would like to load when PHP starts by + modifying your php.ini. You can also load a module dynamically in your + script using dl(). + + The DLLs for PHP extensions are prefixed with php_. + + Note: In PHP 4.3.1 BCMath, Calendar, COM, Ctype, FTP, MySQL, ODBC, + Overload, PCRE, Session, Tokenizer, WDDX, XML and Zlib support is + built in. You don't need to load any additional extensions in order + to use these functions. See your distributions README.txt or + install.txt or this table for a list of built in modules. + + The default location PHP searches for extensions is c:\php4\extensions + in PHP 4 and c:\php5 in PHP 5. To change this setting to reflect your + setup of PHP edit your php.ini file: + + * You will need to change the extension_dir setting to point to the + directory where your extensions lives, or where you have placed + your php_*.dll files. Please do not forget the last backslash. For + example: + +extension_dir = c:/php/extensions/ + + * Enable the extension(s) in php.ini you want to use by uncommenting + the extension=php_*.dll lines in php.ini. This is done by deleting + the leading ; from the extension you want to load. + + Example 2-8. Enable Bzip2 extension for PHP-Windows +// change the following line from ... +;extension=php_bz2.dll + +// ... to +extension=php_bz2.dll + + * Some of the extensions need extra DLLs to work. Couple of them can + be found in the distribution package, in the C:\php\dlls\ folder + in PHP 4 or in the main folder in PHP 5, but some, for example + Oracle (php_oci8.dll) require DLLs which are not bundled with the + distribution package. If you are installing PHP 4, copy the + bundled DLLs from C:\php\dlls folder to the main C:\php folder. + Don't forget to include C:\php in the system PATH (this process is + explained in a separate FAQ entry). + * Some of these DLLs are not bundled with the PHP distribution. See + each extensions documentation page for details. Also, read the + manual section titled Installation of PECL extensions for details + on PECL. An increasingly large number of PHP extensions are found + in PECL, and these extensions require a separate download. + + Note: If you are running a server module version of PHP remember to + restart your webserver to reflect your changes to php.ini. + + The following table describes some of the extensions available and + required additional dlls. + + Table 2-1. PHP Extensions + Extension Description Notes + php_bz2.dll bzip2 compression functions None + php_calendar.dll Calendar conversion functions Built in since PHP + 4.0.3 + php_cpdf.dll ClibPDF functions None + php_crack.dll Crack functions None + php_ctype.dll ctype family functions Built in since PHP 4.3.0 + php_curl.dll CURL, Client URL library functions Requires: + libeay32.dll, ssleay32.dll (bundled) + php_cybercash.dll Cybercash payment functions PHP <= 4.2.0 + php_db.dll DBM functions Deprecated. Use DBA instead (php_dba.dll) + php_dba.dll DBA: DataBase (dbm-style) Abstraction layer functions None + php_dbase.dll dBase functions None + php_dbx.dll dbx functions + php_domxml.dll DOM XML functions PHP <= 4.2.0 requires: libxml2.dll + (bundled) PHP >= 4.3.0 requires: iconv.dll (bundled) + php_dotnet.dll .NET functions PHP <= 4.1.1 + php_exif.dll EXIF functions php_mbstring.dll. And, php_exif.dll must + be loaded after php_mbstring.dll in php.ini. + php_fbsql.dll FrontBase functions PHP <= 4.2.0 + php_fdf.dll FDF: Forms Data Format functions. Requires: fdftk.dll + (bundled) + php_filepro.dll filePro functions Read-only access + php_ftp.dll FTP functions Built-in since PHP 4.0.3 + php_gd.dll GD library image functions Removed in PHP 4.3.2. Also note + that truecolor functions are not available in GD1, instead, use + php_gd2.dll. + php_gd2.dll GD library image functions GD2 + php_gettext.dll Gettext functions PHP <= 4.2.0 requires + gnu_gettext.dll (bundled), PHP >= 4.2.3 requires libintl-1.dll, + iconv.dll (bundled). + php_hyperwave.dll HyperWave functions None + php_iconv.dll ICONV characterset conversion Requires: iconv-1.3.dll + (bundled), PHP >=4.2.1 iconv.dll + php_ifx.dll Informix functions Requires: Informix libraries + php_iisfunc.dll IIS management functions None + php_imap.dll IMAP POP3 and NNTP functions None + php_ingres.dll Ingres II functions Requires: Ingres II libraries + php_interbase.dll InterBase functions Requires: gds32.dll (bundled) + php_java.dll Java functions PHP <= 4.0.6 requires: jvm.dll (bundled) + php_ldap.dll LDAP functions PHP <= 4.2.0 requires libsasl.dll + (bundled), PHP >= 4.3.0 requires libeay32.dll, ssleay32.dll (bundled) + php_mbstring.dll Multi-Byte String functions None + php_mcrypt.dll Mcrypt Encryption functions Requires: libmcrypt.dll + php_mhash.dll Mhash functions PHP >= 4.3.0 requires: libmhash.dll + (bundled) + php_mime_magic.dll Mimetype functions Requires: magic.mime (bundled) + php_ming.dll Ming functions for Flash None + php_msql.dll mSQL functions Requires: msql.dll (bundled) + php_mssql.dll MSSQL functions Requires: ntwdblib.dll (bundled) + php_mysql.dll MySQL functions PHP >= 5.0.0, requires libmysql.dll + (bundled) + php_mysqli.dll MySQLi functions PHP >= 5.0.0, requires libmysql.dll + (libmysqli.dll in PHP <= 5.0.2) (bundled) + php_oci8.dll Oracle 8 functions Requires: Oracle 8.1+ client libraries + php_openssl.dll OpenSSL functions Requires: libeay32.dll (bundled) + php_oracle.dll Oracle functions Requires: Oracle 7 client libraries + php_overload.dll Object overloading functions Built in since PHP 4.3.0 + php_pdf.dll PDF functions None + php_pgsql.dll PostgreSQL functions None + php_printer.dll Printer functions None + php_shmop.dll Shared Memory functions None + php_snmp.dll SNMP get and walk functions NT only! + php_soap.dll SOAP functions PHP >= 5.0.0 + php_sockets.dll Socket functions None + php_sybase_ct.dll Sybase functions Requires: Sybase client libraries + php_tidy.dll Tidy functions PHP >= 5.0.0 + php_tokenizer.dll Tokenizer functions Built in since PHP 4.3.0 + php_w32api.dll W32api functions None + php_xmlrpc.dll XML-RPC functions PHP >= 4.2.1 requires: iconv.dll + (bundled) + php_xslt.dll XSLT functions PHP <= 4.2.0 requires sablot.dll, + expat.dll (bundled). PHP >= 4.2.1 requires sablot.dll, expat.dll, + iconv.dll (bundled). + php_yaz.dll YAZ functions Requires: yaz.dll (bundled) + php_zip.dll Zip File functions Read only access + php_zlib.dll ZLib compression functions Built in since PHP 4.3.0 + _________________________________________________________________ + +Chapter 3. Installation of PECL extensions + +Introduction to PECL Installations + + PHP extensions may be installed in a variety of ways. PECL is a + repository of PHP extensions living within the PEAR structure, and the + following demonstrates how to install these extensions. + + These instructions assume /your/phpsrcdir/ is the path to the PHP + source, and extname is the name of the PECL extension. Adjust + accordingly. These instructions also assume a familiarity with the + pear command. + + Shared extensions may be installed by including them inside of php.ini + using the extension PHP directive. See also the extensions_dir + directive, and dl(). The installation methods described below do not + automatically configure PHP to include these extensions, this step + must be done manually. + + When building PHP modules, it's important to have the appropriate + versions of the required tools (autoconf, automake, libtool, etc.) See + the Anonymous CVS Instructions for details on the required tools, and + required versions. + _________________________________________________________________ + +Downloading PECL extensions + + There are several options for downloading PECL extensions, such as: + + * http://pecl.php.net + Listed here is information like the ChangeLog, release + information, requirements, revisions, etc. Although not every PECL + extension has a webpage, most do. + * pear download extname + The pear command may also be used to download source files. + Specific revisions may also be specified. + * CVS + All PECL files reside in CVS. A web-based view may be seen at + http://cvs.php.net/pecl/. To download straight from CVS, consider + the following where phpfi is the password for user cvsread: + +$ cvs -d:pserver:cvsread@cvs.php.net:/repository login +$ cvs -d:pserver:cvsread@cvs.php.net:/repository co pecl/extname + + * Windows downloads + Windows users may find compiled PECL binaries by downloading the + Collection of PECL modules from the PHP Downloads page, and by + retrieving a PECL Snapshot. To compile PHP under Windows, read the + Win32 Build README. + _________________________________________________________________ + +PECL for Windows users + + Like with any other PHP extension DLL, to install move the PECL + extension DLLs into the extension_dir folder and include them within + php.ini. For example: + + extension=php_extname.dll + + After doing this, restart the web server. + _________________________________________________________________ + +Compiling shared PECL extensions with PEAR + + PEAR makes it easy to create shared PHP extensions. Using the pear + command, do the following: + + $ pear install extname + + That will download the source for extname, and compile it on the + system. This results in an extname.so file that may then be included + in php.ini + + In case the systems preferred_state is set higher than an available + extname version, like it's set to stable and the extension is still in + beta, either alter the preferred_state via pear config-set or specify + a specific version of the PECL extension. For example: + + $ pear install extname-0.1.1 + + Regardless, pear will copy this extname.so into the extensions + directory. Adjust php.ini accordingly. + _________________________________________________________________ + +Compiling shared PECL extensions with phpize + + If using pear is not an option, like for building shared PECL + extensions from CVS, or for unreleased PECL packages, then creating a + shared extension may also be done by manually using the phpize + command. The pear command essentially does this but it may also be + done manually. Assuming the source file is named extname.tgz, and that + it was downloaded into the current directory, consider the following: + +$ pear download extname +$ gzip -d < extname.tgz | tar -xvf - +$ cd extname +$ phpize +$ ./configure && make - Syntax error on line 1025 of c:/apache/apache/conf/httpd.conf: - Cannot load c:/php/php-4.2.1-win32/php5apache.dll into server + Upon success, this will create extname.so and put it into the modules/ + and/or .libs/ directory within the extname/ source. Move this shared + extension (extname.so) into the PHP extensions directory, and adjust + php.ini accordingly. + _________________________________________________________________ + +Compiling PECL extensions statically into PHP - But c:/php/php-4.2.1-win32/php5apache.dll definitely - exists: + To statically include the extension within the PHP build, put the + extensions source into the ext/ directory found in the PHP source. For + example: - dir c:\php\php-4.2.1-win32\php5apache.dll - Directory of c:\php\php-4.2.1-win32 - 13.05.2002 00:01 24.576 php5apache.dll +$ cd /your/phpsrcdir/ext +$ pear download extname +$ gzip -d < extname.tgz | tar -xvf - +$ mv extname-x.x.x extname +$ rm package.xml - 'strace'ing the apache.exe binary revealed the following: - c: - cd \apache\apache - strace apache >strace.txt + This will result in the following directory: - Then looking into strace.txt: - [...] -729 3348 3248 NtOpenSection (0xe, {24, 24, 0x40, 0, 0, "php5ts.dll"}, ... ) == STATUS_OBJECT_NAME_NOT_FOUND -731 3348 3248 NtQueryAttributesFile ({24, 0, 0x40, 0, 0, "\??\c:\php\php-4.2.1-win32\php5ts.dll"}, 1234824, ... ) == STATUS_OBJECT_NAME_NOT_FOUND -733 3348 3248 NtQueryAttributesFile ({24, 108, 0x40, 0, 0, "php5ts.dll"}, 1234824, ... ) == STATUS_OBJECT_NAME_NOT_FOUND -735 3348 3248 NtQueryAttributesFile ({24, 0, 0x40, 0, 0, "\??\C:\WINNT\System32\php5ts.dll"}, 1234824, ... ) == STATUS_OBJECT_NAME_NOT_FOUND - [...] - - This went on quiet some time for all directories in the %PATH% - environment variable. The solution finally was to copy - php5ts.dll in any of the directories searched by the System (I - prefered to use c:\php\php-4.2.1-win32). - - Note: This does not only apply to php5ts.dll but in fact to every - DLL which gets loaded through PHP too. So, if you've - problems running your PHP CLI application because it - can't load a certain library but you're sure it's there, - try this tool. - - - I'm using IIS/CGI and everytime I try to access a php file I get - "Security Alert! The PHP CGI cannot be accessed directly." - - Since 4.1.2, the php.ini setting cgi.force_redirect defaults to '1' which - effectively prevents the cgi from working within IIS. You need to set up at - least a minimal php.ini file with the following directive: - - cgi.force_redirect = 0 - - If it doesn't work immidiately, make sure you have the php.ini file in the - right place (%SYSTEMROOT%\php.ini). - - - Other problems - If you are still stuck, someone on the PHP installation mailing list may be - able to help you. You should check out the archive first, in case - someone already answered someone else who had the same problem as - you. The archives are available from the support page on www.php.net - To subscribe to the PHP installation mailing list, send an empty mail to: - - php-install-subscribe@lists.php.net + /your/phpsrcdir/ext/extname - The mailing list address is php-install@lists.php.net - - If you want to get help on the mailing list, please try to be - precise and give the necessary details about your environment - (which operating system, what PHP version, what web server, if - ou are running PHP as CGI or a server module, etc.), and - referably enough code to make others able to reproduce and test - our problem. + From here, build PHP as normal: -Bug reports -=========== +$ cd /your/phpsrcdir +$ ./buildconf +$ ./configure --help +$ ./configure --with-extname --enable-someotherext --with-foobar +$ make +$ make install + + Whether --enable-extname or --with-extname is used depends on the + extension. Typically an extension that does not require external + libraries uses --enable. To be sure, run the following after + buildconf: + + $ ./configure --help | grep extname + _________________________________________________________________ - If you think you have found a bug in PHP, please report it. The - PHP developers probably don't know about it, and unless you - report it, chances are it won't be fixed. +Chapter 4. Problems? - 1) Read about Bugs-Dos-And-Donts - http://bugs.php.net/bugs-dos-and-donts.php +Read the FAQ - 2) If you think you've found a bug, read - http://bugs.php.net/bugs-dos-and-donts.php + Some problems are more common than others. The most common ones are + listed in the PHP FAQ, part of this manual. + _________________________________________________________________ + +Other problems + + If you are still stuck, someone on the PHP installation mailing list + may be able to help you. You should check out the archive first, in + case someone already answered someone else who had the same problem as + you. The archives are available from the support page on + http://www.php.net/support.php. To subscribe to the PHP installation + mailing list, send an empty mail to + php-install-subscribe@lists.php.net. The mailing list address is + php-install@lists.php.net. + + If you want to get help on the mailing list, please try to be precise + and give the necessary details about your environment (which operating + system, what PHP version, what web server, if you are running PHP as + CGI or a server module, safe mode, etc...), and preferably enough code + to make others able to reproduce and test your problem. + _________________________________________________________________ + +Bug reports - 3) Feel welcome to file a report at - http://bugs.php.net/ + If you think you have found a bug in PHP, please report it. The PHP + developers probably don't know about it, and unless you report it, + chances are it won't be fixed. You can report bugs using the + bug-tracking system at http://bugs.php.net/. Please do not send bug + reports in mailing list or personal letters. The bug system is also + suitable to submit feature requests. + + Read the How to report a bug document before submitting any bug + reports! + _________________________________________________________________ + +Chapter 5. Runtime Configuration + +The configuration file + + The configuration file (called php3.ini in PHP 3, and simply php.ini + as of PHP 4) is read when PHP starts up. For the server module + versions of PHP, this happens only once when the web server is + started. For the CGI and CLI version, it happens on every invocation. + + The default location of php.ini is a compile time option (see the FAQ + entry), but can be changed for the CGI and CLI version with the -c + command line switch, see the chapter about using PHP from the command + line. You can also use the environment variable PHPRC for an + additional path to search for a php.ini file. + + If php-SAPI.ini exists (where SAPI is used SAPI, so the filename is + e.g. php-cli.ini or php-apache.ini), it's used instead of php.ini. + + Note: The Apache web server changes the directory to root at + startup causing PHP to attempt to read php.ini from the root + filesystem if it exists. + + The php.ini directives handled by extensions are documented + respectively on the pages of the extensions themselves. The list of + the core directives is available in the appendix. Probably not all the + PHP directives are documented in the manual though. For a completel + list of directives available in your PHP version, please read your + well commented php.ini file. Alternatively, you may find the the + latest php.ini from CVS helpful too. + + Example 5-1. php.ini example +; any text on a line after an unquoted semicolon (;) is ignored +[php] ; section markers (text within square brackets) are also ignored +; Boolean values can be set to either: +; true, on, yes +; or false, off, no, none +register_globals = off +track_errors = yes + +; you can enclose strings in double-quotes +include_path = ".:/usr/local/lib/php" + +; backslashes are treated the same as any other character +include_path = ".;c:\php\lib" + _________________________________________________________________ + +How to change configuration settings + +Running PHP as an Apache module + + When using PHP as an Apache module, you can also change the + configuration settings using directives in Apache configuration files + (e.g. httpd.conf) and .htaccess files. You will need "AllowOverride + Options" or "AllowOverride All" privileges to do so. + + With PHP 4 and PHP 5, there are several Apache directives that allow + you to change the PHP configuration from within the Apache + configuration files. For a listing of which directives are + PHP_INI_ALL, PHP_INI_PERDIR, or PHP_INI_SYSTEM, have a look at the + List of php.ini directives appendix. + + Note: With PHP 3, there are Apache directives that correspond to + each configuration setting in the php3.ini name, except the name is + prefixed by "php3_". + + php_value name value + Sets the value of the specified directive. Can be used only + with PHP_INI_ALL and PHP_INI_PERDIR type directives. To clear a + previously set value use none as the value. + + Note: Don't use php_value to set boolean values. php_flag (see + below) should be used instead. + + php_flag name on|off + Used to set a boolean configuration directive. Can be used only + with PHP_INI_ALL and PHP_INI_PERDIR type directives. + + php_admin_value name value + Sets the value of the specified directive. This can not be used + in .htaccess files. Any directive type set with php_admin_value + can not be overridden by .htaccess or virtualhost directives. + To clear a previously set value use none as the value. + + php_admin_flag name on|off + Used to set a boolean configuration directive. This can not be + used in .htaccess files. Any directive type set with + php_admin_flag can not be overridden by .htaccess or + virtualhost directives. + + Example 5-2. Apache configuration example + + php_value include_path ".:/usr/local/lib/php" + php_admin_flag safe_mode on + + + php_value include_path ".:/usr/local/lib/php" + php_admin_flag safe_mode on + + + php3_include_path ".:/usr/local/lib/php" + php3_safe_mode on + + + Caution + + PHP constants do not exist outside of PHP. For example, in httpd.conf + you can not use PHP constants such as E_ALL or E_NOTICE to set the + error_reporting directive as they will have no meaning and will + evaluate to 0. Use the associated bitmask values instead. These + constants can be used in php.ini + _________________________________________________________________ + +Changing PHP configuration via the Windows registry + + When running PHP on Windows, the configuration values can be modified + on a per-directory basis using the Windows registry. The configuration + values are stored in the registry key HKLM\SOFTWARE\PHP\Per Directory + Values, in the sub-keys corresponding to the path names. For example, + configuration values for the directory c:\inetpub\wwwroot would be + stored in the key HKLM\SOFTWARE\PHP\Per Directory + Values\c\inetpub\wwwroot. The settings for the directory would be + active for any script running from this directory or any subdirectory + of it. The values under the key should have the name of the PHP + configuration directive and the string value. PHP constants in the + values are not parsed. However, only configuration values changeable + in PHP_INI_USER can be set this way, PHP_INI_PERDIR values can not. + _________________________________________________________________ + +Other interfaces to PHP + + Regardless of how you run PHP, you can change certain values at + runtime of your scripts through ini_set(). See the documentation on + the ini_set() page for more information. + + If you are interested in a complete list of configuration settings on + your system with their current values, you can execute the phpinfo() + function, and review the resulting page. You can also access the + values of individual configuration directives at runtime using + ini_get() or get_cfg_var(). diff --git a/win32/php5dllts.dsp b/win32/php5dllts.dsp index 6412a95d57e9..60bbad92eb0e 100644 --- a/win32/php5dllts.dsp +++ b/win32/php5dllts.dsp @@ -209,6 +209,10 @@ SOURCE=..\main\php_scandir.c # End Source File # Begin Source File +SOURCE=..\main\php_sprintf.c +# End Source File +# Begin Source File + SOURCE=..\main\php_ticks.c # End Source File # Begin Source File diff --git a/sapi/activescript/php5as_classfactory.h b/win32/php_win32_globals.h old mode 100644 new mode 100755 similarity index 50% rename from sapi/activescript/php5as_classfactory.h rename to win32/php_win32_globals.h index 61823fb689d5..7153478cda36 --- a/sapi/activescript/php5as_classfactory.h +++ b/win32/php_win32_globals.h @@ -12,48 +12,47 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Authors: Wez Furlong | + | Author: Wez Furlong | +----------------------------------------------------------------------+ - */ +*/ + /* $Id$ */ -/* IClassFactory Implementation */ +#ifndef PHP_WIN32_GLOBALS_H +#define PHP_WIN32_GLOBALS_H + +/* misc globals for thread-safety under win32 */ -#include +#include "pwd.h" -// {CF108A38-59A9-468a-AF45-1368D7855DAE} -DEFINE_GUID(CLSID_PHPActiveScriptEngine, -0xcf108a38, 0x59a9, 0x468a, 0xaf, 0x45, 0x13, 0x68, 0xd7, 0x85, 0x5d, 0xae); +typedef struct _php_win32_core_globals php_win32_core_globals; -#if 0 -/* this was for PHP 4 */ -// {A0AD8E7A-95EC-4819-986F-78D93895F2AE} -DEFINE_GUID(CLSID_PHPActiveScriptEngine, -0xa0ad8e7a, 0x95ec, 0x4819, 0x98, 0x6f, 0x78, 0xd9, 0x38, 0x95, 0xf2, 0xae); +#ifdef ZTS +# define PW32G(v) TSRMG(php_win32_core_globals_id, php_win32_core_globals*, v) +extern PHPAPI int php_win32_core_globals_id; +#else +# define PW32G(v) (php_win32_core_globals.v) +extern PHPAPI struct _php_win32_core_globals php_win32_core_globals; #endif -class TPHPClassFactory: - public IClassFactory -{ -protected: - volatile LONG m_refcount; - - static volatile LONG factory_count; - static volatile LONG object_count; - -public: /* IUnknown */ - STDMETHODIMP QueryInterface(REFIID iid, void **ppvObject); - STDMETHODIMP_(DWORD) AddRef(void); - STDMETHODIMP_(DWORD) Release(void); -public: /* IClassFactory */ - STDMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **ppvObject); - STDMETHODIMP LockServer(BOOL fLock); - - TPHPClassFactory(); - ~TPHPClassFactory(); - - static void AddToObjectCount(void); - static void RemoveFromObjectCount(void); - static int CanUnload(void); +struct _php_win32_core_globals { + /* syslog */ + char *log_header; + HANDLE log_source; + + /* getpwuid */ + struct passwd pwd; + + /* getlogin */ + char *login_name; + + /* time */ + struct timeval starttime; + __int64 lasttime, freq; }; +void php_win32_core_globals_ctor(void *vg TSRMLS_DC); +PHP_RSHUTDOWN_FUNCTION(win32_core_globals); + +#endif + diff --git a/win32/pwd.c b/win32/pwd.c index 2c76480cead6..de3112db0859 100644 --- a/win32/pwd.c +++ b/win32/pwd.c @@ -26,10 +26,7 @@ #include #include "pwd.h" #include "grp.h" - -#ifndef THREAD_SAFE -static struct passwd pwd; -#endif +#include "php_win32_globals.h" static char *home_dir = "."; static char *login_shell = "not command.com!"; @@ -44,21 +41,26 @@ getpwnam(char *name) char * getlogin() { - static char name[256]; + char name[256]; DWORD max_len = 256; + TSRMLS_FETCH(); + STR_FREE(PW32G(login_name)); GetUserName(name, &max_len); - return name; + name[max_len] = '\0'; + PW32G(login_name) = estrdup(name); + return PW32G(login_name); } struct passwd * getpwuid(int user_id) { - pwd.pw_name = getlogin(); - pwd.pw_dir = home_dir; - pwd.pw_shell = login_shell; - pwd.pw_uid = 0; + TSRMLS_FETCH(); + PW32G(pwd).pw_name = getlogin(); + PW32G(pwd).pw_dir = home_dir; + PW32G(pwd).pw_shell = login_shell; + PW32G(pwd).pw_uid = 0; - return &pwd; + return &PW32G(pwd); } diff --git a/win32/registry.c b/win32/registry.c index 6eda0f9fffa3..95d142cfa8b5 100644 --- a/win32/registry.c +++ b/win32/registry.c @@ -38,6 +38,9 @@ void UpdateIniFromRegistry(char *path TSRMLS_DC) drive_letter = tmp_buf[0]; cwd++; } + while (*cwd == '\\' || *cwd == '/') { + cwd++; + } path = (char *) emalloc(2+strlen(cwd)+1+strlen(orig_path)+1); sprintf(path, "%c\\%s\\%s", drive_letter, cwd, orig_path); efree(orig_path); diff --git a/win32/sendmail.c b/win32/sendmail.c index 98659d4db48f..ba754f7cda08 100644 --- a/win32/sendmail.c +++ b/win32/sendmail.c @@ -24,10 +24,10 @@ #include #ifndef NETWARE #include +#include "time.h" #else /* NETWARE */ -#include +#include #endif /* NETWARE */ -#include "time.h" #include #include #ifndef NETWARE @@ -83,13 +83,11 @@ SOCKET sc; #ifndef NETWARE WSADATA Data; struct hostent *adr; -#endif /* NETWARE */ -SOCKADDR_IN sock_in; -#ifndef NETWARE int WinsockStarted; /* values set by the constructor */ char *AppName; #endif /* NETWARE */ +SOCKADDR_IN sock_in; char MailHost[HOST_NAME_LEN]; char LocalHost[HOST_NAME_LEN]; #endif @@ -225,6 +223,7 @@ PHPAPI int TSendMail(char *host, int *error, char **error_message, int ret; char *RPath = NULL; char *headers_lc = NULL; /* headers_lc is only created if we've a header at all */ + char *pos1 = NULL, *pos2 = NULL; TSRMLS_FETCH(); #ifndef NETWARE @@ -266,9 +265,21 @@ PHPAPI int TSendMail(char *host, int *error, char **error_message, /* Fall back to sendmail_from php.ini setting */ if (mailRPath && *mailRPath) { RPath = estrdup(mailRPath); - } - else if (INI_STR("sendmail_from")) { + } else if (INI_STR("sendmail_from")) { RPath = estrdup(INI_STR("sendmail_from")); + } else if ( headers_lc && + (pos1 = strstr(headers_lc, "from:")) && + ((pos1 == headers_lc) || (*(pos1-1) == '\n')) + ) { + /* Real offset is memaddress from the original headers + difference of + * string found in the lowercase headrs + 5 characters to jump over + * the from: */ + pos1 = headers + (pos1 - headers_lc) + 5; + if (NULL == (pos2 = strstr(pos1, "\r\n"))) { + RPath = estrndup(pos1, strlen(pos1)); + } else { + RPath = estrndup(pos1, pos2-pos1); + } } else { if (headers) { efree(headers); @@ -333,14 +344,7 @@ PHPAPI void TSMClose() */ shutdown(sc, 0); -#ifndef NETWARE closesocket(sc); -#else - /* closesocket commented out since it was giving undefined symbol linker error - * close added in its place - */ - close(sc); -#endif /* NETWARE */ } @@ -472,7 +476,7 @@ int SendText(char *RPath, char *Subject, char *mailTo, char *mailCc, char *mailB efree(tempMailTo); } /* Send mail to all Cc rcpt's */ - else if (headers && (pos1 = strstr(headers_lc, "cc:")) && ((pos1 == headers_lc) || iscntrl(*(pos1-1)))) { + else if (headers && (pos1 = strstr(headers_lc, "cc:")) && ((pos1 == headers_lc) || (*(pos1-1) == '\n'))) { /* Real offset is memaddress from the original headers + difference of * string found in the lowercase headrs + 3 characters to jump over * the cc: */ @@ -828,11 +832,7 @@ int MailConnect() // Author/Date: jcar 20/9/96 // History: //********************************************************************/ -#ifndef NETWARE int Post(LPCSTR msg) -#else -int Post(char *msg) -#endif { int len = strlen(msg); int slen; @@ -919,11 +919,7 @@ int Ack(char **server_response) // Author/Date: jcar 20/9/96 // History: //********************************************************************/ -#ifndef NETWARE unsigned long GetAddr(LPSTR szHost) -#else -unsigned long GetAddr(char * szHost) -#endif { LPHOSTENT lpstHost; u_long lAddr = INADDR_ANY; @@ -939,11 +935,7 @@ unsigned long GetAddr(char * szHost) lpstHost = gethostbyname(szHost); if (lpstHost) { /* success */ -#ifndef NETWARE lAddr = *((u_long FAR *) (lpstHost->h_addr)); -#else - lAddr = *((u_long *) (lpstHost->h_addr)); -#endif /* NETWARE */ } else { lAddr = INADDR_ANY; /* failure */ } diff --git a/win32/sendmail.h b/win32/sendmail.h index 3f3539e24c4c..28b5d734994f 100644 --- a/win32/sendmail.h +++ b/win32/sendmail.h @@ -44,18 +44,7 @@ PHPAPI char *GetSMErrorText(int index); int MailConnect(); int PostHeader(char *, char *, char *, char *); -#ifndef NETWARE int Post(LPCSTR msg); -#else -int Post(char *msg); -#endif int Ack(char **server_response); -#ifndef NETWARE unsigned long GetAddr(LPSTR szHost); -#else -unsigned long GetAddr(char * szHost); -#endif - - - #endif /* sendmail_h */ diff --git a/win32/time.c b/win32/time.c index 9a3e004a4d5c..693f07418536 100644 --- a/win32/time.c +++ b/win32/time.c @@ -33,6 +33,7 @@ #include #include #include +#include "php_win32_globals.h" int getfilesystemtime(struct timeval *time_Info) { @@ -51,64 +52,61 @@ __int64 ff; PHPAPI int gettimeofday(struct timeval *time_Info, struct timezone *timezone_Info) { - - static struct timeval starttime = {0, 0}; - static __int64 lasttime = 0; - static __int64 freq = 0; __int64 timer; LARGE_INTEGER li; BOOL b; double dt; + TSRMLS_FETCH(); /* Get the time, if they want it */ if (time_Info != NULL) { - if (starttime.tv_sec == 0) { + if (PW32G(starttime).tv_sec == 0) { b = QueryPerformanceFrequency(&li); if (!b) { - starttime.tv_sec = -1; + PW32G(starttime).tv_sec = -1; } else { - freq = li.QuadPart; + PW32G(freq) = li.QuadPart; b = QueryPerformanceCounter(&li); if (!b) { - starttime.tv_sec = -1; + PW32G(starttime).tv_sec = -1; } else { - getfilesystemtime(&starttime); + getfilesystemtime(&PW32G(starttime)); timer = li.QuadPart; - dt = (double)timer/freq; - starttime.tv_usec -= (int)((dt-(int)dt)*1000000); - if (starttime.tv_usec < 0) { - starttime.tv_usec += 1000000; - --starttime.tv_sec; + dt = (double)timer/PW32G(freq); + PW32G(starttime).tv_usec -= (int)((dt-(int)dt)*1000000); + if (PW32G(starttime).tv_usec < 0) { + PW32G(starttime).tv_usec += 1000000; + --PW32G(starttime).tv_sec; } - starttime.tv_sec -= (int)dt; + PW32G(starttime).tv_sec -= (int)dt; } } } - if (starttime.tv_sec > 0) { + if (PW32G(starttime).tv_sec > 0) { b = QueryPerformanceCounter(&li); if (!b) { - starttime.tv_sec = -1; + PW32G(starttime).tv_sec = -1; } else { timer = li.QuadPart; - if (timer < lasttime) { + if (timer < PW32G(lasttime)) { getfilesystemtime(time_Info); - dt = (double)timer/freq; - starttime = *time_Info; - starttime.tv_usec -= (int)((dt-(int)dt)*1000000); - if (starttime.tv_usec < 0) { - starttime.tv_usec += 1000000; - --starttime.tv_sec; + dt = (double)timer/PW32G(freq); + PW32G(starttime) = *time_Info; + PW32G(starttime).tv_usec -= (int)((dt-(int)dt)*1000000); + if (PW32G(starttime).tv_usec < 0) { + PW32G(starttime).tv_usec += 1000000; + --PW32G(starttime).tv_sec; } - starttime.tv_sec -= (int)dt; + PW32G(starttime).tv_sec -= (int)dt; } else { - lasttime = timer; - dt = (double)timer/freq; - time_Info->tv_sec = starttime.tv_sec + (int)dt; - time_Info->tv_usec = starttime.tv_usec + (int)((dt-(int)dt)*1000000); + PW32G(lasttime) = timer; + dt = (double)timer/PW32G(freq); + time_Info->tv_sec = PW32G(starttime).tv_sec + (int)dt; + time_Info->tv_usec = PW32G(starttime).tv_usec + (int)((dt-(int)dt)*1000000); if (time_Info->tv_usec > 1000000) { time_Info->tv_usec -= 1000000; ++time_Info->tv_sec; @@ -116,7 +114,7 @@ PHPAPI int gettimeofday(struct timeval *time_Info, struct timezone *timezone_Inf } } } - if (starttime.tv_sec < 0) { + if (PW32G(starttime).tv_sec < 0) { getfilesystemtime(time_Info); } @@ -144,6 +142,7 @@ void usleep(unsigned int useconds) CloseHandle(timer); } +#if 0 /* looks pretty ropey in here */ #ifdef HAVE_SETITIMER @@ -225,3 +224,5 @@ PHPAPI int setitimer(int which, const struct itimerval *value, struct itimerval } #endif +#endif + diff --git a/win32/wsyslog.c b/win32/wsyslog.c index 7db5156011cb..ca1e45b9ca4f 100644 --- a/win32/wsyslog.c +++ b/win32/wsyslog.c @@ -56,15 +56,14 @@ #include #include -#ifndef THREAD_SAFE -static char *loghdr; /* log file header string */ -static HANDLE loghdl = NULL; /* handle of event source */ -#endif +#include "php_win32_globals.h" void closelog(void) { - DeregisterEventSource(loghdl); - efree(loghdr); + TSRMLS_FETCH(); + DeregisterEventSource(PW32G(log_source)); + STR_FREE(PW32G(log_header)); + PW32G(log_header) = NULL; } /* Emulator for BSD syslog() routine @@ -77,12 +76,14 @@ void syslog(int priority, const char *message, ...) { va_list args; LPTSTR strs[2]; - char tmp[1024]; /* callers must be careful not to pop this */ unsigned short etype; - + char *tmp = NULL; + TSRMLS_FETCH(); + /* default event source */ - if (!loghdl) - openlog("c-client", LOG_PID, LOG_MAIL); + if (!PW32G(log_source)) + openlog("php", LOG_PID, LOG_SYSLOG); + switch (priority) { /* translate UNIX type into NT type */ case LOG_ALERT: etype = EVENTLOG_ERROR_TYPE; @@ -94,12 +95,13 @@ void syslog(int priority, const char *message, ...) etype = EVENTLOG_WARNING_TYPE; } va_start(args, message); /* initialize vararg mechanism */ - vsprintf(tmp, message, args); /* build message */ - strs[0] = loghdr; /* write header */ + vspprintf(&tmp, 0, message, args); /* build message */ + strs[0] = PW32G(log_header); /* write header */ strs[1] = tmp; /* then the message */ /* report the event */ - ReportEvent(loghdl, etype, (unsigned short) priority, 2000, NULL, 2, 0, strs, NULL); + ReportEvent(PW32G(log_source), etype, (unsigned short) priority, 2000, NULL, 2, 0, strs, NULL); va_end(args); + efree(tmp); } @@ -111,12 +113,14 @@ void syslog(int priority, const char *message, ...) void openlog(const char *ident, int logopt, int facility) { - char tmp[1024]; + TSRMLS_FETCH(); - if (loghdl) { + if (PW32G(log_source)) { closelog(); } - loghdl = RegisterEventSource(NULL, ident); - sprintf(tmp, (logopt & LOG_PID) ? "%s[%d]" : "%s", ident, getpid()); - loghdr = estrdup(tmp); /* save header for later */ + + STR_FREE(PW32G(log_header)); + + PW32G(log_source) = RegisterEventSource(NULL, ident); + spprintf(&PW32G(log_header), 0, (logopt & LOG_PID) ? "%s[%d]" : "%s", ident, getpid()); }